diff --git a/setup.py b/setup.py index acf5e4fe..9a0d3489 100644 --- a/setup.py +++ b/setup.py @@ -68,6 +68,7 @@ "dcore_bse = dcore.dcore_bse:run", "dcore_gk = dcore.dcore_gk:run", "dcore_mpicheck = dcore.dcore_mpicheck:run", + "dcore_anacont = dcore.dcore_anacont:run", "dcore_anacont_pade = dcore.dcore_anacont_pade:run", "dcore_anacont_spm = dcore.dcore_anacont_spm:run", "dcore_anacont_spm_interactive = dcore.dcore_anacont_spm_interactive:run", diff --git a/src/dcore/anacont/__init__.py b/src/dcore/anacont/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/dcore/anacont/pade.py b/src/dcore/anacont/pade.py new file mode 100644 index 00000000..7f30c99c --- /dev/null +++ b/src/dcore/anacont/pade.py @@ -0,0 +1,62 @@ +# +# DCore -- Integrated DMFT software for correlated electrons +# Copyright (C) 2017 The University of Tokyo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import numpy + +from dcore._dispatcher import MeshImFreq, GfReFreq, GfImFreq +from dcore.program_options import create_parser, parse_parameters + + +def _set_n_pade(omega_cutoff, beta, n_min, n_max): + """ + Return (int)n_pade: the number of Matsubara frequencies below the cutoff frequency. + n_pade is bounded between n_min and n_max + """ + n_pade = int((beta * omega_cutoff + numpy.pi) / (2.0 * numpy.pi)) + print("n_pade = {} (evaluated from omega_pade)".format(n_pade)) + n_pade = max(n_pade, n_min) + n_pade = min(n_pade, n_max) + print("n_pade = {}".format(n_pade)) + return n_pade + + +def anacont(sigma_iw_npz, beta, mesh_w, params_pade): + iw_max = params_pade["iomega_max"] + n_min = params_pade["n_min"] + n_max = params_pade["n_max"] + eta = params_pade["eta"] + n_pade = _set_n_pade(iw_max, beta, n_min=n_min, n_max=n_max) + + data_w = {} + num_data = numpy.sum([key.startswith("data") for key in sigma_iw_npz.keys()]) + for idata in range(num_data): + key = f"data{idata}" + data = sigma_iw_npz[key] + mesh_iw = MeshImFreq(beta, "Fermion", data.shape[0] // 2) + sigma_iw = GfImFreq(data=data, beta=beta, mesh=mesh_iw) + sigma_w = GfReFreq(mesh=mesh_w, target_shape=data.shape[1:]) + sigma_w.set_from_pade(sigma_iw, n_points=n_pade, freq_offset=eta) + data_w[key] = sigma_w.data + return data_w + + +def parameters_from_ini(inifile): + parser = create_parser(["post.anacont.pade"]) + parser.read(inifile) + params = parser.as_dict() + return params["post.anacont.pade"] diff --git a/src/dcore/anacont/spm.py b/src/dcore/anacont/spm.py new file mode 100644 index 00000000..775f9492 --- /dev/null +++ b/src/dcore/anacont/spm.py @@ -0,0 +1,351 @@ +# +# DCore -- Integrated DMFT software for correlated electrons +# Copyright (C) 2017 The University of Tokyo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import sys + +import numpy as np +import cvxpy as cp +from scipy.interpolate import interp1d +from scipy.sparse.linalg import svds + +from dcore._dispatcher import MeshImFreq, GfImFreq, GfReFreq +from dcore.program_options import create_parser + +def set_default_values(dictionary, default_values_dict): + for key, value in default_values_dict.items(): + if key not in dictionary: + dictionary[key] = value + return dictionary + + +def _find_sum_rule_const(matsubara_frequencies, gf_wn, ntail, show_fit=False): + wntail = matsubara_frequencies[-ntail:] + gftail = gf_wn[-ntail:] + const_imagpart = -np.mean(np.imag(gftail) * wntail) + const_realpart = np.mean(np.real(gftail)) + if show_fit: + import matplotlib.pyplot as plt + + z = np.linspace(wntail[0], wntail[-1], num=1000) + plt.scatter(wntail, np.imag(gftail), zorder=5, color="C0", label="data") + plt.plot(z, -const_imagpart / z, zorder=10, color="C1", label="fit") + plt.xlabel(r"$\omega_n$") + plt.ylabel(r"Im $G( \omega_n )$") + plt.legend() + plt.tight_layout() + plt.show() + return const_realpart, const_imagpart + + +def _calc_gf_tau( + matsubara_frequencies, gf_wn, beta, const_real_tail, const_imag_tail, ntau +): + tau_grid = np.linspace(0, beta, num=ntau) + gf_tau = -0.5 * const_imag_tail * np.ones(tau_grid.shape, dtype=np.float64) + kernel = lambda tau: np.sum( + (np.real(gf_wn) - const_real_tail) * np.cos(matsubara_frequencies * tau) + + (np.imag(gf_wn) + const_imag_tail / matsubara_frequencies) + * np.sin(matsubara_frequencies * tau) + ) + gf_tau += 2 / beta * np.vectorize(kernel)(tau_grid) + gf_tau *= -1 + return tau_grid, gf_tau + + +def calc_gf_tau_from_gf_matsubara( + matsubara_frequencies, gf_wn, ntau, ntail, beta, show_fit=False +): + const_real_tail, const_imag_tail = _find_sum_rule_const( + matsubara_frequencies, gf_wn, ntail, show_fit=show_fit + ) + print("Determined tail constants: {}, {}".format(const_real_tail, const_imag_tail)) + tau_grid, gf_tau = _calc_gf_tau( + matsubara_frequencies, gf_wn, beta, const_real_tail, const_imag_tail, ntau + ) + return tau_grid, gf_tau, const_real_tail, const_imag_tail + + +def get_single_continuation( + tau_grid, + gf_tau, + nsv, + beta, + emin, + emax, + num_energies, + sum_rule_const, + lambd, + verbose=True, + max_iters=100, + solver="ECOS", +): + U, S, Vt, delta_energy, energies_extract = _get_svd_for_continuation( + tau_grid, nsv, beta, emin, emax, num_energies + ) + rho_prime, gf_tau_fit, chi2 = _solveProblem( + delta_energy, + U, + S, + Vt, + gf_tau, + sum_rule_const, + lambd, + verbose=verbose, + max_iters=max_iters, + solver=solver, + ) + rho = np.dot(Vt.T, rho_prime) + rho_integrated = np.trapz(y=rho, x=energies_extract) + return rho, gf_tau_fit, energies_extract, rho_integrated, chi2 + + +def get_multiple_continuations( + tau_grid, + gf_tau, + nsv, + beta, + emin, + emax, + num_energies, + sum_rule_const, + lambdas, + verbose=True, + max_iters=100, + solver="ECOS", +): + U, S, Vt, delta_energy, energies_extract = _get_svd_for_continuation( + tau_grid, nsv, beta, emin, emax, num_energies + ) + continued_densities = [] + chi2_values = [] + rho_values = [] + for lambd in lambdas: + rho_prime, _, chi2 = _solveProblem( + delta_energy, + U, + S, + Vt, + gf_tau, + sum_rule_const, + lambd, + verbose=verbose, + max_iters=max_iters, + solver=solver, + ) + rho = np.dot(Vt.T, rho_prime) + rho_integrated = np.trapz(y=rho, x=energies_extract) + continued_densities.append(rho) + chi2_values.append(chi2) + rho_values.append(rho_integrated) + return energies_extract, continued_densities, chi2_values, rho_values + + +def _get_kernel_matrix( + energies, tau_grid, beta, delta_energy, z_critical=20 +): # with z_critical=20 error of asymptote is below 1e-10 + assert tau_grid[0] == 0 + assert tau_grid[-1] == beta + i_lc = np.searchsorted(energies, -z_critical / beta) + i_rc = np.searchsorted(energies, +z_critical / beta) + kernel = np.zeros((len(tau_grid), len(energies))) + kernel[:, i_lc : i_rc + 1] = ( + 0.5 + * np.exp(np.multiply.outer(0.5 * beta - tau_grid, energies[i_lc : i_rc + 1])) + / np.cosh(0.5 * beta * energies[i_lc : i_rc + 1]) + ) + if i_lc > 0: # asymptote for kernel for w -> -inf + kernel[:, 0:i_lc] = np.exp(np.multiply.outer(beta - tau_grid, energies[0:i_lc])) + if i_rc < len(energies) - 1: # asymptote for kernel for w -> +inf + kernel[:, i_rc + 1 : len(energies)] = np.exp( + np.multiply.outer(-tau_grid, energies[i_rc + 1 : len(energies)]) + ) + kernel[:, 0] *= 0.5 + kernel[:, -1] *= 0.5 + kernel *= delta_energy + return kernel + + +def _getSVD(matrix, nsv=None): + if nsv == None or nsv >= min(matrix.shape) or nsv <= 0: + raise Exception( + "nsv must be 0 < nsv < {} (min(matrix.shape))".format(min(matrix.shape)) + ) + U, S, V = svds(matrix, k=nsv, which="LM") + S = np.flip(S, axis=0) + U = np.flip(U, axis=1) + Vt = np.flip(V, axis=0) + return U, S, Vt + + +def _solveProblem( + delta_energy, + U, + S, + Vt, + gf_tau, + sum_rule_const, + lambd, + verbose=True, + max_iters=100, + solver="ECOS", +): + Q = len(S) + Smat = np.diag(S) + rho_prime = cp.Variable(Q) + errTerm = gf_tau - U @ Smat @ rho_prime + objective = cp.Minimize(0.5 * cp.norm2(errTerm) ** 2 + lambd * cp.norm1(rho_prime)) + V_mod = np.copy(Vt.T) + V_mod[0, :] *= 0.5 + V_mod[-1, :] *= 0.5 + constraints = [ + Vt.T @ rho_prime >= 0, + cp.sum(delta_energy * V_mod @ rho_prime) == sum_rule_const, + ] # uniform real energy grid is assumed here + prob = cp.Problem(objective, constraints) + _ = prob.solve(verbose=verbose, solver=solver, max_iters=max_iters) + gf_tau_fit = np.dot(U, np.dot(Smat, rho_prime.value)) + chi2 = 0.5 * np.linalg.norm(gf_tau - gf_tau_fit, ord=2) ** 2 + return rho_prime.value, gf_tau_fit, chi2 + + +def _get_svd_for_continuation(tau_grid, nsv, beta, emin, emax, num_energies): + energies_extract = np.linspace(emin, emax, num=num_energies) + delta_energy = energies_extract[1] - energies_extract[0] + kernel = _get_kernel_matrix(energies_extract, tau_grid, beta, delta_energy) + U, S, Vt = _getSVD(kernel, nsv=nsv) + return U, S, Vt, delta_energy, energies_extract + + +def _integral_kramers_kronig( + energies_imagpart, energy_realpart, gf_imag_interp, energy_threshold +): + enum1 = gf_imag_interp(energies_imagpart) - gf_imag_interp(energy_realpart) + enum2 = np.gradient(gf_imag_interp(energies_imagpart), energies_imagpart) + den = energies_imagpart - energy_realpart + mask = np.where(np.abs(den) < energy_threshold, 1, 0) # 1 if den is below threshold + # avoid divide by zero with mask * energy_threshold, in this case (1 - mask == 0) + term1 = enum1 / (den + mask * energy_threshold) * (1 - mask) + term2 = enum2 * mask + kernel = term1 + term2 + integral = np.trapz(y=kernel, x=energies_imagpart) + return integral + + +def get_kramers_kronig_realpart( + energies, gf_imag, energy_threshold=1e-10, dos_threshold=1e-5 +): + if np.abs(gf_imag[0]) > dos_threshold: + print("Warning! DOS at left interval end exceeds {}.".format(dos_threshold)) + if np.abs(gf_imag[-1]) > dos_threshold: + print("Warning! DOS at right interval end exceeds {}.".format(dos_threshold)) + gf_real = np.zeros(energies.shape, dtype=np.float64) + gf_imag_interp = interp1d( + energies, gf_imag, kind="linear", bounds_error=False, fill_value=0.0 + ) + energies_noend = energies[1:-1] + a, b = energies[0], energies[-1] + gf_real[1:-1] = ( + gf_imag_interp(energies_noend) + / np.pi + * np.log((b - energies_noend) / (energies_noend - a)) + ) # assume zero DOS at endpoints + integral_func = lambda y: _integral_kramers_kronig( + energies, y, gf_imag_interp, energy_threshold + ) + gf_real += np.vectorize(integral_func)(energies) / np.pi + return energies, gf_real, gf_imag + + +def dos_to_gf_imag(dos): + return -np.pi * dos + + +def check_parameters(params): + n_tau = params["n_tau"] + if n_tau <= 0: + sys.exit("n_tau must be positive.") + pass + +def parameters_from_ini(inifile): + parser = create_parser(["post.anacont.spm"]) + parser.read(inifile) + params = parser.as_dict() + return params["post.anacont.spm"] + +def anacont(sigma_iw_npz, beta, mesh_w, params_spm): + + n_tau = params_spm["n_tau"] + n_tail = params_spm["n_tail"] + show_fit = params_spm["show_fit"] + + n_sv = params_spm["n_sv"] + L1_coeff = params_spm["lambda"] + max_iters = params_spm["max_iters_opt"] + solver_opt = params_spm["solver_opt"] + verbose_opt = params_spm["verbose_opt"] + + data_w = {} + num_data = np.sum([key.startswith("data") for key in sigma_iw_npz.keys()]) + for idata in range(num_data): + key = f"data{idata}" + data = sigma_iw_npz[key] + n_matsubara = data.shape[0] // 2 + n_matsubara_retain = min(n_matsubara, params_spm["n_matsubara"]) + mesh_iw = MeshImFreq(beta, "Fermion", n_matsubara_retain) + gf_iw = GfImFreq(data=data, beta=beta, mesh=mesh_iw) + n_orbitals = gf_iw.data.shape[1] + matsubara_frequencies = np.imag(gf_iw.mesh.values()[n_matsubara_retain:]) + sigma_w_data = np.zeros( + (mesh_w.size, n_orbitals, n_orbitals), dtype=np.complex128 + ) + for i_orb in range(n_orbitals): + print( + f"Performing analytic continuation for data index {idata} and orbital index {i_orb}..." + ) + gf_imag_matsubara = gf_iw.data[ + n_matsubara : n_matsubara + n_matsubara_retain, i_orb, i_orb + ] + + tau_grid, gf_tau, const_real_tail, const_imag_tail = calc_gf_tau_from_gf_matsubara( + matsubara_frequencies, gf_imag_matsubara, n_tau, n_tail, beta, show_fit=show_fit + ) + + density, gf_tau_fit, energies_extract, sum_rule_const, chi2 = get_single_continuation( + tau_grid, gf_tau, n_sv, beta, mesh_w.values()[0], mesh_w.values()[-1], mesh_w.size, sum_rule_const=const_imag_tail, lambd=L1_coeff, verbose=verbose_opt, max_iters=max_iters, solver=solver_opt + ) + energies, gf_real, gf_imag = get_kramers_kronig_realpart( + energies_extract, dos_to_gf_imag(density) + ) + gf_real += const_real_tail + + sigma_w_data[:, i_orb, i_orb] = gf_real + 1j * gf_imag + if params_spm["show_result"]: + import matplotlib.pyplot as plt + + plt.axhline(y=0, xmin=energies[0], xmax=energies[-1], color="lightgrey") + plt.plot(energies, gf_real, label=r"Re $G( \omega )$") + plt.plot(energies, gf_imag, label=r"Im $G( \omega )$") + plt.xlim(energies[0], energies[-1]) + plt.xlabel(r"$\omega$") + plt.legend() + plt.tight_layout() + plt.show() + plt.close() + sigma_w = GfReFreq(mesh=mesh_w, data=sigma_w_data) + data_w[key] = sigma_w.data + return data_w \ No newline at end of file diff --git a/src/dcore/anacont_spm.py b/src/dcore/anacont_spm.py deleted file mode 100644 index 54070cf1..00000000 --- a/src/dcore/anacont_spm.py +++ /dev/null @@ -1,157 +0,0 @@ -# -# DCore -- Integrated DMFT software for correlated electrons -# Copyright (C) 2017 The University of Tokyo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -import numpy as np -import cvxpy as cp -from scipy.interpolate import interp1d -from scipy.sparse.linalg import svds - -def set_default_values(dictionary, default_values_dict): - for key, value in default_values_dict.items(): - if key not in dictionary: - dictionary[key] = value - return dictionary - -def _find_sum_rule_const(matsubara_frequencies, gf_wn, ntail, show_fit=False): - wntail = matsubara_frequencies[-ntail:] - gftail = gf_wn[-ntail:] - const_imagpart = -np.mean(np.imag(gftail) * wntail) - const_realpart = np.mean(np.real(gftail)) - if show_fit: - import matplotlib.pyplot as plt - z = np.linspace(wntail[0], wntail[-1], num=1000) - plt.scatter(wntail, np.imag(gftail), zorder=5, color='C0', label='data') - plt.plot(z, -const_imagpart / z, zorder=10, color='C1', label='fit') - plt.xlabel(r'$\omega_n$') - plt.ylabel(r'Im $G( \omega_n )$') - plt.legend() - plt.tight_layout() - plt.show() - return const_realpart, const_imagpart - -def _calc_gf_tau(matsubara_frequencies, gf_wn, beta, const_real_tail, const_imag_tail, ntau): - tau_grid = np.linspace(0, beta, num=ntau) - gf_tau = -0.5 * const_imag_tail * np.ones(tau_grid.shape, dtype=np.float64) - kernel = lambda tau : np.sum((np.real(gf_wn) - const_real_tail) * np.cos(matsubara_frequencies * tau) + (np.imag(gf_wn) + const_imag_tail / matsubara_frequencies) * np.sin(matsubara_frequencies * tau)) - gf_tau += 2 / beta * np.vectorize(kernel)(tau_grid) - gf_tau *= -1 - return tau_grid, gf_tau - -def calc_gf_tau_from_gf_matsubara(matsubara_frequencies, gf_wn, ntau, ntail, beta, show_fit=False): - const_real_tail, const_imag_tail = _find_sum_rule_const(matsubara_frequencies, gf_wn, ntail, show_fit=show_fit) - print('Determined tail constants: {}, {}'.format(const_real_tail, const_imag_tail)) - tau_grid, gf_tau = _calc_gf_tau(matsubara_frequencies, gf_wn, beta, const_real_tail, const_imag_tail, ntau) - return tau_grid, gf_tau, const_real_tail, const_imag_tail - -def get_single_continuation(tau_grid, gf_tau, nsv, beta, emin, emax, num_energies, sum_rule_const, lambd, verbose=True, max_iters=100, solver='ECOS'): - U, S, Vt, delta_energy, energies_extract = _get_svd_for_continuation(tau_grid, nsv, beta, emin, emax, num_energies) - rho_prime, gf_tau_fit, chi2 = _solveProblem(delta_energy, U, S, Vt, gf_tau, sum_rule_const, lambd, verbose=verbose, max_iters=max_iters, solver=solver) - rho = np.dot(Vt.T, rho_prime) - rho_integrated = np.trapz(y=rho, x=energies_extract) - return rho, gf_tau_fit, energies_extract, rho_integrated, chi2 - -def get_multiple_continuations(tau_grid, gf_tau, nsv, beta, emin, emax, num_energies, sum_rule_const, lambdas, verbose=True, max_iters=100, solver='ECOS'): - U, S, Vt, delta_energy, energies_extract = _get_svd_for_continuation(tau_grid, nsv, beta, emin, emax, num_energies) - continued_densities = [] - chi2_values = [] - rho_values = [] - for lambd in lambdas: - rho_prime, _, chi2 = _solveProblem(delta_energy, U, S, Vt, gf_tau, sum_rule_const, lambd, verbose=verbose, max_iters=max_iters, solver=solver) - rho = np.dot(Vt.T, rho_prime) - rho_integrated = np.trapz(y=rho, x=energies_extract) - continued_densities.append(rho) - chi2_values.append(chi2) - rho_values.append(rho_integrated) - return energies_extract, continued_densities, chi2_values, rho_values - -def _get_kernel_matrix(energies, tau_grid, beta, delta_energy, z_critical=20): #with z_critical=20 error of asymptote is below 1e-10 - assert tau_grid[0] == 0 - assert tau_grid[-1] == beta - i_lc = np.searchsorted(energies, -z_critical / beta) - i_rc = np.searchsorted(energies, +z_critical / beta) - kernel = np.zeros((len(tau_grid), len(energies))) - kernel[:, i_lc:i_rc + 1] = 0.5 * np.exp(np.multiply.outer(0.5 * beta - tau_grid, energies[i_lc:i_rc + 1])) / np.cosh(0.5 * beta * energies[i_lc:i_rc + 1]) - if i_lc > 0: #asymptote for kernel for w -> -inf - kernel[:, 0:i_lc] = np.exp(np.multiply.outer(beta - tau_grid, energies[0:i_lc])) - if i_rc < len(energies) - 1: #asymptote for kernel for w -> +inf - kernel[:, i_rc+1:len(energies)] = np.exp(np.multiply.outer(-tau_grid, energies[i_rc+1:len(energies)])) - kernel[:, 0] *= 0.5 - kernel[:, -1] *= 0.5 - kernel *= delta_energy - return kernel - -def _getSVD(matrix, nsv=None): - if nsv == None or nsv >= min(matrix.shape) or nsv <= 0: - raise Exception("nsv must be 0 < nsv < {} (min(matrix.shape))".format(min(matrix.shape))) - U, S, V = svds(matrix, k=nsv, which='LM') - S = np.flip(S, axis=0) - U = np.flip(U, axis=1) - Vt = np.flip(V, axis=0) - return U, S, Vt - -def _solveProblem(delta_energy, U, S, Vt, gf_tau, sum_rule_const, lambd, verbose=True, max_iters=100, solver='ECOS'): - Q = len(S) - Smat = np.diag(S) - rho_prime = cp.Variable(Q) - errTerm = gf_tau - U @ Smat @ rho_prime - objective = cp.Minimize(0.5 * cp.norm2(errTerm) ** 2 + lambd * cp.norm1(rho_prime)) - V_mod = np.copy(Vt.T) - V_mod[0, :] *= 0.5 - V_mod[-1, :] *= 0.5 - constraints = [Vt.T @ rho_prime >= 0, cp.sum(delta_energy * V_mod @ rho_prime) == sum_rule_const] #uniform real energy grid is assumed here - prob = cp.Problem(objective, constraints) - _ = prob.solve(verbose=verbose, solver=solver, max_iters=max_iters) - gf_tau_fit = np.dot(U, np.dot(Smat, rho_prime.value)) - chi2 = 0.5 * np.linalg.norm(gf_tau - gf_tau_fit, ord=2) ** 2 - return rho_prime.value, gf_tau_fit, chi2 - -def _get_svd_for_continuation(tau_grid, nsv, beta, emin, emax, num_energies): - energies_extract = np.linspace(emin, emax, num=num_energies) - delta_energy = energies_extract[1] - energies_extract[0] - kernel = _get_kernel_matrix(energies_extract, tau_grid, beta, delta_energy) - U, S, Vt = _getSVD(kernel, nsv=nsv) - return U, S, Vt, delta_energy, energies_extract - -def _integral_kramers_kronig(energies_imagpart, energy_realpart, gf_imag_interp, energy_threshold): - enum1 = gf_imag_interp(energies_imagpart) - gf_imag_interp(energy_realpart) - enum2 = np.gradient(gf_imag_interp(energies_imagpart), energies_imagpart) - den = energies_imagpart - energy_realpart - mask = np.where(np.abs(den) < energy_threshold, 1, 0) #1 if den is below threshold - #avoid divide by zero with mask * energy_threshold, in this case (1 - mask == 0) - term1 = enum1 / (den + mask * energy_threshold) * (1 - mask) - term2 = enum2 * mask - kernel = term1 + term2 - integral = np.trapz(y=kernel, x=energies_imagpart) - return integral - -def get_kramers_kronig_realpart(energies, gf_imag, energy_threshold=1e-10, dos_threshold=1e-5): - if np.abs(gf_imag[0]) > dos_threshold: - print('Warning! DOS at left interval end exceeds {}.'.format(dos_threshold)) - if np.abs(gf_imag[-1]) > dos_threshold: - print('Warning! DOS at right interval end exceeds {}.'.format(dos_threshold)) - gf_real = np.zeros(energies.shape, dtype=np.float64) - gf_imag_interp = interp1d(energies, gf_imag, kind='linear', bounds_error=False, fill_value=0.0) - energies_noend = energies[1:-1] - a, b = energies[0], energies[-1] - gf_real[1:-1] = gf_imag_interp(energies_noend) / np.pi * np.log((b - energies_noend) / (energies_noend - a)) #assume zero DOS at endpoints - integral_func = lambda y : _integral_kramers_kronig(energies, y, gf_imag_interp, energy_threshold) - gf_real += np.vectorize(integral_func)(energies) / np.pi - return energies, gf_real, gf_imag - -def dos_to_gf_imag(dos): - return -np.pi * dos diff --git a/src/dcore/dcore_anacont.py b/src/dcore/dcore_anacont.py new file mode 100644 index 00000000..5134e53f --- /dev/null +++ b/src/dcore/dcore_anacont.py @@ -0,0 +1,92 @@ +# +# DCore -- Integrated DMFT software for correlated electrons +# Copyright (C) 2017 The University of Tokyo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import argparse +import os.path +import numpy +from dcore._dispatcher import MeshReFreq +from dcore.version import version, print_header +from dcore.program_options import create_parser, parse_parameters +from dcore.anacont import pade, spm + +def dcore_anacont(inifile): + parser = create_parser(["system", "model", "post", "post.anacont"]) + parser.read(inifile) + params = parser.as_dict() + parse_parameters(params) + + beta = params["system"]["beta"] + + omega_min = params["post"]["omega_min"] + omega_max = params["post"]["omega_max"] + if omega_min >= omega_max: + # ToDo: stop the program properly + assert omega_min < omega_max + + Nomega = params["post"]["Nomega"] + mesh_w = MeshReFreq(omega_min, omega_max, Nomega) + + seedname = params["model"]["seedname"] + file_sigma_iw = seedname + "_sigma_iw.npz" + # file_sigma_iw = params["post"]["file_sigma_iw"] + if not os.path.exists(file_sigma_iw): + assert False, "File not found: " + file_sigma_iw + sigma_iw_npz = numpy.load(file_sigma_iw) + + dir_work = params["post"]["dir_work"] + if not os.path.exists(dir_work): + os.makedirs(dir_work) + + solver = params["post.anacont"]["solver"] + if solver == "pade": + params_ac = pade.parameters_from_ini(inifile) + data_w = pade.anacont(sigma_iw_npz, beta, mesh_w, params_ac) + elif solver == "spm": + params_ac = spm.parameters_from_ini(inifile) + data_w = spm.anacont(sigma_iw_npz, beta, mesh_w, params_ac) + else: + assert False, "Unknown solver: " + solver + + file_sigma_w = os.path.join(dir_work, "sigma_w.npz") + print("Writing to", file_sigma_w + "...") + numpy.savez(file_sigma_w, **data_w) + +def run(): + + print_header() + + parser = argparse.ArgumentParser( + prog='dcore_anacont.py', + description='DCore post script -- analytic continuation.', + usage='$ dcore_anacont input.ini', + add_help=True, + formatter_class=argparse.RawTextHelpFormatter, + #epilog=generate_all_description() + ) + parser.add_argument('path_input_files', + action='store', + default=None, + type=str, + nargs='*', + help="Input filename(s)", + ) + parser.add_argument('--version', action='version', version='DCore {}'.format(version)) + + args = parser.parse_args() + + dcore_anacont(args.path_input_files) \ No newline at end of file diff --git a/src/dcore/dcore_anacont_pade.py b/src/dcore/dcore_anacont_pade.py index ce2149c8..16c2bfe9 100644 --- a/src/dcore/dcore_anacont_pade.py +++ b/src/dcore/dcore_anacont_pade.py @@ -17,70 +17,59 @@ # import argparse -from dcore._dispatcher import MeshReFreq, MeshImFreq, GfReFreq, GfImFreq -from dcore.version import version, print_header import numpy import toml -def _set_n_pade(omega_cutoff, beta, n_min, n_max): - """ - Return (int)n_pade: the number of Matsubara frequencies below the cutoff frequency. - n_pade is bounded between n_min and n_max - """ - n_pade = int((beta * omega_cutoff + numpy.pi) / (2.0 * numpy.pi)) - print("n_pade = {} (evaluated from omega_pade)".format(n_pade)) - n_pade = max(n_pade, n_min) - n_pade = min(n_pade, n_max) - print("n_pade = {}".format(n_pade)) - return n_pade +from dcore._dispatcher import MeshReFreq +from dcore.version import version, print_header +from dcore.anacont.pade import anacont + -def dcore_anacont_pade(seedname): +def dcore_anacont_pade_from_seedname(seedname): print("Reading ", seedname + "_anacont.toml...") with open(seedname + "_anacont.toml", "r") as f: params = toml.load(f) - + print("Reading ", seedname + "_sigma_iw.npz...") - npz = numpy.load(seedname + "_sigma_iw.npz") + sigma_iw_npz = numpy.load(seedname + "_sigma_iw.npz") assert params["omega_min"] < params["omega_max"] mesh_w = MeshReFreq(params["omega_min"], params["omega_max"], params["Nomega"]) - n_pade = _set_n_pade(params["pade"]["omega_max"], params['beta'], n_min=params["pade"]["n_min"], n_max=params["pade"]["n_max"]) + beta = params["beta"] + params_pade = params.get("pade", {}) + params_pade["iomega_max"] = params_pade.get("omega_max", -1.0) + params_pade["eta"] = params_pade.get("eta", 0.01) + params_pade["n_min"] = params_pade.get("n_min", 0) + params_pade["n_max"] = params_pade.get("n_max", 100000000) - data_w = {} + data_w = anacont( + sigma_iw_npz, beta=beta, mesh_w=mesh_w, params_pade=params_pade + ) - num_data = numpy.sum([key.startswith("data") for key in npz.keys()]) - for idata in range(num_data): - key = f"data{idata}" - data = npz[key] - mesh_iw = MeshImFreq(params["beta"], "Fermion", data.shape[0]//2) - sigma_iw = GfImFreq(data=data, beta=params["beta"], mesh=mesh_iw) - sigma_w = GfReFreq(mesh=mesh_w, target_shape=data.shape[1:]) - sigma_w.set_from_pade(sigma_iw, n_points=n_pade, freq_offset=params["pade"]["eta"]) - data_w[key] = sigma_w.data print("Writing to", seedname + "_sigma_w.npz...") numpy.savez(seedname + "_sigma_w.npz", **data_w) + def run(): print_header() parser = argparse.ArgumentParser( - prog='dcore_anacont_pade.py', - description='pre script for dcore.', - usage='$ dcore_anacont_pade input', + prog="dcore_anacont_pade.py", + description="pre script for dcore.", + usage="$ dcore_anacont_pade input", add_help=True, formatter_class=argparse.RawTextHelpFormatter, - #epilog=generate_all_description() + # epilog=generate_all_description() + ) + parser.add_argument( + "seedname", action="store", default=None, type=str, help="seedname" + ) + parser.add_argument( + "--version", action="version", version="DCore {}".format(version) ) - parser.add_argument('seedname', - action='store', - default=None, - type=str, - help="seedname" - ) - parser.add_argument('--version', action='version', version='DCore {}'.format(version)) args = parser.parse_args() - dcore_anacont_pade(args.seedname) + dcore_anacont_pade_from_seedname(args.seedname) diff --git a/src/dcore/dcore_anacont_spm.py b/src/dcore/dcore_anacont_spm.py index 476a955e..f45752d0 100644 --- a/src/dcore/dcore_anacont_spm.py +++ b/src/dcore/dcore_anacont_spm.py @@ -19,77 +19,48 @@ import argparse import toml import numpy as np -from dcore._dispatcher import MeshReFreq, MeshImFreq, GfReFreq, GfImFreq +from dcore._dispatcher import MeshReFreq from dcore.version import version, print_header -from dcore.anacont_spm import set_default_values, calc_gf_tau_from_gf_matsubara, get_single_continuation, get_kramers_kronig_realpart, dos_to_gf_imag +from dcore.anacont.spm import set_default_values, anacont -def _anacont_spm_per_gf(params, matsubara_frequencies, gf_matsubara): - tau_grid, gf_tau, const_real_tail, const_imag_tail = calc_gf_tau_from_gf_matsubara(matsubara_frequencies, gf_matsubara, params['spm']['n_tau'], params['spm']['n_tail'], params['beta'], show_fit=params['spm']['show_fit']) - density, gf_tau_fit, energies_extract, density_integrated, chi2 = get_single_continuation(tau_grid, gf_tau, params['spm']['n_sv'], params['beta'], params['omega_min'], params['omega_max'], params['Nomega'], const_imag_tail, params['spm']['lambda'], verbose=params['spm']['verbose_opt'], max_iters=params['spm']['max_iters_opt'], solver=params['spm']['solver_opt']) - energies, gf_real, gf_imag = get_kramers_kronig_realpart(energies_extract, dos_to_gf_imag(density)) - gf_real += const_real_tail - return energies, gf_real, gf_imag def set_default_config(params): - default_values = {'show_fit' : False, - 'show_result' : False, - 'show_fit': False, - 'verbose_opt' : False, - 'max_iters_opt' : 100, - 'solver_opt' : 'ECOS'} - params['spm'] = set_default_values(params['spm'], default_values) + default_values = { + "show_fit": False, + "show_result": False, + "show_fit": False, + "verbose_opt": False, + "max_iters_opt": 100, + "solver_opt": "ECOS", + } + params["spm"] = set_default_values(params["spm"], default_values) return params -def dcore_anacont_spm(seedname): - print('Reading ', seedname + '_anacont.toml...') - with open(seedname + '_anacont.toml', 'r') as f: + +def dcore_anacont_spm_from_seedname(seedname): + print("Reading ", seedname + "_anacont.toml...") + with open(seedname + "_anacont.toml", "r") as f: params = toml.load(f) params = set_default_config(params) - print('Using configuration: ', params) - - print('Reading ', seedname + '_sigma_iw.npz...') - npz = np.load(seedname + '_sigma_iw.npz') - - assert params['omega_min'] < params['omega_max'] - mesh_w = MeshReFreq(params['omega_min'], params['omega_max'], params['Nomega']) - - assert params['spm']['n_matsubara'] > 0 - - data_w = {} - num_data = np.sum([key.startswith('data') for key in npz.keys()]) - for idata in range(num_data): - key = f'data{idata}' - data = npz[key] - n_matsubara = data.shape[0]//2 - n_matsubara_retain = min(n_matsubara, params['spm']['n_matsubara']) - mesh_iw = MeshImFreq(params['beta'], 'Fermion', n_matsubara_retain) - gf_iw = GfImFreq(data=data, beta=params['beta'], mesh=mesh_iw) - n_orbitals = gf_iw.data.shape[1] - matsubara_frequencies = np.imag(gf_iw.mesh.values()[n_matsubara_retain:]) - sigma_w_data = np.zeros((params['Nomega'], n_orbitals, n_orbitals), dtype=np.complex128) - for i_orb in range(n_orbitals): - print(f'Performing analytic continuation for data index {idata} and orbital index {i_orb}...') - gf_imag_matsubara = gf_iw.data[n_matsubara:n_matsubara + n_matsubara_retain, i_orb, i_orb] - energies, gf_real, gf_imag = _anacont_spm_per_gf(params, matsubara_frequencies, gf_imag_matsubara) - sigma_w_data[:, i_orb, i_orb] = gf_real + 1j * gf_imag - if params['spm']['show_result']: - import matplotlib.pyplot as plt - plt.axhline(y=0, xmin=energies[0], xmax=energies[-1], color='lightgrey') - plt.plot(energies, gf_real, label=r'Re $G( \omega )$') - plt.plot(energies, gf_imag, label=r'Im $G( \omega )$') - plt.xlim(energies[0], energies[-1]) - plt.xlabel(r'$\omega$') - plt.legend() - plt.tight_layout() - plt.show() - plt.close() - sigma_w = GfReFreq(mesh=mesh_w, data=sigma_w_data) - data_w[key] = sigma_w.data - - print('Writing to', seedname + '_sigma_w.npz...') - np.savez(seedname + '_sigma_w.npz', **data_w) - -#example file for 'seedname_anacont.toml' + print("Using configuration: ", params) + + print("Reading ", seedname + "_sigma_iw.npz...") + npz = np.load(seedname + "_sigma_iw.npz") + + assert params["omega_min"] < params["omega_max"] + mesh_w = MeshReFreq(params["omega_min"], params["omega_max"], params["Nomega"]) + + assert params["spm"]["n_matsubara"] > 0 + + beta = params["beta"] + params_spm = params["spm"] + data_w = anacont(npz, beta, mesh_w, params_spm) + + print("Writing to", seedname + "_sigma_w.npz...") + np.savez(seedname + "_sigma_w.npz", **data_w) + + +# example file for 'seedname_anacont.toml' # beta = 40.0 # Nomega = 4000 # omega_min = -6.0 @@ -107,25 +78,25 @@ def dcore_anacont_spm(seedname): # max_iters_opt = 100 # solver_opt = 'ECOS' + def run(): print_header() parser = argparse.ArgumentParser( - prog='dcore_anacont_spm.py', - description='pre script for dcore.', - usage='$ dcore_anacont_spm input', + prog="dcore_anacont_spm.py", + description="pre script for dcore.", + usage="$ dcore_anacont_spm input", add_help=True, formatter_class=argparse.RawTextHelpFormatter, - #epilog=generate_all_description() + # epilog=generate_all_description() + ) + parser.add_argument( + "seedname", action="store", default=None, type=str, help="seedname" + ) + parser.add_argument( + "--version", action="version", version="DCore {}".format(version) ) - parser.add_argument('seedname', - action='store', - default=None, - type=str, - help='seedname' - ) - parser.add_argument('--version', action='version', version='DCore {}'.format(version)) args = parser.parse_args() - dcore_anacont_spm(args.seedname) + dcore_anacont_spm_from_seedname(args.seedname) diff --git a/src/dcore/dcore_anacont_spm_interactive.py b/src/dcore/dcore_anacont_spm_interactive.py index d7bd0d97..133fc3e5 100644 --- a/src/dcore/dcore_anacont_spm_interactive.py +++ b/src/dcore/dcore_anacont_spm_interactive.py @@ -23,7 +23,7 @@ from matplotlib.ticker import MultipleLocator from dcore._dispatcher import MeshReFreq, MeshImFreq, GfReFreq, GfImFreq from dcore.version import version, print_header -from dcore.anacont_spm import set_default_values, calc_gf_tau_from_gf_matsubara, get_single_continuation, get_multiple_continuations, get_kramers_kronig_realpart, dos_to_gf_imag +from dcore.anacont.spm import set_default_values, calc_gf_tau_from_gf_matsubara, get_single_continuation, get_multiple_continuations, get_kramers_kronig_realpart, dos_to_gf_imag def _plot_overview(lambdas, chi2_values, energies, densities, nrows=3, ncols=5): fig, axes = plt.subplots(nrows=nrows, ncols=ncols, sharex=False, figsize=(15, 10)) diff --git a/src/dcore/program_options.py b/src/dcore/program_options.py index f6fba8b4..53312425 100644 --- a/src/dcore/program_options.py +++ b/src/dcore/program_options.py @@ -46,7 +46,7 @@ def create_parser(target_sections=None): Create a parser for all program options of DCore """ if target_sections is None: - parser = TypedParser(['mpi', 'model', 'system', 'impurity_solver', 'control', 'tool', 'bse', 'vertex', 'sparse_bse']) + parser = TypedParser(['mpi', 'model', 'system', 'impurity_solver', 'control', 'tool', 'post', 'bse', 'vertex', 'sparse_bse']) else: parser = TypedParser(target_sections) @@ -143,6 +143,36 @@ def create_parser(target_sections=None): "Each line after the first line must contain two integer numbers: The first one is an sequential index of a sampling frequency (start from 0), and the second one is a fermionic sampling frequency (i.e, -1, 0, 1)." ) + # [post] + parser.add_option("post", "omega_min", float, -1, "Minimum value of real frequency") + parser.add_option("post", "omega_max", float, 1, "Max value of real frequency") + parser.add_option("post", "Nomega", int, 100, "Number of real frequencies") + # parser.add_option("post", "file_sigma_iw", str, "sigma_iw.npz", "Filename of the self-energy in Matsubara frequency") + parser.add_option("post", "dir_post", str, "post", "Directory to which results of dcore_post are stored.") + parser.add_option("post", "dir_work", str, "work/post", "Directory to which temporary files of dcore_post are stored.") + + # [post.anacont] + parser.add_option("post.anacont", "solver", str, "algorithm", "Algorithm for analytic continuation") + + # [post.anacont.pade] + parser.add_option( "post.anacont.pade", "iomega_max", float, -1.0, "Cut-off frequency of the Matsubara frequency",) + parser.add_option( "post.anacont.pade", "n_min", int, 0, "lower bound of the order of Pade approximation",) + parser.add_option( "post.anacont.pade", "n_max", int, 100000000, "upper bound of the order of Pade approximation",) + parser.add_option( "post.anacont.pade", "eta", float, 0.01, "Imaginary Frequency shift to avoid divergence",) + + # [post.anacont.spm] + parser.add_option("post.anacont.spm", "n_matsubara", int, 100000, "number of tau points") + parser.add_option("post.anacont.spm", "n_tau", int, -1, "number of tau points") + parser.add_option("post.anacont.spm", "n_tail", int, 10, "number of matsubara points for tail-fitting") + parser.add_option("post.anacont.spm", "n_sv", int, 50, "number of singular values to be used") + parser.add_option("post.anacont.spm", "lambda", float, 1e-5, "coefficient of L1 regularization") + parser.add_option("post.anacont.spm", "max_iters_opt", int, 100, "maximum number of iterations") + parser.add_option("post.anacont.spm", "solver_opt", str, "ECOS", "solver to be used") + + parser.add_option("post.anacont.spm", "verbose_opt", bool, False, "show optimization progress") + parser.add_option("post.anacont.spm", "show_fit", bool, False, "plot result of tail-fitting") + parser.add_option("post.anacont.spm", "show_result", bool, False, "plot result of analytic continuation") + # [bse] parser.add_option("bse", "num_wb", int, 1, "Number of bosonic frequencies (>0)") parser.add_option("bse", "num_wf", int, 10, "Number of fermionic frequencies (>0)") diff --git a/tests/non-mpi/anacont_spm/anacont_spm.py b/tests/non-mpi/anacont_spm/anacont_spm.py index ab94c406..93c4d530 100644 --- a/tests/non-mpi/anacont_spm/anacont_spm.py +++ b/tests/non-mpi/anacont_spm/anacont_spm.py @@ -32,7 +32,7 @@ def _get_dos_semicircular(energies, r): return 2.0 / np.pi / r * np.sqrt(np.maximum(1 - np.square(energies / r), 0)) def test_find_sum_rule_const(): - from dcore.anacont_spm import _find_sum_rule_const + from dcore.anacont.spm import _find_sum_rule_const a = 1.123 b = 2.234 beta = 40 @@ -45,7 +45,7 @@ def test_find_sum_rule_const(): assert np.allclose(b_test, b, atol=1e-9) def test_calc_gf_tau_trivial(): - from dcore.anacont_spm import _calc_gf_tau + from dcore.anacont.spm import _calc_gf_tau a = 1.123 b = 2.234 beta = 40 @@ -60,7 +60,7 @@ def test_calc_gf_tau_trivial(): assert np.allclose(gf_tau, gf_tau_expected, atol=1e-10) def test_calc_gf_tau_nontrivial(): - from dcore.anacont_spm import _calc_gf_tau, _find_sum_rule_const + from dcore.anacont.spm import _calc_gf_tau, _find_sum_rule_const beta = 40 n_matsubara = 1000 n_matsubara_tail = 100 @@ -87,7 +87,7 @@ def test_calc_gf_tau_nontrivial(): assert np.allclose(gf_tau, gf_tau_expected, atol=1e-10) def test_calc_gf_tau_from_gf_matsubara(): - from dcore.anacont_spm import calc_gf_tau_from_gf_matsubara + from dcore.anacont.spm import calc_gf_tau_from_gf_matsubara ntau = 11 n_matsubara = 1000 n_matsubara_tail = 100 @@ -111,7 +111,7 @@ def test_calc_gf_tau_from_gf_matsubara(): assert np.allclose(gf_tau, gf_tau_expected, atol=1e-10) def test_get_kernel_matrix(): - from dcore.anacont_spm import _get_kernel_matrix + from dcore.anacont.spm import _get_kernel_matrix beta = 40 energies = np.linspace(-3, 3, num=5) delta_energy = energies[1] - energies[0] @@ -121,7 +121,7 @@ def test_get_kernel_matrix(): assert np.allclose(kernel, kernel_expected, atol=1e-10) def test_get_kernel_matrix_extreme_energies(): - from dcore.anacont_spm import _get_kernel_matrix + from dcore.anacont.spm import _get_kernel_matrix beta = 40 energies = np.linspace(-30, 30, num=5) delta_energy = energies[1] - energies[0] @@ -134,7 +134,7 @@ def test_get_kernel_matrix_extreme_energies(): assert np.allclose(kernel, kernel_expected, atol=1e-10) def test_getSVD(): - from dcore.anacont_spm import _getSVD, _get_kernel_matrix + from dcore.anacont.spm import _getSVD, _get_kernel_matrix beta = 40 nsv = 2 ntau = 3 @@ -150,7 +150,7 @@ def test_getSVD(): assert Vt.shape == (nsv, nenergies) def test_get_svd_for_continuation(): - from dcore.anacont_spm import _get_svd_for_continuation + from dcore.anacont.spm import _get_svd_for_continuation beta = 40 nsv = 2 ntau = 5 @@ -171,7 +171,7 @@ def test_get_svd_for_continuation(): assert np.allclose(energies_extract, energies_extract_expected, atol=1e-7) def test_solveProblem(): - from dcore.anacont_spm import _solveProblem, _find_sum_rule_const, _calc_gf_tau, _get_svd_for_continuation + from dcore.anacont.spm import _solveProblem, _find_sum_rule_const, _calc_gf_tau, _get_svd_for_continuation beta = 40 nsv = 100 n_matsubara = 1000 @@ -202,7 +202,7 @@ def test_solveProblem(): assert np.allclose(chi2, 3.4763690885418575e-06, atol=1e-5) def test_integral_kramers_kronig(): - from dcore.anacont_spm import _integral_kramers_kronig, dos_to_gf_imag + from dcore.anacont.spm import _integral_kramers_kronig, dos_to_gf_imag from scipy.interpolate import interp1d energies = np.linspace(-5, 5, num=1000) @@ -225,7 +225,7 @@ def test_integral_kramers_kronig(): assert np.allclose(results, expected_results, atol=1e-7) def test_get_kramers_kronig_realpart(): - from dcore.anacont_spm import get_kramers_kronig_realpart, dos_to_gf_imag + from dcore.anacont.spm import get_kramers_kronig_realpart, dos_to_gf_imag energies = np.linspace(-5, 5, num=10) dos = _get_dos_semicircular(energies, 4) gf_imag = dos_to_gf_imag(dos) @@ -237,7 +237,7 @@ def test_get_kramers_kronig_realpart(): assert np.allclose(gf_real_result, gf_real_expected, atol=1e-7) def test_get_single_continuation(): - from dcore.anacont_spm import get_single_continuation, calc_gf_tau_from_gf_matsubara, calc_gf_tau_from_gf_matsubara + from dcore.anacont.spm import get_single_continuation, calc_gf_tau_from_gf_matsubara, calc_gf_tau_from_gf_matsubara beta = 40 nsv = 24 emin = -10 @@ -269,7 +269,7 @@ def test_get_single_continuation(): def test_get_multiple_continuations(): - from dcore.anacont_spm import get_multiple_continuations, calc_gf_tau_from_gf_matsubara, calc_gf_tau_from_gf_matsubara + from dcore.anacont.spm import get_multiple_continuations, calc_gf_tau_from_gf_matsubara, calc_gf_tau_from_gf_matsubara beta = 40 nsv = 24 emin = -10