VIE2
Non-singular VIE2
The second important equation is an integral equation of the form:
This linear equation is to be solved for \(G(t,t^\prime)\) for a given input kernel \(F(t,t^\prime)\), its hermitian conjugate \(F^\ddagger(t,t^\prime)\), and a source term \(Q(t,t^\prime)\). A typical physical application of (11) is the summation of a random phase approximation (RPA) series for a susceptibility \(\chi\),
In the solution of the equation, we assume that both \(Q\) and \(G\) are hermitian. In general, the hermitian symmetry would not hold for an arbitrary input \(F\) and \(Q\). However, it does hold when \(F\) and \(Q\) satisfy the relation \(F\ast Q=Q\ast F^\ddagger\) and \(Q=Q^\ddagger\), which is the case for the typical applications such as the RPA series. In this case, there is an equivalent conjugate equation:
In the implementation, the solution of Eq (11) is reduced to a Volterra Integral Equation of 2nd kind,
which is why the corresponding routines are called vie2.
Because of its causal nature, the VIE2 equation can be solved in a time-stepping manner (see explanation of the input/output relation below). The following routines are used to solve the VIE2 equation:
|
Solve (11) for |
|
Solve (11) for |
|
Solve (11) for |
|
Same as |
The type
GGofG,F,Fcc, andQiscntr::herm_matrix<T>.FandFccstore the hermitian domain of \(F\) and \(F^\ddagger\), respectively.SolveOrder\(\in\)1,...,MAX_SOLVE_ORDER, the order of accuracy for the solution. UseSolveOrder=5(=MAX_SOLVE_ORDER) if there is no good reason against it.dtis the time-discretisation step \(\Delta t\) on the real-time branchbetais the length of the imaginary-time contour (inverse temperature)Size requirements:
G,F,Fcc, andQmust have the samesize1andntauFor
vie2_start:G,F,Fcc, andQmust havent>= SolveOrderFor
vie2_timestep:G,F,Fcc, andQmust havent >= tstp
Special numerical parameters for
vie2_mat:MAT_METHOD=CNTR_MAT_FOURIERorCNTR_MAT_FIXPOINT.CNTR_MAT_FIXPOINTis default and should be used.
Input/Output relation and time-stepping:
vie2_mat:FandQare read on timesteptstp=-1;Gis written on timesteptstp=-1vie2_start:FandQare read on timesteptstp=-1,...,SolveOrder,Gis read on timesteptstp=-1;Gis written on timesteptstp=0,...,SolveOrdervie2_timestep:FandQare read on timestept=-1,...,tstp,Gis read on timestept=-1,...tstp-1;Gis written on timestept=tstp
Because of this causal structure, the VIE2 equation can be solved by time-stepping, analogous to dyson: First G is determined on timestep tstp=-1 using vie2_mat. The result enters the determination of G on timesteps 0,...,SolveOrder with vie2_start. The equation is solved successively for timesteps tstp=SolveOrder+1,SolveOrder+2,..., where the result at timestep tstp depends on all previous timesteps.
Example:
Solution of the RPA series \(\chi = \chi_0 + \chi_0\ast W\ast \chi\) for \(\chi\), where \(\chi_0\) is a known (hermitian) two-time function, and \(W\) is a known one-time function (also hermitian, \(W(t)=W(t)^\dagger\)). The equation is cast in the form (11) with \(F (t,t')= -\chi_0(t,t') W(t')\), \(F^\ddagger (t,t')= -W(t)\chi_0(t,t')\), and \(Q=\chi_0\).
int tstp;
int nt=10;
int ntau=20;
int size1=2;
int SolveOrder=5;
double dt=0.01; // time-discretization
double beta=10.0; // inverse temperature
GREEN chi(nt,ntau,size1,BOSON);
GREEN chi0(nt,ntau,size1,BOSON);
CFUNC W(nt,size1);
GREEN F(nt,ntau,size1,BOSON);
GREEN Fcc(nt,ntau,size1,BOSON);
//
// ... do something to determine chi0 and W on timestep -1
// determine F, Fcc, and solve for chi on timestep -1:
tstp=-1;
F.set_timestep(tstp,chi0);
F.right_multiply(tstp,W,-1.0);
Fcc.set_timestep(tstp,chi0);
Fcc.left_multiply(tstp,W,-1.0);
cntr::vie2_mat(chi,F,Fcc,chi0,beta,SolveOrder,CNTR_MAT_FIXPOINT);
// .... do something to determine chi0 and W on timesteps 0 ... SolveOrder=5
// get F, Fcc, and solve for chi on timesteps 0 ... SolveOrder=5:
for(int tstp=0;tstp<=SolveOrder;tstp++){
F.set_timestep(tstp,chi0);
F.right_multiply(tstp,W,-1.0);
Fcc.set_timestep(tstp,chi0);
Fcc.left_multiply(tstp,W,-1.0);
}
cntr::vie2_start(chi,F,Fcc,chi0,beta,dt,SolveOrder);
//all other timesteps:
for(int tstp=SolveOrder+1;tstp<=nt;tstp++){
// .... do something to determine chi0 and W on timesteps tstp
F.set_timestep(tstp,chi0);
F.right_multiply(tstp,W,-1.0);
Fcc.set_timestep(tstp,chi0);
Fcc.left_multiply(tstp,W,-1.0);
cntr::vie2_timestep(tstp,chi,F,Fcc,chi0,beta,dt,SolveOrder);
}
OpenMP parallelization:
The variant vie2_timestep_omp uses shared memory openMP parallelization to distribute the evaluation of \(G(t,t')\) for different time arguments of the timestep tstp over omp_num_threads tasks. Note that vie2_timestep_omp and vie2_timestep follow a slightly different implementation, thus the result differs by the numerical error. Similar to dyson_timestep_omp, the implementation prevents any race conditions if omp_num_threads is set to the number of threads in the current team.
Singular VIE2
The singular vie2 is a generalized solver of VIE2, where propagators have an instantaneous term, for example:
where \(G^\delta\) is the instantaneous part and \(G^R(t,t^\prime)\) is the retarded part. The generalization of Eq. (11) to the following example leads to:
First, for a given timestep \(t\), we solve this equation for an instantaneous part leading to:
The retarded part of the VIE2 can be rewritten in a form where a routine for the non-singular VIE2 can be employed, see Non-singular VIE2:
where \(G^\delta\) is known from the solution of the instantaneous part.
A typical physical usage of the singular version of VIE2 is an evaluation of the retarded interaction within the GW approximation, see Lattice GW for an example:
where \(V\) is an instantaneous interaction, \(\chi_0\) is a bare bubble and \(W\) is a retarded interaction entering the GW self-energy.
The following routines are used to solve Eq. (15):
|
Solve (15) for |
|
Same as |
These routines use the same input as cntr::vie2_timestep, see Non-singular VIE2, with an addition of a singular part of the propagator Gsin presented by cntr::function<T>.