Light-weight generic iterative self-consistency loop.

Basic usage

green-sc is a header-only C++ template library that implements generic iterative self-consistency loop.

To add this library into your project, first


        GIT_TAG origin/main # or a later release

Add predefined alias GREEN::SC it to your target:

target_link_libraries(<target> PUBLIC GREEN::SC)

And then simply include the following header:

#include <green/sc/sc_loop.h>

It uses green-params library to read parameters either from a command line or from parameter string. Please check green-params documentation for more details. The following parameters have to be specified:

  • itermax - maximum number of iterations to run
  • mixing_type - type of mixing between iterations
  • mixing_weight - how mach of a previous iteration to be mixed with the current iteration results
  • results_file - file to store results at each iteration
  • restart - checkpointing
  • threshold - convergence threshold, iterations will be stopped if convergence creteria is smaller than threshold.

Class has to be parametrized with user defined Dyson type. Dyson publicly defines the following three types: G - type for Green’s function, Sigma1 - type for static part of self-energy, Sigma_tau - type for dynamic-part of self-energy, and implements the following methods:

  • solve(G&, Sigma1&, Sigma_tau&) - for a given self-energies
  • diff(G&, Sigma1&, Sigma_tau&) - computes convergence creteria
  • dump_iteration(int iter, const std::string&f) - store additional data into a results file f for a given iteration iter.

The method solve needs four parameters:

  • Solver - solver object that implements
    • solve(A, B, C)

Even though we use diagrammatic names such as Green’s function and self-energy, this library can be used to solve arbitrary equation that can be written in iterative form. Here is a small example of solving square equation $\beta X^2 - X + \alpha = 0$

using namespace green::sc;

// define dyson solver
class square_equation_dyson {
  using G         = double;
  using Sigma1    = double;
  using Sigma_tau = double;
  double _alpha;
  double _beta;
  double _diff;

  square_equation_dyson(const green::params::params &p) : _alpha(p["a"]),
                                                          _beta(p["b"]) {}

  void solve(G& g, Sigma1& sigma1, Sigma_tau& sigma_tau) {
    double g_new = _alpha + _alpha * sigma1 * g;
    _diff        = std::abs(g - g_new);
    g            = g_new;
  double diff(const G& g, const Sigma1& sigma1, const Sigma_tau& sigma_tau) {
    return _diff;
  void   dump_iteration(size_t iter, const std::string& result_file){};

// define solver class
class square_equation_solver {
  double _U;
  second_power_equation_solver(double alpha, double beta) : _U(beta / alpha) {}
  void solve(const G& g, Sigma1& sigma1, Sigma_tau& sigma_tau) { sigma1 = _U * g; }

p.define<double>("a", "a", 1.0);
p.define<double>("b", "b", 0.5);
// create with a given green-params parameter object:
sc_loop<square_equation_dyson> sc(MPI_COMM_WORLD, p);
double g = 0, s1=0, st = 0;
// create solver for square equation
square_equation_solver solver(p["a"], p["b"]);

// solve equation
sc.solve(solver, g, s1, st);