├── README.md ├── fort_rot ├── Makefile └── fort_rot.f ├── examples ├── LaTiO3_tilted_t2g_only │ ├── run.sh │ └── parms ├── CaRuO3_titled_t2g_only │ ├── lsf.sh │ └── parms ├── calculate_dos_bethe_lattice.py ├── calculate_dos_tight_binding.py ├── calculate_dos_dft_mlwf.py └── calculate_dos_average_green.py ├── Makefile ├── Make.inc ├── cppext ├── cubic_spline_ft │ ├── Makefile │ ├── main.cpp │ ├── fouriertransform.h │ └── fouriertransform.cpp ├── Makefile ├── main.cpp ├── fourier.cpp ├── eval.cpp └── others.cpp ├── integrate_bethe_lattice ├── Makefile ├── integrand.h ├── integrand.cpp └── main.cpp ├── integrate_tight_binding ├── Makefile ├── integrand.h ├── integrand.cpp └── main.cpp ├── integrate_dft_mlwf ├── Makefile ├── integrand.h ├── integrand.cpp └── main.cpp ├── alps_interface.py ├── user_config.py ├── LICENSE ├── include ├── integrate.h ├── eigen_integrate.h ├── numpy_eigen.h └── inverse.h ├── rotation_matrix.py ├── calculate_DOS.py ├── calculate_green.py ├── system_dependence.py ├── triqs_interface_old.py ├── triqs_interface.py ├── dmft.py ├── calculate_spectra.py ├── hartree.py ├── init.py ├── average_green.py ├── share_fun.py ├── eval.py └── functions.py /README.md: -------------------------------------------------------------------------------- 1 | scf_dmft 2 | ======== 3 | 4 | A general self consistent loop for Dynamical Mean-Field Theory using Python 5 | -------------------------------------------------------------------------------- /fort_rot/Makefile: -------------------------------------------------------------------------------- 1 | include ../Make.inc 2 | 3 | TARGET = fort_rot.so 4 | 5 | all: 6 | f2py -c fort_rot.f -m fort_rot --fcompiler=gnu95 --f77flags="-fopenmp -ffixed-line-length-132" -lgomp $(LAPACK) 7 | 8 | copy: all 9 | -cp -f $(TARGET) .. 10 | 11 | clean: 12 | -rm -f $(TARGET) 13 | -------------------------------------------------------------------------------- /examples/LaTiO3_tilted_t2g_only/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | NN=32 4 | 5 | # the path to dmft.py in the main code 6 | PYDMFT=../../dmft.py 7 | 8 | # run dmft.py --help for some more info 9 | # here -p for parameter file 10 | # and -n for the number of cores in use 11 | $PYDMFT -p parms -n $NN 12 | -------------------------------------------------------------------------------- /examples/CaRuO3_titled_t2g_only/lsf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #BSUB -J cro_u2.3j0.4b60 4 | #BSUB -n 128 5 | #BSUB -a "bcs openmpi" 6 | #BSUB -M 512 7 | #BSUB -W 24:00 8 | #BSUB -o output_%J.out 9 | #BSUB -e output_%J.err 10 | #BSUB -P jara0112 11 | 12 | source $HOME/.zshrc 13 | NN=$LSB_DJOB_NUMPROC 14 | 15 | /home/td120143/codes/scf_dmft/dmft.py -p parms -n $NN 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include Make.inc 2 | 3 | all: 4 | @(\ 5 | for d in $(DIRS); do \ 6 | cd $$d; \ 7 | echo Working in $$d; \ 8 | make copy; \ 9 | cd ..; \ 10 | done) 11 | 12 | clean: 13 | -rm -f *.so *.pyc 14 | @(\ 15 | for d in $(DIRS); do \ 16 | cd $$d; \ 17 | echo Clean the directory $$d; \ 18 | make clean; \ 19 | cd ..; \ 20 | done) 21 | 22 | -------------------------------------------------------------------------------- /Make.inc: -------------------------------------------------------------------------------- 1 | CXXFLAGS = -O3 -ffast-math -mtune=native 2 | 3 | PYTHON = /usr/local_rwth/sw/python/2.7.5/x86_64 4 | PYTHON_INC = $(PYTHON)/include/python2.7 5 | PYTHON_LIB = -L$(PYTHON)/lib -lpython2.7 6 | 7 | EIGEN = $(HOME)/apps/include/eigen 8 | NUMPY = /rwthfs/rz/SW/UTIL.common/Python/2.7.5/x86_64/extra/lib/python2.7/site-packages/numpy/core/include 9 | MYINC = ../include 10 | 11 | DIRS = cppext fort_rot integrate_dft_mlwf integrate_tight_binding integrate_bethe_lattice 12 | 13 | LAPACK = -L/usr/lib64/atlas -llapack -lf77blas -lcblas -latlas 14 | -------------------------------------------------------------------------------- /cppext/cubic_spline_ft/Makefile: -------------------------------------------------------------------------------- 1 | # $(ALPS_HOME) is the installation directory of ALPS 2 | include $(ALPS_HOME)/share/alps/include.mk 3 | 4 | include ../../Make.inc 5 | 6 | CXXFLAGS += -I$(PYTHON_INC) -I$(EIGEN) -I$(NUMPY) -I$(MYINC) -fPIC 7 | LIBS += $(PYTHON_LIB) -lboost_python 8 | 9 | # compile mesh classes 10 | TARGET = fourier.so 11 | 12 | OBJECTS = main.o fouriertransform.o 13 | 14 | all: $(TARGET) 15 | 16 | $(TARGET): $(OBJECTS) 17 | $(CXX) -shared $(OBJECTS) $(LDFLAGS) $(LIBS) -o $(TARGET) 18 | 19 | clean: 20 | -rm -f *.o $(TARGET) 21 | 22 | -------------------------------------------------------------------------------- /examples/CaRuO3_titled_t2g_only/parms: -------------------------------------------------------------------------------- 1 | ID = u2.3j0.4b60; 2 | 3 | BETA = 60; 4 | U = 2.3; 5 | J = 0.4; 6 | DENSITY = 4; 7 | MU0 = 15.96453; 8 | RHAM = rham.py; 9 | INTEGRATE_MOD = int_donly_tilted_3bands; 10 | N_LAYERS = 4; 11 | DTYPE = 3bands; 12 | NO_TUNEUP = 0; 13 | 14 | SWEEPS = 200000000; 15 | THERMALIZATION = 150000; 16 | N_TAU = 500; 17 | MAX_FREQ = 400; 18 | MAX_ITER = 15; 19 | MIXING = 1; 20 | TOLERANCE = 0.001; 21 | 22 | DATA_FILE = data.h5; 23 | USE_DATAFILE = self_energy.in; 24 | 25 | HARTREE_INIT = 1; 26 | NUMK = 26; 27 | USE_LAYER_SYMMETRY = 1; 28 | PARAMAGNET = 1; 29 | 30 | SOLVER_TYPE = TRIQS; 31 | -------------------------------------------------------------------------------- /cppext/Makefile: -------------------------------------------------------------------------------- 1 | include ../Make.inc 2 | 3 | # this is to get info from the old ALPS for the impurity solver from P. Werner 4 | # I don't include it here, so this line is commented 5 | #include /home/td120143/apps/alps-1.3.5/share/alps/include.mk 6 | 7 | CXXFLAGS += -I$(PYTHON_INC) -I$(EIGEN) -I$(NUMPY) -I$(MYINC) -fPIC 8 | LIBS += $(PYTHON_LIB) -lboost_python 9 | 10 | # compile mesh classes 11 | TARGET = cppext.so 12 | 13 | # the file eval.cpp is for P. Werner's impurity solver, not needed 14 | OBJECTS = main.o fourier.o others.o # eval.o 15 | 16 | all: $(TARGET) 17 | 18 | $(TARGET): $(OBJECTS) 19 | $(CXX) -shared $(OBJECTS) $(LDFLAGS) $(LIBS) -o $(TARGET) 20 | 21 | copy: $(TARGET) 22 | -cp -f $(TARGET) .. 23 | 24 | clean: 25 | -rm -f *.o $(TARGET) 26 | 27 | -------------------------------------------------------------------------------- /integrate_bethe_lattice/Makefile: -------------------------------------------------------------------------------- 1 | include ../Make.inc 2 | 3 | CXXFLAGS += -I$(PYTHON_INC) -I$(EIGEN) -I$(NUMPY) -I$(MYINC) -fPIC -fopenmp -DEIGEN_DONT_PARALLELIZE 4 | LIBS += $(PYTHON_LIB) -lboost_python -lgomp $(LAPACK) 5 | 6 | NAME = bethe_lattice 7 | TARGET = int_$(NAME).so 8 | 9 | OBJECTS = main.o integrand.o 10 | 11 | all: process_main $(TARGET) 12 | 13 | $(TARGET): $(OBJECTS) 14 | $(CXX) -shared $(OBJECTS) $(LIBS) -o $(TARGET) 15 | 16 | copy: $(TARGET) 17 | -cp -f $(TARGET) .. 18 | 19 | clean: 20 | -rm -f *.o $(TARGET) 21 | 22 | process_main: 23 | @(\ 24 | if ! grep "BOOST_PYTHON_MODULE(int_$(NAME))" main.cpp >> /dev/null ; then \ 25 | rm -f *.o *.so; \ 26 | sed -i 's/^BOOST_PYTHON_MODULE.*/BOOST_PYTHON_MODULE(int_$(NAME))/' main.cpp; \ 27 | fi) ; 28 | 29 | .PHONY: process_main 30 | -------------------------------------------------------------------------------- /integrate_tight_binding/Makefile: -------------------------------------------------------------------------------- 1 | include ../Make.inc 2 | 3 | CXXFLAGS += -I$(PYTHON_INC) -I$(EIGEN) -I$(NUMPY) -I$(MYINC) -fPIC -fopenmp -DEIGEN_DONT_PARALLELIZE 4 | LIBS += $(PYTHON_LIB) -lboost_python -lgomp $(LAPACK) 5 | 6 | NAME = 2dhopping 7 | TARGET = int_$(NAME).so 8 | 9 | OBJECTS = main.o integrand.o 10 | 11 | all: process_main $(TARGET) 12 | 13 | $(TARGET): $(OBJECTS) 14 | $(CXX) -shared $(OBJECTS) $(LIBS) -o $(TARGET) 15 | 16 | copy: $(TARGET) 17 | -cp -f $(TARGET) .. 18 | 19 | clean: 20 | -rm -f *.o $(TARGET) 21 | 22 | process_main: 23 | @(\ 24 | if ! grep "BOOST_PYTHON_MODULE(int_$(NAME))" main.cpp >> /dev/null ; then \ 25 | rm -f *.o *.so; \ 26 | sed -i 's/^BOOST_PYTHON_MODULE.*/BOOST_PYTHON_MODULE(int_$(NAME))/' main.cpp; \ 27 | fi) ; 28 | 29 | .PHONY: process_main 30 | -------------------------------------------------------------------------------- /integrate_dft_mlwf/Makefile: -------------------------------------------------------------------------------- 1 | include ../Make.inc 2 | 3 | CXXFLAGS += -I$(PYTHON_INC) -I$(EIGEN) -I$(NUMPY) -I$(MYINC) -fPIC -fopenmp -DEIGEN_DONT_PARALLELIZE 4 | LIBS += $(PYTHON_LIB) -lboost_python -lgomp $(LAPACK) 5 | 6 | NAME = donly_tilted_3bands 7 | TARGET = int_$(NAME).so 8 | 9 | OBJECTS = main.o integrand.o 10 | 11 | all: process_main $(TARGET) 12 | 13 | $(TARGET): $(OBJECTS) 14 | $(CXX) -shared $(OBJECTS) $(LIBS) -o $(TARGET) 15 | 16 | copy: $(TARGET) 17 | -cp -f $(TARGET) .. 18 | 19 | clean: 20 | -rm -f *.o $(TARGET) 21 | 22 | process_main: 23 | @(\ 24 | if ! grep "BOOST_PYTHON_MODULE(int_$(NAME))" main.cpp >> /dev/null ; then \ 25 | rm -f *.o *.so; \ 26 | sed -i 's/^BOOST_PYTHON_MODULE.*/BOOST_PYTHON_MODULE(int_$(NAME))/' main.cpp; \ 27 | fi) ; 28 | 29 | .PHONY: process_main 30 | -------------------------------------------------------------------------------- /examples/calculate_dos_bethe_lattice.py: -------------------------------------------------------------------------------- 1 | # demo: generate the noninteracting DOS for the Bethe lattice 2 | 3 | import sys 4 | # directory for the main code 5 | sys.path.append('..') 6 | 7 | from int_bethe_lattice import * 8 | from numpy import * 9 | from share_fun import grule 10 | from functions import rotate_all 11 | 12 | nflavors = 3 13 | 14 | emin = -3 15 | emax = 3 16 | nbin = 500 17 | broadening = 0.005 18 | 19 | double_counting = 0. 20 | mu = 0. 21 | magnetic_field = 0.0 22 | bp, wf = grule(1000) 23 | 24 | w = linspace(emin, emax, nbin) + 1j*broadening 25 | self_energy = zeros((nbin, nflavors*nflavors), dtype = 'c16') 26 | quarter_bandwidth = array([1.,0]) 27 | 28 | Gavg = calc_Gavg(w, double_counting, mu, self_energy, quarter_bandwidth, 29 | magnetic_field, bp, wf, 0).reshape(nbin, nflavors, nflavors) 30 | G = rotate_all(Gavg, [matrix(eye(nflavors))]) 31 | dos = -1/pi*G.imag 32 | savetxt('dos_bethe_lattice.out', c_[w.real, dos]) 33 | -------------------------------------------------------------------------------- /alps_interface.py: -------------------------------------------------------------------------------- 1 | import pyalps.cthyb as cthyb 2 | import pyalps.mpi as mpi 3 | import sys, re 4 | 5 | def readParameters(str_parms): 6 | comment_symbol = '(!|#|%|//)' 7 | propFile= open(str_parms, "rU") 8 | propDict= dict() 9 | for propLine in propFile: 10 | propDef= propLine.strip(); 11 | if re.match(comment_symbol, propDef) is not None \ 12 | or re.search('=', propDef) is None: continue; 13 | tmp = re.split('=', propDef); 14 | name = tmp[0].strip(); 15 | value = re.split(';', re.split(comment_symbol, tmp[1])[0])[0].strip(); 16 | propDict[name]= value; 17 | propFile.close(); 18 | return propDict; 19 | 20 | parms = readParameters(sys.argv[1]); 21 | parms.update({ 22 | 'VERBOSE' : 0, 23 | 'TEXT_OUTPUT' : 1, 24 | 'MEASURE_nn': 1, 25 | 'SPINFLIP' : 1, 26 | 'GLOBALFLIP' : 1, 27 | }); 28 | if mpi.rank==0: 29 | for k, v in parms.iteritems(): print k, ' = ', v; 30 | cthyb.solve(parms) 31 | -------------------------------------------------------------------------------- /user_config.py: -------------------------------------------------------------------------------- 1 | import os; 2 | 3 | src_dir = os.path.dirname(os.path.abspath(__file__)); 4 | 5 | # the path for the "mpirun" command (for MPI parallel running 6 | mpirun = "$MPIEXEC -x PYTHONPATH"; 7 | 8 | # this is for the interface with the private CT-HYB solver 9 | # from Philipp Werner and Emanuel Gull 10 | LatticeLibrary = '"/home/hungdt/works1/share/lattices.xml"'; 11 | ModelLibrary = '"/home/hungdt/works1/share/models.xml"'; 12 | Model = '"hung_multiorbital"'; 13 | parm2xml = "parameter2xml"; 14 | solver_matrix = "/home/hungdt/works/code/DMFT/Matrix/MPI_dca"; 15 | 16 | # for segment solvers in ALPS code 17 | # the path for alpspython, usually in $ALPS_ROOT_DIR/bin 18 | alpspython = "/home/td120143/apps/alps/bin/alpspython" 19 | solver_segment = "sh %s %s/alps_interface.py"%(alpspython, src_dir); 20 | 21 | # for TRIQS code 22 | # the path for pytriqs, usually in $TRIQS_ROOT_DIR/bin 23 | pytriqs = "pytriqs" 24 | solver_triqs = "%s %s/triqs_interface.py"%(pytriqs, src_dir); 25 | 26 | pytriqs_old = '$HOME/apps/triqs/v1.0/bin/pytriqs' 27 | solver_triqs_old = "%s %s/triqs_interface_old.py"%(pytriqs, src_dir); 28 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Hung T. Dang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /examples/calculate_dos_tight_binding.py: -------------------------------------------------------------------------------- 1 | # demo: generate the noninteracting DOS from the tight binding parameters 2 | 3 | import sys 4 | # directory for the main code 5 | sys.path.append('..') 6 | 7 | from int_2dhopping import * 8 | from numpy import * 9 | from share_fun import grule 10 | from functions import rotate_all 11 | 12 | nflavors = 3 13 | 14 | nbin = 500 15 | emin = -6. 16 | emax = 6. 17 | broadening = 0.05 18 | 19 | mu = 0. 20 | double_counting = 0. # unused in models containing only correlated orbitals 21 | 22 | magnetic_field = 0.0 23 | numk = 100 24 | bp, wf = grule(numk) # the Gaussian points and weights 25 | 26 | w = linspace(emin, emax, nbin) + 1j*broadening 27 | self_energy = zeros((nbin, 1, nflavors, nflavors), dtype = complex) 28 | self_energy = array([s.flatten() for s in self_energy], dtype = complex) 29 | tight_binding_parameters = array([1.,0.3]) 30 | 31 | Gavg = calc_Gavg(w, double_counting, mu, self_energy, tight_binding_parameters, 32 | magnetic_field, bp, wf, 0).reshape(nbin, nflavors, nflavors) 33 | G = rotate_all(Gavg, [matrix(eye(nflavors))]) 34 | dos = -1/pi*G.imag 35 | savetxt('dos_tight_binding.out', c_[w.real, dos], fmt='%.6f') 36 | -------------------------------------------------------------------------------- /cppext/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace boost::python; 5 | 6 | 7 | PyObject* ewald_sum(const int &NLa, const double &CLa, const int &NSr, const double &CSr, PyObject *nV, const int &Nxy, const int &Nz); 8 | PyObject* new_ewald_sum(const int &NLa, const double &CLa, const int &NSr, const double &CSr, PyObject *nVpy, const int &Nxy, const int &Nz); 9 | PyObject* IFT_mat2tau(PyObject *f_mat_in, const int &Nmax, const double &beta, const double &asymp_coefs1, const double &asymp_coefs2); 10 | PyObject* FT_tau2mat(PyObject *f_tau_py_in, const double &beta, const int &Nmax); 11 | 12 | // get_raw_data is for extracting data from P. Werner's impurity solver 13 | // which is not included here, thus it is commented 14 | //PyObject * get_raw_data(boost::python::str &path, const int &measure, PyObject *obs_str_list); 15 | double norm(PyObject *v); 16 | double interp_root(PyObject *x, PyObject *y, const double &y0); 17 | PyObject* array_erfc(PyObject *x); 18 | 19 | 20 | BOOST_PYTHON_MODULE(cppext) 21 | { 22 | using namespace boost::python; 23 | def("IFT_mat2tau", IFT_mat2tau); 24 | def("FT_tau2mat", FT_tau2mat); 25 | def("ewald_sum", ewald_sum); 26 | def("new_ewald_sum", new_ewald_sum); 27 | // def("get_raw_data", get_raw_data); 28 | } 29 | -------------------------------------------------------------------------------- /integrate_bethe_lattice/integrand.h: -------------------------------------------------------------------------------- 1 | #ifndef __GREEN_INTEGRAND_H__ 2 | #define __GREEN_INTEGRAND_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | const int MSIZE = 3; 11 | const int DIM = 1; 12 | 13 | typedef std::complex complex_t; 14 | 15 | class GreenIntegrand: public md_int::GeneralIntegrand { 16 | public: 17 | GreenIntegrand(const Eigen::VectorXcd &w_, const double &mu_, 18 | const Eigen::MatrixXcd &SE, const Eigen::VectorXd &SK, 19 | const double &Hf); 20 | void CalculateOriginalIntegrand(const Eigen::VectorXd &x, 21 | Eigen::VectorXcd &y) const; 22 | void set_data(const int &i); 23 | private: 24 | Eigen::MatrixXcd SEall; 25 | Eigen::VectorXcd wall; 26 | Eigen::Matrix SE; 27 | Eigen::VectorXd SK; 28 | double mu, H; 29 | complex_t w; 30 | }; 31 | 32 | 33 | class HIntegrand: public md_int::GeneralIntegrand { 34 | public: 35 | HIntegrand(const int &Norder, const Eigen::VectorXd &SK_, 36 | const double &H_in); 37 | void CalculateOriginalIntegrand(const Eigen::VectorXd &x, 38 | Eigen::VectorXcd &y) const; 39 | private: 40 | Eigen::VectorXd SK; 41 | double Hf; 42 | int N_order; 43 | }; 44 | 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /integrate_tight_binding/integrand.h: -------------------------------------------------------------------------------- 1 | #ifndef __GREEN_INTEGRAND_H__ 2 | #define __GREEN_INTEGRAND_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | const int MSIZE = 3; 11 | const int DIM = 2; 12 | 13 | typedef std::complex complex_t; 14 | 15 | class GreenIntegrand: public md_int::GeneralIntegrand { 16 | public: 17 | GreenIntegrand(const Eigen::VectorXcd &w_, const double &mu_, 18 | const Eigen::MatrixXcd &SE, 19 | const Eigen::VectorXd &SK, const double &Hf); 20 | void CalculateOriginalIntegrand(const Eigen::VectorXd &x, 21 | Eigen::VectorXcd &y) const; 22 | void set_data(const int &i); 23 | private: 24 | Eigen::MatrixXcd SEall; 25 | Eigen::VectorXcd wall; 26 | Eigen::Matrix SE; 27 | Eigen::VectorXd SK; 28 | double mu, H; 29 | complex_t w; 30 | }; 31 | 32 | 33 | class HIntegrand: public md_int::GeneralIntegrand { 34 | public: 35 | HIntegrand(const int &Norder, const Eigen::VectorXd &SK_, 36 | const double &H_in); 37 | void CalculateOriginalIntegrand(const Eigen::VectorXd &x, 38 | Eigen::VectorXcd &y) const; 39 | private: 40 | Eigen::VectorXd SK; 41 | double Hf; 42 | int N_order; 43 | }; 44 | 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /integrate_bethe_lattice/integrand.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "integrand.h" 3 | 4 | using namespace Eigen; 5 | 6 | 7 | GreenIntegrand::GreenIntegrand(const VectorXcd &w_, const double &mu_, 8 | const MatrixXcd &SE_, const VectorXd &SK_, const double &Hf) 9 | : md_int::GeneralIntegrand(), mu(mu_), 10 | H(Hf), wall(w_), SEall(SE_), SK(SK_) 11 | { 12 | set_dim_in(DIM); 13 | set_dim_out(MSIZE); 14 | } 15 | 16 | 17 | void GreenIntegrand::set_data(const int &r) 18 | { 19 | w = wall(r); 20 | for (int i = 0; i < MSIZE; ++i) 21 | SE(i) = SEall(r, MSIZE*i+i); // diagonal terms 22 | } 23 | 24 | 25 | void GreenIntegrand::CalculateOriginalIntegrand(const VectorXd &x, 26 | VectorXcd &y) const { 27 | double t = SK(0); 28 | y.resize(dim_out()); 29 | 30 | for (int L = 0; L < MSIZE; ++L) 31 | y(L) = 1./(2*M_PI*t*t)*sqrt(4*t*t-x(0)*x(0)) / (w + mu - x(0) - SE(L)); 32 | } 33 | 34 | HIntegrand::HIntegrand(const int &Norder, const VectorXd &SK_, 35 | const double &Hf_in) 36 | : md_int::GeneralIntegrand(), N_order(Norder), Hf(Hf_in), SK(SK_) 37 | { 38 | set_dim_in(DIM); 39 | set_dim_out(N_order*MSIZE); 40 | } 41 | 42 | 43 | void HIntegrand::CalculateOriginalIntegrand(const VectorXd &x, 44 | VectorXcd &y) const { 45 | double t = SK(0); 46 | complex_t Hband, Hpow = 1.; 47 | y.resize(dim_out()); 48 | Hband = x(0); 49 | for (int n = 0; n < N_order; ++n) { 50 | Hpow *= Hband; 51 | for (int i = 0; i < MSIZE; ++i) 52 | y(MSIZE*n+i) = 1./(2*M_PI*t*t)*sqrt(4*t*t-x(0)*x(0))*Hpow; 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /cppext/cubic_spline_ft/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "fouriertransform.h" 5 | 6 | PyObject* ArminForwardFourierTransform(PyObject *py_ftau, const double beta, 7 | PyObject *py_ftail, const int num_matsubara) { 8 | Eigen::VectorXd ftau, ftail; 9 | numpy::from_numpy(py_ftau, ftau); 10 | numpy::from_numpy(py_ftail, ftail); 11 | 12 | Eigen::VectorXcd fmat; 13 | FourierTransformer fourier(beta, ftail); 14 | fourier.Armin_forward_ft(ftau, fmat, num_matsubara); 15 | 16 | return numpy::to_numpy(fmat); 17 | } 18 | 19 | PyObject* ForwardFourierTransform(PyObject *py_ftau, const double beta, 20 | PyObject *py_ftail, const int num_matsubara) { 21 | Eigen::VectorXd ftau, ftail; 22 | numpy::from_numpy(py_ftau, ftau); 23 | numpy::from_numpy(py_ftail, ftail); 24 | 25 | Eigen::VectorXcd fmat; 26 | FourierTransformer fourier(beta, ftail); 27 | fourier.forward_ft(ftau, fmat, num_matsubara); 28 | 29 | return numpy::to_numpy(fmat); 30 | } 31 | 32 | PyObject* BackwardFourierTransform(PyObject *py_fmat, const double beta, 33 | PyObject *py_ftail, const int num_tau) { 34 | Eigen::VectorXcd fmat; 35 | Eigen::VectorXd ftail; 36 | numpy::from_numpy(py_fmat, fmat); 37 | numpy::from_numpy(py_ftail, ftail); 38 | 39 | Eigen::VectorXd ftau; 40 | FourierTransformer fourier(beta, ftail); 41 | fourier.backward_ft(fmat, ftau, num_tau); 42 | return numpy::to_numpy(ftau); 43 | } 44 | 45 | BOOST_PYTHON_MODULE(fourier) 46 | { 47 | boost::python::def("Armin_forward_ft", ArminForwardFourierTransform); 48 | boost::python::def("forward_ft", ForwardFourierTransform); 49 | boost::python::def("backward_ft", BackwardFourierTransform); 50 | } 51 | -------------------------------------------------------------------------------- /integrate_dft_mlwf/integrand.h: -------------------------------------------------------------------------------- 1 | #ifndef INTEGRATE_RH_GREEN_INTEGRAND_H_ 2 | #define INTEGRATE_RH_GREEN_INTEGRAND_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | const int kNLayers = 4; 11 | const int kNCor = 3; 12 | const int kMSize = kNLayers*kNCor; 13 | const int kDim = 3; 14 | 15 | typedef std::complex Complex; 16 | typedef Eigen::Matrix ComplexMatrix; 17 | EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(ComplexMatrix) 18 | 19 | 20 | class GreenIntegrand: public md_int::GeneralIntegrand { 21 | public: 22 | GreenIntegrand(const Eigen::VectorXcd &omega, const double &chemical_potential, 23 | const std::vector &hamiltonian_r, const Eigen::MatrixXi &r_vectors, 24 | const Eigen::MatrixXcd &all_self_energy, const double &magnetic_field, const double &double_counting); 25 | void CalculateOriginalIntegrand(const Eigen::VectorXd &x, Eigen::VectorXcd &y) const; 26 | void set_data(const int &i); 27 | 28 | private: 29 | const std::vector &ham_r_; 30 | const Eigen::MatrixXi &r_vectors_; 31 | const Eigen::MatrixXcd &all_self_energy_; 32 | const Eigen::VectorXcd &all_omega_; 33 | ComplexMatrix self_energy_; 34 | double chemical_potential_, h_field_, delta_; 35 | Complex w_; 36 | }; 37 | 38 | 39 | class HamiltonianIntegrand: public md_int::GeneralIntegrand { 40 | public: 41 | HamiltonianIntegrand(const int &num_order, const std::vector &hamiltonian_r, 42 | const Eigen::MatrixXi &r_vectors, const double &magnetic_field, const double &double_counting); 43 | void CalculateOriginalIntegrand(const Eigen::VectorXd &x, Eigen::VectorXcd &y) const; 44 | 45 | private: 46 | const std::vector &ham_r_; 47 | const Eigen::MatrixXi &r_vectors_; 48 | double h_field_, delta_; 49 | int num_order_; 50 | }; 51 | 52 | 53 | #endif // INTEGRATE_RH_GREEN_INTEGRAND_H_ 54 | -------------------------------------------------------------------------------- /integrate_tight_binding/integrand.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "integrand.h" 3 | 4 | using namespace Eigen; 5 | 6 | void getHband(const VectorXd &x, complex_t &mat, 7 | const VectorXd &SK, const double &H) { 8 | // SK : t, t1 9 | double t = SK[0], t1 = SK[1]; 10 | mat = -2*t*(cos(x(0)) + cos(x(1))) - 4*t1*cos(x(0))*cos(x(1)) - H; 11 | } 12 | 13 | 14 | GreenIntegrand::GreenIntegrand(const VectorXcd &w_, const double &mu_, 15 | const MatrixXcd &SE_, const VectorXd &SK_, const double &Hf) 16 | : md_int::GeneralIntegrand(), mu(mu_), 17 | H(Hf), wall(w_), SEall(SE_), SK(SK_) { 18 | set_dim_in(DIM); 19 | set_dim_out(MSIZE); 20 | } 21 | 22 | 23 | void GreenIntegrand::set_data(const int &r) { 24 | w = wall(r); 25 | SE.setZero(); 26 | for (int i = 0; i < MSIZE; ++i) 27 | SE(i) = SEall(r, MSIZE*i+i); // diagonal terms 28 | } 29 | 30 | 31 | void GreenIntegrand::CalculateOriginalIntegrand(const VectorXd &x, 32 | VectorXcd &y) const { 33 | y.resize(dim_out()); 34 | complex_t Hband; 35 | getHband(x, Hband, SK, H); 36 | 37 | for (int L = 0; L < MSIZE; ++L) { 38 | y(L) = 1. / (w + mu - Hband - SE(L)); 39 | } 40 | } 41 | 42 | 43 | HIntegrand::HIntegrand(const int &Norder, const VectorXd &SK_, 44 | const double &Hf_in) 45 | : md_int::GeneralIntegrand(), N_order(Norder), 46 | Hf(Hf_in), SK(SK_) { 47 | set_dim_in(DIM); 48 | set_dim_out(N_order*MSIZE); 49 | } 50 | 51 | 52 | void HIntegrand::CalculateOriginalIntegrand(const VectorXd &x, 53 | VectorXcd &y) const { 54 | complex_t Hband, Hpow = 1.; 55 | y.resize(dim_out()); 56 | y.setZero(); 57 | getHband(x, Hband, SK, Hf); 58 | for (int n = 0; n < N_order; ++n) { 59 | Hpow *= Hband; 60 | for (int i = 0; i < MSIZE; ++i) 61 | y(MSIZE*n+i) = Hpow; 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /examples/calculate_dos_dft_mlwf.py: -------------------------------------------------------------------------------- 1 | # demo: generate the noninteracting DOS from the Hamiltonian produced by DFT+MLWF 2 | 3 | import sys 4 | # directory for the main code 5 | sys.path.append('..') 6 | 7 | from int_donly_tilted_3bands import calc_Gavg 8 | from numpy import * 9 | from functions import * 10 | from share_fun import grule 11 | import init 12 | 13 | N_LAYERS = 4 14 | FLAVORS = 3 15 | SPINS = 1 16 | 17 | mu = 15.45 18 | double_counting = 0. 19 | 20 | nbin = 300 21 | emin = -1.5 22 | emax = 1.5 23 | broadening = 0.02 24 | magnetic_field = 0. 25 | nthreads = 10 26 | 27 | rham_file = "LaTiO3_tilted_t2g_only/lto_rham.py" # the file for the Hamiltonian produced by DFT+MLWF 28 | 29 | HR, R = init.getHamiltonian(rham_file, 4) 30 | NORB = size(HR, 1) 31 | rot_mat = init.getRotationMatrix(N_LAYERS, FLAVORS, 32 | H0 = HR[nonzero(sum(R**2, 1)==0)[0][0]]) 33 | 34 | numk = 26 35 | bp, wf = grule(numk) # the Gaussian points and weights 36 | 37 | w = linspace(emin, emax, nbin) 38 | SelfEnergy = zeros((SPINS, nbin, N_LAYERS*FLAVORS), dtype = 'c16') 39 | # convert self energy to the C++ form 40 | SelfEnergy_rot = array([irotate(SelfEnergy[s], rot_mat) for s in range(SPINS)]) 41 | SE = array([array([s.flatten() for s in SelfEnergy_rot[n]]) for n in range(SPINS)]) 42 | Gavg = array([calc_Gavg(w+1j*broadening, double_counting, mu, 43 | SE[n].copy(), HR, R, magnetic_field*(-1)**n, 44 | bp, wf, nthreads).reshape(nbin, NORB, NORB) 45 | for n in range(SPINS)]) 46 | 47 | # swap the Gavg to the format of the main code 48 | swap_vec = zeros((2, N_LAYERS*FLAVORS), dtype = int) 49 | for L in range(N_LAYERS): 50 | for f in range(FLAVORS): swap_vec[:,f*N_LAYERS+L] = array([f*N_LAYERS+L, L*FLAVORS+f]) 51 | for s in range(SPINS): 52 | for n in range(len(Gavg[s])): 53 | Gavg[s, n,:,swap_vec[0]] = Gavg[s, n, :, swap_vec[1]] 54 | Gavg[s, n,swap_vec[0],:] = Gavg[s, n, swap_vec[1], :] 55 | Gavg = array([rotate_all(Gavg[s], rot_mat, need_extra = True) for s in range(SPINS)]) 56 | 57 | dos = -1/pi*Gavg[0].imag 58 | savetxt('dos_dft_mlwf.openmp', c_[w, dos], fmt='%.6f') 59 | 60 | -------------------------------------------------------------------------------- /fort_rot/fort_rot.f: -------------------------------------------------------------------------------- 1 | subroutine rotate(fin,rot,fout,Nw,Nd) 2 | implicit none 3 | integer Nw, Nd 4 | complex*16 fin(Nw,Nd,Nd), fout(Nw,Nd), rot(Nd,Nd) 5 | Cf2py intent(in) fin,rot,Nw,Nd 6 | Cf2py intent(out) fout 7 | 8 | ! local vars 9 | integer i,j,k 10 | complex*16 tmp(Nd,Nd) 11 | 12 | !$OMP PARALLEL SHARED(fin,rot,fout) PRIVATE(i,j,tmp) 13 | !$OMP DO 14 | do i=1,Nw 15 | call mat_transform(fin(i,:,:), rot, tmp, Nd, 1) 16 | do j=1,Nd 17 | fout(i,j) = tmp(j,j); 18 | enddo 19 | enddo 20 | !$OMP END PARALLEL 21 | end 22 | 23 | 24 | subroutine irotate(fin,rot,fout,Nw,Nd) 25 | implicit none 26 | integer Nw, Nd 27 | complex*16 fin(Nw,Nd), fout(Nw,Nd,Nd), rot(Nd,Nd) 28 | Cf2py intent(in) fin,rot,Nw,Nd 29 | Cf2py intent(out) fout 30 | 31 | ! local vars 32 | integer i,j,k 33 | complex*16 tmp(Nd,Nd) 34 | 35 | 36 | !$OMP PARALLEL SHARED(fin,rot,fout) PRIVATE(i,j,tmp) 37 | !$OMP DO 38 | do i=1,Nw 39 | tmp = 0; 40 | do j=1,Nd 41 | tmp(j,j) = fin(i,j); 42 | enddo 43 | call mat_transform(tmp, rot, fout(i,:,:), Nd, 0) 44 | enddo 45 | !$OMP END PARALLEL 46 | end 47 | 48 | 49 | subroutine mat_transform(A,B,C,L, direction) 50 | ! return C = BxAxB^t if direction > 0 51 | ! return C = B^txAxB if direction = 0 52 | ! input A a symmetric matrix of size L 53 | complex*16 A(L,L), B(L,L), C(L,L), tmp(L,L) 54 | integer L, direction 55 | character C1, C2 56 | complex*16 ALPHA,BETA 57 | 58 | ALPHA=1.0; BETA=0.0; 59 | 60 | if (direction > 0) then 61 | !dsymm to the right: BxA 62 | C1='N'; C2='N' 63 | call zgemm(C1,C2,L,L,L,ALPHA,B,L,A,L,BETA,tmp,L) 64 | 65 | !dgemm with B^t: BxAxB^t 66 | C1='N'; C2='C' ! here is Hermitian conjugate 67 | call zgemm(C1,C2,L,L,L,ALPHA,tmp,L,B,L,BETA,C,L) 68 | else 69 | !dsymm to the left: AxB 70 | C1='N'; C2='N' 71 | call zgemm(C1,C2,L,L,L,ALPHA,A,L,B,L,BETA,tmp,L) 72 | 73 | !dgemm with B^t: B^txAxB 74 | C1='C'; C2='N' ! Hermitian conjugate 75 | call zgemm(C1,C2,L,L,L,ALPHA,B,L,tmp,L,BETA,C,L) 76 | endif 77 | end 78 | -------------------------------------------------------------------------------- /examples/calculate_dos_average_green.py: -------------------------------------------------------------------------------- 1 | # demo: generate the noninteracting DOS from the DFT+MLWF Hamiltonian 2 | # using average_green module 3 | 4 | from numpy import * 5 | import sys 6 | # directory for the main code 7 | sys.path.append('..') 8 | 9 | from functions import rotate_all, irotate 10 | from share_fun import grule 11 | import init 12 | import average_green 13 | 14 | N_LAYERS = 4 15 | FLAVORS = 3 16 | SPINS = 1 17 | 18 | mu = 15.45 19 | double_counting = 0. 20 | magnetic_field = 0. 21 | 22 | # the file for the Hamiltonian produced by DFT+MLWF 23 | rham_file = "LaTiO3_tilted_t2g_only/lto_rham.py" 24 | 25 | nbin = 300 26 | emin = -1.5 27 | emax = 1.5 28 | broadening = 0.02 29 | numk = 26 30 | 31 | # parallelization: parallel 32 | # 0: no parallelization 33 | # 1: OpenMP with number of threads set by OMP_NUM_THREADS 34 | # 2: MPI with number of processes from the input 35 | parallel = 2 36 | num_processes = 10 37 | if len(sys.argv) > 1: num_processes = int(sys.argv[1]) 38 | 39 | HR, R = init.getHamiltonian(rham_file, 4) 40 | NORB = size(HR, 1) 41 | rot_mat = init.getRotationMatrix(N_LAYERS, FLAVORS, 42 | H0 = HR[nonzero(sum(R**2, 1)==0)[0][0]]) 43 | w = linspace(emin, emax, nbin) 44 | 45 | # set zero self energy and convert it into the flattened format 46 | SelfEnergy = zeros((SPINS, nbin, N_LAYERS*FLAVORS), dtype = 'c16') 47 | SelfEnergy_rot = array([irotate(SelfEnergy[s], rot_mat) 48 | for s in range(SPINS)]) 49 | SE = array([array([s.flatten() for s in SelfEnergy_rot[n]]) 50 | for n in range(SPINS)]) 51 | 52 | # prepare the parameter dict 53 | parms = { 54 | 'H' : magnetic_field, 55 | 'N_LAYERS' : N_LAYERS, 56 | 'FLAVORS' : FLAVORS, 57 | 'SPINS' : SPINS, 58 | 'NORB' : NORB, 59 | 'INTEGRATE_MOD' : 'int_donly_tilted_3bands', 60 | 'np' : num_processes, 61 | } 62 | 63 | extra = { 64 | 'HR' : HR, 65 | 'R' : R, 66 | 'GaussianData' : grule(numk), 67 | } 68 | 69 | # calculate the k-integral 70 | Gavg = average_green.integrate(w+1j*broadening, double_counting, mu, SE, 71 | parms, extra, parallel) 72 | Gavg = array([rotate_all(Gavg[s], rot_mat, need_extra = True) for s in range(SPINS)]) 73 | 74 | dos = -1/pi*Gavg[0].imag 75 | savetxt('dos_dft_mlwf.mpi', c_[w, dos], fmt='%.6f') 76 | 77 | -------------------------------------------------------------------------------- /cppext/fourier.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | PyObject* IFT_mat2tau(PyObject *f_mat_in, const int &Nmax, const double &beta, const double &asymp_coefs1, const double &asymp_coefs2) 7 | { 8 | PyArrayObject *f_mat = (PyArrayObject *) f_mat_in; 9 | import_array1(NULL); 10 | uint nfreq = f_mat->dimensions[0]; 11 | npy_intp Nm = (npy_intp)Nmax; 12 | PyArrayObject *f_tau = (PyArrayObject *)PyArray_SimpleNew(1, &Nm, NPY_DOUBLE); 13 | Py_INCREF(f_tau); 14 | double *buf = (double *)PyArray_DATA(f_tau); 15 | std::complex *f_matsubara = (std::complex *)PyArray_DATA(f_mat); 16 | double C[2] = {asymp_coefs1, asymp_coefs2}; 17 | 18 | for (int i = 0; i < Nmax; i++) { 19 | double tau=double(i)*beta/double(Nmax - 1); 20 | buf[i] = -C[0]/2. + C[1]/4.*(-beta+2*tau); 21 | for (uint k = 0; k < nfreq; ++k) { 22 | double wt((2*k+1)*double(i)*M_PI/double(Nmax - 1)); 23 | std::complex iomegan(0,(2*k+1)*M_PI/beta); 24 | std::complex f_matsubara_nomodel = f_matsubara[k] - C[0]/iomegan - C[1]/(iomegan*iomegan); 25 | buf[i] += 2./beta*(cos(wt)*f_matsubara_nomodel.real() + sin(wt)*f_matsubara_nomodel.imag()); 26 | } 27 | } 28 | return PyArray_Return(f_tau); 29 | } 30 | 31 | PyObject* FT_tau2mat(PyObject *f_tau_py_in, const double &beta, const int &Nmax) 32 | { 33 | PyArrayObject *f_tau_py = (PyArrayObject *) f_tau_py_in; 34 | import_array1(NULL); 35 | double *f_tau = (double *)PyArray_DATA(f_tau_py); 36 | int nfreq = f_tau_py->dimensions[0] - 1; 37 | PyArrayObject *f_mat; 38 | npy_intp Nm = (npy_intp)Nmax; 39 | f_mat = (PyArrayObject *)PyArray_SimpleNew(1, &Nm, NPY_CDOUBLE); 40 | Py_INCREF(f_mat); 41 | std::complex *f_matsubara = (std::complex *)PyArray_DATA(f_mat); 42 | 43 | // trapezoidal rule for integration 44 | for (int n = 0; n < Nmax; n++) { 45 | double wn = (2*n + 1)*M_PI/beta; 46 | f_matsubara[n] = 0; 47 | for (int p = 1; p < nfreq; p++) { 48 | double tau = beta/double(nfreq)*p; 49 | f_matsubara[n] += f_tau[p]*(cos(wn*tau) + std::complex(0,1)*sin(wn*tau)); 50 | } 51 | f_matsubara[n] = beta/2./double(nfreq)*(f_tau[0] - f_tau[nfreq]) + beta/double(nfreq)*f_matsubara[n]; 52 | } 53 | return PyArray_Return(f_mat); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /integrate_bethe_lattice/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "integrand.h" 7 | 8 | using namespace Eigen; 9 | 10 | 11 | PyObject* calc_Gavg(PyObject *pyw, const double &delta, const double &mu, 12 | PyObject *pySE, PyObject *pyTB, const double &Hf, PyObject *py_bp, 13 | PyObject *py_wf, const int nthreads) { 14 | try { 15 | if (nthreads > 0) omp_set_num_threads(nthreads); 16 | MatrixXcd SE; 17 | VectorXcd w; 18 | VectorXd bp, wf; 19 | VectorXd SlaterKosterCoeffs; 20 | 21 | numpy::from_numpy(pySE, SE); 22 | numpy::from_numpy(pyTB, SlaterKosterCoeffs); 23 | numpy::from_numpy(py_bp, bp); 24 | numpy::from_numpy(py_wf, wf); 25 | numpy::from_numpy(pyw, w); 26 | assert(w.size() == SE.rows()); 27 | 28 | double t = SlaterKosterCoeffs(0); 29 | VectorXd xl(DIM), xh(DIM); 30 | xl << -2*t; 31 | xh << 2*t; 32 | double BZ1 = 1.; 33 | 34 | MatrixXcd result(SE.rows(), MSIZE*MSIZE); 35 | VectorXcd tmp(MSIZE); 36 | GreenIntegrand green_integrand(w, mu, SE, SlaterKosterCoeffs, Hf); 37 | result.setZero(); 38 | for (int n = 0; n < w.size(); ++n) { 39 | green_integrand.set_data(n); 40 | tmp = md_int::Integrate(xl, xh, green_integrand, bp, wf); 41 | for (int i = 0; i < MSIZE; ++i) 42 | result(n, MSIZE*i + i) = tmp(i); 43 | } 44 | result /= BZ1; 45 | return numpy::to_numpy(result); 46 | } catch (const char *str) { 47 | std::cerr << str << std::endl; 48 | return Py_None; 49 | } 50 | } 51 | 52 | PyObject* calc_Havg(const int &Norder, PyObject *pyTB, const double &Hf, 53 | const double &delta, PyObject *py_bp, PyObject *py_wf) { 54 | try { 55 | MatrixXi R; 56 | VectorXd bp, wf; 57 | VectorXd SlaterKosterCoeffs; 58 | 59 | numpy::from_numpy(pyTB, SlaterKosterCoeffs); 60 | numpy::from_numpy(py_bp, bp); 61 | numpy::from_numpy(py_wf, wf); 62 | 63 | double t = SlaterKosterCoeffs(0); 64 | VectorXd xl(DIM), xh(DIM); 65 | xl << -2*t; 66 | xh << 2*t; 67 | double BZ1 = 1.; 68 | 69 | HIntegrand h_integrand(Norder, SlaterKosterCoeffs, Hf); 70 | VectorXd result = (md_int::Integrate(xl, xh, h_integrand, bp, wf)).real(); 71 | result /= BZ1; 72 | VectorXd ret(Norder*MSIZE*MSIZE); 73 | ret.setZero(); 74 | for (int i = 0; i < Norder; ++i) 75 | for (int j = 0; j < MSIZE; ++j) 76 | ret(MSIZE*MSIZE*i + MSIZE*j + j) = result(MSIZE*i + j); 77 | return numpy::to_numpy(ret); 78 | } catch (const char *str) { 79 | std::cerr << str << std::endl; 80 | return Py_None; 81 | } 82 | } 83 | 84 | BOOST_PYTHON_MODULE(int_bethe_lattice) 85 | { 86 | using namespace boost::python; 87 | def("calc_Gavg", calc_Gavg); 88 | def("calc_Havg", calc_Havg); 89 | } 90 | -------------------------------------------------------------------------------- /cppext/cubic_spline_ft/fouriertransform.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * 3 | * ALPS DMFT Project 4 | * 5 | * Copyright (C) 2005 - 2009 by Emanuel Gull 6 | * Philipp Werner , 7 | * Sebastian Fuchs 8 | * Matthias Troyer 9 | * 10 | * 11 | * This software is part of the ALPS Applications, published under the ALPS 12 | * Application License; you can use, redistribute it and/or modify it under 13 | * the terms of the license, either version 1 or (at your option) any later 14 | * version. 15 | * 16 | * You should have received a copy of the ALPS Application License along with 17 | * the ALPS Applications; see the file LICENSE.txt. If not, the license is also 18 | * available from http://alps.comp-phys.org/. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 | * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 | * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | * DEALINGS IN THE SOFTWARE. 27 | * 28 | *****************************************************************************/ 29 | 30 | #ifndef FOURIER_TRANSFORM_H 31 | #define FOURIER_TRANSFORM_H 32 | #include 33 | #include 34 | #include 35 | 36 | 37 | inline std::complex f_omega(std::complex iw, 38 | double c1, double c2, double c3) { 39 | std::complex iwsq=iw*iw; 40 | return c1/iw + c2/(iwsq) + c3/(iw*iwsq); 41 | } 42 | 43 | inline double f_tau(double tau, double beta, 44 | double c1, double c2, double c3) { 45 | return -0.5*c1 + (c2*0.25)*(-beta+2.*tau) + (c3*0.25)*(beta*tau-tau*tau); 46 | } 47 | 48 | 49 | class FourierTransformer { 50 | public: 51 | FourierTransformer(const double beta, const Eigen::VectorXd &ftail); 52 | virtual ~FourierTransformer() {} 53 | void forward_ft(const Eigen::VectorXd &G_tau, Eigen::VectorXcd &G_omega, 54 | const int num_matsubara) const; 55 | void Armin_forward_ft(const Eigen::VectorXd &G_tau, Eigen::VectorXcd &G_omega, 56 | const int num_matsubara) const; 57 | void backward_ft(const Eigen::VectorXcd &G_omega, 58 | Eigen::VectorXd &G_tau, const int N_tau) const; 59 | protected: 60 | double beta_; 61 | // coefficients for the Green's functions 62 | const Eigen::VectorXd &c_; 63 | }; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /include/integrate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * n-dim Gaussian quadrature for general functions with vector output 3 | * using OpenMP for parallelization 4 | * 5 | * Hung Dang (May 12, 2011) 6 | */ 7 | 8 | #ifndef __INTEGRATE_H__ 9 | #define __INTEGRATE_H__ 10 | 11 | #include 12 | 13 | namespace md_int { 14 | 15 | 16 | // 17 | // N : dim of space for integrating 18 | // M : size of the integrand vector 19 | // L : size of vector bp 20 | // ret must be allocated to be a vector of size M 21 | // 22 | inline void calculate_id(const int &n, const int &L, const int &d, int *&new_num) 23 | { 24 | int div, rem; 25 | 26 | div = n; 27 | 28 | int id = 0; 29 | while (div != 0) { 30 | rem = div % L; 31 | div = div / L; 32 | new_num[id] = rem; 33 | id++; 34 | } 35 | 36 | for (int i = id; i < d; ++i) 37 | new_num[i] = 0; 38 | } 39 | 40 | template 41 | T* integrate(const int N, const int M, 42 | const double *xl, const double *xh, 43 | const int &L, const double *bp, const double *wf, 44 | void (*integrand)(const int &, const double *in, const int &, T *out, const void *data), 45 | void *integrand_data) 46 | { 47 | double *qx = new double[N], 48 | *px = new double[N]; 49 | for (int i = 0; i < N; ++i) { 50 | qx[i] = (xh[i] - xl[i])/2.; 51 | px[i] = (xh[i] + xl[i])/2.; 52 | } 53 | T *ret = new T[M]; 54 | memset(ret, 0, M*sizeof(T)); 55 | 56 | #pragma omp parallel default(shared) 57 | { 58 | double *x = new double[N]; 59 | double weight; 60 | int *id = new int[N]; 61 | T *tmp = new T[M]; 62 | T *ret_local = new T[M]; 63 | memset(ret_local, 0, M*sizeof(T)); 64 | 65 | #pragma omp for 66 | for (int n = 0; n < int(pow(L, N)); ++n) { 67 | // calculate the index id for each n 68 | calculate_id(n, L, N, id); 69 | // calculate the integrand and add to vector ret 70 | weight = 1.; 71 | for (int i = 0; i < N; ++i) { 72 | x[i] = qx[i]*bp[id[i]] + px[i]; 73 | weight *= wf[id[i]]; 74 | } 75 | integrand(N, x, M, tmp, integrand_data); 76 | for (int i = 0; i < M; ++i) 77 | ret_local[i] += tmp[i]*weight; 78 | } 79 | #pragma omp critical 80 | { 81 | for (int i = 0; i < M; ++i) 82 | ret[i] += ret_local[i]; 83 | } 84 | 85 | delete[] x; 86 | delete[] id; 87 | delete[] tmp; 88 | delete[] ret_local; 89 | } 90 | 91 | // Jacobian 92 | for (int i = 0; i < M; ++i) 93 | for (int j = 0; j < N; ++j) 94 | ret[i] *= qx[j]; 95 | 96 | 97 | delete[] qx; 98 | delete[] px; 99 | 100 | return ret; 101 | } 102 | 103 | } // end of namespace md_int 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /integrate_tight_binding/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "integrand.h" 7 | 8 | using namespace Eigen; 9 | 10 | PyObject* calc_Gavg(PyObject *pyw, const double &delta, const double &mu, 11 | PyObject *pySE, PyObject *pyTB, const double &Hf, 12 | PyObject *py_bp, PyObject *py_wf, const int nthreads) { 13 | try { 14 | if (nthreads > 0) omp_set_num_threads(nthreads); 15 | VectorXd xl(DIM), xh(DIM); 16 | xl << -M_PI, -M_PI; 17 | xh << M_PI, M_PI; 18 | double BZ1 = (xh - xl).prod(); 19 | MatrixXcd SE; 20 | VectorXcd w; 21 | VectorXd bp, wf; 22 | VectorXd SlaterKosterCoeffs; 23 | 24 | numpy::from_numpy(pySE, SE); 25 | numpy::from_numpy(pyTB, SlaterKosterCoeffs); 26 | numpy::from_numpy(py_bp, bp); 27 | numpy::from_numpy(py_wf, wf); 28 | numpy::from_numpy(pyw, w); 29 | assert(w.size() == SE.rows()); 30 | 31 | MatrixXcd result(SE.rows(), MSIZE*MSIZE); 32 | VectorXcd tmp(MSIZE); 33 | GreenIntegrand green_integrand(w, mu, SE, SlaterKosterCoeffs, Hf); 34 | result.setZero(); 35 | for (int n = 0; n < w.size(); ++n) { 36 | green_integrand.set_data(n); 37 | tmp = md_int::Integrate(xl, xh, green_integrand, bp, wf); 38 | for (int i = 0; i < MSIZE; ++i) 39 | result(n, MSIZE*i + i) = tmp(i); 40 | } 41 | result /= BZ1; 42 | return numpy::to_numpy(result); 43 | } catch (const char *str) { 44 | std::cerr << str << std::endl; 45 | return Py_None; 46 | } 47 | } 48 | 49 | PyObject* calc_Havg(const int &Norder, PyObject *pyTB, const double &Hf, 50 | const double &delta, PyObject *py_bp, PyObject *py_wf) { 51 | try { 52 | VectorXd xl(DIM), xh(DIM); 53 | xl << -M_PI, -M_PI; 54 | xh << M_PI, M_PI; 55 | double BZ1 = (xh - xl).prod(); 56 | MatrixXi R; 57 | VectorXd bp, wf; 58 | VectorXd SlaterKosterCoeffs; 59 | 60 | numpy::from_numpy(pyTB, SlaterKosterCoeffs); 61 | numpy::from_numpy(py_bp, bp); 62 | numpy::from_numpy(py_wf, wf); 63 | 64 | HIntegrand h_integrand(Norder, SlaterKosterCoeffs, Hf); 65 | VectorXd result = (md_int::Integrate(xl, xh, h_integrand, bp, wf)).real(); 66 | result /= BZ1; 67 | VectorXd ret(Norder*MSIZE*MSIZE); 68 | ret.setZero(); 69 | for (int i = 0; i < Norder; ++i) 70 | for (int j = 0; j < MSIZE; ++j) 71 | ret(MSIZE*MSIZE*i + MSIZE*j + j) = result(MSIZE*i + j); 72 | return numpy::to_numpy(ret); 73 | } catch (const char *str) { 74 | std::cerr << str << std::endl; 75 | return Py_None; 76 | } 77 | } 78 | 79 | BOOST_PYTHON_MODULE(int_2dhopping) 80 | { 81 | using namespace boost::python; 82 | def("calc_Gavg", calc_Gavg); 83 | def("calc_Havg", calc_Havg); 84 | } 85 | -------------------------------------------------------------------------------- /integrate_dft_mlwf/integrand.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "integrand.h" 3 | 4 | using namespace Eigen; 5 | 6 | 7 | void GetBandHamiltonian(const VectorXd &x, ComplexMatrix &mat, const std::vector &HR, 8 | const MatrixXi &R, const double &H, const double &delta) 9 | { 10 | static Complex I(0,1); 11 | mat.fill(0); 12 | for (int i = 0; i < R.rows(); ++i) { 13 | mat += HR[i]*exp(I*(x(0)*R(i,0) + x(1)*R(i,1) + x(2)*R(i,2))); 14 | } 15 | for (int i = 0; i < mat.rows(); ++i) 16 | mat(i,i) -= H; 17 | for (int i = 0; i < kNCor*kNLayers; ++i) 18 | mat(i,i) -= delta; 19 | } 20 | 21 | 22 | GreenIntegrand::GreenIntegrand(const Eigen::VectorXcd &omega, const double &chemical_potential, 23 | const std::vector &hamiltonian_r, const Eigen::MatrixXi &r_vectors, 24 | const Eigen::MatrixXcd &all_self_energy, const double &magnetic_field, const double &double_counting) 25 | : md_int::GeneralIntegrand(), delta_(double_counting), chemical_potential_(chemical_potential), 26 | ham_r_(hamiltonian_r), r_vectors_(r_vectors), h_field_(magnetic_field), all_omega_(omega), 27 | all_self_energy_(all_self_energy), self_energy_(ComplexMatrix::Zero()) { 28 | set_dim_in(kDim); 29 | set_dim_out(kMSize*kMSize); 30 | } 31 | 32 | // set omega and self energy: 33 | // e.g. tilted 5d band case: 4 blocks for 4 cell, each block is a 5x5 matrix 34 | void GreenIntegrand::set_data(const int &r) { 35 | w_ = all_omega_(r); 36 | 37 | for (int c = 0; c < kNLayers; ++c) 38 | for (int i = 0; i < kNCor; ++i) 39 | for (int j = 0; j < kNCor; ++j) 40 | self_energy_(kNCor*c+i,kNCor*c+j) = all_self_energy_(r, kNCor*kNCor*c+kNCor*i+j); 41 | } 42 | 43 | void GreenIntegrand::CalculateOriginalIntegrand(const VectorXd &x, VectorXcd &y) const 44 | { 45 | y.resize(dim_out()); 46 | ComplexMatrix tmp, negative_green; 47 | GetBandHamiltonian(x, tmp, ham_r_, r_vectors_, h_field_, delta_); 48 | 49 | for (int n = 0; n < kMSize; ++n) tmp(n, n) -= w_ + chemical_potential_; 50 | tmp += self_energy_; 51 | 52 | inv::inverse(tmp, negative_green); 53 | for (int i = 0; i < kMSize; ++i) 54 | for (int j = 0; j < kMSize; ++j) 55 | y(kMSize*i+j) = -negative_green(i, j); 56 | } 57 | 58 | 59 | HamiltonianIntegrand::HamiltonianIntegrand(const int &num_order, const std::vector &hamiltonian_r, 60 | const Eigen::MatrixXi &r_vectors, const double &magnetic_field, const double &double_counting) 61 | : md_int::GeneralIntegrand(), num_order_(num_order), ham_r_(hamiltonian_r), 62 | r_vectors_(r_vectors), h_field_(magnetic_field), delta_(double_counting) { 63 | set_dim_in(kDim); 64 | set_dim_out(num_order_*kMSize*kMSize); 65 | } 66 | 67 | void HamiltonianIntegrand::CalculateOriginalIntegrand(const VectorXd &x, VectorXcd &y) const 68 | { 69 | ComplexMatrix ham, ham_pow(ComplexMatrix::Identity()); 70 | y.resize(dim_out()); 71 | GetBandHamiltonian(x, ham, ham_r_, r_vectors_, h_field_, delta_); 72 | for (int n = 0; n < num_order_; ++n) { 73 | ham_pow *= ham; 74 | for (int i = 0; i < kMSize; ++i) 75 | for (int j = 0; j < kMSize; ++j) 76 | y(kMSize*kMSize*n+kMSize*i+j) = ham_pow(i, j); 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /cppext/eval.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | PyObject * get_raw_data(boost::python::str &path, const int &measure, PyObject *obs_str_list) 12 | { 13 | import_array1(NULL); 14 | char *s = boost::python::extract(path); 15 | std::string str_parms = std::string(s) + ".task1.out.xml"; 16 | alps::scheduler::SimpleMCFactory factory; 17 | alps::scheduler::init(factory); 18 | boost::filesystem::path p(str_parms.c_str(), boost::filesystem::native); 19 | alps::ProcessList nowhere; 20 | alps::scheduler::MCSimulation sim(nowhere,p); 21 | 22 | alps::RealVectorObsevaluator G=sim.get_measurements()["Greens"]; 23 | int N = int(sim.get_parameters()["N"]), 24 | FLAVORS = int(sim.get_parameters()["SPINS"])*int(sim.get_parameters()["SITES"]); 25 | alps::RealVectorObsevaluator n=sim.get_measurements()["n"]; 26 | alps::RealObsevaluator sign=sim.get_measurements()["Sign"]; 27 | 28 | npy_intp dim[2] = {N+1, FLAVORS}; 29 | PyArrayObject *Gtau = (PyArrayObject *) PyArray_SimpleNew(2, dim, NPY_DOUBLE), 30 | *Gerr = (PyArrayObject *) PyArray_SimpleNew(2, dim, NPY_DOUBLE); 31 | Py_INCREF(Gtau); Py_INCREF(Gerr); 32 | double *buf = (double *)PyArray_DATA(Gtau), 33 | *buf_err = (double *)PyArray_DATA(Gerr); 34 | 35 | for (int j=0; j 0) { 60 | int Nlist = PyList_Size(obs_str_list); 61 | for (int i = 0; i < Nlist; ++i) { 62 | alps::RealVectorObsevaluator o = sim.get_measurements()[PyString_AsString(PyList_GetItem(obs_str_list, i))]; 63 | npy_intp o_size = o.mean().size(); 64 | PyArrayObject *tmp = (PyArrayObject *) PyArray_SimpleNew(1, &o_size, NPY_DOUBLE); 65 | double *buffer = (double *)PyArray_DATA(tmp); 66 | for (int j = 0; j < o_size; ++j) 67 | buffer[j] = o.mean()[j]; 68 | PyDict_SetItem(obs, PyList_GetItem(obs_str_list, i), PyArray_Return(tmp)); 69 | Py_DECREF(tmp); 70 | } 71 | } 72 | PyObject *t = PyTuple_New(3); 73 | PyTuple_SetItem(t, 0, PyArray_Return(Gtau)); 74 | PyTuple_SetItem(t, 1, PyArray_Return(Gerr)); 75 | PyTuple_SetItem(t, 2, obs); 76 | return t; 77 | } 78 | -------------------------------------------------------------------------------- /include/eigen_integrate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Eigen wrapper for integrate 3 | * need eigen3 (see http://eigen.tuxfamily.org) 4 | * 5 | * Hung Dang (Oct 29, 2013) 6 | */ 7 | 8 | #ifndef __EIGEN_INTEGRATE_H__ 9 | #define __EIGEN_INTEGRATE_H__ 10 | 11 | #include 12 | #include 13 | 14 | namespace md_int { 15 | 16 | template class GeneralIntegrand { 17 | public: 18 | typedef Eigen::Matrix ReturnVectorType; 19 | GeneralIntegrand() : dim_in_(0), dim_out_(0) {} 20 | 21 | int dim_out() const { return dim_out_; } 22 | int dim_in() const { return dim_in_; } 23 | 24 | void CalculateTransformedIntegrand(const Eigen::VectorXd &x, ReturnVectorType &y) const { 25 | Eigen::VectorXd x_original = this->XTransformation(x); 26 | ReturnType jacobian = this->GetJacobian(x); 27 | this->CalculateOriginalIntegrand(x_original, y); 28 | y *= jacobian; 29 | } 30 | 31 | void WrapperTransformedIntegrand(const double *x, ReturnType* y) const { 32 | Eigen::Map xx((double *)x, dim_in_); 33 | Eigen::Map yy(y, dim_out_); 34 | CalculateTransformedIntegrand((Eigen::VectorXd &)xx, (Eigen::Matrix &)yy); 35 | } 36 | 37 | virtual void CalculateOriginalIntegrand(const Eigen::VectorXd &x, ReturnVectorType &y) const = 0; 38 | ReturnType* operator()(const double *x) const { 39 | ReturnType* y = new ReturnType[dim_out]; 40 | WrapperTransformedIntegrand(x, y); 41 | return y; 42 | } 43 | 44 | ReturnVectorType operator()(const Eigen::VectorXd &x) const { 45 | ReturnVectorType y; 46 | CalculateTransformedIntegrand(x, y); 47 | return y; 48 | } 49 | 50 | protected: 51 | void set_dim_in(const int d_in) { dim_in_ = d_in; } 52 | void set_dim_out(const int d_out) { dim_out_ = d_out; } 53 | virtual ReturnType GetJacobian(const Eigen::VectorXd &x) const { return 1.; } 54 | virtual Eigen::VectorXd XTransformation(const Eigen::VectorXd &x) const { return x; } 55 | 56 | private: 57 | int dim_in_, dim_out_; 58 | }; 59 | 60 | 61 | template void IntegrandWrapper(const int &n_in, const double *in, 62 | const int &n_out, ReturnType *out, const void *data) { 63 | GeneralIntegrand *my_integrand = (GeneralIntegrand *)data; 64 | if (n_out != my_integrand->dim_out()) 65 | throw "Output size not matched."; 66 | if (n_in != my_integrand->dim_in()) 67 | throw "Input size not matched."; 68 | my_integrand->WrapperTransformedIntegrand(in, out); 69 | } 70 | 71 | template Eigen::Matrix Integrate( 72 | const Eigen::VectorXd &xl, const Eigen::VectorXd &xh, const GeneralIntegrand &my_integrand, 73 | const Eigen::VectorXd &bp, const Eigen::VectorXd &wf) { 74 | int n_in = my_integrand.dim_in(), 75 | n_out = my_integrand.dim_out(), 76 | n_gauss = bp.size(); 77 | if (n_in > xl.size() || xl.size() != xh.size()) 78 | throw "Variable dim not consistent"; 79 | ReturnType *ret_ptr = integrate(n_in, n_out, xl.data(), xh.data(), 80 | n_gauss, bp.data(), wf.data(), &IntegrandWrapper, (void *)&my_integrand); 81 | return Eigen::Map >(ret_ptr, n_out); 82 | } 83 | 84 | } // namespace md_int 85 | #endif 86 | -------------------------------------------------------------------------------- /rotation_matrix.py: -------------------------------------------------------------------------------- 1 | from numpy import *; 2 | 3 | def generate_transform_mat(mat_file, L=[2]): 4 | tmp = genfromtxt(mat_file); 5 | ncell = len(tmp) / 3; 6 | ret = {}; 7 | for l in L: 8 | ret[l] = []; 9 | for c in range(ncell): 10 | R = tmp[3*c:3*(c+1),:]; 11 | ret[l].append(mat(rot_Ylm(l, R))); 12 | return ret; 13 | 14 | def rot_mat(p): 15 | x1 = p[1] - p[0]; 16 | y1 = p[2] - p[0]; 17 | z1 = p[3] - p[0]; 18 | x1 /= linalg.norm(x1); y1 /= linalg.norm(y1); z1 /= linalg.norm(z1); 19 | 20 | Rorig = array([x1,y1,z1]) 21 | 22 | z1 = cross(x1,y1); x1 = cross(y1,z1); 23 | R = array([x1, y1, z1]); 24 | return Rorig, R; 25 | 26 | def get_Euler_angles(R): 27 | # get Euler angle: b, a, g 28 | b = arccos(R[2,2]); 29 | if sin(b) > 1e-10: 30 | cosa = R[2,0]/sin(b); 31 | cosg = -R[0,2]/sin(b); 32 | if abs(abs(cosa) - 1) < 1e-4: cosa = cosa/abs(cosa); 33 | if abs(abs(cosg) - 1) < 1e-4: cosg = cosg/abs(cosg); 34 | a = arccos(cosa) if R[2,1] >= 0 else 2*pi-arccos(cosa); 35 | g = arccos(cosg) if R[1,2] >= 0 else 2*pi-arccos(cosg); 36 | else: 37 | if R[0,1] >= 0: a = g = arccos(R[0,0])/2; 38 | if R[0,1] < 0 : a = g = (pi - arccos(R[0,0]))/2; 39 | return (a, b, g); 40 | 41 | def rot_mat_Euler(a, b, g): 42 | mat = array([ 43 | [cos(a)*cos(b)*cos(g)-sin(a)*sin(g), cos(a)*sin(g)+sin(a)*cos(b)*cos(g), -sin(b)*cos(g)], 44 | [-cos(a)*cos(b)*sin(g)-sin(a)*cos(g), cos(a)*cos(g)-sin(a)*cos(b)*sin(g), sin(b)*sin(g)], 45 | [cos(a)*sin(b), sin(a)*sin(b), cos(b)]]); 46 | return mat; 47 | 48 | def dY(l, m1, m, b): 49 | binom = lambda a,b: math.factorial(a) / float(math.factorial(a-b)*math.factorial(b)); 50 | ret = 0.; 51 | for k in range(max(0, m-m1), min(l-m1, l+m)+1): ret += (-1)**k * binom(l+m, k) * binom(l-m, l-m1-k) * cos(b/2)**(2*l-m1+m-2*k) * sin(b/2)**(2*k-m+m1); 52 | ret *= sqrt(math.factorial(l+m1) * math.factorial(l-m1) / float(math.factorial(l+m) * math.factorial(l-m))) * (-1)**(m1-m); 53 | return ret; 54 | 55 | def rot_Ylm(l, R): 56 | (a, b, g) = get_Euler_angles(R); 57 | # print "Euler angles: a = %.4f, b = %.4f, g = %.4f"%(a,b,g); 58 | 59 | U = zeros((2*l+1, 2*l+1)); 60 | 61 | # ylm1 = yl0 + yl1+ + yl1- + ... 62 | # Yl0 63 | u = zeros(2*l+1); 64 | u[0] = dY(l,0,0,b); 65 | for m1 in range(1, l+1): 66 | u[2*m1-1] = 1/sqrt(2)*((-1)**m1*dY(l, m1, 0, b) + dY(l, -m1, 0, b))*cos(m1*a); 67 | u[2*m1] = 1/sqrt(2)*((-1)**m1*dY(l, m1, 0, b) + dY(l, -m1, 0, b))*sin(m1*a); 68 | U[0,:] = u; 69 | 70 | # Ylm for m > 0 71 | for m in range(1, l+1): 72 | u = zeros(2*l+1); 73 | u[0] = (-1)**m * dY(l, 0, m, b) * cos(m*g) * sqrt(2); 74 | for m1 in range(1, l+1): 75 | u[2*m1-1] = (-1)**(m+m1)*dY(l,m1,m,b)*cos(m*g+m1*a) + (-1)**m*dY(l,-m1,m,b)*cos(m*g-m1*a); 76 | u[2*m1] = (-1)**(m+m1)*dY(l,m1,m,b)*sin(m*g+m1*a) - (-1)**m*dY(l,-m1,m,b)*sin(m*g-m1*a); 77 | U[2*m-1,:] = u; 78 | 79 | u[0] = (-1)**(m+1) * dY(l, 0, m, b) * sin(m*g) * sqrt(2); 80 | for m1 in range(1, l+1): 81 | u[2*m1-1] = (-1)**(m+m1+1)*dY(l,m1,m,b)*sin(m*g+m1*a) + (-1)**(m+1)*dY(l,-m1,m,b)*sin(m*g-m1*a); 82 | u[2*m1] = (-1)**(m+m1)*dY(l,m1,m,b)*cos(m*g+m1*a) - (-1)**m*dY(l,-m1,m,b)*cos(m*g-m1*a); 83 | U[2*m,:] = u; 84 | return mat(U); 85 | 86 | -------------------------------------------------------------------------------- /calculate_DOS.py: -------------------------------------------------------------------------------- 1 | import sys, os, argparse 2 | from share_fun import load_parms, val_def, grule, readParameters; 3 | from numpy import *; 4 | from init import getHamiltonian, getRotationMatrix; 5 | from average_green import integrate, averageGreen; 6 | from functions import *; 7 | 8 | # This is different from calculate_spectra.py 9 | # no need hdf5 file 10 | # calculate directly from rham.py 11 | # can provide self energy data separately 12 | 13 | 14 | def getGavgFromSelfEnergy(parms, se_filename = None): 15 | N_LAYERS = int(parms['N_LAYERS']); 16 | FLAVORS = int(parms['FLAVORS']); 17 | SPINS = int(parms['SPINS']); 18 | parms['BETA'] = 10; 19 | 20 | # prepare data 21 | NMaxFreq = int(parms['N_MAX_FREQ']); 22 | if se_filename is not None: 23 | print 'load self energy from file: ', se_filename; 24 | tmp = genfromtxt(se_filename); 25 | if NMaxFreq > len(tmp): NMaxFreq = len(tmp); 26 | w = tmp[:,0] + 1j*float(parms['BROADENING']); 27 | tmp = tmp[:, 1:]; 28 | tmp = tmp[:NMaxFreq, 0::2] + 1j*tmp[:NMaxFreq, 1::2]; 29 | se = zeros((SPINS, NMaxFreq, N_LAYERS*FLAVORS), dtype = complex); 30 | for s in range(SPINS): 31 | for f in range(N_LAYERS*FLAVORS): 32 | se[s, :, f] = tmp[:, SPINS*f+s]; 33 | else: 34 | se = zeros((SPINS, NMaxFreq, N_LAYERS*FLAVORS), dtype = complex); 35 | w = linspace(float(parms['EMIN']), float(parms['EMAX']), NMaxFreq) + 1j*float(parms['BROADENING']); 36 | 37 | # tight binding Hamiltonian 38 | HR, R = getHamiltonian(parms['RHAM'], 4); 39 | parms['NORB'] = len(HR[0]) 40 | extra = { 'HR' : HR, 'R': R }; 41 | if int(val_def(parms, 'FORCE_DIAGONAL', 0)) > 0: 42 | print 'FORCE_DIAGONAL is used'; 43 | ind = nonzero(sum(R**2, 1)==0)[0][0]; 44 | H0 = HR[ind]; 45 | else: H0 = None; 46 | rot_mat = getRotationMatrix(N_LAYERS, FLAVORS, val_def(parms, 'ROT_MAT', None), H0); 47 | 48 | # prepare for k-integrate 49 | bp, wf = grule(int(parms['NUMK'])); 50 | extra.update({ 51 | 'GaussianData' : [bp, wf], 52 | 'rot_mat' : rot_mat 53 | }); 54 | delta = float(parms['DELTA']); 55 | mu = float(parms['MU']); 56 | 57 | # running 58 | Gavg = averageGreen(delta, mu, w, se, parms, -1, -1, 0, extra)[1]; 59 | # swap the Gavg to the format of my code 60 | # swap_vec = zeros((2, N_LAYERS*FLAVORS), dtype = int); 61 | # for L in range(N_LAYERS): 62 | # for f in range(FLAVORS): swap_vec[:,f*N_LAYERS+L] = array([f*N_LAYERS+L, L*FLAVORS+f]); 63 | # for s in range(SPINS): Gavg[s, :, swap_vec[1]] = Gavg[s, :, swap_vec[0]]; 64 | 65 | spec = -1/pi * Gavg.imag; 66 | if SPINS == 1: savetxt('spec.dat', c_[w.real, spec[0]]); 67 | elif SPINS > 1: 68 | savetxt('spec_up.dat', c_[w.real, spec[0]]); 69 | savetxt('spec_dn.dat', c_[w.real, spec[1]]); 70 | 71 | 72 | if __name__ == '__main__': 73 | parser = argparse.ArgumentParser(description='DMFT process.'); 74 | parser.add_argument('-p', dest='parmsfile', type = str, required = True, help='Parameter file'); 75 | parser.add_argument('-se', dest='sefilename', type = str, default = None, help='Matsubara frequency self energy'); 76 | args = parser.parse_args(sys.argv[1:]); 77 | 78 | set_printoptions(linewidth=150, suppress=True, precision=4); 79 | parms = readParameters(args.parmsfile); 80 | 81 | getGavgFromSelfEnergy(parms, args.sefilename); 82 | 83 | -------------------------------------------------------------------------------- /integrate_dft_mlwf/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "integrand.h" 7 | 8 | using namespace Eigen; 9 | 10 | template 11 | void convert3dArray(PyObject *pyArr, std::vector > &out) 12 | { 13 | import_array(); 14 | if (PyArray_NDIM(pyArr)!=3) throw "dim != 3"; 15 | 16 | PyArrayObject *arr = reinterpret_cast(pyArr); 17 | npy_intp *sz = arr->dimensions; 18 | npy_intp strides[3]; 19 | int elsize = (PyArray_DESCR(pyArr))->elsize; 20 | 21 | for (int i = 0; i < 3; ++i) strides[i] = PyArray_STRIDE(arr, i)/(PyArray_DESCR(arr))->elsize; 22 | out.resize(sz[0]); 23 | T *source = (T *)PyArray_DATA(arr); 24 | for (int i=0; i 0) omp_set_num_threads(nthreads); 36 | VectorXd xl(kDim), xh(kDim); 37 | xl << -M_PI, -M_PI, -M_PI; 38 | xh << M_PI, M_PI, M_PI; 39 | double BZ1 = (xh - xl).prod(); 40 | std::vector HR; 41 | MatrixXcd SE; 42 | MatrixXi R; 43 | VectorXcd w; 44 | VectorXd bp, wf; 45 | 46 | convert3dArray(pyHR, HR); 47 | numpy::from_numpy(pySE, SE); 48 | numpy::from_numpy(pyR, R); 49 | numpy::from_numpy(py_bp, bp); 50 | numpy::from_numpy(py_wf, wf); 51 | numpy::from_numpy(pyw, w); 52 | 53 | assert(w.size() == SE.rows()); 54 | 55 | MatrixXcd result(SE.rows(), kMSize*kMSize); 56 | GreenIntegrand green_integrand(w, mu, HR, R, SE, Hf, delta); 57 | for (int i = 0; i < w.size(); ++i) { 58 | green_integrand.set_data(i); 59 | result.row(i) = md_int::Integrate(xl, xh, green_integrand, bp, wf); 60 | } 61 | result /= BZ1; 62 | return numpy::to_numpy(result); 63 | } catch (const char *str) { 64 | std::cerr << str << std::endl; 65 | return Py_None; 66 | } 67 | } 68 | 69 | PyObject* CalculateHavg(const int &Norder, PyObject *pyHR, PyObject *pyR, const double &Hf, const double &delta, PyObject *py_bp, PyObject *py_wf) 70 | { 71 | try { 72 | VectorXd xl(kDim), xh(kDim); 73 | xl << -M_PI, -M_PI, -M_PI; 74 | xh << M_PI, M_PI, M_PI; 75 | double BZ1 = (xh - xl).prod(); 76 | std::vector HR; 77 | MatrixXi R; 78 | VectorXd bp, wf; 79 | 80 | convert3dArray(pyHR, HR); 81 | numpy::from_numpy(pyR, R); 82 | numpy::from_numpy(py_bp, bp); 83 | numpy::from_numpy(py_wf, wf); 84 | 85 | HamiltonianIntegrand h_integrand(Norder, HR, R, Hf, delta); 86 | VectorXcd result = (md_int::Integrate(xl, xh, h_integrand, bp, wf)); 87 | result /= BZ1; 88 | return numpy::to_numpy(result); 89 | } catch (const char *str) { 90 | std::cerr << str << std::endl; 91 | return Py_None; 92 | } 93 | } 94 | 95 | BOOST_PYTHON_MODULE(int_donly_tilted_3bands) 96 | { 97 | using namespace boost::python; 98 | def("calc_Gavg", CalculateGavg); 99 | def("calc_Havg", CalculateHavg); 100 | } 101 | -------------------------------------------------------------------------------- /examples/LaTiO3_tilted_t2g_only/parms: -------------------------------------------------------------------------------- 1 | ID = u4.3j0.65b10; # The name of the calculation, arbitrary 2 | 3 | BETA = 10; # Inverse temperature 4 | U = 4.3; # Hubbard U values 5 | J = 0.65; # Hund's coupling J (note that U and J are in Kanamori's notation, U, U-2J, U-3J) 6 | DENSITY = 1; # Define the total d occupancy per correlated atom, in this case LaTiO3, it is d^1 -> DENSITY=1 7 | RHAM = lto_rham.py; # The file for the tight binding Hamiltonian obtained from DFT+MLWF 8 | INTEGRATE_MOD = int_donly_tilted_3bands; # The module for k-integral, which can be different for different models 9 | # in this case, it is for the frontier band 3-t2g-orbital model 10 | N_LAYERS = 4; # Corresponding to the number of times the impurity solver is run 11 | # depending on the problems, it can the number of layers in the heterostructure 12 | # or number of correlated atoms in a unit cell 13 | # in this example for LaTiO3, it is the number of Ti atoms in a unit cell 14 | # (recall that LTO has Pnma structure with 4ABO3 in a unit cell) 15 | 16 | DTYPE = 3bands; # Used extensively in "system_dependence.py", it defines which kind of correlated model 17 | # eg: for systems where eg bands at the Fermi level such as NiO, LaNiO3 or cuprates 18 | # t2g: for systems where t2g bands at the Fermi level such as LaTiO3, LaVO3... 19 | 20 | SWEEPS = 200000000; # Number of Monte Carlo updates 21 | N_TAU = 10000; # Number of imaginary time slices 22 | MAX_FREQ = 500; # Max value of w_n considered in k-integral 23 | MAX_ITER = 15; # Max number of DMFT iterations 24 | MIXING = 1; # Mixing values (there are some special types of mixing used if MIXING > 1, but I found it is not so useful 25 | # a linear mixing (MIXING in 0->1) would be good enough 26 | 27 | DATA_FILE = data.h5; # The HDF5 file contains all data produced by the code 28 | 29 | HARTREE_INIT = 1; # Trigger the Hartree calculation for initial input self energy 30 | # the result is averaged over all spins and orbitals to avoid bias in DMFT 31 | # this is useful for model with p and d orbitals (where p orbitals is uncorrelated) 32 | # so as to fixed the relative positions between two bands 33 | NUMK = 26; # Number of k-points for the k-integral in one direction, thus for 3D case, it is NUMK^3 34 | USE_LAYER_SYMMETRY = 1; # To exploit the symmetry if exists between correlated atoms (GdFeO3-distorted structure) or layers in heterostructure 35 | # the symmetry is defined in "system_dependence.py" 36 | FORCE_DIAGONAL = 1; # This option is for obtaining the rotation basis of the octahedron 37 | # to minimize off-diagonal terms of the input hybridization function for the impurity solver 38 | PARAMAGNET = 1; # Restrict to paramagnetic calculation 39 | 40 | SOLVER_TYPE = TRIQS; # Choose the type of solver (see file "solver_types.py" for details) 41 | -------------------------------------------------------------------------------- /calculate_green.py: -------------------------------------------------------------------------------- 1 | import sys, os, argparse 2 | from share_fun import load_parms, val_def, grule, readParameters; 3 | from numpy import *; 4 | from init import getHamiltonian, getRotationMatrix; 5 | from average_green import integrate; 6 | from functions import *; 7 | 8 | # This is different from calculate_spectra.py 9 | # no need hdf5 file 10 | # calculate directly from rham.py 11 | # can provide self energy data separately 12 | 13 | 14 | def getGavgFromSelfEnergy(parms, se_filename = None): 15 | N_LAYERS = int(parms['N_LAYERS']) 16 | FLAVORS = int(parms['FLAVORS']) 17 | SPINS = int(parms['SPINS']) 18 | beta = float(parms['BETA']) 19 | 20 | # prepare data 21 | NMaxFreq = int(round((beta*float(parms['MAX_FREQ'])/pi - 1)/2.)) 22 | iwn = 1j * (2*arange(NMaxFreq)+1)*pi/beta 23 | if se_filename is not None: 24 | print 'load self energy from file: ', se_filename; 25 | tmp = genfromtxt(se_filename); 26 | if NMaxFreq > len(tmp): NMaxFreq = len(tmp); 27 | tmp = tmp[:, 1:] 28 | tmp = tmp[:NMaxFreq, 0::2] + 1j*tmp[:NMaxFreq, 1::2] 29 | se = zeros((SPINS, NMaxFreq, N_LAYERS*FLAVORS), dtype = complex) 30 | for s in range(SPINS): 31 | for f in range(N_LAYERS*FLAVORS): 32 | se[s, :, f] = tmp[:NMaxFreq, SPINS*f+s] 33 | else: 34 | se = zeros((SPINS, NMaxFreq, N_LAYERS*FLAVORS), dtype = complex) 35 | 36 | 37 | # tight binding Hamiltonian 38 | HR, R = getHamiltonian(parms['RHAM'], 4); 39 | parms['NORB'] = len(HR[0]) 40 | extra = { 'HR' : HR, 'R': R }; 41 | if int(val_def(parms, 'FORCE_DIAGONAL', 0)) > 0: 42 | print 'FORCE_DIAGONAL is used'; 43 | ind = nonzero(sum(R**2, 1)==0)[0][0]; 44 | H0 = HR[ind]; 45 | else: H0 = None; 46 | rot_mat = getRotationMatrix(N_LAYERS, FLAVORS, val_def(parms, 'ROT_MAT', None), H0); 47 | 48 | # prepare for k-integrate 49 | bp, wf = grule(int(parms['NUMK'])); 50 | extra.update({ 51 | 'GaussianData' : [bp, wf], 52 | 'rot_mat' : rot_mat 53 | }); 54 | delta = float(parms['DELTA']); 55 | mu = float(parms['MU']); 56 | 57 | # running 58 | SelfEnergy_rot = array([irotate(se[s], rot_mat) for s in range(SPINS)]) 59 | SE = array([array([s.flatten() for s in SelfEnergy_rot[n]]) for n in range(SPINS)]) 60 | Gavg = integrate(iwn, delta, mu, SE, parms, extra, parallel = False) 61 | g = array([rotate_green(Gavg, rot_mat, layer=L) for L in range(N_LAYERS)]) 62 | 63 | return iwn, g 64 | 65 | def rotate_green(g, rot_mat, layer=0): 66 | nlayers = len(rot_mat) 67 | nspins = size(g, 0) 68 | nfreq = size(g, 1) 69 | nflavors = size(g, 2) / nlayers 70 | 71 | out = zeros((nspins, nfreq, nflavors, nflavors), dtype = g.dtype) 72 | rot = matrix(rot_mat[layer]) 73 | rot_inv = matrix(linalg.inv(rot)) 74 | for s in range(nspins): 75 | for n in range(nfreq): 76 | mat = matrix(g[s, n, layer::nlayers, layer::nlayers]) 77 | out[s, n] = rot * mat * rot_inv 78 | return out 79 | 80 | def get_density_matrix(beta, g): 81 | nspins = size(g, 0) 82 | nfreq = size(g, 1) 83 | nflavors = size(g, 2) 84 | 85 | density = zeros((nspins, nflavors, nflavors)) 86 | for s in range(nspins): 87 | density[s] = 2./beta*real(sum(g[s], 0)) + 0.5*eye(nflavors) 88 | return density 89 | 90 | 91 | if __name__ == '__main__': 92 | parser = argparse.ArgumentParser(description='DMFT process.'); 93 | parser.add_argument('-p', dest='parmsfile', type = str, required = True, help='Parameter file'); 94 | parser.add_argument('-se', dest='sefilename', type = str, default = None, help='Matsubara frequency self energy'); 95 | args = parser.parse_args(sys.argv[1:]); 96 | 97 | set_printoptions(linewidth=150, suppress=True, precision=4); 98 | parms = readParameters(args.parmsfile); 99 | 100 | beta = float(parms['BETA']) 101 | iwn, g = getGavgFromSelfEnergy(parms, args.sefilename); 102 | density = [] 103 | for ll in range(len(g)): 104 | density.append(get_density_matrix(beta, g[ll]).flatten()) 105 | savetxt('density.dat', density) 106 | 107 | 108 | -------------------------------------------------------------------------------- /system_dependence.py: -------------------------------------------------------------------------------- 1 | from numpy import *; 2 | import functions as fun; 3 | import share_fun; 4 | 5 | 6 | def getAvgDispersion(parms, NthOrder_in, extra): 7 | int_module = __import__(share_fun.val_def(parms, 'INTEGRATE_MOD', 'integrate'), fromlist=[]); 8 | NthOrder = 3; 9 | rot_mat = extra['rot_mat']; 10 | NORB = int(parms['NORB']); N = int(parms['N_LAYERS']); F = int(parms['FLAVORS']); S = int(parms['SPINS']); 11 | bp,wf = extra['GaussianData']; 12 | if 'HR' in extra: 13 | out = array([int_module.calc_Havg(NthOrder, extra['HR'], extra['R'], 14 | float(share_fun.val_def(parms, 'H', 0))*(-1)**s, float(parms['DELTA']), bp, wf).reshape(NthOrder, NORB, NORB) for s in range(S)]); 15 | else: 16 | out = array([int_module.calc_Havg(NthOrder, extra['tight_binding_parms'], 17 | float(share_fun.val_def(parms, 'H', 0))*(-1)**s, float(parms['DELTA']), bp, wf).reshape(NthOrder, NORB, NORB) for s in range(S)]); 18 | ret = zeros((NthOrder, NORB)); 19 | 20 | rret = zeros((S, NthOrder, NORB)); 21 | for s in range(S): 22 | for n in range(NthOrder): 23 | for L in range(N): 24 | tmp = mat(out[s, n, L*F:(L+1)*F, L*F:(L+1)*F]); 25 | dtmp = diag(rot_mat[L]*tmp*rot_mat[L].H); 26 | if linalg.norm(dtmp.imag) > 1e-10: print 'getAvgDispersion: imaginary part is rather large: %g'%linalg.norm(dtmp.imag); 27 | ret[n, L*F:(L+1)*F] = dtmp.real; 28 | swap_vec = zeros((2, N*F), dtype = int); 29 | for L in range(N): 30 | for f in range(F): swap_vec[:,f*N+L] = array([f*N+L, L*F+f]); 31 | ret[:, swap_vec[0]] = ret[:, swap_vec[1]]; 32 | rret[s] = ret; 33 | 34 | # avg dispersion of uncorrelated orbitals (no need for matrix rotation) 35 | for s in range(S): 36 | for n in range(NthOrder): 37 | for f in range(N*F,NORB): rret[s, n, f] = out[s, n, f, f]; 38 | return rret[:, :NthOrder_in, :]; 39 | 40 | 41 | def calc_sym_layers(parms): 42 | return array([ 43 | [0, 1], 44 | [0, 2], 45 | [0, 3]]); 46 | 47 | 48 | def getCorrIndex(parms): 49 | return arange(int(parms['N_LAYERS'])*int(parms['FLAVORS'])); 50 | 51 | def getDMFTCorrIndex(parms, all = True): 52 | N_LAYERS = int(parms['N_LAYERS']); FLAVORS = int(parms['FLAVORS']); 53 | DTYPE = parms['DTYPE']; 54 | if DTYPE == 'eg': ind = array([0, 3]); 55 | elif DTYPE == 't2g': ind = array([1, 2, 4]); 56 | elif DTYPE == 'd' : ind = array([0, 1, 2, 3, 4]); 57 | elif DTYPE == '3bands' : ind = array([0, 1, 2]); 58 | else: 59 | if 'CORR_ID' in parms: ind = array([int(s) for s in parms['CORR_ID'].split()]); 60 | else: ind = arange(FLAVORS); 61 | if not all: return ind; 62 | 63 | ret = zeros(N_LAYERS*len(ind), dtype = int); 64 | for L in range(N_LAYERS): 65 | for n, f in enumerate(ind): ret[n*N_LAYERS+L] = f*N_LAYERS+L; 66 | return ret; 67 | 68 | 69 | def getInfoForDensityCalculation(h5, it): 70 | p = share_fun.load_parms(h5, it); 71 | corr_id = getCorrIndex(p); 72 | dmft_id = getDMFTCorrIndex(p); 73 | N_LAYERS = int(p['N_LAYERS']); FLAVORS = int(p['FLAVORS']); SPINS = int(p['SPINS']); 74 | NORB = int(p['NORB']); NCOR = int(p['NCOR']); 75 | se = h5['SolverData/selfenergy_asymp_coeffs'][:]; 76 | se = se[se[:,0] == it][0, 1:].reshape(SPINS,2,-1); 77 | mu = float(p['MU']); 78 | Gcoefs = h5['SolverData/AvgDispersion'][:, 0, :] - mu; 79 | Gcoefs[:, corr_id] += se[:, 0, :]; 80 | ret = dict({ 81 | 'G_asymp_coefs' : Gcoefs, 82 | 'correction' : zeros(SPINS) 83 | }); 84 | ret1 = dict({ 85 | 'G_asymp_coefs' : Gcoefs[:,corr_id], 86 | 'correction' : zeros(SPINS) 87 | }); 88 | 89 | if float(p['U']) != 0 and it > 0: 90 | approx_dens = fun.getDensityFromGmat(h5['ImpurityGreen/'+str(it)][:], float(p['BETA']), ret1); 91 | try: correct_dens = -h5['SolverData/Gtau/%d'%it][:, -1, :]; 92 | except: correct_dens = None; 93 | if correct_dens is None: d = 0; 94 | else: 95 | d = zeros((SPINS, NCOR)); 96 | for L in range(N_LAYERS): d[:, dmft_id] = correct_dens[:, dmft_id] - approx_dens[:, dmft_id]; 97 | else: d = 0; 98 | ret['correction'] = zeros((SPINS, NORB)); 99 | # ret['correction'][:, corr_id] = d; # correction not needed 100 | return ret; 101 | 102 | -------------------------------------------------------------------------------- /triqs_interface_old.py: -------------------------------------------------------------------------------- 1 | from pytriqs.archive import HDFArchive 2 | from pytriqs.gf.local import * 3 | from pytriqs.operators import * 4 | from pytriqs.applications.impurity_solvers.cthyb_matrix import Solver 5 | import pytriqs.utility.mpi as mpi 6 | 7 | import sys, os, time 8 | from share_fun import val_def, readParameters; 9 | from numpy import *; 10 | 11 | 12 | # 13 | # Interface for TRIQS solver 14 | # Caution: works for diagonal Weiss field only 15 | # 16 | 17 | 18 | # input data 19 | parms = readParameters(sys.argv[1]); 20 | NCOR = int(parms['NCOR']); 21 | SPINS = 2; spins = ('up', 'dn'); 22 | BETA = float(parms['BETA']); 23 | hyb_mat = genfromtxt(parms['HYB_MAT']+'.real')[:,1:] + 1j*genfromtxt(parms['HYB_MAT']+'.imag')[:,1:]; 24 | hyb_coefs = genfromtxt(parms['HYB_MAT']+'.tail'); 25 | MUvector = genfromtxt(parms['MU_VECTOR']); 26 | 27 | solver_parms = { 28 | 'n_cycles' : int(parms['SWEEPS_EACH_NODE']), 29 | 'length_cycle' : int(parms['N_MEAS']), 30 | 'n_warmup_cycles' : int(parms['THERMALIZATION']), 31 | 'random_seed' : int(1e6*time.time()*(mpi.rank+1) % 1e6) 32 | }; 33 | 34 | 35 | # prepare Green function structure, local H and quantum numbers 36 | # Slater-Kanamori style 37 | Umat = genfromtxt(parms['U_MATRIX']); 38 | GFstruct = [ ('%s%d'%(s,f), [0]) for f in range(NCOR) for s in spins ]; 39 | H_Local = None; 40 | for n in range(SPINS*NCOR): 41 | s = n % SPINS; f = n / SPINS; 42 | for n1 in range(n+1, SPINS*NCOR): 43 | s1 = n1 % SPINS; f1 = n1 / SPINS; 44 | tmp = Umat[n, n1] * N('%s%d'%(spins[s],f),0) * N('%s%d'%(spins[s1],f1), 0); 45 | if H_Local is None: H_Local = tmp; 46 | else: H_Local += tmp; 47 | 48 | 49 | # exchange and pair hopping terms 50 | if int(parms['SPINFLIP']) > 0: 51 | Jmat = Umat[::2,1::2] - Umat[::2,::2]; 52 | for f1 in range(NCOR): 53 | for f2 in range(NCOR): 54 | if f1 == f2: continue; 55 | u1 = '%s%d'%(spins[0],f1); 56 | u2 = '%s%d'%(spins[0],f2); 57 | d1 = '%s%d'%(spins[1],f1); 58 | d2 = '%s%d'%(spins[1],f2); 59 | H_Local += Jmat[f1,f2]*Cdag(u1,0)*C(u2,0)*Cdag(d2,0)*C(d1,0) + Jmat[f1,f2]*Cdag(u1,0)*C(u2,0)*Cdag(d1,0)*C(d2,0); 60 | Ntot = sum( [ N('%s%d'%(s,f),0) for s in spins for f in range(NCOR) ]); 61 | Sz = sum( [ N('%s%d'%(spins[0],f),0) - N('%s%d'%(spins[1],f),0) for f in range(NCOR) ]); 62 | Quantum_Numbers = { 'Ntot' : Ntot, 'Sztot' : Sz }; 63 | for f in range(NCOR): 64 | Quantum_Numbers['Sz2_%d'%f] = N('%s%d'%(spins[0],f),0) + N('%s%d'%(spins[1],f),0) - 2*N('%s%d'%(spins[0],f),0)*N('%s%d'%(spins[1],f),0) 65 | else: 66 | Quantum_Numbers = {}; 67 | for sp in spins: 68 | for f in range(NCOR): Quantum_Numbers['N%s%d'%(sp,f)] = N('%s%d'%(sp,f),0); 69 | solver_parms['quantum_numbers'] = Quantum_Numbers; 70 | solver_parms['use_segment_picture'] = int(parms['SPINFLIP']) == 0; 71 | solver_parms['H_local'] = H_Local; 72 | 73 | 74 | # create a solver object 75 | solver = Solver(beta = BETA, gf_struct = GFstruct, n_w = int(val_def(parms, 'N_MATSUBARA', len(hyb_mat)))); 76 | 77 | 78 | # Legendre or Time accumulation 79 | accumulation = val_def(parms, 'ACCUMULATION', 'time'); 80 | if accumulation not in ['time', 'legendre']: exit('ACCUMULATION should be either "time" or "legendre"'); 81 | if accumulation == 'time': 82 | solver_parms['time_accumulation'] = True; 83 | solver_parms['legendre_accumulation'] = False; 84 | solver_parms['fit_start'] = len(hyb_mat)-10; 85 | solver_parms['fit_stop'] = len(hyb_mat)-1; # I don't want to use the fitTails() 86 | elif accumulation == 'legendre': 87 | solver_parms['legendre_accumulation'] = True; 88 | solver_parms['n_legendre'] = int(val_def(parms, 'N_LEGENDRE', 50)); 89 | 90 | 91 | # prepare input G0 from hybridization \Gamma 92 | if len(MUvector) == 1: MUvector = MUvector[0]*ones(SPINS*NCOR); 93 | assert len(MUvector) == SPINS*NCOR, 'Length of MUvector must be equal to #FLAVORS'; 94 | Delta = BlockGf(name_block_generator = solver.G0, make_copies = True, name = "Delta"); 95 | for s, sp in enumerate(spins): 96 | for f in range(NCOR): 97 | name = '%s%d'%(sp,f); 98 | Delta[name].data[:, 0, 0] = hyb_mat[:, 2*f+s]; 99 | for n in range(size(hyb_coefs, 0)): 100 | Delta[name].tail[n+1][0, 0] = hyb_coefs[n, 2*f+s]; 101 | MU = MUvector[2*f+s]; 102 | solver.G0[name] <<= inverse(iOmega_n + MU - Delta[name]); 103 | 104 | 105 | # operators for measurement 106 | Measured_Operators = {}; 107 | for sp in spins: 108 | for f in range(NCOR): 109 | Measured_Operators['N_%s%d'%(sp,f)] = N('%s%d'%(sp,f), 0); 110 | for n1 in range(SPINS*NCOR): 111 | for n2 in range(n1+1, SPINS*NCOR): 112 | f1 = n1 / SPINS; sp1 = spins[n1 % SPINS]; 113 | f2 = n2 / SPINS; sp2 = spins[n2 % SPINS]; 114 | Measured_Operators['nn_%d_%d'%(n2,n1)] = N('%s%d'%(sp1, f1), 0) * N('%s%d'%(sp2, f2), 0); 115 | solver_parms['measured_operators'] = Measured_Operators; 116 | 117 | solver_parms['measured_time_correlators'] = {} 118 | if int(val_def(parms, 'MEASURE', 0)) > 0: 119 | if 'Sztot' in Quantum_Numbers: 120 | solver_parms['measured_time_correlators'] = { 121 | 'Sztot' : [ Quantum_Numbers['Sztot'], 300 ] 122 | } 123 | 124 | 125 | # run solver 126 | solver.solve(**solver_parms); 127 | 128 | 129 | # save data 130 | NfileMax = 100; 131 | if mpi.is_master_node(): 132 | R = HDFArchive(parms['HDF5_OUTPUT'], 'w'); 133 | if accumulation == 'legendre': 134 | for s, gl in solver.G_legendre: solver.G[s] <<= LegendreToMatsubara(gl); 135 | R['G_Legendre'] = solver.G_legendre; 136 | Gl_out = None; 137 | for f in range(NCOR): 138 | for sp in spins: 139 | tmp = solver.G_legendre['%s%d'%(sp, f)]._data.array[0, 0, :]; 140 | Gl_out = tmp if Gl_out is None else c_[Gl_out, tmp]; 141 | for n in range(1,NfileMax): 142 | filename = 'Green_Legendre.%03d'%n; 143 | if not os.path.isfile(filename): break; 144 | savetxt(filename, c_[arange(len(Gl_out)), Gl_out]); 145 | 146 | solver.Sigma <<= solver.G0_inv - inverse(solver.G); 147 | R['G'] = solver.G; 148 | R['Sigma'] = solver.Sigma; 149 | R['Observables'] = solver.measured_operators_results; 150 | if len(solver_parms['measured_time_correlators']) > 0: 151 | R['TimeCorrelators'] = solver.measured_time_correlators_results 152 | 153 | 154 | -------------------------------------------------------------------------------- /triqs_interface.py: -------------------------------------------------------------------------------- 1 | import pytriqs.operators as triqs_ops 2 | import pytriqs.operators.util as triqs_ops_util 3 | import pytriqs.applications.impurity_solvers.cthyb_mod as triqs_solver 4 | import pytriqs.gf.local as triqs_gf 5 | 6 | from pytriqs.archive import HDFArchive 7 | import pytriqs.utility.mpi as mpi 8 | 9 | import os 10 | import sys 11 | import time 12 | from numpy import * 13 | 14 | from share_fun import readParameters 15 | 16 | 17 | def load_parms_from_file(filename): 18 | parms = readParameters(filename) 19 | for s in ('NSPINS', 'NFLAVORS', 'N_CUTOFF', 'N_MAX_FREQ', 'N_TAU', 20 | 'MEASURE', 21 | 'n_cycles', 'length_cycle', 'n_warmup_cycles', 'max_time'): 22 | if s in parms: parms[s] = int(parms[s]) 23 | for s in ('BETA', 'U', 'J'): 24 | if s in parms: parms[s] = float(parms[s]) 25 | return parms 26 | 27 | 28 | def assign_weiss_field(G0, parms, nspins, spin_names, nflavors, flavor_names): 29 | hyb_mat_prefix = parms.get('HYB_MAT', '%s.hybmat'%parms['PREFIX']) 30 | hyb_mat = genfromtxt('%s.real'%hyb_mat_prefix)[:,1:]\ 31 | + 1j*genfromtxt('%s.imag'%hyb_mat_prefix)[:,1:] 32 | hyb_tail = genfromtxt('%s.tail'%hyb_mat_prefix) 33 | mu_vec = genfromtxt(parms.get('MU_VECTOR', '%s.mu_eff'%parms['PREFIX'])) 34 | for s in range(nspins): 35 | for f in range(nflavors): 36 | hyb_w = triqs_gf.GfImFreq(indices=[0], beta=parms['BETA'], 37 | n_points=parms['N_MAX_FREQ']) 38 | hyb_w.data[:, 0, 0] = hyb_mat[:, nspins*f+s] 39 | for n in range(len(hyb_tail)): 40 | hyb_w.tail[n+1][0, 0] = hyb_tail[n, nspins*f+s] 41 | block, i = mkind(spin_names[s], flavor_names[f]) 42 | G0[block][i, i] << triqs_gf.inverse(triqs_gf.iOmega_n\ 43 | +mu_vec[nspins*f+s]-hyb_w) 44 | 45 | 46 | def get_interaction_hamiltonian(parms, spin_names, flavor_names, is_kanamori): 47 | U_int = parms['U'] 48 | J_hund = parms['J'] 49 | if is_kanamori: 50 | U, Uprime = triqs_ops_util.U_matrix_kanamori(parms['NFLAVORS'], 51 | U_int, J_hund) 52 | ham = triqs_ops_util.h_int_kanamori(spin_names, flavor_names, 53 | U, Uprime, J_hund, off_diag=False) 54 | else: # Slater-type interaction 55 | l_number = (parms['NFLAVORS']-1)/2 56 | U = triqs_ops_util.U_matrix(l=lnumber, U_int=U_int, J_hund=J_hund, 57 | basis='cubic') 58 | ham = triqs_ops_util.h_int_slater(spin_names, flavor_names, 59 | U, off_diag=False) 60 | return ham 61 | 62 | 63 | def get_quantum_numbers(parms, spin_names, flavor_names, is_kanamori): 64 | qn = [] 65 | for s in spin_names: 66 | tmp = triqs_ops.Operator() 67 | for o in flavor_names: 68 | tmp += triqs_ops.n(*mkind(s, o)) 69 | qn.append(tmp) 70 | if is_kanamori: 71 | for o in flavor_names: 72 | dn = triqs_ops.n(*mkind(spin_names[0], o))\ 73 | - triqs_ops.n(*mkind(spin_names[1],o)) 74 | qn.append(dn*dn) 75 | return qn 76 | 77 | 78 | def get_static_observables(parms, spin_names, flavor_names): 79 | ret = { 80 | 'N' : triqs_ops.Operator(), 81 | 'Sz' : triqs_ops.Operator(), 82 | } 83 | for sn, s in enumerate(spin_names): 84 | for o in flavor_names: 85 | sp = mkind(s, o) 86 | ret['N'] += triqs_ops.n(*sp) 87 | ret['Sz'] += (-1)**sn * triqs_ops.n(*sp) 88 | return ret 89 | 90 | 91 | if __name__ == '__main__': 92 | mkind = triqs_ops_util.get_mkind(off_diag=False, 93 | map_operator_structure=None) 94 | parms = load_parms_from_file(sys.argv[1]) 95 | if parms['INTERACTION'].upper() not in ('SLATER', 'KANAMORI'): 96 | raise ValueError('Key INTERACTION must be either "Slater" or "Kanamori"') 97 | is_kanamori = True if parms['INTERACTION'].upper() == 'KANAMORI'\ 98 | else False 99 | assert parms['NSPINS'] == 2 100 | nspins = parms['NSPINS'] 101 | spin_names = ('up', 'dn') 102 | nflavors = parms['NFLAVORS'] 103 | flavor_names = [str(i) for i in range(nflavors)] 104 | gf_struct = triqs_ops_util.set_operator_structure(spin_names, flavor_names, 105 | off_diag=False) 106 | 107 | solver = triqs_solver.Solver(beta=parms['BETA'], gf_struct=gf_struct, 108 | n_tau=parms['N_TAU'], n_iw=parms['N_MAX_FREQ']) 109 | solver_parms = {} 110 | for s in parms: 111 | if s.lower() == s: solver_parms[s] = parms[s] 112 | assign_weiss_field(solver.G0_iw, parms, nspins, spin_names, 113 | nflavors, flavor_names) 114 | ham_int = get_interaction_hamiltonian(parms, spin_names, flavor_names, 115 | is_kanamori) 116 | if solver_parms['partition_method'] == 'quantum_numbers': 117 | solver_parms['quantum_numbers'] = get_quantum_numbers(parms, 118 | spin_names, flavor_names, 119 | is_kanamori) 120 | 121 | solver_parms.update({ 122 | 'h_int' : ham_int, 123 | 'random_seed' : int(1e6*time.time()*(mpi.rank+1) % 1e6), 124 | 'use_trace_estimator' : False, 125 | 'measure_g_tau' : True, 126 | 'measure_g_l' : False, 127 | 'performance_analysis' : False, 128 | 'perform_tail_fit' : False, 129 | 'perform_post_proc' : True, 130 | 'move_shift' : True, 131 | 'move_double' : False, 132 | }) 133 | if parms.get('MEASURE', 0) > 0: 134 | solver_parms['static_observables'] = get_static_observables(parms, 135 | spin_names, flavor_names) 136 | 137 | # run the solver 138 | solver.solve(**solver_parms) 139 | 140 | # save data 141 | if mpi.is_master_node(): 142 | h5file = HDFArchive(parms.get('HDF5_OUTPUT', 143 | '%s.triqs.out.h5'%parms['PREFIX']), 'w') 144 | h5file['Gtau'] = solver.G_tau 145 | h5file['Giwn'] = solver.G_iw 146 | h5file['Siwn'] = solver.Sigma_iw 147 | h5file['Occupancy'] = solver.G_iw.density() 148 | h5file['G0iwn'] = solver.G0_iw 149 | h5file['average_sign'] = solver.average_sign 150 | if len(solver.static_observables) > 0: 151 | h5file['Observables'] = solver.static_observables 152 | 153 | r = solver.eigensystems 154 | eigvals = [] 155 | for rr in r: 156 | eigvals = r_[eigvals, rr[0]] 157 | savetxt('%s.eigvals'%parms['PREFIX'], sort(eigvals)) 158 | -------------------------------------------------------------------------------- /cppext/others.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | PyObject* ewald_sum(const int &NLa, const double &CLa, const int &NSr, const double &CSr, PyObject *nV, const int &Nxy, const int &Nz) 13 | { 14 | assert(((PyArrayObject *)nV)->dimensions[0] == NLa + NSr); 15 | import_array1(NULL); 16 | double sigma = M_PI; 17 | int N = NLa + NSr; 18 | double *C = new double[2*N], 19 | *pt_nV = (double *) PyArray_DATA((PyArrayObject *) nV); 20 | double *x = new double[2*N], 21 | *y = new double[2*N], 22 | *z = new double[2*N], 23 | *Vsi = new double[N]; 24 | std::complex *Vli = new std::complex[N]; 25 | double sum_nV = 0.; 26 | for (int i = 0; i < N; ++i) 27 | sum_nV += pt_nV[i]; 28 | 29 | for (int i = 0; i < N; ++i) { 30 | C[i] = pt_nV[i]/sum_nV * (-NLa*CLa - NSr*CSr); 31 | C[N+i] = (i < NLa) ? CLa : CSr; 32 | x[i] = y[i] = 0.; 33 | x[N+i] = y[N+i] = 0.5; 34 | z[i] = double(i); 35 | z[N+i] = -0.5+double(i); 36 | Vsi[i] = 0.; 37 | Vli[i] = std::complex(0., 0.); 38 | } 39 | 40 | 41 | double e_charge = -1.; 42 | int Nx = Nxy, Ny = Nxy; 43 | double *R = new double[2*N], 44 | kv[3], ksquare = 0.; 45 | 46 | for (int i = 0; i < N; ++i) 47 | for (int m = -Nx; m < Nx; ++m) 48 | for (int n = -Ny; n < Ny; ++n) 49 | for (int l = - Nz; l < Nz; ++l) { 50 | for (int k = 0; k < 2*N; ++k) 51 | R[k] = sqrt(pow(m+x[k], 2) + pow(n+y[k],2) + pow(N*l+z[i]-z[k], 2)); 52 | // for short-range terms 53 | if (m == 0 and n == 0 and l == 0) { 54 | for (int k = 0; k < 2*N; ++k) 55 | if (k != i) 56 | Vsi[i] += e_charge*C[k] / R[k] * erfc(R[k]/sqrt(2)/sigma); 57 | continue; 58 | } 59 | for (int k = 0; k < 2*N; ++k) 60 | Vsi[i] += e_charge * C[k] / R[k] * erfc(R[k]/sqrt(2)/sigma); 61 | 62 | // for long-range terms 63 | kv[0] = 2*M_PI*n; 64 | kv[1] = 2*M_PI*m; 65 | kv[2] = 2*M_PI/N*l; 66 | ksquare = pow(kv[0], 2) + pow(kv[1], 2) + pow(kv[2], 2); 67 | for (int k = 0; k < 2*N; ++k) 68 | Vli[i] += 4*M_PI/N * e_charge*C[k] / ksquare * 69 | exp(std::complex(0., -kv[0]*x[k] - kv[1]*y[k] + kv[2]*(z[i] - z[k]))) * exp(-pow(sigma,2)*ksquare/2.); 70 | } 71 | npy_intp Nconvert = npy_intp(N); 72 | PyArrayObject *result = (PyArrayObject *)PyArray_SimpleNew(1, &Nconvert, NPY_DOUBLE); 73 | Py_INCREF(result); 74 | double *result_buf = (double *)PyArray_DATA(result); 75 | for (int i = 0; i < N; ++i) 76 | result_buf[i] = Vsi[i] + Vli[i].real() - e_charge*C[i]*sqrt(2/M_PI)*1./sigma; 77 | 78 | delete[] R; 79 | delete[] C; 80 | delete[] x; 81 | delete[] y; 82 | delete[] z; 83 | delete[] Vsi; 84 | delete[] Vli; 85 | 86 | return PyArray_Return(result); 87 | } 88 | 89 | 90 | using namespace Eigen; 91 | 92 | typedef struct { 93 | Vector3d r; // position in the unitcell 94 | double C; // ion charge 95 | double ne; // electron occupation 96 | double V; // dimensionless electric potential (whose unit is smt like V :) 97 | } AtomInfo; 98 | typedef std::vector UnitCell; 99 | 100 | void general_ewald_sum(UnitCell &uc, const Vector3d &a1, const Vector3d &a2, const Vector3d &a3, const Vector3i &Rcutoff); 101 | 102 | 103 | PyObject* new_ewald_sum(const int &NLa, const double &CLa, const int &NSr, const double &CSr, PyObject *nVpy, const int &Nxy, const int &Nz) 104 | { 105 | try { 106 | int N = NLa + NSr; 107 | VectorXd nV; 108 | numpy::from_numpy(nVpy, nV); 109 | 110 | UnitCell uc(2*N); 111 | for (int i = 0; i < N; ++i) { 112 | uc[2*i].C = (i < NLa) ? CLa : CSr; 113 | uc[2*i].ne = 0; 114 | uc[2*i].r << 0.5, 0.5, -0.5 + double(i); 115 | 116 | uc[2*i+1].C = 0; 117 | uc[2*i+1].ne = nV(i); 118 | uc[2*i+1].r << 0, 0, i; 119 | } 120 | 121 | Vector3d a1(1,0,0), a2(0,1,0), a3(0,0,N); 122 | Vector3i Rcutoff(Nxy, Nxy, Nz); 123 | general_ewald_sum(uc, a1, a2, a3, Rcutoff); 124 | 125 | VectorXd out(N); 126 | for (int i = 0; i < N; ++i) 127 | out(i) = -uc[2*i+1].V; 128 | return numpy::to_numpy(out); 129 | } catch (const char *str) { 130 | std::cerr << str << std::endl; 131 | return Py_None; 132 | } 133 | } 134 | 135 | 136 | void general_ewald_sum(UnitCell &uc, const Vector3d &a1, const Vector3d &a2, const Vector3d &a3, const Vector3i &Rcutoff) 137 | { 138 | int N = uc.size(); 139 | const double sigma = M_PI; 140 | 141 | // renormalize electron occupation 142 | double unrenorm_Ne = 0, Ne = 0; 143 | for (UnitCell::iterator it = uc.begin(); it < uc.end(); ++it) { 144 | unrenorm_Ne += it->ne; 145 | Ne += it->C; 146 | } 147 | for (UnitCell::iterator it = uc.begin(); it < uc.end(); ++it) 148 | it->ne *= Ne/unrenorm_Ne; 149 | 150 | // get reciprocal vectors 151 | Vector3d b1, b2, b3; 152 | double uc_vol = a1.dot(a2.cross(a3)); 153 | b1 = 2*M_PI*a2.cross(a3)/uc_vol; 154 | b2 = 2*M_PI*a3.cross(a1)/uc_vol; 155 | b3 = 2*M_PI*a1.cross(a2)/uc_vol; 156 | 157 | // Ewald sum 158 | double Vs, Vl; 159 | Vector3d k; 160 | for (int id = 0; id < N; ++id) { 161 | Vs = 0; Vl = 0; 162 | for (int m = -Rcutoff[0]; m < Rcutoff[0]; ++m) 163 | for (int n = -Rcutoff[1]; n < Rcutoff[1]; ++n) 164 | for (int l = -Rcutoff[2]; l < Rcutoff[2]; ++l) { 165 | k = n*b1 + m*b2 + l*b3; 166 | double ksquare = k.dot(k); 167 | for (int i = 0; i < N; ++i) { 168 | double dR = (uc[id].r - (uc[i].r + m*a1 + n*a2 + l*a3)).norm(); 169 | // for long-range terms 170 | if ( !(m == 0 && n == 0 && l == 0) ) 171 | Vl += 4*M_PI/uc_vol*(uc[i].C-uc[i].ne)/ksquare * cos(k.dot(uc[id].r-uc[i].r)) * exp(-pow(sigma,2)*ksquare/2.); 172 | 173 | // for short-range terms 174 | if ( !(m == 0 && n == 0 && l == 0 && i == id) ) 175 | Vs += (uc[i].C - uc[i].ne) / dR * erfc(dR/sqrt(2)/sigma); 176 | } 177 | } 178 | uc[id].V = Vs + Vl - (uc[id].C - uc[id].ne)*sqrt(2/M_PI)/sigma; 179 | } 180 | } 181 | 182 | -------------------------------------------------------------------------------- /dmft.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import h5py, time, sys, os; 4 | import re 5 | import init, solver, system_dependence as system; 6 | 7 | from numpy import *; 8 | from average_green import averageGreen; 9 | from functions import *; 10 | from share_fun import *; 11 | 12 | 13 | # 14 | # INIT: for the details of variables, see return of init.py 15 | # 16 | 17 | # read input arguments 18 | parms, np, parms_file = getOptions(sys.argv[1:]); 19 | 20 | # create or open database (HDF5) 21 | h5file = h5py.File(parms['DATA_FILE'], 'a'); 22 | vars_dict = init.initialize(h5file, parms); 23 | for k, v in vars_dict.iteritems(): exec('%s=v'%k); 24 | 25 | 26 | # 27 | # DMFT, DMFT, DMFT !!! 28 | # 29 | set_printoptions(suppress=True, precision=4, linewidth=150); 30 | for k, v in parms.iteritems(): print k + " = " + str(v) + ";"; 31 | print "\n\n" 32 | 33 | parms['MEASURE'] = int(val_def(parms, 'MEASURE', -1)); 34 | if 'OBSERVABLES' in parms and parms['MEASURE'] < 0: parms['MEASURE'] = 0; 35 | if int(val_def(parms, 'ADJUST_DELTA_ONCE', 1)) > 0: Nd = -1; print "Only adjust double counting at the beginning"; 36 | 37 | it = h5["iter"][0]; 38 | SelfEnergy_out = h5['SelfEnergy/%d'%it][:]; 39 | mu_out = mu_in = float(parms['MU']); 40 | delta_out = delta_in = float(parms['DELTA']); 41 | while True: 42 | # start a new iteration 43 | MaxIter = int(val_def(parms, "MAX_ITER", 20)); 44 | if it >= MaxIter and parms['MEASURE'] < 0: break; 45 | it += 1; 46 | if parms['MEASURE'] > 0: 47 | print 'Final loop for measuring' 48 | for k, v in parms.iteritems(): 49 | if re.match('^FINAL_', k): 50 | key_to_change = re.split('^FINAL_', k)[1] 51 | parms[key_to_change] = v 52 | print ' %s=%s'%(key_to_change, str(v)) 53 | if key_to_change == 'CUTOFF_FREQ': 54 | parms['N_CUTOFF'] = int(round((float(parms['BETA'])/pi*float(v) - 1)/2.)); 55 | print ' %s=%s'%('N_CUTOFF', str(parms['N_CUTOFF'])) 56 | time_spent = time.time(); 57 | print "ITERATION: %d\n"%it; 58 | 59 | # average over k-space for Gavg then produce Weiss field 60 | # use Gauss quadrature with C++ extension code 61 | # mixing self energy 62 | tmp = mixer_SE.do_task(r_[SelfEnergy_out.real.flatten(), SelfEnergy_out.imag.flatten()]).reshape(2, -1); 63 | SelfEnergy_in = (tmp[0] + 1j*tmp[1]).reshape(SelfEnergy_out.shape); 64 | mu_orig = mu_in; delta_orig = delta_in; 65 | if str(it) not in h5['WeissField']: 66 | print "Tedious part: averaging Green function"; 67 | extra.update(system.getInfoForDensityCalculation(h5, it-1)); 68 | print 'Density correction = \n', extra['correction'][:, :NCOR]; 69 | 70 | Gavg, Gavg0, delta_out, mu_out, VCoulomb = averageGreen(delta_in, mu_in, 1j*wn, SelfEnergy_in, parms, Nd, DENSITY, int(val_def(parms, 'NO_TUNEUP', 0)) == 0, extra); 71 | delta_in, mu_in = mixer.do_task(r_[delta_out, mu_out]); 72 | if mu_in != mu_out or delta_in != delta_out: 73 | print 'There is mixing, average Green function once more'; 74 | extra['G_asymp_coefs'][:N_LAYERS*int(parms['FLAVORS'])] -= delta_out - delta_in; 75 | extra['G_asymp_coefs'] -= mu_out - mu_in; 76 | Gavg, Gavg0, delta_in, mu_in, VCoulomb = averageGreen(delta_in, mu_in, 1j*wn, SelfEnergy_in, parms, Nd, DENSITY, False, extra); 77 | parms["DELTA"] = delta_in; 78 | parms["MU"] = mu_in; # just want MU shown in log_density corresponding to nf 79 | 80 | nf = getDensityFromGmat(Gavg0, float(parms['BETA']), extra); 81 | nf = c_[nf[:,:NCOR], sum(nf[:,NCOR:], 1)]; 82 | log_density(h5, it-1, parms, nf); 83 | 84 | parms["DELTA"] = delta_in; 85 | parms["MU"] = mu_in; 86 | h5['parms/%d/DELTA'%it][...] = str(delta_in); 87 | h5['parms/%d/MU'%it][...] = str(mu_in); 88 | 89 | aWeiss = 1./Gavg[:, :, corr_id] + SelfEnergy_in; 90 | save_data(h5, it, ['avgGreen', 'WeissField', 'StaticCoulomb'], [Gavg0, aWeiss, VCoulomb]); 91 | 92 | NthOrder = 3; 93 | dispersion_avg = system.getAvgDispersion(parms, NthOrder, extra); 94 | h5['SolverData/AvgDispersion'][:] = dispersion_avg; 95 | 96 | else: 97 | Gavg0 = h5['avgGreen/%d'%it][:]; 98 | aWeiss = h5['WeissField/%d'%it][:]; 99 | VCoulomb = h5['StaticCoulomb/%d'%it][:]; 100 | 101 | time_spent = r_[time_spent, time.time()]; 102 | 103 | 104 | # run the solver here and get Gimp 105 | # need: path for data file, iteration number, layer index 106 | if str(it) not in h5['SelfEnergy']: 107 | print "Tedious part: Running impurity solver %d times"%N_LAYERS; 108 | dispersion_avg = h5['SolverData/AvgDispersion'][:]; 109 | nf = getDensity(h5, it-1); 110 | h5file.close(); del h5; 111 | tmph5filename = solver.run_solver(dispersion_avg, nf, 1j*wn, it, parms, aWeiss, np, VCoulomb); 112 | if tmph5filename is None: print >> sys.stderr, "Something wrong while running the solver"; break; 113 | h5file = h5py.File(parms['DATA_FILE'], 'a'); 114 | h5 = h5file[parms['ID']]; 115 | Gimp, SelfEnergy_out = solver.solver_post_process(parms, aWeiss, h5, tmph5filename); 116 | if SelfEnergy_out is None: break; 117 | save_data(h5, it, ['ImpurityGreen', 'SelfEnergy'], [Gimp, SelfEnergy_out]); 118 | else: SelfEnergy_out = h5['SelfEnergy/%d'%it][:]; 119 | time_spent = r_[time_spent, time.time()]; 120 | 121 | # finish the iteration 122 | time_spent = array(diff(time_spent), dtype = int); 123 | log_data(h5, 'log_time', it, r_[time_spent, sum(time_spent)], data_type = int); 124 | 125 | # check if needs to adjust parms 126 | new_parms = parms_file; 127 | if os.path.isfile(new_parms): 128 | parms_new = readParameters(new_parms); 129 | print 'Check for updating parameters'; 130 | updated = False; 131 | for k, v in parms_new.iteritems(): 132 | if k not in parms or str(parms[k]) != str(v): 133 | print k, ' = ', v 134 | parms[k] = v 135 | updated = True; 136 | if k == 'MU': 137 | mu_in = float(parms_new['MU']) 138 | print ' chemical potential is forced to be %s'%parms_new['MU'] 139 | if not updated: print 'no new parameters.'; 140 | save_parms(h5, it+1, parms); 141 | 142 | h5["iter"][...] = it; # this is the mark that iteration 'it' is done 143 | print "Time for iteration %d: %d, %d, %d\n"%(it, time_spent[0], time_spent[1], sum(time_spent)); 144 | 145 | # check stop condition 146 | # generate criterion for convergence: DOS at Fermi level 147 | # DOS_in = getFermiDOS(Gavg0, float(parms['BETA'])); 148 | # Gavg0 = averageGreen(delta_in, mu_in, 1j*wn, SelfEnergy_out, parms, Nd, DENSITY, False, extra)[1]; 149 | # DOS_out = getFermiDOS(Gavg0, float(parms['BETA'])); 150 | # DOS_in = c_[DOS_in[:,:NCOR:N_LAYERS], sum(DOS_in[:, NCOR:], 1)/N_LAYERS]; 151 | # DOS_out = c_[DOS_out[:,:NCOR:N_LAYERS], sum(DOS_out[:, NCOR:], 1)/N_LAYERS]; 152 | print 'End iteration %d\n\n'%it; 153 | 154 | if check_convergence(h5, it, r_[mu_orig, delta_orig, SelfEnergy_in.flatten()], r_[mu_in, delta_in, SelfEnergy_out.flatten()], 155 | abstol = float(val_def(parms, 'TOLERANCE', 0.001*int(parms['SPINS']))), mixing = mixer.get_mixing_value(), Ntime=3): 156 | print 'CONVERGE!' 157 | if parms['MEASURE'] == 0: parms['MEASURE'] = 1; 158 | else: break; 159 | # check if it goes beyond max iter, measure and stop 160 | elif parms['MEASURE'] > 0: break; 161 | if it >= MaxIter: 162 | if parms['MEASURE'] < 0: break; 163 | else: parms['MEASURE'] = 1; 164 | 165 | # the end 166 | h5file.close(); 167 | -------------------------------------------------------------------------------- /calculate_spectra.py: -------------------------------------------------------------------------------- 1 | import sys, os, h5py, argparse, system_dependence as system; 2 | from share_fun import load_parms, val_def, grule; 3 | from numpy import *; 4 | import maxent; 5 | from scipy.interpolate import *; 6 | from init import getHamiltonian, getRotationMatrix; 7 | from average_green import averageGreen; 8 | 9 | 10 | 11 | def getSpectraFromSelfEnergy(h5, se_filename, rham, rotmat, numk = None, setail_filename = None, it = 0): 12 | 13 | # prepare data 14 | w, se_refreq = ProcessSelfEnergy(se_filename, emin = -5, emax = 5, NFreq = 500); 15 | 16 | it = h5['iter'][0] - it; 17 | parms = load_parms(h5, it); 18 | print 'work on iteration ', it; 19 | if rham is not None: print 'new path for rham file is: ', rham; parms['RHAM'] = rham; 20 | if rotmat is not None: print 'new path for rot_mat file is ', rotmat; parms['ROT_MAT'] = rotmat; 21 | BETA = float(parms['BETA']); 22 | N_LAYERS = int(parms['N_LAYERS']); 23 | FLAVORS = int(parms['FLAVORS']); 24 | SPINS = int(parms['SPINS']); 25 | NORB = int(parms['NORB']); 26 | dmft_id = system.getDMFTCorrIndex(parms, all = False); 27 | dmft_id_len = len(dmft_id); 28 | 29 | # get the se tails 30 | tmp = h5['SolverData/selfenergy_asymp_coeffs'][:]; 31 | se_tail = tmp[tmp[:,0] == it, 1:].reshape(SPINS, 2, -1)[:, :, ::N_LAYERS]; 32 | if setail_filename is not None: 33 | print 'use the tail from external source: ', setail_filename; 34 | tmp = genfromtxt(setail_filename); 35 | se_tail[:, :, dmft_id] = array([tmp[:, s::SPINS] for s in range(SPINS)]); 36 | print se_tail; 37 | 38 | # restore SelfEnergy 39 | se = zeros((SPINS, len(se_refreq), N_LAYERS*FLAVORS), dtype = complex); 40 | for s in range(SPINS): 41 | for f in range(N_LAYERS*FLAVORS): 42 | if f/N_LAYERS not in dmft_id: se[s,:,f] = se_tail[s, 0, f/N_LAYERS]; 43 | else: 44 | f1 = nonzero(f/N_LAYERS == dmft_id)[0][0]; 45 | se[s, :, f] = se_refreq[:, SPINS*f1+s]*se_tail[s, 1, f/N_LAYERS] + se_tail[s, 0, f/N_LAYERS]; 46 | 47 | # tight binding Hamiltonian 48 | if 'RHAM' in parms: 49 | HR, R = getHamiltonian(parms['RHAM'], 4); 50 | if parms['DTYPE'] == '3bands': FLAVORS = 3; 51 | extra = { 'HR' : HR, 'R': R }; 52 | 53 | # rotation matrix 54 | if int(val_def(parms, 'FORCE_DIAGONAL', 0)) > 0: 55 | print 'FORCE_DIAGONAL is used'; 56 | ind = nonzero(sum(R**2, 1)==0)[0][0]; 57 | H0 = HR[ind]; 58 | else: H0 = None; 59 | rot_mat = getRotationMatrix(N_LAYERS, FLAVORS, val_def(parms, 'ROT_MAT', None), H0); 60 | 61 | 62 | # prepare for k-integrate 63 | parms['NUMK'] = 16 if numk is None else numk; 64 | bp, wf = grule(int(parms['NUMK'])); 65 | broadening = 0.01; 66 | extra.update({ 67 | 'GaussianData' : [bp, wf], 68 | 'rot_mat' : rot_mat 69 | }); 70 | delta = float(parms['DELTA']); 71 | mu = float(parms['MU']); 72 | 73 | # running 74 | print 'generating interacting DOS with parameters' 75 | for k, v in parms.iteritems(): print '%s = %s'%(k, v); 76 | 77 | Gr = averageGreen(delta, mu, w+1j*broadening, se, parms, float(parms['ND']), float(parms['DENSITY']), 0, extra)[1]; 78 | if SPINS == 1: savetxt(parms['ID']+'.idos', c_[w, -1/pi*Gr[0].imag], fmt = '%g'); 79 | elif SPINS == 2: 80 | savetxt(parms['ID']+'_up.idos', c_[w, -1/pi*Gr[0].imag], fmt = '%g'); 81 | savetxt(parms['ID']+'_dn.idos', c_[w, -1/pi*Gr[1].imag], fmt = '%g'); 82 | 83 | # calculate original G(iwn), only consider one "LAYERS" 84 | Giwn_orig = h5['ImpurityGreen/%d'%it][:,:,::N_LAYERS]; 85 | NMatsubara = size(Giwn_orig, 1); 86 | wn = (2*arange(NMatsubara) + 1)*pi/BETA; 87 | Giwn = zeros((NMatsubara, 2*FLAVORS*SPINS), dtype = float); # 2 for real and imag 88 | for f in range(FLAVORS): 89 | for s in range(SPINS): 90 | Giwn[:, 2*(SPINS*f+s)] = Giwn_orig[s, :, f].real; 91 | Giwn[:, 2*(SPINS*f+s)+1] = Giwn_orig[s, :, f].imag; 92 | savetxt(parms['ID']+'.gmat', c_[wn, Giwn]); 93 | 94 | # calculate G(iwn) for reference, only consider one "LAYERS" 95 | NMatsubara = 200; 96 | wn = (2*arange(NMatsubara) + 1)*pi/BETA; 97 | Giwn = zeros((NMatsubara, 2*FLAVORS*SPINS), dtype = float); # 2 for real and imag 98 | for f in range(FLAVORS): 99 | for s in range(SPINS): 100 | A = -1/pi * Gr[s, :, f*N_LAYERS].imag; 101 | for n in range(NMatsubara): 102 | tck_re = splrep(w, real(A / (1j*wn[n] - w))); 103 | tck_im = splrep(w, imag(A / (1j*wn[n] - w))); 104 | Giwn[n, 2*(SPINS*f+s)] = splint(w[0], w[-1], tck_re); 105 | Giwn[n, 2*(SPINS*f+s)+1] = splint(w[0], w[-1], tck_im); 106 | savetxt(parms['ID']+'.gmat.ref', c_[wn, Giwn]); 107 | 108 | 109 | def ProcessSelfEnergy(se_filename, emin = None, emax = None, NFreq = None, delta = None): 110 | # remove irrelevant energy ranges 111 | se_refreq = genfromtxt(se_filename); 112 | min_id = 0; 113 | max_id = len(se_refreq); 114 | tmp = sum(se_refreq[:, 2::2], 1); 115 | min_spec_val = 3e-3; 116 | print 'min = %g, max = %g'%(abs(max(tmp)), abs(min(tmp))); 117 | # if min_spec_val > abs(min(tmp)) or min_spec_val < abs(max(tmp)): exit('min_spec_val=%g is out of range'%min_spec_val) 118 | stop1 = False; stop2 = False; 119 | L = len(se_refreq); 120 | for i in xrange(L): 121 | if abs(tmp[i]) > min_spec_val: stop1 = True; min_id = max(0,i-1); 122 | if abs(tmp[L-1-i]) > min_spec_val: stop2 = True; max_id = L-i; 123 | if stop1 and stop2: break; 124 | id_emin = inf; id_emax = -inf; 125 | w = se_refreq[:,0]; 126 | for i in xrange(L): 127 | if emin is not None: 128 | if w[i] < emin: id_emin = i; 129 | if emax is not None: 130 | if w[L-1-i] > emax: id_emax = L-1-i; 131 | if id_emin is not None: min_id = id_emin; 132 | if id_emax is not None: max_id = id_emax; 133 | 134 | se_refreq0 = se_refreq[min_id:max_id, :]; 135 | w0 = se_refreq0[:,0]; 136 | w = linspace(w0[0], w0[-1], NFreq); 137 | se_refreq = None; 138 | for f in range((size(se_refreq0, 1)-1)/2): 139 | tck_re = splrep(w0, se_refreq0[:, 1+2*f]) 140 | tck_im = splrep(w0, se_refreq0[:, 1+2*f+1]); 141 | if se_refreq is None: se_refreq = splev(w, tck_re) + 1j*splev(w, tck_im); 142 | else: se_refreq = c_[se_refreq, splev(w, tck_re) + 1j*splev(w, tck_im)]; 143 | 144 | print 'get self energy from file %s'%se_filename 145 | print 'total number of frequencies considered is %d from wmin=%.4f to wmax=%.4f'%(NFreq, w[0], w[-1]) 146 | return w, se_refreq; 147 | 148 | 149 | if __name__ == '__main__': 150 | parser = argparse.ArgumentParser(description='DMFT process.'); 151 | parser.add_argument('-f', dest='h5filename', type = str, default = None, help='Input HDF5 file'); 152 | parser.add_argument('-g', dest='h5groupname', type = str, default = None, help='HDF5 group name'); 153 | parser.add_argument('-rham', dest='rham', type = str, default = None, help='Tight binding Hamiltonian'); 154 | parser.add_argument('-rotmat', dest='rotmat', type = str, default = None, help='Rotation matrix'); 155 | parser.add_argument('-nk', dest='numk', type = int, default = None, help='Number of kpoints'); 156 | parser.add_argument('-se', dest='sefilename', type = str, default = None, help='Real frequency self energy (normalized to 1)'); 157 | parser.add_argument('-se_tail', dest='setail_filename', type = str, default = None, help='Self eneryg tail (up to 1/iwn)'); 158 | parser.add_argument('-iter', dest='it', type = int, default = 0, help='Iteration number for continuation'); 159 | args = parser.parse_args(sys.argv[1:]); 160 | 161 | if not os.path.isfile(args.sefilename): 162 | exit('Spectra file %s not found'%args.sefilename); 163 | try: h5file = h5py.File(args.h5filename, 'r'); 164 | except: exit('Unable to load hdf5 file %s'%args.h5filename); 165 | 166 | if args.h5groupname is not None: 167 | if args.h5groupname not in h5file: 168 | h5file.close(); 169 | exit('No group %s'%args.h5groupname); 170 | else: h5 = h5file[args.h5groupname]; 171 | else: h5 = h5file[h5file.keys()[0]]; 172 | 173 | set_printoptions(linewidth=150, suppress=True, precision=4); 174 | getSpectraFromSelfEnergy(h5, args.sefilename, args.rham, args.rotmat, args.numk, args.setail_filename, args.it); 175 | 176 | -------------------------------------------------------------------------------- /include/numpy_eigen.h: -------------------------------------------------------------------------------- 1 | /* 2 | This program is free software: you can redistribute it and/or modify 3 | it under the terms of the Lesser GNU General Public License 4 | as published by the Free Software Foundation, either version 3 5 | of the License, or (at your option) any later version. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | the Lesser GNU General Public License for more details. 11 | 12 | You should have received a copy of the the Lesser GNU General 13 | Public License along with this program. If not, see 14 | . 15 | */ 16 | 17 | /* 18 | * Copy and modify the code from the net 19 | * http://forum.kde.org/viewtopic.php?f=74&t=86057 20 | * Hung Dang, May 14, 2011 21 | */ 22 | 23 | #ifndef __NUMPY_EIGEN_H__ 24 | #define __NUMPY_EIGEN_H__ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace numpy { 31 | 32 | 33 | template 34 | struct NumpyEquivalentType {}; 35 | 36 | template <> struct NumpyEquivalentType {enum { type_code = NPY_DOUBLE };}; 37 | template <> struct NumpyEquivalentType {enum { type_code = NPY_INT };}; 38 | template <> struct NumpyEquivalentType {enum { type_code = NPY_FLOAT };}; 39 | template <> struct NumpyEquivalentType > {enum { type_code = NPY_CDOUBLE };}; 40 | 41 | template 42 | struct eigen_python_matrix_converter 43 | { 44 | typedef Eigen::internal::traits traits; 45 | 46 | ////////////////////////// 47 | // to python conversion 48 | static void to_python(const MatrixType& matrix, PyObject *&ret) { 49 | import_array(); 50 | npy_intp shape[2] = { matrix.rows(), matrix.cols() }; 51 | PyArrayObject* python_array = (PyArrayObject*)PyArray_SimpleNew(2, shape, NumpyEquivalentType::type_code); 52 | copy_array(matrix.data(), (typename traits::Scalar*)PyArray_DATA(python_array), matrix.rows(), matrix.cols()); 53 | Py_INCREF(python_array); 54 | ret = PyArray_Return(python_array); 55 | } 56 | 57 | //////////////////////////// 58 | // from python conversion 59 | static void convertible(PyObject* obj_ptr){ 60 | if (!PyArray_Check(obj_ptr)) 61 | throw "PyArray_Check failed"; 62 | if (PyArray_NDIM(obj_ptr)!=2) 63 | throw "dim != 2"; 64 | if (PyArray_ObjectType(obj_ptr, 0) != NumpyEquivalentType::type_code) 65 | throw "types not compatible"; 66 | int elsize = (PyArray_DESCR(obj_ptr))->elsize; 67 | if (PyArray_STRIDE(obj_ptr, 0) % elsize != 0 || PyArray_STRIDE(obj_ptr, 1) % elsize != 0) 68 | throw "strides and type size not matched"; 69 | } 70 | 71 | static void from_python(PyObject* py_obj_ptr, MatrixType &matrix) 72 | { 73 | import_array(); 74 | convertible(py_obj_ptr); 75 | PyArrayObject *array = reinterpret_cast(py_obj_ptr); 76 | 77 | npy_int nb_rows = array->dimensions[0]; 78 | npy_int nb_cols = array->dimensions[1]; 79 | int elsize = (PyArray_DESCR(py_obj_ptr))->elsize; 80 | npy_int row_stride = PyArray_STRIDE(py_obj_ptr, 0)/elsize, 81 | col_stride = PyArray_STRIDE(py_obj_ptr, 1)/elsize; 82 | 83 | matrix.resize(nb_rows, nb_cols); 84 | copy_array((typename traits::Scalar*)PyArray_DATA(array), matrix.data(), nb_rows, nb_cols, 85 | true, traits::Flags & Eigen::RowMajorBit, row_stride, col_stride); 86 | } 87 | 88 | template 89 | static void copy_array(const SourceType* source, DestType* dest, const npy_int &nb_rows, const npy_int &nb_cols, 90 | const bool &isSourceTypeNumpy = false, const bool &isDestRowMajor = true, 91 | const npy_int &numpy_row_stride = 1, const npy_int &numpy_col_stride = 1) 92 | { 93 | // determine source strides 94 | int row_stride = 1, col_stride = 1; 95 | if (isSourceTypeNumpy) { 96 | row_stride = numpy_row_stride; 97 | col_stride = numpy_col_stride; 98 | } else { 99 | if (traits::Flags & Eigen::RowMajorBit) 100 | row_stride = nb_cols; 101 | else col_stride = nb_rows; 102 | } 103 | 104 | if (isDestRowMajor) 105 | for (int r=0; r 122 | struct eigen_python_vector_converter 123 | { 124 | typedef Eigen::internal::traits traits; 125 | 126 | ////////////////////////// 127 | // to python conversion 128 | static void to_python(const VectorType& vector, PyObject *&py_vector) { 129 | import_array(); 130 | npy_intp shape = vector.size(); 131 | PyArrayObject* python_array = (PyArrayObject*)PyArray_SimpleNew(1, &shape, NumpyEquivalentType::type_code); 132 | copy_array(vector.data(), (typename traits::Scalar*)PyArray_DATA(python_array), vector.size()); 133 | Py_INCREF(python_array); 134 | py_vector = PyArray_Return(python_array); 135 | } 136 | 137 | //////////////////////////// 138 | // from python conversion 139 | static void convertible(PyObject* obj_ptr){ 140 | if (!PyArray_Check(obj_ptr)) 141 | throw "PyArray_Check failed"; 142 | if (PyArray_NDIM(obj_ptr) != 1) 143 | throw "dim != 1"; 144 | if (PyArray_ObjectType(obj_ptr, 0) != NumpyEquivalentType::type_code) 145 | throw "types not compatible"; 146 | if (PyArray_STRIDE(obj_ptr, 0) % (PyArray_DESCR(obj_ptr))->elsize != 0) 147 | throw "stride and type size not matched"; 148 | } 149 | 150 | static void from_python(PyObject* py_obj_ptr, VectorType &vector) 151 | { 152 | import_array(); 153 | convertible(py_obj_ptr); 154 | 155 | PyArrayObject *array = reinterpret_cast(py_obj_ptr); 156 | npy_int nb_size = array->dimensions[0]; 157 | 158 | vector.resize(nb_size); 159 | npy_int stride = PyArray_STRIDE(py_obj_ptr, 0) / (PyArray_DESCR(py_obj_ptr))->elsize; 160 | copy_array((typename traits::Scalar*)PyArray_DATA(array), vector.data(), nb_size, stride); 161 | } 162 | 163 | template 164 | static void copy_array(const SourceType* source, DestType* dest, const npy_int &nb_size, const npy_int &stride = 1) { 165 | for (int i = 0; i < nb_size; ++i) 166 | dest[i] = source[stride*i]; 167 | } 168 | }; 169 | 170 | template 171 | void from_numpy(PyObject *py_obj, Eigen::Matrix &ret) { 172 | eigen_python_vector_converter >::from_python(py_obj, ret); 173 | } 174 | 175 | template 176 | void from_numpy(PyObject *py_obj, Eigen::Matrix &ret) { 177 | eigen_python_matrix_converter >::from_python(py_obj, ret); 178 | } 179 | 180 | 181 | template 182 | PyObject* to_numpy(const array_t &arr) 183 | { 184 | PyObject *ret; 185 | if (arr.rows() == 1 || arr.cols() == 1) 186 | eigen_python_vector_converter::to_python(arr, ret); 187 | else 188 | eigen_python_matrix_converter::to_python(arr, ret); 189 | 190 | return ret; 191 | } 192 | 193 | template 194 | void convert3dArray(PyObject *pyArr, std::vector > &out) 195 | { 196 | import_array(); 197 | if (PyArray_NDIM(pyArr)!=3) throw "dim != 3"; 198 | 199 | PyArrayObject *arr = reinterpret_cast(pyArr); 200 | npy_intp *sz = arr->dimensions; 201 | npy_intp strides[3]; 202 | int elsize = (PyArray_DESCR(pyArr))->elsize; 203 | 204 | for (int i = 0; i < 3; ++i) 205 | strides[i] = PyArray_STRIDE(arr, i)/(PyArray_DESCR(arr))->elsize; 206 | out.resize(sz[0]); 207 | T *source = (T *)PyArray_DATA(arr); 208 | for (int i=0; i Ntot: dmu = interp_root(v_mu, v_n, Ntot); 84 | else: dmu += (1. if my_ntot < Ntot else -1.)*mu_step; 85 | 86 | my_nd = 2*sum(nf[:N_LAYERS*FLAVORS]); 87 | 88 | if tuneup: print "adjust double counting: " + str(delta) + " " + str(ddelta) + " " + str(my_nd) + " " + str(my_nd/N_LAYERS); 89 | if Nd < 0 or abs(Nd - my_nd) < tol or not tuneup: break; 90 | 91 | v_delta = r_[v_delta, ddelta]; 92 | v_nd = r_[v_nd, my_nd]; 93 | if v_nd.min() < Nd and v_nd.max() > Nd: ddelta = interp_root(v_delta, v_nd, Nd); 94 | else: ddelta += (1. if my_nd < Nd else -1.)*delta_step; 95 | 96 | Gavg = array([functions.rotate_all(Gavg[s], rot_mat) for s in range(SPINS)]); 97 | return Gavg, delta, mu, Vc; 98 | 99 | 100 | def HartreeRun(parms, extra): 101 | print "Initialization using Hartree approximation\n" 102 | N_LAYERS = int(parms['N_LAYERS']); 103 | FLAVORS = int(parms['FLAVORS']); 104 | SPINS = 1; 105 | 106 | p = dict({ 107 | 'MU' : float(val_def(parms, 'MU', 0)), 108 | 'N_LAYERS': N_LAYERS, 109 | 'NORB' : int(parms['NORB']), 110 | 'U' : float(parms['U']), 111 | 'J' : float(parms['J']), 112 | 'DELTA': float(val_def(parms, 'DELTA', 0)), 113 | 'ND' : N_LAYERS*float(val_def(parms, 'ND', -1)), 114 | 115 | 'DENSITY' : N_LAYERS*float(parms['DENSITY']), 116 | 'FLAVORS' : FLAVORS, 117 | 'SPINS' : 1, 118 | 119 | 'OUTPUT' : '.' + parms['DATA_FILE'] + '_HartreeInit', 120 | 'NN' : None, 121 | 'N_MAX_FREQ' : 30, 122 | 'BETA' : float(parms['BETA']), 123 | 'NUMK' : int(val_def(parms, 'INIT_NUMK', 8)), 124 | 'TUNEUP' : int(val_def(parms, 'NO_TUNEUP', 0)) == 0, 125 | 'MAX_ITER' : 15, 126 | 'ALPHA' : 0.5, # pay attention at this parm sometimes 127 | 'DTYPE' : parms['DTYPE'], 128 | 'INTEGRATE_MOD' : val_def(parms, 'INTEGRATE_MOD', 'integrate'), 129 | 'np' : parms['np'] 130 | }); 131 | 132 | for k, v in p.iteritems(): print k + ': ', v; 133 | 134 | bp, wf = grule(p['NUMK']); 135 | X, W = generateGaussPoints(p['N_MAX_FREQ']); 136 | wn = 1/sqrt(X)/p['BETA']; 137 | p.update({ 138 | 'X' : X, 139 | 'W' : W, 140 | 'w' : wn 141 | }); 142 | if p['NN'] is None and os.path.isfile(p['OUTPUT']+'.nn'): p['NN'] = p['OUTPUT']; 143 | 144 | # running 145 | TOL = 1e-2; 146 | if p['NN'] is None: 147 | nn = ones(N_LAYERS*FLAVORS, dtype = 'f8') * p['DENSITY']/p['NORB']/2; # 2 for spin 148 | mu = p['MU']; 149 | delta = p['DELTA']; 150 | else: 151 | print 'Continue from '+p['NN']; 152 | nn = genfromtxt(p['NN']+'.nn')[2:]; 153 | mu = genfromtxt(p['NN']+'.nn')[1]; 154 | delta = genfromtxt(p['NN']+'.nn')[0]; 155 | Gavg = zeros((p['N_MAX_FREQ'], p['NORB']), dtype = 'c16'); 156 | se = zeros((SPINS, p['N_MAX_FREQ'], N_LAYERS*FLAVORS), dtype = 'c16'); 157 | stop = False; 158 | count = 0; 159 | ALPHA = p['ALPHA']; 160 | corr1 = system.getDMFTCorrIndex(parms, all = False); 161 | corr2 = array([i for i in range(FLAVORS) if i not in corr1]); # index for eg bands 162 | old_GaussianData = extra['GaussianData']; 163 | extra['GaussianData'] = [bp, wf]; 164 | while not stop: 165 | count += 1; 166 | nn_old = nn.copy(); 167 | p['MU'] = mu; 168 | p['DELTA'] = delta; 169 | Gavg_old = Gavg.copy(); 170 | 171 | for L in range(N_LAYERS): 172 | se_coef = functions.get_asymp_selfenergy(p, array([nn[L:N_LAYERS*FLAVORS:N_LAYERS]]))[0, 0, :]; 173 | for s in range(SPINS): 174 | for f in range(len(se_coef)): se[s, :, f*N_LAYERS+L] = se_coef[f]; 175 | 176 | Gavg, delta, mu, Vc = averageGreen(delta, mu, 1j*wn, se, p, p['ND'], p['DENSITY'], p['TUNEUP'], extra); 177 | Gavg = mean(Gavg, 0); 178 | nn = getDensity(Gavg, p); 179 | 180 | # no spin/orbital polarization, no charge order 181 | for L in range(N_LAYERS): 182 | nf1 = nn[0:N_LAYERS*FLAVORS:N_LAYERS]; 183 | for id in range(FLAVORS): 184 | if id in corr1: nf1[id] = mean(nf1[corr1]); 185 | else: nf1[id] = mean(nf1[corr2]); 186 | nn[L:N_LAYERS*FLAVORS:N_LAYERS] = nf1; 187 | 188 | err = linalg.norm(r_[delta, mu, nn] - r_[p['DELTA'], p['MU'], nn_old]); 189 | savetxt(p['OUTPUT']+'.nn', r_[delta, mu, nn]); 190 | print 'Step %d: %.5f'%(count, err); 191 | if (err < TOL): stop = True; print 'converged'; 192 | if count > p['MAX_ITER']: break; 193 | 194 | mu = ALPHA*mu + (1-ALPHA)*p['MU']; 195 | delta = ALPHA*delta + (1-ALPHA)*p['DELTA']; 196 | nn = ALPHA*nn + (1-ALPHA)*nn_old; 197 | 198 | 199 | # DOS 200 | NFREQ = 500; 201 | BROADENING = 0.03; 202 | extra['GaussianData'] = old_GaussianData; 203 | parms_tmp = parms.copy(); parms_tmp['DELTA'] = delta; 204 | Eav = system.getAvgDispersion(parms_tmp, 3, extra)[0,0,:]; 205 | Ed = mean(Eav[:N_LAYERS*FLAVORS][corr1]); 206 | Ep = mean(Eav[N_LAYERS*FLAVORS:]) if N_LAYERS*FLAVORS < p['NORB'] else Ed; 207 | emax = min(4, p['U']); 208 | emin = -(Ed - Ep + max(se_coef) + min(4, p['U'])); 209 | print "Energy range for HF DOS: ", emin, emax 210 | w = linspace(emin, emax, NFREQ) + 1j*BROADENING; 211 | se = zeros((SPINS, NFREQ, N_LAYERS*FLAVORS), dtype = 'c16'); 212 | for L in range(N_LAYERS): 213 | se_coef = functions.get_asymp_selfenergy(p, array([nn[L:N_LAYERS*FLAVORS:N_LAYERS]]))[0, 0, :]; 214 | for s in range(SPINS): 215 | for f in range(len(se_coef)): se[s, :, f*N_LAYERS+L] = se_coef[f]; 216 | Gr = average_green.averageGreen(delta, mu, w, se, p,p['ND'], p['DENSITY'], 0, extra)[1][0]; 217 | savetxt(parms['ID']+'.dos', c_[w.real, -1/pi*Gr.imag], fmt = '%.6f'); 218 | 219 | print ('End Hartree approx.:%d Ntot=%.2f Nd=%.2f Delta=%.4f ' 220 | 'Delta_eff=%.4f')%(count, 2*sum(nn)/N_LAYERS, 221 | 2*sum(nn[:N_LAYERS*FLAVORS]/N_LAYERS), 222 | delta, delta-mean(se_coef[corr1])), ': \n', \ 223 | nn[:N_LAYERS*FLAVORS].reshape(-1, N_LAYERS),\ 224 | '\n\n' 225 | # os.system('rm ' + p['OUTPUT']+'.nn'); 226 | return delta, mu, array([nn for s in range(int(parms['SPINS']))]), Vc; 227 | -------------------------------------------------------------------------------- /init.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, os, h5py; 4 | import hartree, rotation_matrix, system_dependence as system; 5 | 6 | from numpy import *; 7 | from average_green import averageGreen; 8 | from functions import *; 9 | from share_fun import *; 10 | 11 | 12 | def getHamiltonian(rham_file, dist = inf): 13 | # get DFT+MLWF Hamiltonian 14 | if not os.path.isfile(rham_file): sys.exit("Hamiltonian file %s not found..."%rham_file); 15 | execfile(rham_file) 16 | exec("rham = Hopping.copy(); del Hopping;"); 17 | for k in rham.keys(): 18 | if linalg.norm(array(k)) > dist: rham.pop(k) 19 | nr = len(rham); 20 | NORB = len(rham[(0,0,0)]); 21 | R = zeros((nr, 3), dtype = 'i4'); 22 | HR = zeros((nr, NORB, NORB), dtype = complex); 23 | for i,ii in enumerate(sorted(rham.keys())): 24 | R[i, :] = array(ii); 25 | HR[i, :, :] = array(rham[ii]); 26 | return HR, R; 27 | 28 | 29 | def getRotationMatrix(N_LAYERS, FLAVORS, rot_mat_file = None, H0 = None): 30 | rot_mat = []; 31 | if rot_mat_file is not None: rot_mat = rotation_matrix.generate_transform_mat(rot_mat_file)[2]; # for l=2 32 | elif H0 is not None: 33 | for c in range(N_LAYERS): 34 | h = H0[c*FLAVORS:(c+1)*FLAVORS, c*FLAVORS:(c+1)*FLAVORS]; 35 | d, v = linalg.eig(h); 36 | rot_mat.append(mat(v).H); 37 | else: 38 | for c in range(N_LAYERS): rot_mat.append(mat(eye(FLAVORS))); 39 | return rot_mat; 40 | 41 | 42 | def initialize(h5file, parms): 43 | if parms['ID'] in h5file.keys(): 44 | # group exists 45 | h5 = h5file[parms['ID']]; 46 | it = h5["iter"][0]; 47 | if it < 0: del h5file[parms['ID']]; 48 | else: 49 | parms1 = parms.copy(); 50 | # not allow to change these fixed parameters 51 | for s in ('DELTA', 'U', 'J', 'UJRAT', 'BETA'): 52 | if s in parms1: del parms1[s]; 53 | parms = load_parms(h5, it+1); 54 | for k, v in parms1.iteritems(): 55 | try: 56 | if parms[k] != parms1[k]: parms[k] = parms1[k]; 57 | except: parms[k] = parms1[k]; 58 | 59 | # NOTE: basic information for the structure 60 | N_LAYERS = int(parms['N_LAYERS']); 61 | SPINS = int(val_def(parms, 'SPINS', 2)); 62 | if int(val_def(parms, 'PARAMAGNET', 0)) > 0: SPINS = 1; 63 | DENSITY = N_LAYERS*float(parms['DENSITY']); 64 | BETA = float(parms["BETA"]); 65 | Nd = N_LAYERS*float(val_def(parms, 'ND', -1)); 66 | if 'DTYPE' not in parms: parms['DTYPE'] = ''; 67 | if 'RHAM' in parms: 68 | FLAVORS = 5; # 5 d-bands 69 | HR, R = getHamiltonian(parms['RHAM'], 4); # max distance is 4 70 | NORB = len(HR[0]); 71 | if parms['DTYPE'] == '3bands': FLAVORS = 3; 72 | else: 73 | FLAVORS = int(parms['FLAVORS']); 74 | NORB = int(parms['NORB']); 75 | 76 | if int(val_def(parms, 'AFM', 0)) > 0: 77 | print 'This is AFM self consistent loop!'; 78 | if SPINS == 1: exit('SPINS must be 2 for AFM calculation'); 79 | 80 | if int(val_def(parms, 'FORCE_DIAGONAL', 0)) > 0: 81 | print 'FORCE_DIAGONAL is used'; 82 | ind = nonzero(sum(R**2, 1)==0)[0][0]; 83 | H0 = HR[ind]; 84 | else: H0 = None; 85 | rot_mat = getRotationMatrix(N_LAYERS, FLAVORS, val_def(parms, 'ROT_MAT', None), H0); 86 | 87 | 88 | if 'MAX_FREQ' in parms.keys(): parms['N_MAX_FREQ'] = int(round((BETA*float(parms['MAX_FREQ'])/pi - 1)/2.)); 89 | if 'N_CUTOFF' not in parms.keys(): 90 | cutoff_factor = float(val_def(parms, 'CUTOFF_FACTOR', 7)); 91 | parms['N_CUTOFF'] = int(round((BETA/pi*float(val_def(parms,'CUTOFF_FREQ', cutoff_factor*float(parms['U']))) - 1)/2.)); 92 | parms['CUTOFF_FREQ'] = (2*int(parms['N_CUTOFF'])+1)*pi/BETA; 93 | parms['MAX_FREQ'] = (2*int(parms['N_MAX_FREQ'])+1)*pi/BETA; 94 | parms['FLAVORS'] = FLAVORS; 95 | 96 | # mixing 97 | mixer = Mixing(float(val_def(parms, "MIXING", 1)), int(val_def(parms, 'MIXING_FIXED', 1))); 98 | mixer_SE = Mixing(float(val_def(parms, "MIXING", 1)), int(val_def(parms, 'MIXING_FIXED', 1))); 99 | 100 | wn = (2*arange(int(parms['N_MAX_FREQ']))+1)*pi/BETA; 101 | extra = { 102 | 'correction' : zeros(SPINS), 103 | 'GaussianData' : grule(int(val_def(parms, 'NUMK', 30))), 104 | 'rot_mat' : rot_mat 105 | }; 106 | if 'RHAM' in parms: extra.update({'HR' : HR, 'R' : R }); 107 | else: extra.update({ 'tight_binding_parms' : array([float(s) for s in parms['TB_PARMS'].split()]) }); 108 | 109 | corr_id = system.getCorrIndex(parms); 110 | NCOR = len(corr_id); 111 | 112 | if not parms['ID'] in h5file.keys(): 113 | it = 0; 114 | 115 | # create main group ID and its subgroups 116 | h5 = h5file.create_group(parms['ID']); 117 | h5.create_dataset("iter", (1,), int, data = -1); 118 | 119 | crt_tuple = ("ImpurityGreen", "avgGreen", "SelfEnergy", "WeissField", 120 | "parms", "StaticCoulomb", "SolverData", 121 | "SolverData/Gtau", "SolverData/Hybmat", 122 | "SolverData/Hybtau", "SolverData/Observables"); 123 | for obj in crt_tuple: h5.create_group(obj); 124 | 125 | parms['SPINS'] = SPINS; 126 | parms['NORB'] = NORB; 127 | parms['ND'] = Nd/float(N_LAYERS); 128 | parms['NCOR'] = NCOR; 129 | parms['N_TAU'] = val_def(parms, 'N_TAU', 400); 130 | if 'UJRAT' in parms.keys(): parms['J'] = float(parms['U']) / float(parms['UJRAT']); 131 | 132 | # generate initial conditions 133 | if 'USE_DATAFILE' in parms.keys(): 134 | print 'Get initial data from file ' + parms['USE_DATAFILE']; 135 | is_hdf5 = True 136 | if os.path.abspath(parms['USE_DATAFILE']) != os.path.abspath(parms['DATA_FILE']): 137 | try: 138 | g5file = h5py.File(parms['USE_DATAFILE'], 'r'); 139 | g5 = g5file[val_def(parms, 'USE_DATAFILE_ID', g5file.keys()[0])]; 140 | except: is_hdf5 = False 141 | else: 142 | g5file = None; 143 | g5 = h5file[val_def(parms, 'USE_DATAFILE_ID', h5file.keys()[0])]; 144 | if is_hdf5: 145 | g5it = g5['iter'][0]; 146 | parms['MU'] = val_def(parms, 'MU0', str(g5['parms/%d/MU'%(g5it+1)][...])); 147 | parms['DELTA'] = val_def(parms, 'DELTA', str(g5['parms/%d/DELTA'%(g5it+1)][...])); 148 | SelfEnergy, se_coef = get_self_energy_hdf5(g5, parms, wn) 149 | if not g5file is None: g5file.close(); 150 | del g5file, g5; 151 | else: 152 | parms['MU'] = val_def(parms, 'MU0', 0); 153 | parms['DELTA'] = val_def(parms, 'DELTA', 0); 154 | SelfEnergy, se_coef = get_self_energy_text(parms['USE_DATAFILE'], parms, wn) 155 | else: 156 | SelfEnergy = zeros((SPINS, int(parms["N_MAX_FREQ"]), NCOR), dtype = complex); 157 | if int(val_def(parms, 'HARTREE_INIT', 0)) == 1: 158 | delta, mu, nf, VCoulomb = hartree.HartreeRun(parms, extra); 159 | nf = nf[:, corr_id]; 160 | parms['MU'] = mu; parms['DELTA'] = delta; 161 | else: 162 | mu = float(val_def(parms, 'MU0', 0)); # don't know which default MU is good 163 | delta = float(val_def(parms, 'DELTA', 0)); 164 | parms['MU'] = mu; parms['DELTA'] = delta; 165 | Gavg, Gavg0, delta, mu, VCoulomb = averageGreen(delta, mu, 1j*wn, SelfEnergy, parms, Nd, DENSITY, False, extra); 166 | nf = getDensityFromGmat(Gavg, BETA, extra); 167 | se_coef = zeros((SPINS, 2, NCOR), dtype = float); 168 | for L in range(N_LAYERS): se_coef[:, :, L::N_LAYERS] = get_asymp_selfenergy(parms, nf[:, L::N_LAYERS]); 169 | for s in range(SPINS): 170 | for f in range(NCOR): SelfEnergy[s, :, f] = se_coef[s, 0, f]; 171 | if int(val_def(parms, 'NO_TUNEUP', 0)) == 0: parms['MU'] = mu; parms['DELTA'] = delta; 172 | 173 | log_data(h5['SolverData'], 'selfenergy_asymp_coeffs', it, se_coef.flatten(), data_type = float); 174 | save_data(h5, it, ['SelfEnergy'], [SelfEnergy]); 175 | save_parms(h5, it, parms); 176 | save_parms(h5, it+1, parms); 177 | 178 | # get average dispersion up to nth order 179 | NthOrder = 3; 180 | dispersion_avg = system.getAvgDispersion(parms, NthOrder, extra); 181 | h5.create_dataset('SolverData/AvgDispersion', dispersion_avg.shape, dtype = float, data = dispersion_avg); 182 | 183 | h5["iter"][...] = it; # this is the mark that iteration 'it' is done 184 | 185 | return { 186 | 'parms' : parms, 187 | 'h5' : h5, 188 | 'mixer' : mixer, 189 | 'mixer_SE': mixer_SE, 190 | 'extra' : extra, 191 | 'N_LAYERS': N_LAYERS, 192 | 'NCOR' : NCOR, 193 | 'Nd' : Nd, 194 | 'DENSITY' : DENSITY, 195 | 'wn' : wn, 196 | 'corr_id' : corr_id 197 | } 198 | 199 | 200 | if __name__ == '__main__': 201 | # read input arguments 202 | parms, np, parms_file = getOptions(sys.argv[1:]); 203 | 204 | # create or open database (HDF5) 205 | h5file = h5py.File(parms['DATA_FILE'], 'a'); 206 | 207 | vars_dict = initialize(h5file, parms); 208 | 209 | -------------------------------------------------------------------------------- /average_green.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from socket import gethostname 4 | from uuid import uuid1 5 | from mpi4py import MPI 6 | from numpy import * 7 | from functions import getDensityFromGmat, rotate_all, irotate 8 | from share_fun import interp_root, divideTasks 9 | 10 | 11 | def averageGreen(delta0, mu0, w, SelfEnergy, parms, Nd, Ntot, tuneup, extra): 12 | N_LAYERS = int(parms['N_LAYERS']) 13 | FLAVORS = int(parms['FLAVORS']) 14 | SPINS = int(parms['SPINS']) 15 | rot_mat = extra['rot_mat'] 16 | parallel = int(parms.get('KINT_PARALLEL', 2)) 17 | 18 | # calculate intersite Coulomb energy here 19 | Vc = zeros(N_LAYERS, dtype=float) 20 | 21 | # convert self energy to the C++ form 22 | SelfEnergy_rot = array([irotate(SelfEnergy[s], rot_mat) 23 | for s in range(SPINS)]) 24 | SE = array([array([s.flatten() for s in SelfEnergy_rot[n]]) 25 | for n in range(SPINS)]) 26 | 27 | v_delta = array([]) 28 | ddelta = 0. 29 | delta_step = 1. 30 | v_nd = array([]) 31 | dmu = 0. 32 | mu_step = 0.5 33 | 34 | tol = 0.003 35 | firsttime = True 36 | initial_Gasymp = extra['G_asymp_coefs'] if 'G_asymp_coefs' in extra.keys()\ 37 | else None 38 | starting_error = 0. 39 | # Delta loop 40 | while True: 41 | delta = delta0 + ddelta 42 | if initial_Gasymp is not None: 43 | extra['G_asymp_coefs'][:N_LAYERS*FLAVORS] = initial_Gasymp[:N_LAYERS*FLAVORS] - ddelta 44 | v_mu = array([]) 45 | v_n = array([]) 46 | 47 | # mu loop 48 | while True: 49 | mu = mu0 + dmu 50 | if initial_Gasymp is not None: 51 | extra['G_asymp_coefs'] = initial_Gasymp - dmu 52 | 53 | Gavg = integrate(w, delta, mu, SE, parms, extra, parallel) 54 | Gavg_diag = array([[diag(Gavg[s, n]) for n in range(size(Gavg,1))] 55 | for s in range(SPINS)]) 56 | nf = getDensityFromGmat(Gavg_diag, float(parms['BETA']), extra) 57 | my_ntot = sum(nf) if SPINS == 2 else 2*sum(nf) 58 | 59 | print " adjust mu: %.5f %.5f %.5f"%(mu, dmu, my_ntot) 60 | if firsttime: 61 | starting_error = abs(Ntot - my_ntot)/N_LAYERS 62 | Gavg0 = Gavg.copy() 63 | firsttime = False 64 | if Ntot < 0 or abs(Ntot - my_ntot)/N_LAYERS < tol or not tuneup: 65 | break 66 | 67 | v_mu = r_[v_mu, dmu] 68 | v_n = r_[v_n, my_ntot] 69 | if v_n.min() < Ntot and v_n.max() > Ntot: 70 | dmu = interp_root(v_mu, v_n, Ntot) 71 | else: 72 | dmu += (1. if my_ntot < Ntot else -1.)*mu_step 73 | 74 | my_nd = sum(nf[:, :N_LAYERS*FLAVORS]) 75 | if tuneup: 76 | print ('adjust double counting: %.5f %.5f ' 77 | '%.5f %.5f')%(delta, ddelta, my_nd, my_nd/N_LAYERS) 78 | if Nd < 0 or abs(Nd - my_nd)/N_LAYERS < tol or not tuneup: 79 | break 80 | 81 | v_delta = r_[v_delta, ddelta] 82 | v_nd = r_[v_nd, my_nd] 83 | if v_nd.min() < Nd and v_nd.max() > Nd: 84 | ddelta = interp_root(v_delta, v_nd, Nd) 85 | else: 86 | ddelta += (1. if my_nd < Nd else -1.)*delta_step 87 | 88 | # adjusted Gavg with mu_new = mu_0 + N*dmu and 89 | # delta_new = delta_0 + N*ddelta; 90 | N = float(parms.get('TUNEUP_FACTOR', 1)) 91 | if N != 1. and (ddelta != 0. or dmu != 0.) and starting_error < 50*tol: 92 | mu = mu0 + N*dmu 93 | delta = delta0 + N*ddelta 94 | Gavg = integrate(w, delta, mu, SE, parms, extra, parallel) 95 | print ('TUNEUP_FACTOR = %d final adjustment: mu = %.4f, dmu = %.4f, ' 96 | 'delta = %.4f, ddelta = %.4f')%(N, mu, N*dmu, delta, N*ddelta) 97 | 98 | Gavg = array([rotate_all(Gavg[s], rot_mat) for s in range(SPINS)]) 99 | Gavg0 = array([rotate_all(Gavg0[s], rot_mat, need_extra = True) 100 | for s in range(SPINS)]) 101 | if initial_Gasymp is not None: 102 | extra['G_asymp_coefs'] = initial_Gasymp 103 | return Gavg, Gavg0, delta, mu, Vc 104 | 105 | 106 | def integrate(w, DELTA, MU, SelfEnergy, parms, extra, parallel=0): 107 | """ 108 | Main function for k-integration 109 | 110 | Input argument: parallel 111 | 0: no parallel computation (nthreads = 1) 112 | 1: OpenMP computation (nthreads = -1, use OMP_NUM_THREADS) 113 | 2: MPI computation (but no OpenMP, nthreads = 1) 114 | """ 115 | data = { 116 | 'w' : w, 117 | 'DELTA' : DELTA, 118 | 'MU' : MU, 119 | 'SelfEnergy': SelfEnergy, 120 | 'Hf' : float(parms.get('H', 0)), 121 | 'N_LAYERS' : int(parms['N_LAYERS']), 122 | 'FLAVORS' : int(parms['FLAVORS']), 123 | 'SPINS' : int(parms['SPINS']), 124 | 'NORB' : int(parms['NORB']), 125 | 'nthreads' : 1, 126 | 'integrate_mod': parms.get('INTEGRATE_MOD', 'integrate'), 127 | 'extra' : extra, 128 | } 129 | 130 | # this should be changed depending on queuing system 131 | if parallel < 2 or parms['np'] == 1: 132 | if parallel == 1: 133 | data['nthreads'] = -1 134 | # print 'average_green.integrate: OpenMP parallelization' 135 | # print 'average_green.integrate: no MPI parallelization' 136 | return run_task(**data) 137 | # else: print 'average_green.integrate: MPI parallelization' 138 | 139 | # prepare for spawning 140 | nprocs = parms['np'] - 1 141 | myinfo = MPI.Info.Create() 142 | for job_hostfile in ('LSB_DJOB_HOSTFILE', 'PBS_NODEFILE'): 143 | if job_hostfile in os.environ: 144 | myinfo.Set("hostfile", os.environ[job_hostfile]) 145 | print 'Found MPI hostfile: %s'%job_hostfile 146 | running_script = __file__ 147 | comm = MPI.COMM_SELF.Spawn(sys.executable, args=[running_script, 'child'], 148 | maxprocs=nprocs, info=myinfo) 149 | 150 | # prepare data 151 | w = data['w'] 152 | se = data['SelfEnergy'] 153 | del data['w'] 154 | del data['SelfEnergy'] 155 | 156 | # broadcast data 157 | comm.bcast(data, root=MPI.ROOT) 158 | ntasks, displs = divideTasks(nprocs+1, len(w)) # also count the parent 159 | 160 | # this is data for parent process 161 | data['w'] = w[displs[0]:displs[0] + ntasks[0]] 162 | data['SelfEnergy'] = se[:, displs[0]:displs[0]+ntasks[0]] 163 | 164 | ntasks = ntasks[1:] 165 | displs = displs[1:] 166 | for n in range(nprocs): 167 | comm.send(w[displs[n]:displs[n]+ntasks[n]], dest=n, tag=100*n) 168 | comm.send(se[:, displs[n]:displs[n]+ntasks[n]], dest=n, tag=100*n+1) 169 | 170 | # run task from parent process 171 | Gout = run_task(**data) 172 | 173 | # collect data 174 | for n in range(nprocs): 175 | results = comm.recv(source=n, tag=100*n+3) 176 | Gout = r_['1', Gout, results] 177 | 178 | comm.Disconnect() 179 | return Gout 180 | 181 | 182 | def run_child_task(): 183 | comm = MPI.Comm.Get_parent() 184 | rank = comm.Get_rank() 185 | # print 'child task rank %d/%d at %s'%(rank, comm.Get_size(), gethostname()) 186 | 187 | data = comm.bcast(None, root=0) 188 | data['w'] = comm.recv(source=0, tag=100*rank) 189 | data['SelfEnergy'] = comm.recv(source=0, tag=100*rank+1) 190 | 191 | out = run_task(**data) 192 | comm.send(out, dest=0, tag=100*rank+3) 193 | comm.Disconnect() 194 | 195 | 196 | # task run by both parent and children 197 | def run_task(w, DELTA, MU, SelfEnergy, Hf, N_LAYERS, FLAVORS, SPINS, NORB, 198 | nthreads, integrate_mod, extra): 199 | # print >> sys.stderr, gethostname(), len(w); 200 | int_module = __import__(integrate_mod, fromlist=[]) 201 | nbin = len(w) 202 | bp, wf = extra['GaussianData'] 203 | if 'HR' in extra: 204 | Gavg = array([int_module.calc_Gavg(w, DELTA, MU, SelfEnergy[n].copy(), 205 | extra['HR'], extra['R'], 206 | Hf*(-1)**n, bp, wf, 207 | nthreads).reshape(nbin, NORB, NORB) 208 | for n in range(SPINS)]) 209 | # swap the Gavg to the format of my code 210 | swap_vec = zeros((2, N_LAYERS*FLAVORS), dtype=int) 211 | for L in range(N_LAYERS): 212 | for f in range(FLAVORS): 213 | swap_vec[:,f*N_LAYERS+L] = array([f*N_LAYERS+L, L*FLAVORS+f]) 214 | for s in range(SPINS): 215 | for n in range(len(Gavg[s])): 216 | Gavg[s, n,:,swap_vec[0]] = Gavg[s, n, :, swap_vec[1]] 217 | Gavg[s, n,swap_vec[0],:] = Gavg[s, n, swap_vec[1], :] 218 | else: 219 | Gavg = array([int_module.calc_Gavg(w, DELTA, MU, SelfEnergy[n].copy(), 220 | extra['tight_binding_parms'], 221 | Hf*(-1)**n, bp, wf, 222 | nthreads).reshape(nbin, NORB, NORB) 223 | for n in range(SPINS)]) 224 | return Gavg 225 | 226 | 227 | # main part just for child only 228 | if __name__ == '__main__': 229 | if sys.argv[1] == 'child': 230 | run_child_task(); 231 | else: 232 | print >> sys.stderr, ('This is a child process for MPI integrate. ' 233 | 'Improper running.') 234 | sys.exit() 235 | -------------------------------------------------------------------------------- /include/inverse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * several ways to inverse a matrix 3 | * work only for square matrix 4 | * no pseudoinverse here 5 | * Hung Dang 6 | * Apr 21, 2011 7 | */ 8 | 9 | #ifndef __INVERSE_H__ 10 | #define __INVERSE_H__ 11 | 12 | #include 13 | #include 14 | 15 | #ifdef EIGEN_UMFPACK_SUPPORT 16 | #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET 17 | #include 18 | #endif 19 | 20 | namespace inv { 21 | 22 | extern "C" { 23 | void zgetrf_(const int &M, const int &N, std::complex *A, const int &LDA, int *IPIV, int &INFO); 24 | void zgbtrf_(const int &M, const int &N, const int &KL, const int &KU, std::complex *A, const int &LDA, int *IPIV, int &INFO); 25 | void zgbtrs_(const char &TRANS, const int &N, const int &KL, const int &KU, const int &NRHS, 26 | const std::complex *A, const int &LDA, int *IPIV, std::complex *B, const int &LDB, int &INFO); 27 | void zgetrs_(const char &TRANS, const int &N, const int &NRHS, const std::complex *A, const int &LDA, 28 | int *IPIV, std::complex *B, const int &LDB, int &INFO); 29 | 30 | void dgetrf_(const int &M, const int &N, double *A, const int &LDA, int *IPIV, int &INFO); 31 | void dgbtrf_(const int &M, const int &N, const int &KL, const int &KU, double *A, const int &LDA, int *IPIV, int &INFO); 32 | void dgbtrs_(const char &TRANS, const int &N, const int &KL, const int &KU, const int &NRHS, 33 | const double *A, const int &LDA, int *IPIV, double *B, const int &LDB, int &INFO); 34 | void dgetrs_(const char &TRANS, const int &N, const int &NRHS, const double *A, const int &LDA, int *IPIV, double *B, const int &LDB, int &INFO); 35 | } 36 | 37 | 38 | inline int max(int a, int b) { return (a > b) ? a : b;} 39 | inline int min(int a, int b) { return (a < b) ? a : b;} 40 | 41 | 42 | // class for band matrix working with lapack 43 | // square matrix only 44 | template 45 | class BandMatrix { 46 | public: 47 | typedef Eigen::Matrix<_Scalar, 2*KL+KU+1, _Cols> raw_matrix_t; 48 | typedef _Scalar Scalar; 49 | enum { 50 | RowsAtCompileTime = 2*KL+KU+1, 51 | ColsAtCompileTime = _Cols 52 | }; 53 | 54 | BandMatrix() : mat() {} 55 | BandMatrix(const int &N) : mat(2*KL+KU+1, N) {} 56 | BandMatrix(const BandMatrix &b) : mat(b.mat) {} 57 | 58 | void resize(const int &N) { mat.resize(2*KL+KU+1, N); } 59 | void fill(const Scalar &v) { mat.fill(v); } 60 | 61 | int supers() const { return KU; } 62 | int subs() const { return KL; } 63 | int cols() const { return mat.cols(); } 64 | int rows() const { return mat.cols(); } 65 | 66 | void print_raw_mat(std::ostream &os) const { os << mat << std::endl;} 67 | 68 | void to_dense_matrix(Eigen::Matrix<_Scalar, _Cols, _Cols> &dense_mat) 69 | { 70 | int N = mat.cols(); 71 | dense_mat.resize(N, N); 72 | dense_mat.fill(0); 73 | for (int j = 0; j < N; ++j) 74 | for (int i = max(0, j-KU); i <= min(N-1, j+KL); ++i) 75 | dense_mat(i,j) = mat(KL+KU+i-j, j); 76 | } 77 | 78 | inline const _Scalar& operator()(const int &i, const int &j) const 79 | { 80 | int N = mat.cols(); 81 | if (max(0, j-KU) <= i && min(N-1, j+KL) >= i) { 82 | return mat(KL+KU+i-j, j); 83 | } else 84 | throw "Out of band of the band matrix"; 85 | } 86 | 87 | inline _Scalar& operator()(const int &i, const int &j) 88 | { 89 | int N = mat.cols(); 90 | if (max(0, j-KU) <= i && min(N-1, j+KL) >= i) { 91 | return mat(KL+KU+i-j, j); 92 | } else 93 | throw "Out of band of the band matrix"; 94 | } 95 | 96 | inline const _Scalar& raw_index(const int &i, const int &j) const { return mat(i, j); } 97 | inline _Scalar& raw_index(const int &i, const int &j) { return mat(i, j); } 98 | inline _Scalar *data() { return mat.data(); } 99 | inline const _Scalar *data() const { return mat.data(); } 100 | 101 | 102 | private: 103 | raw_matrix_t mat; 104 | }; 105 | 106 | template 107 | inline std::ostream &operator<<(std::ostream &os, const BandMatrix<_Scalar, KL, KU, _Cols> &M) 108 | { 109 | int N = M.cols(); 110 | for (int i = 0; i < N; ++i) { 111 | for (int j = 0; j < N; ++j) 112 | if (i <= min(N-1, j+KL) && i >= max(0, j-KU)) 113 | os << M(i, j) << " "; 114 | else 115 | os << "0" << " "; 116 | os << std::endl; 117 | } 118 | return os; 119 | } 120 | 121 | 122 | // number traits 123 | template 124 | struct n_traits {}; 125 | 126 | template<> 127 | struct n_traits > { 128 | static void xgetrf_(const int &M, const int &N, std::complex *A, const int &LDA, int *IPIV, int &INFO) { 129 | zgetrf_(M, N, A, LDA, IPIV, INFO); 130 | } 131 | static void xgbtrf_(const int &M, const int &N, const int &KL, const int &KU, 132 | std::complex *A, const int &LDA, int *IPIV, int &INFO) { 133 | zgbtrf_(M, N, KL, KU, A, LDA, IPIV, INFO); 134 | } 135 | static void xgbtrs_(const char &TRANS, const int &N, const int &KL, const int &KU, const int &NRHS, 136 | const std::complex *A, const int &LDA, int *IPIV, std::complex *B, const int &LDB, int &INFO) { 137 | zgbtrs_(TRANS, N, KL, KU, NRHS, A, LDA, IPIV, B, LDB, INFO); 138 | } 139 | static void xgetrs_(const char &TRANS, const int &N, const int &NRHS, const std::complex *A, const int &LDA, 140 | int *IPIV, std::complex *B, const int &LDB, int &INFO) { 141 | zgetrs_(TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO); 142 | } 143 | }; 144 | 145 | template<> 146 | struct n_traits { 147 | static void xgetrf_(const int &M, const int &N, double *A, const int &LDA, int *IPIV, int &INFO) { 148 | dgetrf_(M, N, A, LDA, IPIV, INFO); 149 | } 150 | static void xgbtrf_(const int &M, const int &N, const int &KL, const int &KU, double *A, const int &LDA, int *IPIV, int &INFO) { 151 | dgbtrf_(M, N, KL, KU, A, LDA, IPIV, INFO); 152 | } 153 | static void xgbtrs_(const char &TRANS, const int &N, const int &KL, const int &KU, const int &NRHS, 154 | const double *A, const int &LDA, int *IPIV, double *B, const int &LDB, int &INFO) { 155 | dgbtrs_(TRANS, N, KL, KU, NRHS, A, LDA, IPIV, B, LDB, INFO); 156 | } 157 | static void xgetrs_(const char &TRANS, const int &N, const int &NRHS, const double *A, const int &LDA, 158 | int *IPIV, double *B, const int &LDB, int &INFO) { 159 | dgetrs_(TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO); 160 | } 161 | }; 162 | 163 | 164 | // matrix traits 165 | template 166 | struct matrix_traits {}; 167 | 168 | // general dense matrix 169 | template 170 | struct matrix_traits > { 171 | static void xxxtrf(const int &N, Eigen::Matrix &A, Eigen::VectorXi &IPIV, int &INFO) { 172 | n_traits::xgetrf_(N, N, A.data(), N, IPIV.data(), INFO); 173 | } 174 | static void xxxtrs(const int &N, const Eigen::Matrix &A, Eigen::Matrix &B, Eigen::VectorXi &IPIV, int &INFO) { 175 | static const char TRANS = 'N'; 176 | n_traits::xgetrs_(TRANS, N, N, A.data(), N, IPIV.data(), B.data(), N, INFO); 177 | } 178 | }; 179 | 180 | // band matrix 181 | template 182 | struct matrix_traits > { 183 | static void xxxtrf(const int &N, BandMatrix &A, Eigen::VectorXi &IPIV, int &INFO) { 184 | static const int LDA = 2*KL+KU+1; 185 | n_traits::xgbtrf_(N, N, KL, KU, A.data(), LDA, IPIV.data(), INFO); 186 | } 187 | static void xxxtrs(const int &N, const BandMatrix &A, Eigen::Matrix &B, 188 | Eigen::VectorXi &IPIV, int &INFO) { 189 | static const int LDA = 2*KL+KU+1; 190 | static const char TRANS = 'N'; 191 | n_traits::xgbtrs_(TRANS, N, KL, KU, N, A.data(), LDA, IPIV.data(), B.data(), N, INFO); 192 | } 193 | }; 194 | 195 | 196 | // main routine 197 | template 198 | void inverse(matrix_t &mat, Eigen::Matrix &result) 199 | { 200 | if (mat.rows() != mat.cols()) 201 | throw "This code works for square matrix only."; 202 | int N = mat.rows(), INFO; 203 | Eigen::VectorXi IPIV(N); 204 | 205 | matrix_traits::xxxtrf(N, mat, IPIV, INFO); 206 | if (INFO != 0) 207 | throw "LU decomposition failed."; 208 | 209 | result.resize(N, N); 210 | result.setIdentity(N, N); 211 | matrix_traits::xxxtrs(N, mat, result, IPIV, INFO); 212 | if (INFO != 0) 213 | throw "Inversion failed."; 214 | } 215 | 216 | 217 | 218 | // for sparse matrix 219 | #ifdef EIGEN_UMFPACK_SUPPORT 220 | template 221 | void sparse_inverse(const Eigen::SparseMatrix &mat, matrix_t &result) 222 | { 223 | int N = mat.rows(); 224 | if (mat.cols() != N) 225 | throw "This code works for square matrix only."; 226 | 227 | if ((matrix_t::ColsAtCompileTime != Eigen::Dynamic) && (matrix_t::ColsAtCompileTime != N)) 228 | throw "Size of input and output matrices not matched."; 229 | 230 | Eigen::SparseLU, Eigen::UmfPack> lu(mat); 231 | if(!lu.succeeded()) 232 | throw "Sparse matrix: LU decomposition failed."; 233 | 234 | matrix_t B; 235 | B.setIdentity(N, N); 236 | result.resize(N, N); 237 | if (!lu.solve(B, &result)) 238 | throw "Inversion failed."; 239 | } 240 | 241 | #endif // EIGEN_UMFPACK_SUPPORT 242 | 243 | } // end namespace inv 244 | 245 | #endif // __INVERSE_H__ 246 | -------------------------------------------------------------------------------- /cppext/cubic_spline_ft/fouriertransform.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * 3 | * ALPS DMFT Project 4 | * 5 | * Copyright (C) 2005 - 2009 by Emanuel Gull 6 | * Philipp Werner , 7 | * Sebastian Fuchs 8 | * Matthias Troyer 9 | * 10 | * 11 | * This software is part of the ALPS Applications, published under the ALPS 12 | * Application License; you can use, redistribute it and/or modify it under 13 | * the terms of the license, either version 1 or (at your option) any later 14 | * version. 15 | * 16 | * You should have received a copy of the ALPS Application License along with 17 | * the ALPS Applications; see the file LICENSE.txt. If not, the license is also 18 | * available from http://alps.comp-phys.org/. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 | * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 | * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | * DEALINGS IN THE SOFTWARE. 27 | * 28 | *****************************************************************************/ 29 | 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "fouriertransform.h" 36 | 37 | using namespace Eigen; 38 | 39 | typedef boost::numeric::ublas::matrix dense_matrix; 40 | 41 | FourierTransformer::FourierTransformer(const double beta, 42 | const VectorXd &ftail) 43 | : beta_(beta), c_(ftail) { 44 | if (c_.size() < 3) 45 | throw std::length_error("The tail should contains up to at least the third order"); 46 | } 47 | 48 | // backward_ft G(iwn)->G(tau) works for cluster Green's functions 49 | void FourierTransformer::backward_ft(const VectorXcd &G_omega, 50 | VectorXd &G_tau, const int N_tau) const { 51 | unsigned int N_omega = G_omega.size(); 52 | VectorXcd G_omega_no_model(G_omega); 53 | double dt = beta_/N_tau; 54 | 55 | G_tau.resize(N_tau+1); 56 | if (c_(0) == 0 && c_(1) == 0 && c_(2) == 0) { 57 | //nothing happening in this gf. 58 | for (int i = 0; i <= N_tau; i++) { 59 | G_tau(i)=0.; 60 | } 61 | } else { 62 | for (int k = 0; k < N_omega; k++) { 63 | std::complex iw(0,(2*k+1)*M_PI/beta_); 64 | G_omega_no_model(k) -= f_omega(iw, c_(0),c_(1), c_(2)); 65 | } 66 | for (int i=0; i(Np1); 94 | 95 | for (int i=1; i(Np1); 109 | boost::numeric::ublas::vector ipivot(A.size1()); 110 | boost::numeric::bindings::lapack::gesv(A, ipivot,spline_matrix); 111 | } 112 | 113 | void evaluate_second_derivatives(double dt, dense_matrix & spline_matrix, 114 | std::vector & g, std::vector & second_derivatives, 115 | const double c1g, const double c2g, const double c3g) { 116 | // g, rhs and second_derivatives have dimension N+1 117 | int Np1 = spline_matrix.size1(); 118 | //assert(c1g==1); 119 | // rhs is the vector containing the data of the curve y = g(tau), which allows to 120 | // compute the vector of second derivatives y'' at times tau_n by evaluating 121 | // y'' = spline_matrix * rhs(y) 122 | // 123 | // 0 124 | // y0 - 2*y1 + y2 125 | // y1 - 2*y2 + y3 126 | // rhs = 6/(delta_tau)^2 * ... 127 | // 128 | // yNp1-3 - 2*yNp1-2 + yNp1-1 129 | // y0 - y1 + yNp1-2 - yNp1-1 130 | 131 | std::vector rhs(Np1, 0); 132 | std::cout<<"constants: "<= 0; --i) 190 | X(i) = (Z(i) - X(i+1) - d(i)*X(L-1))/a(i); 191 | X(L) = S2 - X(0); 192 | 193 | return X; 194 | } 195 | 196 | 197 | // forward_ft G(tau)->G(iwn) works for cluster Green's functions 198 | void FourierTransformer::Armin_forward_ft(const VectorXd >au, VectorXcd &gomega, 199 | const int num_matsubara) const { 200 | int N = gtau.size()-1; 201 | double dt = beta_/N; 202 | VectorXcd v_omega(num_matsubara); 203 | gomega.resize(num_matsubara); 204 | VectorXd v2(ArminGetSecondDerivative(gtau, beta_, c_(1), -c_(2))); 205 | 206 | // DEBUG 207 | // const VectorXd &v(gtau); 208 | // std::cout<<"c1 is: "< iw(0, M_PI*(2*k+1)/beta_); 215 | for (int n = 1; n < N; n++) { 216 | //partial integration, four times. 217 | //Then approximate the fourth derivative by finite differences 218 | v_omega(k) += exp(iw*(n*dt))*(v2(n+1)-2*v2(n)+v2(n-1)); 219 | } 220 | // the third derivative, on the boundary 221 | v_omega(k) += (v2(1) - v2(0) + v2(N) - v2(N-1)); 222 | v_omega(k) *= 1./(dt*iw*iw*iw*iw); 223 | // the boundary terms of the first, second, and third partial integration. 224 | v_omega(k) += f_omega(iw, c_(0), c_(1), c_(2)); 225 | //std::cout<<"derivative at boundary: "<<-v2[1] + v2[0] + v2[N] - v2[N-1]<<" divisor: "<< 1./(dt*iw*iw*iw*iw)<G(iwn) works for cluster Green's functions 232 | void FourierTransformer::forward_ft(const VectorXd >au, VectorXcd &gomega, 233 | const int num_matsubara) const { 234 | std::vector v(gtau.size()); 235 | std::vector > v_omega(num_matsubara); 236 | int Np1 = v.size(); 237 | int N = Np1-1; 238 | int N_omega = v_omega.size(); 239 | double dt = beta_/N; 240 | 241 | gomega.resize(num_matsubara); 242 | for(int tau=0;tau v2(Np1, 0); 251 | evaluate_second_derivatives(dt/*,beta_*/, spline_matrix, v, v2, 252 | c_(0), c_(1), c_(2)); 253 | v_omega.assign(N_omega, 0); 254 | for (int k=0; k iw(0, M_PI*(2*k+1)/beta_); 256 | for (int n=1; n log_conv[i-1]: count += 1; 79 | if count >= 3: 80 | print 'Cannot have a better converged result!'; 81 | # return True; 82 | v = new - old; 83 | if reltol is not None: tol = reltol; err = linalg.norm(v)/linalg.norm(new); 84 | else: tol = abstol; err = linalg.norm(v); 85 | ret = r_[tol, err, mixing]; 86 | if log: 87 | log_data(h5, 'log_convergence', iter, ret); 88 | log_conv = h5['log_convergence'][:]; 89 | if len(log_conv) < Ntime: return False; 90 | log_conv = log_conv[-3:, :]; 91 | if all(log_conv[:,2] < tol): return True; 92 | else: return False; 93 | if err < tol: return True; 94 | else: return False; 95 | 96 | 97 | def log_data(h5, log_name, it, data, data_type = 'f8'): 98 | dt = r_[it, data]; 99 | length = len(dt); 100 | if not log_name in h5.keys(): 101 | log = h5.create_dataset(log_name, (1, length), dtype = data_type, maxshape = (None, length)); 102 | new_pos = 0; 103 | else: 104 | log = h5[log_name]; 105 | new_pos = log.shape[0]; 106 | if length != log.shape[1]: 107 | return False; 108 | length = log.shape[1]; 109 | log.resize((new_pos+1, length)); 110 | log[new_pos, :] = dt; 111 | return True; 112 | 113 | def log_density(h5, iter, parms, nf): 114 | N_LAYERS = int(parms['N_LAYERS']); 115 | MU = float(parms["MU"]); 116 | data = array([MU, sum(nf), sum(nf)/float(N_LAYERS)]); 117 | data = r_[data, nf.flatten()]; 118 | log_data(h5, 'log_density', iter, data); 119 | 120 | reportfile = 'dmft.out'; 121 | fileexist = os.path.isfile(reportfile); 122 | out = open(reportfile, 'a'); 123 | if not fileexist: 124 | if int(val_def(parms, 'AFM', 0)) > 0: out.write('# AFM calculation\n'); 125 | out.write('# Iter MU Ntot Ntot/site Nd nf\n'); 126 | if iter == 0: out.write('\n# ID: %s\n'%parms['ID']); 127 | nf1 = c_[nf[:, :-1:N_LAYERS], nf[:,-1]]; 128 | pattern = '%d %.5f %.2f %.4f %.4f ' + len(nf1.flatten())*' %.4f' + '\n'; 129 | data1 =r_[MU, sum(nf), sum(nf)/float(N_LAYERS), sum(nf1[:,:-1]), nf1.flatten()]; 130 | out.write(pattern%tuple(r_[iter, data1])); 131 | out.close(); 132 | 133 | def save_data(h5, it, list_str, list_data): 134 | assert(len(list_str) == len(list_data)); 135 | for i in range(0, len(list_str)): 136 | h5.create_dataset(list_str[i]+'/'+str(it), list_data[i].shape, list_data[i].dtype, data = list_data[i]); 137 | 138 | def save_parms(h5, iter, parms): 139 | grp = h5.create_group("parms/" + str(iter)); 140 | for k, v in parms.iteritems(): 141 | grp.create_dataset(k, dtype = h5py.new_vlen(str), data = str(v)); 142 | 143 | def load_parms(h5, iter): 144 | p = dict(); 145 | grp = h5["parms/" + str(iter)]; 146 | for k, v in grp.iteritems(): 147 | p[k] = str(v[...]); 148 | return p; 149 | 150 | def val_def(parms, item, default): 151 | if item in parms.keys(): return parms[item]; 152 | else: return default; 153 | 154 | def grule(n): 155 | # return : 156 | # bp : based points 157 | # wf : corresponding weights 158 | # 159 | # [bp,wf]=grule(n) 160 | # This function computes Gauss base points and weight factors 161 | # using the algorithm given by Davis and Rabinowitz in 'Methods 162 | # of Numerical Integration', page 365, Academic Press, 1975. 163 | 164 | bp=zeros((n,)); 165 | wf=zeros((n,)); 166 | iter=2; 167 | m=int(fix((n+1)/2)); 168 | e1=n*(n+1); 169 | mm=4*m-1; 170 | t=(pi/(4*n+2))*arange(3,mm+1,4); 171 | nn=(1-(1-1/n)/(8*n*n)); 172 | xo=nn*cos(t); 173 | for j in range(1,iter+1): 174 | pkm1=1; 175 | pk=xo; 176 | for k in range(2,n+1): 177 | t1=xo*pk; 178 | pkp1=t1-pkm1-(t1-pkm1)/k+t1; 179 | pkm1=pk; pk=pkp1; 180 | den=1.-xo*xo; 181 | d1=n*(pkm1-xo*pk); 182 | dpn=d1/den; 183 | d2pn=(2*xo*dpn-e1*pk)/den; 184 | d3pn=(4*xo*d2pn+(2-e1)*dpn)/den; 185 | d4pn=(6*xo*d3pn+(6-e1)*d2pn)/den; 186 | u=pk/dpn; 187 | v=d2pn/dpn; 188 | h=-u*(1+(.5*u)*(v+u*(v*v-u*d3pn/(3*dpn)))); 189 | p=pk+h*(dpn+(.5*h)*(d2pn+(h/3)*(d3pn+.25*h*d4pn))); 190 | dp=dpn+h*(d2pn+(.5*h)*(d3pn+h*d4pn/3)); 191 | h=h-p/dp; 192 | xo=xo+h; 193 | 194 | for i in range(0, xo.size): 195 | bp[i]=-xo[i]-h[i]; 196 | fx=d1-h*e1*(pk+(h/2)*(dpn+(h/3)*(d2pn+(h/4)*(d3pn+(.2*h)*d4pn)))); 197 | for i in range(0, xo.size): 198 | wf[i]=2*(1-bp[i]**2)/(fx[i]**2); 199 | if ( (m+m) > n ): 200 | bp[m-1]=0; 201 | if ( not ((m+m) == n) ): 202 | m=m-1; 203 | jj=arange(1,m+1); 204 | n1j=(n+1-jj); 205 | bp[n1j-1]=-bp[jj-1]; 206 | wf[n1j-1]=wf[jj-1]; 207 | 208 | return bp, wf 209 | 210 | def interp_root(xi, yi, y0): 211 | ind = argsort(xi); 212 | x = array(xi)[ind]; 213 | y = array(yi)[ind] - y0; 214 | 215 | order = 1; # linear interpolation only, no need to be fancy 216 | tck = scipy.interpolate.splrep(x, y, k = order); 217 | fun = lambda x: scipy.interpolate.splev(x, tck); 218 | return scipy.optimize.bisect(fun, x[argmin(y)], x[argmax(y)]); 219 | 220 | def divideTasks(np, nt): 221 | remain = nt % np; 222 | ret = zeros((np, ), dtype = 'i4'); 223 | dpl = zeros((np, ), dtype = 'i4'); 224 | ret[0] = nt/np; 225 | dpl[0] = 0; 226 | for i in range(1, np): 227 | ret[i] = nt/np; 228 | if remain > 0: 229 | ret[i] = ret[i] + 1; 230 | remain = remain - 1; 231 | dpl[i] = dpl[i-1] + ret[i - 1]; 232 | return ret, dpl; 233 | 234 | 235 | #-----MIXING-----# 236 | class Mixing: 237 | def __init__(self, mix, mixing_fixed = 1): 238 | self.mix = mix; 239 | self.mixing_data = dict({ 240 | 'Vi' : None, 241 | 'lastF' : None, 242 | 'lastVi' : None, 243 | 'dF' : [], 244 | 'dV' : [], 245 | 'F' : [], 246 | 'Vo' : [], 247 | 'mixing_length' : 3, 248 | 249 | 'linmix' : mix - floor(mix) if floor(mix) != mix else 1., 250 | 'error_change' : 0, 251 | 'error_inc' : 0, 252 | 'error_incmax' : 3, 253 | 'error_dec' : 0, 254 | 'error_decmax' : 3, 255 | 'mix_factor' : 2/3., 256 | 'last_error' : inf 257 | }); 258 | if mixing_fixed > 0: del self.mixing_data['linmix']; 259 | 260 | 261 | def rmm_diis_mixing(self, R): 262 | N = len(R); 263 | A = ones((N+1,N+1), dtype=float); 264 | A[-1,-1] = 0; 265 | for i in xrange(0, N): 266 | for j in xrange(0, N): A[i,j] = dot(R[i], R[j]); 267 | B = zeros(N+1); B[-1] = 1.; 268 | alpha = linalg.solve(A, B)[:N]; 269 | print alpha.transpose(); 270 | return alpha; 271 | 272 | 273 | def broyden_mixing(self, Fm, dV, dF, alpha = 0.7, w0 = 0.01, w = None, start = True): 274 | M = len(dV); 275 | correction = alpha*Fm; 276 | if M == 0 or not start: return correction; 277 | 278 | if w is None: w = ones(M); 279 | u = [alpha*dF[n] + dV[n] for n in range(0,M)]; 280 | a = array([[w[k]*w[n]*dot(conjugate(dF[n]), dF[k]) for n in range(0,M)] for k in range(0,M)]); 281 | cm = array([w[k]*dot(conjugate(dF[k]), Fm) for k in range(0,M)]); 282 | beta = linalg.inv(w0**2*identity(M) + a); 283 | gm = dot(cm, beta); 284 | print gm.transpose(); 285 | 286 | for n in range(0, M): correction -= w[n]*gm[n]*u[n]; 287 | return correction; 288 | 289 | def get_mixing_value(self): 290 | return self.mix if 'linmix' not in self.mixing_data else self.mixing_data['linmix']; 291 | 292 | def do_task(self, so): 293 | mix = self.mix; 294 | data = self.mixing_data; 295 | mixing_length = 5 if 'mixing_length' not in data else data['mixing_length']; 296 | if 'it' not in data: data['it'] = 0; 297 | else: data['it'] += 1; 298 | Vi = so.flatten(); 299 | Vo = so.flatten(); 300 | if data['Vi'] is None: 301 | data['Vi'] = Vo.copy(); 302 | return Vi; 303 | else: 304 | this_error = linalg.norm(Vo - data['Vi'])/linalg.norm(Vo); 305 | data['error_change'] = this_error - data['last_error']; 306 | data['last_error'] = this_error; 307 | 308 | if 'start_other_mixing' not in data: data['start_other_mixing'] = False; 309 | 310 | crit0 = 1e-1; 311 | crit = 5*crit0 if data['start_other_mixing'] else crit0; 312 | if linalg.norm(Vo - data['Vi'])/linalg.norm(Vo) > crit or (mix > 0 and mix <= 1): data['start_other_mixing'] = False; 313 | else: data['start_other_mixing'] = True; 314 | 315 | if not data['start_other_mixing']: # linear mixing 316 | linmix = mix-floor(mix) if floor(mix) != mix else 1.; 317 | mixmin = 0.01; 318 | mixmax = 1.00; 319 | dmix = 0.1; 320 | if 'linmix' in data: 321 | if data['error_change'] > 0: 322 | data['error_dec'] = 0; 323 | data['error_inc'] += 1; 324 | if data['error_inc'] > data['error_incmax']: 325 | data['error_inc'] = 0; 326 | data['linmix'] *= data['mix_factor']; 327 | elif data['error_change'] < 0: 328 | data['error_dec'] += 1; 329 | if data['error_dec'] > data['error_decmax']: 330 | data['linmix'] += dmix; 331 | data['error_dec'] = 0; 332 | if data['linmix'] < mixmin: data['linmix'] = mixmin; 333 | if data['linmix'] > mixmax: data['linmix'] = mixmax; 334 | linmix = data['linmix']; 335 | 336 | print "Linear mixing ... mixing number = %.2f"%linmix; 337 | if linmix < 0.01: 338 | print "Mixing number is too small, probably it cannot converge"; 339 | return None; 340 | Vi = Vo*linmix + (1.0-linmix)*data['Vi']; 341 | 342 | start_other_mixing = data['start_other_mixing']; 343 | if mix > 1 and mix <= 2 and start_other_mixing: # Broyden mixing 344 | alpha = mix - 1; 345 | print "Broyden mixing, mixing length = %d, alpha = %.2f ..."%(mixing_length, alpha); 346 | Vi = data['Vi'].copy(); 347 | Fm = Vo - Vi; 348 | if data['lastF'] is not None: 349 | data['dF'].append((Fm - data['lastF'])/linalg.norm(Fm - data['lastF'])); 350 | data['dV'].append((Vi - data['lastVi'])/linalg.norm(Fm - data['lastF'])); 351 | data['lastVi'] = Vi; data['lastF'] = Fm; 352 | if len(data['dF']) > mixing_length: data['dF'].pop(0); data['dV'].pop(0); 353 | Vi += self.broyden_mixing(Fm, data['dV'], data['dF'], alpha, start = start_other_mixing); 354 | 355 | if mix > 2: # RMM-DIIS mixing 356 | data['F'].append(Vo-data['Vi']); 357 | data['Vo'].append(Vo); 358 | if len(data['F']) > mixing_length: 359 | data['F'].pop(0); 360 | data['Vo'].pop(0); 361 | if start_other_mixing: 362 | print "RMM-DIIS mixing, mixing_length = %d ..."%mixing_length; 363 | alpha = self.rmm_diis_mixing(data['F']); 364 | Vi = zeros(Vo.shape, dtype = Vo.dtype); 365 | for i in xrange(0, len(alpha)): Vi += alpha[i]*data['Vo'][i]; 366 | 367 | data['Vi'] = Vi.copy(); 368 | return Vi; 369 | #-----END MIXING-----# 370 | -------------------------------------------------------------------------------- /eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import h5py, sys, re, system_dependence as system; 4 | 5 | from numpy import *; 6 | from matplotlib.pyplot import *; 7 | from functions import *; 8 | from share_fun import *; 9 | from average_green import averageGreen; 10 | 11 | 12 | def plot_data(h5, st, iter = None, L = None, f = None, 13 | noshow = True, part = None, style = '', 14 | legend_loc = 0, is_subplot = True, 15 | all_spins = True, average_spin = False, 16 | xlimit = None): 17 | if iter == None: iter = h5['iter'][0]; 18 | parms = gget(h5, 'parms', iter); 19 | N_LAYERS = int(parms['N_LAYERS']); SPINS = int(parms['SPINS']); 20 | y = gget(h5, st, iter, L, f); 21 | is_matsubara = True; 22 | if average_spin: 23 | all_spins = False 24 | y = array([mean(y, 0)]) 25 | 26 | 27 | if st == 'Gtau' or st == 'hybtau': 28 | x = linspace(0, 1, size(y, 1)); 29 | is_matsubara = False; 30 | else: x = gget(h5, 'wn')[:size(y,1)]; 31 | 32 | idx = gget(h5, 'idx', L = L, f = f); 33 | legend_str = []; 34 | for i in idx: 35 | layer = int(i) % N_LAYERS; 36 | flavor = int(i) / N_LAYERS; 37 | legend_str.append('L=' + str(layer) + ';F=' + str(flavor) + ';it=' + str(iter)); 38 | 39 | xlimit = None; 40 | if is_matsubara: 41 | xlb = 'Frequencies'; 42 | if 'CUTOFF_FREQ' not in parms: parms['CUTOFF_FREQ'] = (2*int(parms['N_CUTOFF'])+1)*pi/float(parms['BETA']) 43 | if 'MAX_FREQ' not in parms: parms['MAX_FREQ'] = (2*int(parms['N_MAX_FREQ'])+1)*pi/float(parms['BETA']) 44 | if xlimit is None: 45 | xlimit = [0, min(float(parms['CUTOFF_FREQ'])*5/4., float(parms['MAX_FREQ']))]; 46 | if part == None: 47 | if is_subplot: subplot(1,2,1); 48 | else: figure(0); 49 | plot(x, y[0].real, style+'-'); 50 | if SPINS > 1 and all_spins: plot(x, y[1].real, style + '--'); 51 | xlim(xlimit); 52 | title('Real part'); 53 | xlabel(xlb); ylabel(st); 54 | legend(legend_str, loc = legend_loc); 55 | if is_subplot: subplot(1,2,2); 56 | else: figure(1); 57 | plot(x, y[0].imag, style+'-'); 58 | if SPINS > 1 and all_spins: plot(x, y[1].imag, style + '--'); 59 | xlim(xlimit); 60 | title('Imaginary part'); 61 | xlabel(xlb); ylabel(st); 62 | # legend(legend_str, loc = legend_loc); 63 | if not noshow: show(); 64 | return; 65 | if part == 'real' or part == 0: y = y.real; 66 | if part == 'imag' or part == 1: y = y.imag; 67 | else: xlb = 'Tau'; 68 | 69 | plot(x, y[0], style); 70 | if SPINS > 1 and all_spins: plot(x, y[1], style + '--'); 71 | xlabel(xlb); ylabel(st); 72 | legend(legend_str, loc = legend_loc); 73 | 74 | if xlimit is not None: xlim(xlimit); 75 | if not noshow: show(); 76 | 77 | 78 | def view_log(h5, id): 79 | parms = gget(h5, 'parms'); 80 | print "U = " + parms["U"] + "; J = " + val_def(parms, 'J', 0) + "; BETA = " + parms["BETA"]; 81 | print "N_LAYERS = " + parms["N_LAYERS"] 82 | log = gget(h5, 'log'); 83 | print log[id]; 84 | 85 | 86 | def load_data(datafile, ID = None): 87 | h5file = h5py.File(datafile, 'r'); 88 | if ID is None: h5 = h5file[h5file.keys()[0]]; 89 | else: h5 = h5file[str(ID)]; 90 | return h5, h5file; 91 | 92 | 93 | def getRenormFactor(h5, npoint = 2, norder = 1, it = None): 94 | if it == None: it = h5['iter'][0]; 95 | nlayers = int(gget(h5, 'parms')['N_LAYERS']) 96 | se = gget(h5, 'se', it)[:, :npoint, :]; 97 | wn = gget(h5, 'wn')[:npoint]; 98 | z = zeros((size(se, 0), size(se, 2)), dtype = 'f8'); 99 | imse0 = zeros((size(se, 0), size(se, 2)), dtype = float); 100 | for f in range(size(se, 2)): 101 | for s in range(size(se, 0)): 102 | if npoint >= 2: 103 | p = polyfit(wn, imag(se[s, :, f]), norder); 104 | z[s, f] = 1. / (1 - p[-2]); 105 | imse0[s, f] = p[-1]; 106 | # if f % nlayers == 0: 107 | # print 'f=%d, s=%d'%(f/nlayers,s), p; 108 | else: z[s, f] = 1. / (1-imag(se[s, 0, f])/wn[0]); 109 | # print imse0[:, ::4]; 110 | # print 1./mean(z[:, ::4], 0) 111 | # print mean(imse0[:, ::4], 0); 112 | return z 113 | 114 | 115 | def getFermiDOS_old(h5, it = None): 116 | if it is None: it = h5['iter'][0]; 117 | parms = gget(h5, 'parms', it); 118 | BETA = float(parms['BETA']); 119 | dT = 5; 120 | Gtau = gget(h5, 'Gtau', it); 121 | Ntau = size(Gtau, 1); 122 | bG = zeros((size(Gtau, 0), size(Gtau, 2))); 123 | for f in range(size(Gtau, 2)): 124 | for s in range(size(Gtau, 0)): 125 | bG[s, f] = -BETA/pi*mean(Gtau[s, Ntau/2-dT:Ntau/2+dT, f]); 126 | return bG; 127 | 128 | 129 | def getFermiDOS(h5, it = None): 130 | if it is None: it = h5['iter'][0]; 131 | parms = gget(h5, 'parms', it); 132 | BETA = float(parms['BETA']); 133 | N_LAYERS = int(parms['N_LAYERS']); 134 | 135 | Giwn = h5['avgGreen/%d'%it][:]; 136 | bG = zeros((size(Giwn, 0), size(Giwn, 2))); 137 | for f in range(size(Giwn, 2)): 138 | for s in range(size(Giwn, 0)): 139 | tau = BETA/2.; c0 = 1.; 140 | wn = (2*arange(size(Giwn, 1))+1)*pi/BETA; 141 | Gwn = Giwn[s, :, f] - c0/(1j*wn); 142 | Gt = sum(2./BETA * (cos(wn*tau)*Gwn.real + sin(wn*tau)*Gwn.imag)) - c0/2.; 143 | bG[s, f] = -BETA/pi*Gt; 144 | return bG; 145 | 146 | 147 | def show_DOS_results(h5file, filter = '', plot_what = None, L = None, f = None, Navg = 1): 148 | print '# BETA T U Delta N_LAYERS Ndtot DOStot Nd DOS'; 149 | for s in h5file: 150 | if filter not in s: continue; 151 | it = h5file[s+'/iter'][0]; 152 | if str(it+1) in h5file[s+'/avgGreen'].keys(): added = 1; 153 | else: added = 0; 154 | try: parms = gget(h5file[s], 'parms'); 155 | except: print 'ID %s not work'%s; continue; 156 | N_LAYERS = int(parms['N_LAYERS']); SPINS = int(parms['SPINS']); 157 | if L is None: L = arange(N_LAYERS); 158 | corr_id = system.getCorrIndex(parms); 159 | nf = None; 160 | for i in range(Navg): 161 | if nf is None: 162 | nf = getDensity(h5file[s], it-i); 163 | bG = getFermiDOS(h5file[s], it+added-i); 164 | else: 165 | nf += getDensity(h5file[s], it-i); 166 | bG += getFermiDOS(h5file[s], it+added-i); 167 | nf /= Navg; bG /= Navg; 168 | if SPINS == 1: nf = r_[nf, nf]; bG = r_[bG, bG]; 169 | nn = sum(nf[:, corr_id][:, ::N_LAYERS], 0); 170 | bbG = sum(bG[:, corr_id][:, ::N_LAYERS], 0); 171 | 172 | print '%s: %s %.4f %.2f %.4f %d %.4f %.4f '%(s, parms['BETA'], 1/float(parms['BETA']), float(parms['U']), float(parms['DELTA']), N_LAYERS,\ 173 | sum(nf[:,corr_id])/N_LAYERS, sum(bG)/N_LAYERS), \ 174 | (len(nn)*' %.4f' + ' ' + len(bbG)*' %.4f')%tuple(r_[nn, bbG]); 175 | 176 | if plot_what is not None: 177 | for s in h5file: 178 | if filter in s: plot_data(h5file[s], plot_what, f = f, L = L); 179 | 180 | 181 | def show_mag_results(h5file, filter = '', plot_what = None, L = 0, Navg = 1): 182 | print '# BETA T Nd magnetization inv_susceptibility'; 183 | for s in h5file: 184 | if filter not in s: continue; 185 | try: parms = gget(h5file[s], 'parms'); 186 | except: print 'ID %s not work'%s; continue; 187 | tmp = gget(h5file[s], 'log'); 188 | nd = sum(mean(tmp[1][-Navg:, :], 0)); 189 | magnetization = sum(mean(tmp[5][-Navg:, :], 0))/int(parms['N_LAYERS']); 190 | susceptibility = magnetization / float(parms['H']); 191 | print '%s: %s %.4f %.4f'%(s, parms['BETA'], 1/float(parms['BETA']), sum(nd)/int(parms['N_LAYERS'])), magnetization, 1./susceptibility; 192 | 193 | if plot_what is not None: 194 | corr_id = system.getCorrIndex(parms); 195 | for s in h5file: 196 | if filter in s: plot_data(h5file[s], plot_what, f = corr_id, L = L); 197 | 198 | 199 | def show_mass_results(h5file, filter = '', NMat = 6, NOrder = 4, Navg = 1): 200 | print '# U J BETA mass...'; 201 | for s in h5file: 202 | if re.search(filter, s) is None: continue; 203 | try: parms = gget(h5file[s], 'parms'); 204 | except: print 'ID %s not work'%s; continue; 205 | it = h5file[s+'/iter'][0]; 206 | mass = None; 207 | for n in range(Navg): 208 | tmp = 1./getRenormFactor(h5file[s], npoint = NMat, norder = NOrder, it = it-n); 209 | if mass is None: mass = tmp; 210 | else: mass += tmp; 211 | mass /= Navg; 212 | mass = mass[:, ::int(parms['N_LAYERS'])]; 213 | mass = mass.flatten(); 214 | 215 | print '%s %s %s '%(parms['U'], parms['J'], parms['BETA']), len(mass)*'%.4f '%tuple(mass); 216 | 217 | 218 | def getWilsonRatio(h5file, filter = '', Navg = 1, NMat = 6, NOrder = 4): 219 | print '# BETA T susceptibility specific heat Wilson ratio'; 220 | for s in h5file: 221 | if filter not in s: continue; 222 | parms = gget(h5file[s], 'parms'); 223 | N_LAYERS = int(parms['N_LAYERS']); 224 | tmp = gget(h5file[s], 'log'); 225 | nd = sum(mean(tmp[1][-Navg:, :], 0)); 226 | magnetization = sum(mean(tmp[5][-Navg:, :], 0))/N_LAYERS; 227 | susceptibility = magnetization / float(parms['H']); 228 | 229 | bG = None; 230 | for i in range(Navg): 231 | it = h5file[s+'/iter'][0]; 232 | if str(it+1) in h5file[s+'/avgGreen'].keys(): added = 1; 233 | else: added = 0; 234 | 235 | t1 = getFermiDOS(h5file[s], it+added-i); 236 | t2 = getRenormFactor(h5file[s], NMat, NOrder, it-i); 237 | if bG is None: bG = t1; Z = t2; 238 | else: bG += t1; Z += t2; 239 | bG = bG[:, ::N_LAYERS]; 240 | Z = Z[:,::N_LAYERS]; 241 | gamma = sum(bG/Z); 242 | print '%s %.4f %.8f %.8f %.8f'%(parms['BETA'], 1/float(parms['BETA']), susceptibility, gamma, susceptibility/gamma); 243 | 244 | 245 | 246 | 247 | def gget(data, st, iter = None, L = None, f = None): 248 | if iter == None: iter = str(data['iter'][0]); 249 | iter = str(iter); 250 | parms = load_parms(data, int(iter)); 251 | N_LAYERS = int(parms['N_LAYERS']); FLAVORS = int(parms['FLAVORS']); SPINS = int(parms['SPINS']); 252 | NORB = int(parms['NORB']); NCOR = int(parms['NCOR']); 253 | corr_id = system.getCorrIndex(parms); 254 | dmft_id = system.getDMFTCorrIndex(parms); 255 | dmft_site_id = system.getDMFTCorrIndex(parms, all = False); 256 | 257 | if st == 'wn': 258 | NMaxFreq = int(parms['N_MAX_FREQ']); 259 | BETA = float(parms['BETA']); 260 | return (2*arange(0, NMaxFreq)+1)*pi/BETA; 261 | if st == 'parms': return parms; 262 | if st == 'log': 263 | log = data['log_density'][:]; 264 | num_iter = len(log); 265 | nraw = log[:,4:]; 266 | orbital = zeros((num_iter, FLAVORS, N_LAYERS)); 267 | orbital_abs = zeros((num_iter, FLAVORS, N_LAYERS)); 268 | spinup = zeros((num_iter, N_LAYERS)); 269 | spindn = zeros((num_iter, N_LAYERS)); 270 | density = zeros((num_iter, N_LAYERS)); 271 | magnetization = zeros((num_iter, N_LAYERS)); 272 | 273 | for n in range(num_iter): 274 | nf = nraw[n].reshape(SPINS, -1)[:, :NCOR]; 275 | noxy = nraw[n].reshape(SPINS, -1)[:, -1]/N_LAYERS; 276 | # if n > 0: 277 | # nf_gtau = -data['SolverData/Gtau/'+str(n)][:, -1, :]; 278 | # nf[:, dmft_id] = nf_gtau[:, dmft_id]; 279 | nf = nf.reshape(SPINS, FLAVORS, N_LAYERS); 280 | if SPINS == 1: nf = r_[nf, nf]; noxy = r_[noxy, noxy]; 281 | 282 | density[n] = array([sum(nf[:,:,i]) for i in range(N_LAYERS)]); 283 | orbital[n] = (nf[0] + nf[1])/density[n]; 284 | orbital_abs[n] = (nf[0] + nf[1]); 285 | spinup[n] = sum(nf[0], 0)/density[n] - 1./2; 286 | spindn[n] = sum(nf[1], 0)/density[n] - 1./2; 287 | # magnetization[n] = sum(nf[0, dmft_site_id, :] - nf[1, dmft_site_id], 0); 288 | magnetization[n] = sum(nf[0] - nf[1], 0) + noxy[0] - noxy[1]; 289 | # magnetization[n] = sum(nf[0] - nf[1], 0); 290 | 291 | out = (log[:,:4], density, spinup, spindn, orbital, magnetization, orbital_abs); 292 | return out; 293 | 294 | if L == None: L = arange(N_LAYERS); 295 | if f == None: f = arange(FLAVORS); 296 | L = array([L]).flatten(); f = asarray([f]).flatten(); 297 | idx = array([], dtype = 'i4'); 298 | for i in range(0,len(f)): idx = r_[idx, L + f[i]*N_LAYERS]; 299 | idx = sort(idx); 300 | 301 | if st == 'idx': return idx; 302 | if st == 'Gimp': return data['ImpurityGreen/' + iter][:,:,idx]; 303 | if st == 'se': return data['SelfEnergy/' + iter][:,:,idx]; 304 | if st == 'as': return data['WeissField/' + iter][:,:,idx]; 305 | if st == 'Gavg': return data['avgGreen/' + iter][:,:, corr_id][:,:,idx]; 306 | if st == 'hybmat': return data['SolverData/Hybmat/' + iter][:,:,idx]; 307 | if st == 'hybtau': return data['SolverData/Hybtau/' + iter][:,:,idx]; 308 | if st == 'Gtau': return data['SolverData/Gtau/' + iter][:,:,idx]; 309 | if st == 'G0': return 1. / data['WeissField/' + iter][:,:,idx]; 310 | if st == 'bG': return getFermiDOS(data, iter); 311 | if st == 'Gtot': return getTotalGtau(data, iter); 312 | if st == 'Z' : return getRenormFactor(data, npoint = 2, it = iter); 313 | 314 | 315 | def save_data(data, st, it = None): 316 | if it == None: it = data['iter'][0] 317 | parms = gget(data, 'parms', it) 318 | n_cutoff = int(parms['N_CUTOFF']) 319 | n_layers = int(parms['N_LAYERS']) 320 | d = gget(data, st, it) 321 | d = d[:, :n_cutoff, ::n_layers] 322 | is_matsubara = isinstance(d.item(0), complex) 323 | if is_matsubara: 324 | x = gget(data, 'wn')[:size(d, 1)] 325 | else: 326 | beta = float(parms['BETA']) 327 | x = linspace(0, beta, size(d, 1)) 328 | out = x 329 | for f in range(size(d, 2)): 330 | for s in range(size(d, 0)): 331 | if is_matsubara: 332 | out = c_[out, d[s, :, f].real, d[s, :, f].imag] 333 | else: 334 | out = c_[out, d[s, :, f]] 335 | idname = parms['ID'] 336 | savetxt('%s.%s.i%d'%(idname, st, it), out) 337 | 338 | 339 | from solver import solver_input_data; 340 | def solver_prepare(data, it = None, L = 0): 341 | if it is None: it = data['iter'][0]; 342 | print 'Getting data from iteration ', it 343 | parms = gget(data, 'parms', it); 344 | SPINS = int(parms['SPINS']); N_LAYERS = int(parms['N_LAYERS']); FLAVORS = int(parms['FLAVORS']); 345 | wn = gget(data, 'wn', it); 346 | 347 | htau = gget(data, 'hybtau', it); 348 | hmat = gget(data, 'hybmat', it); 349 | htail = data['SolverData/hyb_asym_coeffs'][it-1, 1:].reshape(SPINS, -1, N_LAYERS*FLAVORS); 350 | hyb_data_all = [htau, hmat, htail]; 351 | 352 | AvgDispersion = data['SolverData/AvgDispersion'][:]; 353 | nf = getDensity(h5, it-1); 354 | VCoulomb = h5['StaticCoulomb/%d'%it][:]; 355 | 356 | out = solver_input_data(parms, L, hyb_data_all, AvgDispersion, VCoulomb, nf); 357 | 358 | savetxt('hybmat.real', c_[wn, out['hybmat'].real]); 359 | savetxt('hybmat.imag', c_[wn, out['hybmat'].imag]); 360 | savetxt('hybmat.tail', out['hybtail']); 361 | print out['MU']; 362 | 363 | 364 | 365 | 366 | if __name__ == '__main__': 367 | set_printoptions(suppress=True, precision=4,linewidth=150); 368 | 369 | if len(sys.argv) == 2: h5, h5file = load_data(sys.argv[1]); 370 | else: h5, h5file = load_data(sys.argv[1], sys.argv[2]); 371 | print h5, h5["iter"][0]; 372 | 373 | -------------------------------------------------------------------------------- /functions.py: -------------------------------------------------------------------------------- 1 | import h5py, system_dependence as system; 2 | from numpy import *; 3 | from share_fun import load_parms, val_def, log_data; 4 | from scipy import interpolate; 5 | 6 | 7 | 8 | def getDensity(h5, it = None): 9 | if it is None: it = h5['iter'][0]; 10 | parms = load_parms(h5, it); 11 | N_LAYERS = int(parms['N_LAYERS']); 12 | SPINS = int(parms['SPINS']); 13 | NCOR = int(parms['NCOR']); 14 | U = float(parms['U']); 15 | n_f = h5['log_density'][0 if it == 0 else it-1, 4:].reshape(SPINS, -1)[:, :NCOR]; 16 | if U != 0 and it > 0: 17 | if int(val_def(parms, 'FIXED_HARTREE', 0)) > 0: 18 | n_f = h5['log_density'][0, 4:].reshape(SPINS, -1)[:, :NCOR]; 19 | dmft_id = system.getDMFTCorrIndex(parms); 20 | gtau = h5['SolverData/Gtau/'+str(it)][:] 21 | n_f[:, dmft_id] = -gtau[:, -1, dmft_id]; 22 | return n_f; 23 | 24 | 25 | def getDensityFromGmat(gmat, beta, extra): 26 | SPINS = len(gmat); 27 | wn = (2*arange(size(gmat, 1))+1)*pi/beta; 28 | C = extra['G_asymp_coefs'] if 'G_asymp_coefs' in extra else zeros(SPINS); 29 | correction = extra['correction'] if 'correction' in extra else zeros(SPINS); 30 | density = array([2./beta*real((sum(gmat[s], 0)) + C[s]*sum(1./wn**2)) + 0.5 - beta*C[s]/4 + correction[s] for s in range(SPINS)]); 31 | return density; 32 | 33 | 34 | def getFermiDOS(Giwn, BETA): 35 | bG = zeros((size(Giwn, 0), size(Giwn, 2))); 36 | for f in range(size(Giwn, 2)): 37 | for s in range(size(Giwn, 0)): 38 | tau = BETA/2.; c0 = 1.; 39 | wn = (2*arange(size(Giwn, 1))+1)*pi/BETA; 40 | Gwn = Giwn[s, :, f] - c0/(1j*wn); 41 | Gt = sum(2./BETA * (cos(wn*tau)*Gwn.real + sin(wn*tau)*Gwn.imag)) - c0/2.; 42 | bG[s, f] = -BETA/pi*Gt; 43 | return bG; 44 | 45 | 46 | def smooth(hyb, C, NMaxFreq, BETA, list_NCutoff, minorder = 1): 47 | w = 1j*(2*arange(NMaxFreq)+1)*pi/float(BETA); 48 | ret_hyb = zeros((size(hyb, 0), NMaxFreq, size(hyb, 2)), complex); 49 | for s in range(size(hyb, 0)): 50 | for f in range(size(hyb, 2)): 51 | NCutoff = list_NCutoff[s, f]; 52 | ret_hyb[s, :NCutoff, f] = hyb[s, :NCutoff,f]; 53 | ret_hyb[s, NCutoff:, f] = 0; 54 | for norder in range(size(C, 1)): ret_hyb[s, NCutoff:, f] += C[s, norder, f]/w[NCutoff:]**(norder+minorder); 55 | return ret_hyb; 56 | 57 | 58 | def smooth_selfenergy(it, h5, SelfEnergy, nf): 59 | parms = load_parms(h5, it); 60 | N_LAYERS = int(parms['N_LAYERS']); FLAVORS = int(parms['FLAVORS']); 61 | SPINS = size(nf, 0); # this SPINS may be different from parms['SPINS'] 62 | NCOR = int(parms['NCOR']); 63 | 64 | # calculate asymptotic coeffs and smooth 65 | se_coefs = zeros((SPINS, 2, NCOR), dtype = float); 66 | for L in range(N_LAYERS): 67 | st='SolverData/Observables/%d/L%d'%(it, L); 68 | try: nn = h5[st+'/nn'][:]; 69 | except: nn = None; 70 | se_coefs[:, :, L::N_LAYERS] = get_asymp_selfenergy(parms, nf[:, L::N_LAYERS], nn); 71 | if int(val_def(parms, 'USE_SELFENERGY_TAIL', 0)) > 0: 72 | minorder = 0 73 | se_coefs = None 74 | 75 | for L in range(N_LAYERS): 76 | st='SolverData/Observables/%d/L%d'%(it, L); 77 | se_tail = h5[st+'/SelfEnergyTail'][:] 78 | minorder = se_tail[0, 0] 79 | maxorder = se_tail[-1, 0] 80 | se_tail = se_tail[1:-1] 81 | if se_coefs is None: se_coefs = zeros((SPINS, maxorder-minorder+1, NCOR)) 82 | for n in range(len(se_tail)): 83 | tail = se_tail[n].reshape(-1, 2) 84 | if SPINS == 1: tail = [mean(tail, 1)] 85 | for s in range(SPINS): 86 | se_coefs[s, n, L::N_LAYERS] = tail[s] 87 | elif int(parms.get('FIT_SELFENERGY_TAIL', 1)) > 0: 88 | n_max_freq = int(parms['N_MAX_FREQ']) 89 | n_cutoff = int(parms['N_CUTOFF']) 90 | n_fit_stop = n_cutoff + 5 91 | n_fit_start = n_cutoff - 5 92 | wn = (2*arange(n_max_freq)+1)*pi/float(parms['BETA']) 93 | for f in range(NCOR): 94 | for s in range(SPINS): 95 | x_fit = wn[n_fit_start:n_fit_stop] 96 | y_fit = x_fit*SelfEnergy[s, n_fit_start:n_fit_stop, f].imag 97 | p = polyfit(x_fit, y_fit, 0) 98 | se_coefs[s, 1, f] = -p[0] 99 | log_data(h5['SolverData'], 'selfenergy_asymp_coeffs', it, se_coefs.flatten(), data_type = float); 100 | list_NCutoff = ones((SPINS, NCOR), dtype = int)*int(parms['N_CUTOFF']); 101 | ind = SelfEnergy.imag > 0; 102 | SelfEnergy[ind] = real(SelfEnergy[ind]); 103 | return smooth(SelfEnergy, se_coefs, int(parms['N_MAX_FREQ']), float(parms['BETA']), list_NCutoff, minorder = 0); 104 | 105 | 106 | def get_asymp_hybmat(parms, nf, MU, Eav): 107 | SPINS = int(parms['SPINS']); 108 | S = get_asymp_selfenergy(parms, nf); 109 | G = zeros((SPINS, 3, int(parms['FLAVORS'])), dtype = float); 110 | epsav = Eav[:, 0, :]; 111 | epssqav = Eav[:, 1, :]; 112 | epscubeav = Eav[:, 2, :]; 113 | for s in range(SPINS): 114 | G[s, 0, :] = epssqav[s] - epsav[s]**2; 115 | G[s, 1, :] = (epssqav[s] - epsav[s]**2)*(S[s, 0, :] - 2*epsav[s] - MU) + (epscubeav[s] - epsav[s]**3); 116 | return G; 117 | 118 | 119 | def get_asymp_selfenergy(parms, nf_in, nn_in = None): 120 | dmft_id = system.getDMFTCorrIndex(parms, all = False); 121 | FLAVORS = int(parms['FLAVORS']); 122 | SPINS = 2; 123 | U = generate_Umatrix(float(parms['U']), float(parms['J']), 124 | int(parms['FLAVORS']), val_def(parms, 'INTERACTION_TYPE', 'SlaterKanamori')); 125 | if int(val_def(parms, 'TMP_HELD_DC' , 0)) > 0: 126 | for m in range(2*FLAVORS): 127 | for n in range(2*FLAVORS): 128 | f1 = m/2 129 | f2 = n/2 130 | if (f1 not in dmft_id) or (f2 not in dmft_id): 131 | U[m, n] = 0. 132 | 133 | nf = zeros(SPINS*FLAVORS); 134 | nf[::2] = nf[1::2] = nf_in[0]; 135 | if int(parms['SPINS']) == 2: nf[1::2] = nf_in[1]; 136 | 137 | nn = zeros((FLAVORS*SPINS, FLAVORS*SPINS)); 138 | pos = 0; 139 | for i in range(FLAVORS*SPINS): 140 | for j in range(i+1): 141 | f1 = i/SPINS; 142 | f2 = j/SPINS; 143 | if f1 in dmft_id and f2 in dmft_id and nn_in is not None: 144 | nn[i,j] = nn[j,i] = nn_in[pos]; 145 | pos += 1; 146 | if f1 in dmft_id: nn[i,i] = nf[i]; 147 | 148 | S = zeros((2, SPINS*FLAVORS)); # 2: expansion orders: (iwn)^0, (iwn)^{-1} 149 | for f in range(SPINS*FLAVORS): 150 | # zeroth order is easy: \Sigma^0_f = U_{f, f'} * 151 | S[0, f] = sum(U[f, :]*nf); 152 | 153 | # first order is harder: \Sigma^1_f = U_{f,f1}*U_{f,f2}* - (\Sigma^0_f)^2 154 | for f1 in range(SPINS*FLAVORS): 155 | for f2 in range(SPINS*FLAVORS): 156 | S[1, f] += U[f, f1]*U[f,f2]*nn[f1,f2]; 157 | S[1,f] -= S[0,f]**2; 158 | ret = array([S[:,::2], S[:,1::2]]); 159 | 160 | # for mean field, there is only \Sigma^0, other terms vanish 161 | # so I set \Sigma^1 to be zero 162 | for f in range(FLAVORS): 163 | if f not in dmft_id: 164 | ret[:, 1, f] = 0; 165 | if int(val_def(parms, 'TMP_HELD_DC' , 0)) > 0: 166 | uu = float(parms['U']) 167 | jj = float(parms['J']) 168 | ntot = sum(nf_in[0][dmft_id] + nf_in[1][dmft_id]) 169 | ret[:, 0, f] = ((uu-2*jj) + jj*(2 - (3-1)) / (2*3.-1.))*(ntot-0.5) 170 | if int(parms['SPINS']) == 1: ret = array([ret[0]]); 171 | return ret; 172 | 173 | def get_self_energy_hdf5(h5, nparms, nwn): 174 | NCOR = int(nparms['NCOR']); SPINS = int(nparms['SPINS']); 175 | oit = h5['iter'][0]; 176 | oparms = load_parms(h5, oit); 177 | try: MU = float(str(h5['parms/%d/MU'%(oit+1)][...])); 178 | except: MU = float(str(h5['parms/%d/MU'%oit][...])); 179 | eMU = MU - h5['StaticCoulomb/%d'%oit][:]; 180 | ose = h5['SelfEnergy/%d'%oit][:]; 181 | own = (2*arange(size(ose, 1))+1)*pi/float(oparms['BETA']); 182 | oSPINS = int(oparms['SPINS']); 183 | assert NCOR == int(oparms['NCOR']); 184 | otail = h5['SolverData/selfenergy_asymp_coeffs'][-1, 1:].reshape(oSPINS, 2, -1); 185 | return extrapolate_self_energy(own, ose, otail, nwn, SPINS) 186 | 187 | def get_self_energy_text(se_filename, nparms, nwn): 188 | NCOR = int(nparms['NCOR']) 189 | SPINS = int(nparms['SPINS']) 190 | N_LAYERS = int(nparms['N_LAYERS']) 191 | FLAVORS = int(nparms['FLAVORS']) 192 | se_data = genfromtxt(se_filename) 193 | own = se_data[:, 0] 194 | oSPINS = (size(se_data, 1)-1) / (2*NCOR) 195 | short_form = False 196 | if oSPINS == 0: 197 | oSPINS = (size(se_data, 1)-1) / (2*FLAVORS) 198 | short_form = True 199 | ose = zeros((oSPINS, len(own), NCOR), dtype=complex) 200 | otail = zeros((oSPINS, 2, NCOR)) 201 | for s in range(oSPINS): 202 | for f in range(FLAVORS if short_form else NCOR): 203 | # SE data: wn, f0up real, f0up imag, f0dn real, f0dn imag ... 204 | se_real = se_data[:, 1 + 2*(oSPINS*f+s)+0] 205 | se_imag = se_data[:, 1 + 2*(oSPINS*f+s)+1] 206 | if short_form: 207 | for L in range(N_LAYERS): 208 | ose[s, :, N_LAYERS*f+L] = se_real + 1j*se_imag 209 | otail[s, 0, N_LAYERS*f+L] = mean(se_real[-5:]) 210 | otail[s, 1, N_LAYERS*f+L] = -mean(se_imag[-5:]*own[-5]) 211 | else: 212 | ose[s, :, f] = se_real + 1j*se_imag 213 | otail[s, 0, f] = mean(se_real[-5:]) 214 | otail[s, 1, f] = -mean(se_imag[-5:]*own[-5]) 215 | return extrapolate_self_energy(own, ose, otail, nwn, SPINS) 216 | 217 | def extrapolate_self_energy(own, ose, tail, nwn, SPINS): 218 | oSPINS = size(ose, 0) 219 | NCOR = size(ose, 2) 220 | 221 | tck_real = []; 222 | tck_imag = []; 223 | for s in range(oSPINS): 224 | tck_real.append([]); 225 | tck_imag.append([]); 226 | for f in range(NCOR): 227 | tck_real[s].append(interpolate.splrep(own, ose[s, :, f].real)); 228 | tck_imag[s].append(interpolate.splrep(own, ose[s, :, f].imag)); 229 | 230 | ret = zeros((oSPINS, len(nwn), NCOR), dtype = 'c16'); 231 | for s in range(oSPINS): 232 | for n in range(len(nwn)): 233 | if nwn[n] < own[0]: 234 | # linear extrapolate; 235 | ret[s, n, :] = (nwn[n]-own[0])/(own[0] - own[1])*(ose[s, 0,:] - ose[s, 1,:]) + ose[s, 0,:]; 236 | if nwn[n] >= own[0] and nwn[n] <= own[-1]: 237 | for f in range(NCOR): 238 | ret[s, n, f] = interpolate.splev(nwn[n], tck_real[s][f]) + 1j*interpolate.splev(nwn[n], tck_imag[s][f]); 239 | if nwn[n] > own[-1]: 240 | for k in range(size(tail, 1)): 241 | ret[s, n, :] += tail[s, k,:]/(1j*nwn[n])**k; 242 | 243 | ind = ret.imag > 0; 244 | ret[ind] = ret[ind].real; 245 | nse = ret 246 | ntail = tail 247 | if SPINS < oSPINS: 248 | nse = array([mean(ret, 0)]) 249 | ntail = array([mean(tail, 0)]) 250 | elif SPINS > oSPINS: 251 | nse = array([ret[0], ret[0]]) 252 | ntail = r_[tail, tail] 253 | return nse, ntail; 254 | 255 | 256 | def assign(data, N_LAYERS, s = [0, 1]): # s: spin index 257 | data_shape = data.shape; 258 | s = sort(array(s).flatten()); 259 | SPINS = 2; 260 | FLAVORS = size(data, len(data_shape) - 1) / N_LAYERS / SPINS; 261 | if len(data_shape) == 2: ret = zeros((len(s), size(data, 0), N_LAYERS*FLAVORS), dtype = data.dtype); 262 | elif len(data_shape) == 1: ret = zeros((len(s), N_LAYERS*FLAVORS), dtype = data.dtype); 263 | else: print "Data shape not supported"; return None; 264 | for n in range(len(s)): 265 | for L in range(N_LAYERS): 266 | for f in range(FLAVORS): 267 | if len(data_shape) == 2: ret[n, :, f*N_LAYERS+L] = data[:, (2*f+s[n])*N_LAYERS+L]; 268 | if len(data_shape) == 1: ret[n, f*N_LAYERS+L] = data[(2*f+s[n])*N_LAYERS+L]; 269 | return ret; 270 | 271 | 272 | # matrix rotation 273 | import fort_rot; 274 | def irotate(fin, rot_mat): 275 | N_LAYERS = len(rot_mat); 276 | FLAVORS = len(rot_mat[0]); 277 | assert(size(fin,1) == N_LAYERS*FLAVORS); 278 | 279 | fout = zeros((len(fin), N_LAYERS, FLAVORS, FLAVORS), dtype = fin.dtype); 280 | for L in range(N_LAYERS): 281 | tmp = fort_rot.irotate(fin[:,L::N_LAYERS], rot_mat[L]); 282 | fout[:,L,:,:] = tmp; 283 | return fout; 284 | 285 | def rotate(fin, rot_mat): 286 | N_LAYERS = len(rot_mat); 287 | FLAVORS = len(rot_mat[0]); 288 | assert(size(fin,1) == N_LAYERS and size(fin, 2) == FLAVORS); 289 | 290 | fout = zeros((len(fin), N_LAYERS*FLAVORS), dtype = fin.dtype); 291 | for L in range(N_LAYERS): 292 | fout[:, L::N_LAYERS] = fort_rot.rotate(fin[:,L,:,:], rot_mat[L]); 293 | return fout; 294 | 295 | def rotate_all(mat, rot_mat, need_extra = False): 296 | Nm = len(mat); 297 | N = len(rot_mat); 298 | L2 = len(rot_mat[0]); 299 | 300 | out = zeros((Nm, N*L2), dtype = mat.dtype); 301 | for L in range(N): 302 | mat_tmp = mat[:, L:L2*N:N, L:L2*N:N]; 303 | tmp = fort_rot.rotate(mat_tmp, rot_mat[L]); 304 | out[:, L::N] = tmp; 305 | 306 | if need_extra: 307 | for n in range(N*L2, size(mat, 2)): out = c_[out, mat[:, n, n]]; 308 | return out; 309 | 310 | 311 | def generate_Umatrix(U, J, FLAVORS, Utype, triqs_format=False): 312 | Umatrix = zeros((2*FLAVORS, 2*FLAVORS)); 313 | if Utype == 'SlaterKanamori': 314 | U1 = U-2*J; U2 = U1-J; 315 | for f1 in range(2*FLAVORS): 316 | for f2 in range(2*FLAVORS): 317 | s1 = f1 % 2; a1 = f1 / 2; 318 | s2 = f2 % 2; a2 = f2 / 2; 319 | if a1 == a2: 320 | if s1 != s2: Umatrix[f1, f2] = U; 321 | else: 322 | if s1 != s2: Umatrix[f1, f2] = U1; 323 | else: Umatrix[f1, f2] = U2; 324 | elif Utype == 'SlaterIntegrals': 325 | assert FLAVORS == 5, 'only accept FLAVORS=5 for d bands'; 326 | F0 = U; F2 = 70*J/13.; F4 = 112*J/13.; 327 | U0 = F0 + 8/7.*(F2+F4)/14.; 328 | J1 = 3/49.*F2 + 20/9.*1/49.*F4; 329 | J2 =-2*5/7.*(F2+F4)/14. + 3*J1; 330 | J3 = 6*5/7.*(F2+F4)/14. - 5*J1; 331 | J4 = 4*5/7.*(F2+F4)/14. - 3*J1; 332 | # row(column) info: xy, yz, 3z^2, xz, x^2-y^2 333 | UPavarini = array([ 334 | [ U0, U0-2*J1, U0-2*J2, U0-2*J1, U0-2*J3 ], 335 | [ U0-2*J1, U0, U0-2*J4, U0-2*J1, U0-2*J1 ], 336 | [ U0-2*J2, U0-2*J4, U0, U0-2*J4, U0-2*J2 ], 337 | [ U0-2*J1, U0-2*J1, U0-2*J4, U0, U0-2*J1 ], 338 | [ U0-2*J3, U0-2*J1, U0-2*J2, U0-2*J1, U0 ] 339 | ]); 340 | JPavarini = array([ 341 | [ U0, J1, J2, J1, J3 ], 342 | [ J1, U0, J4, J1, J1 ], 343 | [ J2, J4, U0, J4, J2 ], 344 | [ J1, J1, J4, U0, J1 ], 345 | [ J3, J1, J2, J1, U0 ] 346 | ]); 347 | 348 | # swap to the order of wannier90: 3z^2, xz, yz, x^2-y^2, xy 349 | dmap = array([ 350 | [0, 1, 2, 3, 4], 351 | [2, 3, 1, 4, 0] 352 | ]); 353 | 354 | UPavarini[:, dmap[0]] = UPavarini[:, dmap[1]]; 355 | UPavarini[dmap[0], :] = UPavarini[dmap[1], :]; 356 | JPavarini[:, dmap[0]] = JPavarini[:, dmap[1]]; 357 | JPavarini[dmap[0], :] = JPavarini[dmap[1], :]; 358 | 359 | for f1 in range(2*FLAVORS): 360 | for f2 in range(2*FLAVORS): 361 | s1 = f1 % 2; a1 = f1 / 2; 362 | s2 = f2 % 2; a2 = f2 / 2; 363 | if s1 == s2: Umatrix[f1, f2] = UPavarini[a1, a2] - JPavarini[a1, a2]; 364 | else: Umatrix[f1, f2] = UPavarini[a1, a2]; 365 | else: exit('Unknown interaction type'); 366 | 367 | if triqs_format: 368 | ncor = 2*FLAVORS 369 | dmap = array([ 370 | arange(ncor), 371 | r_[arange(0, ncor, 2), arange(1, ncor, 2)] 372 | ]) 373 | Umatrix[:, dmap[0]] = Umatrix[:, dmap[1]] 374 | Umatrix[dmap[0], :] = Umatrix[dmap[1], :] 375 | return Umatrix; 376 | 377 | 378 | --------------------------------------------------------------------------------