#!/usr/bin/env python
# Author: KH, March 2007
from scipy import * 
import os,sys,subprocess
"""
This module runs ctqmc impurity solver for one-band model.
The executable shoule exist in directory params['exe']
"""
params = {"exe":   ["code/ctqmc",    "# Path to executable"],
          "Delta": ["Delta.inp",        "# Input bath function hybridization"],
          "cix":   ["one_band.imp",     "# Input file with atomic state"],
          "U":     [2.4,                "# Coulomb repulsion (F0)"],
          "mu":    [1.2,                "# Chemical potential"],
          "beta":  [100,                "# Inverse temperature"],
          "M" :    [2000000,            "# Number of Monte Carlo steps"],
          "nom":   [50,                 "# number of Matsubara frequency points to sample"],
          "CleanUpdate": [100000,       "# clean update after QMC steps"],
          "aom":         [10,           "# number of frequency points to determin high frequency tail"]}

icix="""# Cix file for cluster DMFT with CTQMC
# cluster_size, number of states, number of baths, maximum matrix size
1 4 2 1
# baths, dimension, symmetry, global flip
0       1 0 0
1       1 0 0
# cluster energies for unique baths, eps[k]
0 0
#   N   K   Sz size F^{+,dn}, F^{+,up}, Ea  S
1   0   0    0   1   2         3        0   0
2   1   0 -0.5   1   0         4        0   0.5
3   1   0  0.5   1   4         0        0   0.5
4   2   0    0   1   0         0        0   0
# matrix elements
1  2  1  1    1    # start-state,end-state, dim1, dim2, <2|F^{+,dn}|1>
1  3  1  1    1    # start-state,end-state, dim1, dim2, <3|F^{+,up}|1>
2  0  0  0
2  4  1  1   -1    # start-state,end-state, dim1, dim2, <4|F^{+,up}|2>
3  4  1  1    1
3  0  0  0
4  0  0  0
4  0  0  0
HB1                # Hubbard-I is used to determine high-frequency
# number of operators needed
0
# Data for HB1
1 4 2 1
#  ind  N   K   Sz size
1  1   0   0    0   1     2  3     0   0
2  2   1   0 -0.5   1     0  4     0   0.5
3  3   1   0  0.5   1     4  0     0   0.5
4  4   2   0    0   1     0  0     0   0
# matrix elements
1  2  1  1    1
1  3  1  1    1
2  0  0  0
2  4  1  1   -1
3  4  1  1    1
3  0  0  0
4  0  0  0
4  0  0  0
"""

def CreateInputFile(params):
    " Creates input file (PARAMS) for CT-QMC solver"
    f = open('PARAMS', 'w')
    print >> f, '# Input file for continuous time quantum Monte Carlo'
    for p in params:
        print >> f, p, params[p][0], '\t', params[p][1]
    f.close()

def DMFT_SCC(fDelta):
    """This subroutine creates Delta.inp from Gf.out for DMFT on bethe lattice: Delta=t^2*G
    If Gf.out does not exist, it creates Gf.out which corresponds to the non-interacting model
    In the latter case also creates the inpurity cix file, which contains information about
    the atomic states.
    """
    fileGf = 'Gf.out'
    if (os.path.exists(fileGf)): # If output file exists, start from previous iteration
        # Gf = io.read_array(fileGf, columns=(0,-1), lines=(1,-1))
        # In the new Python, io.readarray is dropped and we should use loadtxt instead!
        Gf = loadtxt(fileGf)
    else: # otherwise start from non-interacting limit
        print 'Starting from non-interacting model'
        Gf=[]
        for n in range(2000):
            iom = (2*n+1)*pi/params['beta'][0]
            gf = 2*1j*(iom-sqrt(iom**2+1))
            Gf.append([iom, gf.real, gf.imag])
        Gf = array(Gf)
        # creating impurity cix file
        f = open(params['cix'][0], 'w')
        print >> f, icix
        f.close()
        
    # Preparing input file Delta.inp
    f = open(fDelta, 'w')
    for i in range(len(Gf)):
        print >> f, Gf[i,0], 0.25*Gf[i,1], 0.25*Gf[i,2] # This is DMFT SCC: Delta = t**2*G (with t=1/2)
    f.close()

# Number of DMFT iterations
Niter = 10

# Creating parameters file PARAMS for qmc execution
CreateInputFile(params)

for it in range(Niter):
    # Constructing bath Delta.inp from Green's function
    DMFT_SCC(params['Delta'][0])

    # Running ctqmc
    print 'Running ---- qmc itt.: ', it, '-----'
    #print os.popen(params['exe'][0]).read()

    out, err = subprocess.Popen(params['exe'][0], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
    print out #, err

    # Some copying to store data obtained so far (at each iteration)
    cmd = 'cp Gf.out Gf.out.'+str(it)
    print os.popen(cmd).read() # copying Gf
    cmd = 'cp Sig.out Sig.out.'+str(it)
    print os.popen(cmd).read() # copying Sig
