import Hilbertxx
import math
from math import sqrt
import os
import sys

import os
place=os.path.dirname(__file__)
sys.path.append(place+"/../../python")
print place+"/../../python"


from Operatori import *
import Operatori
# ----------------------------------------------------------------------
# termini intracouche


def WriteIntra(basis, prefix):
    for couche in [0,1]:
        L=coucheL(couche)
        # termini diretti
        for multiK in range(2*L,-2,-2):
            operatore = Coulomb_NoCI(  couche  , couche , multiK, direct=1)
            for base,nome in zip(basis, NOMIBASI):
                ScriviOperatore(base, operatore,base, prefix+nome+"_couche%d_F%d"%(couche,multiK) )
   
# termini intercouche
def WriteInter(basis, prefix):
    for coucheA in range(1):
        La=coucheL(coucheA)
        for coucheB in range(coucheA+1,2):
            Lb=coucheL(coucheB)
            # termini diretti
            for multiK in range( 0,2*min(La,Lb)+1,2 ):
                operatore = Coulomb_NoCI(  coucheA  , coucheB , multiK, direct=1)
                for base,nome in zip(basis, NOMIBASI):
                    ScriviOperatore(base, operatore,base,  prefix+nome+"_couche%d_%d_F%d"%(coucheA, coucheB, multiK) )
            #termini di scambio
            for multiK in range(La+Lb,0,-2 ):
                operatore = Coulomb_NoCI(  coucheA  , coucheB , multiK, direct=0)
                for base,nome in zip(basis, NOMIBASI):                
                    ScriviOperatore(base, operatore,base, prefix+nome+"_couche%d_%d_G%d"%(coucheA, coucheB, multiK) )
            
#termini So
def WriteSo(basis, prefix):
    for couche in [0,1]:
        operatore = SpinOrbital(  couche)
        for base,nome in zip(basis, NOMIBASI):                
            ScriviOperatore(base, operatore,base, prefix+nome+"_SO_%d"% couche )


# quanti els nel guscio p
def WriteCounterP(basis, prefix):
    operatore = counter([2])
    for base,nome in zip(basis, NOMIBASI):                
        ScriviOperatore(base, operatore,base, prefix+nome+"_counterDL" )





# termini di operatore multipolare

#OK I
def WriteQuadrupoles(base, exci, prefix):
    coucheA= 0
    for multiK in [1]:
        nome, coucheB={1:("dipole", 1  ) }[multiK]
        
        for Km  in range(-multiK, multiK+1):
            operatore = Multipole(  coucheA  , coucheB , multiK,Km )
            ScriviOperatore(base, operatore,exci, prefix+nome+"_couches_%d_%d_Km_%d"%(coucheA, coucheB, Km) )
    if(0):
     for mz in [-2,-1,0,1,2]:
        nome="mixedDipole"
        operatore = createMixedDipole(mz) 
        ScriviOperatore(base, operatore,exci, prefix+nome+"_couches_%d_%d_mz_%d"%(0, 2, mz) )

            


# termini di ligand field
def WriteLigands(basis, prefix):
    for symm,symmprefix in zip( [0.5,-0.5], ["","anti"]):
        for j in range(7):
            for  i in range(j,7):
                mat   =   [ [0]*7]*7
                mat[i][j]=1.0
                coucheA=1
                for base,nome in zip(basis, NOMIBASI):
                    if ( i==j):
                        fatt=1.0
                    else:
                        fatt=2.0
                    operatore = GenericLigandField(  coucheA  ,  mat, symmetrize =  symm*fatt )
                    # nota bene : si va da j a i  ( vedi Operatori.py per conferma )
                    ScriviOperatore(base, operatore,base, prefix+symmprefix+nome+"_CRYSTAL"+"_%d_%d_%d_"%(coucheA,i,j) )
  


# operatori per il momento angolare
def WriteAngulars(basis, prefix):
    for nome, func in zip(["_Lop_", "_Sop_"],[Loperator, Soperator] ):
        for what in ["Zero","Plus","Minus"]:
            operatore = func(what,[1])
            for base,nomebase in zip(basis, NOMIBASI):                
                ScriviOperatore(base, operatore,base, prefix+nomebase+nome+what )

# DIPENDENTISSMI

# OK I
def coucheL(couche):
    return [2,3][couche]

# OK I
def memory_map(couche, ( mz, spin) ):
    # s ,  d, p
    l= coucheL(couche)
    #    mz va da -l a l, spin puo essere 0 (giu) 1 (su)
    return [0,10][couche]+ 2*(l+mz) +spin 


Operatori.coucheL=coucheL
Operatori.memory_map=memory_map



# OK I
def createWanderer():
    result =  Hilbertxx.Hxx_Normal_Operators_Collection(1,1)

    fromsite=[]
    tosite =[]
    orbitals = []
    # vagabondiamo nelle couches   s, d , dl
    for couche in [0,1]:
        __fromsites = [couche]
        __tosites   = [couche]
        L = coucheL(couche)
        __orbitals   = [(one, ([mza,spina],),([mzb,spinb],) ) for spina in range(2) for mza in range(-L,L+1)
                        for spinb in range(2) for mzb in range(-L,L+1) ]
        fromsite.append(__fromsites )
        tosite.append  (__tosites   )
        orbitals.append(__orbitals  )
    create_operator(result, fromsite, tosite, orbitals, memory_map)        
    return result

# OK I



#------------------------------------------------------------------------


    
NOMIBASI=["base","exci"]



def scriviFiles(nelF, prefix=""):
## Create initial state
    if( not os.path.isdir(prefix) ):
        print " PROVIDE A DIRECTORY NAME WHERE YOU WRITE MATRICES!! "
        return
    try:
        f=open(prefix+"/deldjfhwkeqos.del","w")
    except:
        print " you cannot write to directory  ", prefix
        return
        
    base_seed = Hilbertxx.Hxx_TypeForBits()
    base_seed.setTo0()

    operators=Hilbertxx.Hxx_1p_FermionicOperators.Initialise()

    for  occ_state in range(  memory_map(1, ( -coucheL(1), 0) )+   nelF) :
        base_seed = base_seed | operators[occ_state].get_1p_state()


## Calcul des vecteurs de base

    base = Hilbertxx.Hxx_basis(1)
    exci = Hilbertxx.Hxx_basis(1)


    exci_seed=base_seed ^ operators[  memory_map(1, ( -coucheL(1), 0) )+ nelF].get_1p_state()
    exci_seed=exci_seed ^ operators[0].get_1p_state()

    wanderer = createWanderer()

    # creazione della base
    
    for BB, SS ,  NN in zip([base,exci], [base_seed,exci_seed]  ,["base","exci"] ):
        # BB.set_pyfilter(FF)
        starting_state = Hilbertxx.Hxx_FermionicState(SS)
        BB.add_state(starting_state)

        old_total = -1
        total = 0
        while total != old_total:
            old_total=total
            total=BB.operate_andputin_Tree( wanderer, 1 )
            print "SPANNED %d states after wanderer"%( total)
            BB.reconstruct_basis()
            
    if( prefix!=""  and prefix[-1]!="/" ):
        prefix=prefix+"/"

## Create transition Matrices
    WriteIntra  ([base, exci], prefix )
    WriteInter  ([base, exci], prefix )
    WriteSo     ([base, exci], prefix )
    WriteLigands([base,exci],prefix)
    WriteAngulars([base,exci],prefix)
    
## Creates quadrupoles
    WriteQuadrupoles(base, exci, prefix )

if __name__=="__main__":
    scriviFiles(5,prefix="datas")

 
