TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
pade_approximants.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2013-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2021 Simons Foundation
4// Copyright (c) 2017 Igor Krivenko
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You may obtain a copy of the License at
17// https://www.gnu.org/licenses/gpl-3.0.txt
18//
19// Authors: Michel Ferrero, Igor Krivenko, Olivier Parcollet, Hiroshi Shinaoka, Nils Wentzell
20
25
26#pragma once
27
28#include "./exceptions.hpp"
29
30#include <gmpxx.h>
31#include <triqs/arrays.hpp>
32
33#include <complex>
34#include <ostream>
35
36namespace triqs::utility {
37
38 // Alias for `std::complex<double>`.
39 using dcomplex = std::complex<double>;
40
45
49 struct gmp_complex {
51 mpf_class re;
52
54 mpf_class im;
55
62 gmp_complex operator*(const gmp_complex &z) const { return {.re = z.re * re - z.im * im, .im = z.re * im + z.im * re}; }
63
72 friend gmp_complex inverse(const gmp_complex &z) {
73 mpf_class d = z.re * z.re + z.im * z.im;
74 if (d == 0) TRIQS_RUNTIME_ERROR << "pade_approximant: GMP division by zero";
75 return {.re = z.re / d, .im = -z.im / d};
76 }
77
86 gmp_complex operator/(const gmp_complex &z) const { return (*this) * inverse(z); }
87
94 gmp_complex operator+(const gmp_complex &z) const { return {.re = z.re + re, .im = z.im + im}; }
95
102 gmp_complex operator-(const gmp_complex &z) const { return {.re = re - z.re, .im = im - z.im}; }
103
110 friend mpf_class real(const gmp_complex &z) { return z.re; }
111
118 friend mpf_class imag(const gmp_complex &z) { return z.im; }
119
124 [[nodiscard]] mpf_class norm() const { return real(*this) * real(*this) + imag(*this) * imag(*this); }
125
132 gmp_complex &operator=(const std::complex<double> &z) {
133 re = real(z);
134 im = imag(z);
135 return *this;
136 }
137
145 friend std::ostream &operator<<(std::ostream &out, gmp_complex const &z) {
146 return out << " gmp_complex(" << z.re << "," << z.im << ")" << std::endl;
147 }
148 };
149
172
173 nda::vector<dcomplex> z_in;
174 nda::vector<dcomplex> a;
175
176 public:
178 static const int GMP_default_prec = 256;
179
194 pade_approximant(const nda::vector<dcomplex> &z_in, const nda::vector<dcomplex> &u_in) : z_in(z_in), a(z_in.size()) {
195
196 long N = z_in.size();
197
198 // temporarily switch GMP's default precision
199 unsigned long old_prec = mpf_get_default_prec();
200 mpf_set_default_prec(GMP_default_prec);
201
202 nda::array<gmp_complex, 2> g(N, N);
203 gmp_complex MP_0 = {.re = 0.0, .im = 0.0};
204 g() = MP_0;
205 for (long f = 0; f < N; ++f) { g(0, f) = u_in(f); }
206
207 gmp_complex MP_1 = {.re = 1.0, .im = 0.0};
208
209 for (long p = 1; p < N; ++p) {
210
211 // truncate the continued fraction when |g| becomes very small
212 if (g(p - 1, p - 1).norm() < 1.0e-20) break;
213
214 for (long j = p; j < N; ++j) {
215 gmp_complex x = g(p - 1, p - 1) / g(p - 1, j) - MP_1;
216 gmp_complex y;
217 y = z_in(j) - z_in(p - 1);
218 g(p, j) = x / y;
219 }
220 }
221
222 for (long j = 0; j < N; ++j) {
223 gmp_complex gj = g(j, j);
224 a(j) = dcomplex(real(gj).get_d(), imag(gj).get_d());
225 }
226
227 // restore the precision.
228 mpf_set_default_prec(old_prec);
229 }
230
246 dcomplex operator()(dcomplex z) const {
247
248 dcomplex A1(0);
249 dcomplex A2 = a(0);
250 dcomplex B1(1.0);
251
252 long N = a.size();
253 for (long i = 0; i <= N - 2; ++i) {
254 dcomplex Anew = A2 + (z - z_in(i)) * a(i + 1) * A1;
255 dcomplex Bnew = 1.0 + (z - z_in(i)) * a(i + 1) * B1;
256 A1 = A2 / Bnew;
257 A2 = Anew / Bnew;
258 B1 = 1.0 / Bnew;
259 }
260
261 return A2;
262 }
263 };
264
266
267} // namespace triqs::utility
int size() const
Get the total number of blocks.
Backward-compatibility umbrella header pulling in the nda array library.
dcomplex operator()(dcomplex z) const
Evaluate the Padé continued fraction at the complex point .
pade_approximant(const nda::vector< dcomplex > &z_in, const nda::vector< dcomplex > &u_in)
Constructor computes the Padé coefficients from a set of complex sample points and values.
static const int GMP_default_prec
Default precision (in mantissa bits) used for the GMP floats during coefficient calculation.
TRIQS exception hierarchy and related macros.
#define TRIQS_RUNTIME_ERROR
Throw a triqs::runtime_error with the current source location.
I real(I const &x)
Real part of an integral value.
I imag(I const &x)
Imaginary part of an integral value.
std::complex< double > dcomplex
Convenience alias for std::complex<double>.
Lightweight complex number backed by GMP mpf_class floats, used during Padé coefficient computation.
friend mpf_class real(const gmp_complex &z)
Extract the real part of a complex number.
gmp_complex & operator=(const std::complex< double > &z)
Assign from a regular std::complex<double>.
mpf_class norm() const
Squared magnitude of the complex number .
gmp_complex operator+(const gmp_complex &z) const
Add two complex numbers.
friend gmp_complex inverse(const gmp_complex &z)
Compute the multiplicative inverse of a complex number.
mpf_class im
Imaginary part.
gmp_complex operator/(const gmp_complex &z) const
Divide two complex numbers.
gmp_complex operator*(const gmp_complex &z) const
Multiply two complex numbers.
friend mpf_class imag(const gmp_complex &z)
Extract the imaginary part of a complex number.
gmp_complex operator-(const gmp_complex &z) const
Subtract two complex numbers.
friend std::ostream & operator<<(std::ostream &out, gmp_complex const &z)
Write a gmp_complex to an output stream.