Initial revision

git-svn-id: https://subversion.assembla.com/svn/qmcdev/trunk@4 e5b18d87-469d-4833-9cc0-8cdfa06e9491
This commit is contained in:
Jeongnim Kim 2004-08-24 19:21:10 +00:00
parent 47ef55c27a
commit cb7d66f5af
321 changed files with 63834 additions and 0 deletions

80
CMake/Compilers.cmake Normal file
View File

@ -0,0 +1,80 @@
#
#adding compiler flags
#
#Since F77FLAGS is used with ADD_CUSTOM_COMMAND variable F77FLAGS needs to be comma separated.
# incorrect: SET(F77OPTFLAGS "-fpp2 -O3 -unrol -fno-alias -ftz")
# correct: SET(F77OPTFLAGS -fpp2 -O3 -unrol -fno-alias -ftz)
MESSAGE(STATUS "Configuring compiler flags")
IF($ENV{CXX} MATCHES icc)
SET(INTEL_COMPILER 1)
ADD_DEFINITIONS(-DADD_)
SET(CMAKE_CXX_FLAGS "-restrict -unroll -fno-alias -O3 -xW")
# SET(FORTRAN_LIBS "-lPEPCF90 -lCEPCF90 -lF90 -lintrins")
SET(FORTRAN_LIBS "-lifcore")
SET(F77 ifc)
SET(F77OPTFLAGS -fpp2 -O3)
SET(F77FLAGS ${F77OPTFLAGS})
ENDIF($ENV{CXX} MATCHES icc)
IF($ENV{CXX} MATCHES ecc)
SET(INTEL_COMPILER 1)
ADD_DEFINITIONS(-DADD_)
SET(CMAKE_CXX_FLAGS "-restrict -unroll -fno-alias -O3 -ftz")
SET(FORTRAN_LIBS "-lPEPCF90 -lCEPCF90 -lF90 -lintrins")
SET(F77 efc)
SET(F77OPTFLAGS -fpp2 -O3 -unrol -fno-alias -ftz)
SET(F77FLAGS ${F77OPTFLAGS})
ENDIF($ENV{CXX} MATCHES ecc)
IF(INTEL_COMPILER)
MESSAGE(STATUS "Using intel compiler")
IF(OHMMS_OMP)
ADD_DEFINITIONS(-DUSE_OPENMP)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -openmp")
SET(ENABLE_OMP 1 CACHE BOOL "OpenMP is enabled")
ENDIF(OHMMS_OMP)
ENDIF(INTEL_COMPILER)
IF(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
# set the customized compiler flags
SET(CMAKE_CXX_FLAGS "-O3 -qstrict -qarch=auto -qtune=auto -qansialias -qkeepinlines -qinline=1000 -qspill=2000 -qalias=typeptr -qnoeh -qnothreaded -qrtti=dyna")
# set the fortran libraries for linker
SET(FORTRAN_LIBS " -lxlf90 -lxlf")
# check if the compiler is correct xlC_r xlc_r mpCC_r mpcc_r
IF(OHMMS_OMP)
IF($ENV{CXX} MATCHES "_r")
ADD_DEFINITIONS(-DUSE_OPENMP)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -qsmp=omp")
SET(F77 xlf_r)
SET(ENABLE_OMP 1 CACHE BOOL "OpenMP is enabled")
ELSE($ENV{CXX} MATCHES "_r")
MESSAGE(STATUS "OpenMP is not enabled. Change CXX to xlC_r/mpCC_r")
SET(F77 xlf)
ENDIF($ENV{CXX} MATCHES "_r")
ELSE(OHMMS_OMP)
SET(F77 xlf)
ENDIF(OHMMS_OMP)
SET(F77OPTFLAGS -O3 -qstrict -qarch=auto -qtune=auto)
SET(F77FLAGS ${F77OPTFLAGS})
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
IF(NOT INTEL_COMPILER)
IF(CMAKE_COMPILER_IS_GNUCXX)
ADD_DEFINITIONS(-Drestrict=__restrict__ -DADD_)
SET(CMAKE_CXX_FLAGS "-O3 -ftemplate-depth-60 -Drestrict=__restrict__ -fstrict-aliasing -funroll-all-loops -finline-limit=1000 -ffast-math -Wno-deprecated")
# SET(CMAKE_CXX_FLAGS "-g")
SET(FORTRAN_LIBS "-lg2c")
SET(F77 g77)
SET(F77FLAGS -funroll-loops -O3)
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
ENDIF(NOT INTEL_COMPILER)
IF(APPLE)
INCLUDE_DIRECTORIES(/sw/include)
ENDIF(APPLE)

34
CMake/FindBlitz++.cmake Normal file
View File

@ -0,0 +1,34 @@
#
# this module look for blitz++ (http://www.oonumerics.org/blitz) support
# it will define the following values
#
# BLITZ_INCLUDE_DIR = where blitz/blitz.h can be found
#
# May want to define this but seldom required
# BLITZ_LIBRARY = where blitz library can be found (reserved)
#
IF(EXISTS ${PROJECT_CMAKE}/BlitzppConfig.cmake)
INCLUDE(${PROJECT_CMAKE}/BlitzppConfig.cmake)
ENDIF(EXISTS ${PROJECT_CMAKE}/BlitzppConfig.cmake)
IF(Blitzpp_INCLUDE_DIRS)
FIND_PATH(BLITZ_INCLUDE_DIR blitz/blitz.h ${Blitzpp_INCLUDE_DIRS})
ELSE(Blitzpp_INCLUDE_DIRS)
FIND_PATH(BLITZ_INCLUDE_DIR blitz/blitz.h
/usr/apps/include
/usr/include
/opt/include
/usr/local/include
)
ENDIF(Blitzpp_INCLUDE_DIRS)
IF(BLITZ_INCLUDE_IDR)
SET(FOUND_BLITZ 1 CACHE BOOL "Found blitz++ library")
ELSE(BLITZ_INCLUDE_IDR)
SET(FOUND_BLITZ 0 CACHE BOOL "Found blitz++ library")
ENDIF(BLITZ_INCLUDE_IDR)
MARK_AS_ADVANCED(
BLITZ_INCLUDE_DIR
FOUND_BLITZ
)

51
CMake/FindGSL.cmake Normal file
View File

@ -0,0 +1,51 @@
#
# this module look for gsl (http://www.gnu.org/software/gsl) support
# it will define the following values
#
# GSL_INCLUDE_DIR = where gsl/gsl_version.h can be found
# GSL_LIBRARY = the library to link against libgsl
# FOUND_GSL = set to 1 if gsl is found
#
IF(EXISTS ${PROJECT_CMAKE}/GslConfig.cmake)
INCLUDE(${PROJECT_CMAKE}/GslConfig.cmake)
ENDIF(EXISTS ${PROJECT_CMAKE}/GslConfig.cmake)
IF(Gsl_INCLUDE_DIRS)
FIND_PATH(GSL_INCLUDE_DIR gsl/gsl_version.h ${Gsl_INCLUDE_DIRS})
FIND_LIBRARY(GSL_LIBRARY gsl ${Gsl_LIBRARY_DIRS})
ELSE(Gsl_INCLUDE_DIRS)
SET(TRIAL_LIBRARY_PATHS
/usr/lib
/usr/local/lib
/opt/lib
/sw/lib
)
SET(TRIAL_INCLUDE_PATHS
/usr/include
/opt/include
/usr/local/include
/sw/include
)
FIND_LIBRARY(GSL_LIBRARY gsl ${TRIAL_LIBRARY_PATHS})
FIND_PATH(GSL_INCLUDE_DIR gsl/gsl_version.h ${TRIAL_INCLUDE_PATHS} )
ENDIF(Gsl_INCLUDE_DIRS)
IF(GSL_INCLUDE_DIR AND GSL_LIBRARY)
SET(FOUND_GSL 1 CACHE BOOL "Found gsl library")
SET(GSL_LIBRARY ${GSL_LIBRARY} -lgslcblas)
ELSE(GSL_INCLUDE_DIR AND GSL_LIBRARY)
SET(FOUND_GSL 0 CACHE BOOL "Not fount gsl library")
ENDIF(GSL_INCLUDE_DIR AND GSL_LIBRARY)
MARK_AS_ADVANCED(
GSL_INCLUDE_DIR
GSL_LIBRARY
FOUND_GSL
)

62
CMake/FindHDF5.cmake Normal file
View File

@ -0,0 +1,62 @@
#
# this module look for HDF5 (http://hdf.ncsa.uiuc.edu) support
# it will define the following values
#
# HDF5_INCLUDE_DIR = where hdf5.h can be found
# HDF5_LIBRARY = the library to link against (hdf5 etc)
# FOUND_HDF5 = set to true after finding the library
#
IF(EXISTS ${PROJECT_CMAKE}/Hdf5Config.cmake)
INCLUDE(${PROJECT_CMAKE}/Hdf5Config.cmake)
ENDIF(EXISTS ${PROJECT_CMAKE}/Hdf5Config.cmake)
IF(Hdf5_INCLUDE_DIRS)
FIND_PATH(HDF5_INCLUDE_DIR hdf5.h ${Hdf5_INCLUDE_DIRS})
FIND_LIBRARY(HDF5_LIBRARY hdf5 ${Hdf5_LIBRARY_DIRS})
ELSE(Hdf5_INCLUDE_DIRS)
SET(TRIAL_LIBRARY_PATHS
/usr/apps/lib
/usr/lib
/usr/local/lib
/opt/lib
/sw/lib
)
SET(TRIAL_INCLUDE_PATHS
/usr/apps/include
/usr/include
/opt/include
/usr/local/include
/sw/include
)
IF(CMAKE_COMPILER_IS_GNUCXX)
SET(TRIAL_LIBRARY_PATHS /usr/apps/hdf5/gcc3/lib ${TRIAL_LIBRARY_PATHS} )
SET(TRIAL_INCLUDE_PATHS /usr/apps/hdf5/gcc3/include ${TRIAL_INCLUDE_PATHS} )
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
IF($ENV{HDF5_DIR} MATCHES "hdf")
MESSAGE(STATUS "Using environment variable HDF5_DIR.")
SET(TRIAL_LIBRARY_PATHS $ENV{HDF5_DIR}/lib ${TRIAL_LIBRARY_PATHS} )
SET(TRIAL_INCLUDE_PATHS $ENV{HDF5_DIR}/include ${TRIAL_INCLUDE_PATHS} )
ENDIF($ENV{HDF5_DIR} MATCHES "hdf")
FIND_LIBRARY(HDF5_LIBRARY hdf5 ${TRIAL_LIBRARY_PATHS})
FIND_PATH(HDF5_INCLUDE_DIR hdf5.h ${TRIAL_INCLUDE_PATHS} )
ENDIF(Hdf5_INCLUDE_DIRS)
IF(HDF5_INCLUDE_DIR AND HDF5_LIBRARY)
SET(FOUND_HDF5 1 CACHE BOOL "Found hdf5 library")
ELSE(HDF5_INCLUDE_DIR AND HDF5_LIBRARY)
SET(FOUND_HDF5 0 CACHE BOOL "Not fount hdf5 library")
ENDIF(HDF5_INCLUDE_DIR AND HDF5_LIBRARY)
MARK_AS_ADVANCED(
HDF5_INCLUDE_DIR
HDF5_LIBRARY
FOUND_HDF5
)

136
CMake/FindLapack.cmake Executable file
View File

@ -0,0 +1,136 @@
# this module look for lapack/blas and other numerical library support
# it will define the following values
# LAPACK_LIBRARY
# BLAS_LIBRARY
#
# 1) search ENV MKL
# 2) search MKL in usual paths
# 3) search ENV ATLAS
# 4) search lapack/blas
# 5) give up
#
SET(MKL_PATHS "")
#use environment variables
IF(INTEL_COMPILER)
#use environment variables: e.g, module at OSC uses MKL
IF($ENV{MKL} MATCHES "mkl")
MESSAGE(STATUS "Using intel/mkl library: $ENV{MKL}")
#look for the path where the mkl is installed
STRING(REGEX MATCHALL "[-][L]([^ ;])+" MKL_PATH_WITH_PREFIX "$ENV{MKL}")
STRING(REGEX REPLACE "[-][L]" "" MKL_PATHS ${MKL_PATH_WITH_PREFIX})
ENDIF($ENV{MKL} MATCHES "mkl")
SET(MKL_PATHS ${MKL_PATHS}
/usr/local/intel/mkl60/mkl60/lib/64
/usr/local/intel/mkl/lib/32
/opt/intel/mkl/lib/32
)
MESSAGE(STATUS "Looking for intel/mkl library in ${MKL_PATHS}")
# IF($ENV{MKL}) MATCHES "mkl")
# MESSAGE(STATUS "Using intel/mkl library: $ENV{MKL}")
# SET(LAPACK_LIBRARY $ENV{MKL})
# SET(BLAS_LIBRARY " ")
# SET(LAPACK_LIBRARY_INIT 1)
# ENDIF($ENV{MKL}) MATCHES "mkl")
IF(NOT LAPACK_LIBRARY_INIT)
FIND_LIBRARY(LAPACK_LIBRARY
NAMES mkl_lapack
PATHS ${MKL_PATHS}
)
FIND_LIBRARY(BLAS_LIBRARY
NAMES mkl mkl_itp
PATHS ${MKL_PATHS}
)
FIND_LIBRARY(BLAS_EXTRA_LIBRARY
NAMES guide
PATHS ${MKL_PATHS}
)
IF(LAPACK_LIBRARY MATCHES "mkl")
MESSAGE(STATUS "Found intel/mkl library")
SET(LAPACK_LIBRARY_INIT 1 CACHE BOOL "lapack is initialized")
SET(BLAS_LIBRARY_INIT 1 CACHE BOOL "blas is initialized")
ENDIF(LAPACK_LIBRARY MATCHES "mkl")
ENDIF(NOT LAPACK_LIBRARY_INIT)
ENDIF(INTEL_COMPILER)
IF($ENV{ATLAS} MATCHES "atlas")
IF($ENV{ATLAS} MATCHES "lapack")
SET(LAPACK_LIBRARY_INIT 1 CACHE BOOL "lapack is initialized with ATLAS env")
ENDIF($ENV{ATLAS} MATCHES "lapack")
SET(BLAS_LIBRARY $ENV{ATLAS})
SET(BLAS_LIBRARY_INIT 1 CACHE BOOL "blas is initialized with ATLAS env")
ENDIF($ENV{ATLAS} MATCHES "atlas")
IF($ENV{LAPACK} MATCHES "lapack")
SET(LAPACK_LIBRARY $ENV{LAPACK})
SET(LAPACK_LIBRARY_INIT 1 CACHE BOOL "lapack is initialized")
ENDIF($ENV{LAPACK} MATCHES "lapack")
IF(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
SET(ELIB essl)
IF(ENABLE_OMP)
SET(ELIB esslsmp)
ENDIF(ENABLE_OMP)
IF(NOT LAPACK_LIBRARY_INIT)
SET(LLIB lapack-SP4_32 lapack)
FIND_LIBRARY(LAPACK_LIBRARY
NAMES ${LLIB}
PATHS /usr/apps/math/lapack/LAPACK
lib
)
FIND_LIBRARY(BLAS_LIBRARY ${ELIB}
/usr/lib
)
ENDIF(NOT LAPACK_LIBRARY_INIT)
SET(LAPACK_LIBRARY_INIT 1 CACHE BOOL "lapack is initialized")
SET(BLAS_LIBRARY_INIT 1 CACHE BOOL "blas with essl is initialized")
MESSAGE(STATUS "Found lapack/blas on AIX system")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
IF(NOT LAPACK_LIBRARY_INIT)
FIND_LIBRARY(LAPACK_LIBRARY NAMES lapack lapack_gnu
PATHS /usr/apps/math/lapack
/usr/lib
/opt/lib
/usr/local/lib
/sw/lib
)
IF(LAPACK_LIBRARY)
MESSAGE(STATUS "Found netlib lapack library")
SET(LAPACK_LIBRARY_INIT 1 CACHE BOOL "lapack is initialized")
ENDIF(LAPACK_LIBRARY)
ENDIF(NOT LAPACK_LIBRARY_INIT)
IF(NOT BLAS_LIBRARY_INIT)
FIND_LIBRARY(BLAS_LIBRARY NAMES blas blas_gnu
PATHS /usr/apps/math/lapack
/usr/lib
/opt/lib
/usr/local/lib
/sw/lib
)
IF(BLAS_LIBRARY)
MESSAGE(STATUS "Found netlib blas is found")
SET(BLAS_LIBRARY_INIT 1 CACHE BOOL "lapack is initialized")
ENDIF(BLAS_LIBRARY)
ENDIF(NOT BLAS_LIBRARY_INIT)
### BRANDT
### MOVED BECAUSE OF SCOPE PROBLEM
### PROBABLY SHOULD BE FIXED
#SET(BLAS_LIBRARY ${BLAS_LIBRARY} ${BLAS_EXTRA_LIBRARY})
#SET(BLAS_EXTRA_LIBRARY ${BLAS_EXTRA_LIBRARY} ${ATLAS_LIBS})
SET(BLAS_LIBRARY ${BLAS_LIBRARY})
MARK_AS_ADVANCED(
LAPACK_LIBRARY
BLAS_LIBRARY
)

43
CMake/FindLibxml2.cmake Normal file
View File

@ -0,0 +1,43 @@
#
# this module look for libxml (http://www.xmlsoft.org) support
# it will define the following values
#
# LIBXML2_INCLUDE_DIR = where libxml/xpath.h can be found
# LIBXML2_LIBRARY = the library to link against libxml2
# FOUND_LIBXML2 = set to 1 if libxml2 is found
#
IF(EXISTS ${PROJECT_CMAKE}/Libxml2Config.cmake)
INCLUDE(${PROJECT_CMAKE}/Libxml2Config.cmake)
ENDIF(EXISTS ${PROJECT_CMAKE}/Libxml2Config.cmake)
IF(Libxml2_INCLUDE_DIRS)
FIND_PATH(LIBXML2_INCLUDE_DIR libxml/xpath.h ${Libxml2_INCLUDE_DIRS})
FIND_LIBRARY(LIBXML2_LIBRARY xml2 ${Libxml2_LIBRARY_DIRS})
ELSE(Libxml2_INCLUDE_DIRS)
FIND_LIBRARY(LIBXML2_LIBRARY xml2
/usr/lib
/usr/local/lib
/sw/lib
)
FIND_PATH(LIBXML2_INCLUDE_DIR libxml/xpath.h
/usr/include/libxml2
/usr/local/include/libxml2
/sw/include/libxml2
)
ENDIF(Libxml2_INCLUDE_DIRS)
IF(LIBXML2_INCLUDE_DIR AND LIBXML2_LIBRARY)
SET(FOUND_LIBXML2 1 CACHE BOOL "Found libxml2 library")
ELSE(LIBXML2_INCLUDE_DIR AND LIBXML2_LIBRARY)
SET(FOUND_LIBXML2 0 CACHE BOOL "Not fount libxml2 library")
ENDIF(LIBXML2_INCLUDE_DIR AND LIBXML2_LIBRARY)
MARK_AS_ADVANCED(
LIBXML2_INCLUDE_DIR
LIBXML2_LIBRARY
FOUND_LIBXML2
)

48
CMake/FindLibxmlpp.cmake Normal file
View File

@ -0,0 +1,48 @@
#
# this module look for libxml++ (http://libxmlplusplus.sourceforge.net) support
# it will define the following values
#
# LIBXMLPP_INCLUDE_PATH = where libxml++/libxml++.h can be found
# LIBXMLPP_LIBRARY = the library to link against libxml++
# FOUND_LIBXMLPP = set to 1 if libxml++ is found
#
SET(LIBXMLPP xml++-1.0)
IF(EXISTS ${PROJECT_CMAKE}/LibxmlppConfig.cmake)
INCLUDE(${PROJECT_CMAKE}/LibxmlppConfig.cmake)
ENDIF(EXISTS ${PROJECT_CMAKE}/LibxmlppConfig.cmake)
IF(Libxmlpp_INCLUDE_DIRS)
FIND_PATH(LIBXMLPP_INCLUDE_DIR libxml++/libxml++.h ${Libxmlpp_INCLUDE_DIRS})
FIND_LIBRARY(LIBXMLPP_LIBRARY ${LIBXMLPP} ${Libxmlpp_LIBRARY_DIRS})
ELSE(Libxmlpp_INCLUDE_DIRS)
FIND_LIBRARY(LIBXMLPP_LIBRARY
${LIBXMLPP}
/usr/app/lib
/usr/lib
/usr/local/lib
/sw/lib
)
FIND_PATH(LIBXMLPP_INCLUDE_DIR
libxml++/libxml++.h
/usr/app/include/libxml++-1.0
/usr/include/libxml++-1.0
/usr/local/include/libxml++-1.0
/sw/include/libxml++-1.0
)
ENDIF(Libxmlpp_INCLUDE_DIRS)
IF(LIBXMLPP_INCLUDE_DIR AND LIBXMLPP_LIBRARY)
SET(FOUND_LIBXMLPP 1 CACHE BOOL "Found libxml++ library")
ELSE(LIBXMLPP_INCLUDE_DIR AND LIBXMLPP_LIBRARY)
SET(FOUND_LIBXMLPP 0 CACHE BOOL "Not fount libxml2 library")
ENDIF(LIBXMLPP_INCLUDE_DIR AND LIBXMLPP_LIBRARY)
MARK_AS_ADVANCED(
LIBXMLPP_INCLUDE_DIR
LIBXMLPP_LIBRARY
FOUND_LIBXMLPP
)

13
CMake/GNUCompilers.cmake Executable file
View File

@ -0,0 +1,13 @@
#GNU compilers
IF(CMAKE_COMPILER_IS_GNUCXX)
ADD_DEFINITIONS(-Drestrict=__restrict__ -DADD_)
SET(CMAKE_CXX_FLAGS "-O6 -ftemplate-depth-60 -Drestrict=__restrict__ -fstrict-aliasing -funroll-all-loops -finline-limit=1000 -ffast-math -Wno-deprecated")
# SET(CMAKE_CXX_FLAGS "-g -ftemplate-depth-60 -Drestrict=__restrict__ -fstrict-aliasing -Wno-deprecated")
SET(FORTRAN_LIBS "-lg2c")
SET(F77 g77)
SET(F77FLAGS -funroll-loops -O3)
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
IF(APPLE)
INCLUDE_DIRECTORIES(/sw/include)
ENDIF(APPLE)

18
CMake/IA32Compilers.cmake Normal file
View File

@ -0,0 +1,18 @@
IF(APPLE)
INCLUDE_DIRECTORIES(/sw/include)
ENDIF(APPLE)
IF(CMAKE_COMPILER_IS_GNUCXX)
ADD_DEFINITIONS(-Drestrict=__restrict__ -DADD_)
SET(CMAKE_CXX_FLAGS "-ftemplate-depth-60 -Drestrict=__restrict__ -O3 -fstrict-aliasing -funroll-all-loops -finline-limit=1000 -ffast-math -Wno-deprecated")
SET (FORTRAN_LIBS "-lg2c")
SET(F77 g77)
SET(F77OPTFLAGS "-O3 -funroll-loops")
SET(F77FLAGS ${F77OPTFLAGS})
ELSE(CMAKE_COMPILER_IS_GNUCXX)
ADD_DEFINITIONS(-DADD_)
SET(CMAKE_CXX_FLAGS "-restrict -unroll")
SET(FORTRAN_LIBS "-lPEPCF90 -lCEPCF90 -lF90 -lintrins")
SET(F77 ifc)
SET(F77OPTFLAGS "-fpp2 -O3")
SET(F77FLAGS ${F77OPTFLAGS})
ENDIF(CMAKE_COMPILER_IS_GNUCXX)

18
CMake/addAbinit.cmake Normal file
View File

@ -0,0 +1,18 @@
IF(UNIX)
IF(RUN_CONFIGURE)
EXEC_PROGRAM(
"${ABINITDIR}/configure --prefix=${PROJECT_BINARY_DIR}" ${ABINITDIR}
)
EXEC_PROGRAM(make ${ABINITDIR})
EXEC_PROGRAM(make ${ABINITDIR} ARGS install)
FIND_LIBRARY(ABINIT_LIBRARY abinit ${PROJECT_BINARY_DIR}/lib)
ENDIF(RUN_CONFIGURE)
ENDIF(UNIX)
MARK_AS_ADVANCED(ABINIT_LIBRARY)
#EXEC_PROGRAM(rm ${ABINITDIR} ARGS -f Makefile libabinit.a)
#CONFIGURE_FILE(${ABINITDIR}/Makefile.in ${ABINITDIR}/Makefile)
#EXEC_PROGRAM(make ${ABINITDIR} ARGS -f Makefile)
#EXEC_PROGRAM(cp ${ABINITDIR} ARGS "libabinit.a ${LIBRARY_OUTPUT_PATH}/")

19
CMake/addBlitz++.cmake Normal file
View File

@ -0,0 +1,19 @@
#
# this module look for blitz++ (http://www.oonumerics.org/blitz) support
# it will define the following values
#
# BLITZ_INCLUDE_PATH = where blitz/blitz.h can be found
#
FIND_PATH(BLITZ_INCLUDE_PATH
blitz/blitz.h
/u/ac/esler/lib/blitz/include
/home/common/lib/blitz-0.6-GCC
/usr/apps/tools/blitz
/usr/include
/opt/include
/usr/local/include
${AUXPACKAGES}/Utilities/blitz
)
INCLUDE_DIRECTORIES(${BLITZ_INCLUDE_PATH})

53
CMake/addGSL.cmake Normal file
View File

@ -0,0 +1,53 @@
#
# this module look for GSL (http://sources.redhat.com/gsl/) support
# it will define the following values
#
# GSL_INCLUDE_PATH = where gsl/gsl_multimin.h can be found
# GSL_LIBRARY = the library to link against (gsl etc)
#
FIND_LIBRARY(GSL_LIBRARY
gsl
/u/ac/esler/lib/gsl/lib
/usr/lib
/opt/lib
/usr/local/lib
/sw/lib
)
FIND_LIBRARY(GSLCBLAS_LIBRARY
gslcblas
/u/ac/esler/lib/gsl/lib
/usr/lib
/opt/lib
/usr/local/lib
/sw/lib
)
FIND_PATH(GSL_INCLUDE_PATH
gsl/gsl_vector.h
/u/ac/esler/lib/gsl/include
/usr/include
/opt/include
/usr/local/include
/sw/include
)
IF(GSL_LIBRARY)
MESSAGE(STATUS "Found GSL")
INCLUDE_DIRECTORIES(${GSL_INCLUDE_PATH})
SET(GSL_LIBRARY ${GSL_LIBRARY})
ELSE(GSL_LIBRARY)
INCLUDE_DIRECTORIES(${AUXPACKAGES}/Utilities/gsl ${AUXPACKAGES}/Utilities/gsl)
SUBDIRS(Utilities)
ENDIF(GSL_LIBRARY)
IF(GSLCBLAS_LIBRARY)
MESSAGE(STATUS "Found GSLCBLAS")
INCLUDE_DIRECTORIES(${GSL_INCLUDE_PATH})
SET(GSLCBLAS_LIBRARY ${GSLCBLAS_LIBRARY})
ELSE(GSLCBLAS_LIBRARY)
INCLUDE_DIRECTORIES(${AUXPACKAGES}/Utilities/gslcblas ${AUXPACKAGES}/Utilities/gslcblas)
SUBDIRS(Utilities)
ENDIF(GSLCBLAS_LIBRARY)
LINK_LIBRARIES(${GSL_LIBRARY})
LINK_LIBRARIES(${GSLCBLAS_LIBRARY})

39
CMake/addHDF5.cmake Normal file
View File

@ -0,0 +1,39 @@
#
# this module look for HDF5 (http://hdf.ncsa.uiuc.edu) support
# it will define the following values
#
# HDF5_INCLUDE_PATH = where hdf5.h can be found
# HDF5_LIBRARY = the library to link against (hdf5 etc)
#
FIND_LIBRARY(HDF5_LIBRARY
hdf5
/home/common/lib/hdf5/lib
/u/ac/esler/lib/hdf5/lib
/usr/lib
/opt/lib
/usr/local/lib
/usr/apps/lib
/sw/lib
)
FIND_PATH(HDF5_INCLUDE_PATH
H5Ipublic.h
/home/common/lib/hdf5/include
/u/ac/esler/lib/hdf5/include
/usr/lib
/opt/lib
/usr/local/include
/usr/apps/include
/sw/lib
)
IF(HDF5_LIBRARY)
MESSAGE(STATUS "Found HDF5")
INCLUDE_DIRECTORIES(${HDF5_INCLUDE_PATH})
SET(HDF5_LIBRARY ${HDF5_LIBRARY})
ELSE(HDF5_LIBRARY)
INCLUDE_DIRECTORIES(${AUXPACKAGES}/Utilities/hdf5 ${AUXPACKAGES}/Utilities/hdf5)
SUBDIRS(Utilities)
ENDIF(HDF5_LIBRARY)
LINK_LIBRARIES(${HDF5_LIBRARY})

46
CMake/addLibxml++.cmake Normal file
View File

@ -0,0 +1,46 @@
#
# this module look for libxml++ (http://libxmlplusplus.sourceforge.net) support
# it will define the following values
#
# LIBXMLPP_INCLUDE_PATH = where libxml++/libxml++.h can be found
# LIBXMLPP_LIBRARY = the library to link against
#
FIND_LIBRARY(LIBXMLPP_LIBRARY xml++-1.0
lib
/usr/lib
/usr/local/lib
/usr/apps/lib
/usr/apps/tools/libxml++/lib
)
FIND_PATH(LIBXMLPP_INCLUDE_DIR
libxml++/libxml++.h
/usr/apps/include/libxml++-1.0
/usr/local/include/libxml++-1.0
/usr/apps/tools/libxml++/include
libxml++/libxml++.h
include/libxml++-1.0
)
IF(NOT LIBXMLPP_LIBRARY)
IF(UNIX)
IF(RUN_CONFIGURE)
EXEC_PROGRAM(aclocal ${AUXPACKAGES}/libxml++)
EXEC_PROGRAM(autoconf ${AUXPACKAGES}/libxml++)
EXEC_PROGRAM(automake ${AUXPACKAGES}/libxml++ ARGS -a)
EXEC_PROGRAM(
"${AUXPACKAGES}/libxml++/configure --prefix=${PROJECT_BINARY_DIR} --with-cxx=$ENV{CXX}"
${AUXPACKAGES}/libxml++
)
EXEC_PROGRAM(make ${AUXPACKAGES}/libxml++)
EXEC_PROGRAM("make install" ${AUXPACKAGES}/libxml++)
FIND_PATH(LIBXMLPP_INCLUDE_DIR libxml++/libxml++.h
${PROJECT_BINARY_DIR}/include/libxml++-1.0)
FIND_LIBRARY(LIBXMLPP_LIBRARY xml++-0.1
${PROJECT_BINARY_DIR}/lib)
ENDIF(RUN_CONFIGURE)
ENDIF(UNIX)
ENDIF(NOT LIBXMLPP_LIBRARY)
INCLUDE_DIRECTORIES(${LIBXMLPP_INCLUDE_DIR})
LINK_LIBRARIES(${LIBXMLPP_LIBRARY})

40
CMake/addLibxml.cmake Normal file
View File

@ -0,0 +1,40 @@
#
# this module look for libxml (http://http://xmlsoft.org) support
# it will define the following values
#
# LIBXML_INCLUDE_PATH = where libxml/parser.h can be found
# LIBXML_LIBRARY = the library to link against libxml2
#
FIND_LIBRARY(LIBXML_LIBRARY xml2
/usr/lib
/usr/local/lib
/sw/lib)
FIND_PATH(LIBXML_INCLUDE_DIR
libxml/parser.h
/usr/include/libxml2
/sw/include/libxml2
)
IF(NOT LIBXML_LIBRARY)
MESSAGE(STATUS "libxml is not found in pre-defined paths.")
IF(UNIX)
IF(RUN_CONFIGURE)
EXEC_PROGRAM(
"${AUXPACAKGES}/libxml2/configure --prefix=${PROJECT_BINARY_DIR} --with-cc=${CMAKE _CC_COMPILER}"
${AUXPACAKGES}/libxml2
)
EXEC_PROGRAM(make ${AUXPACKAGES}/libxml2)
EXEC_PROGRAM(make ${AUXPACKAGES}/libxml2 ARGS install)
FIND_LIBRARY(LIBXML_LIBRARY xml2 ${PROJECT_BINARY_DIR}/lib)
FIND_PATH(LIBXML_INCLUDE_DIR libxml/parser.h ${PROJECT_BINARY_DIR}/include)
ENDIF(RUN_CONFIGURE)
ENDIF(UNIX)
ENDIF(NOT LIBXML_LIBRARY)
IF(LIBXML_LIBRARY)
MARK_AS_ADVANCED(LIBXML_INCLUDE_DIR LIBXML_LIBRARY)
ADD_DEFINITIONS(-DENABLE_LIBXML2)
INCLUDE_DIRECTORIES(${LIBXML_INCLUDE_DIR})
LINK_LIBRARIES(${LIBXML_LIBRARY})
ENDIF(LIBXML_LIBRARY)

107
CMake/addNumerics.cmake Normal file
View File

@ -0,0 +1,107 @@
# this module look for lapack/blas and other numerical library support
# it will define the following values
# LAPACK_LIBRARY
# BLAS_LIBRARY
#
# 1) search ENV MKL
# 2) search MKL in usual paths
# 3) search lapack/blas
# 4) give up
#
SET(MKL_PATHS "")
#use environment variables
IF(INTEL_COMPILER)
#use environment variables: e.g, module at OSC uses MKL
IF($ENV{MKL} MATCHES "mkl")
MESSAGE(STATUS "Using intel/mkl library: $ENV{MKL}")
#look for the path where the mkl is installed
STRING(REGEX MATCHALL "[-][L]([^ ;])+" MKL_PATH_WITH_PREFIX "$ENV{MKL}")
STRING(REGEX REPLACE "[-][L]" "" MKL_PATHS ${MKL_PATH_WITH_PREFIX})
ENDIF($ENV{MKL} MATCHES "mkl")
SET(MKL_PATHS ${MKL_PATHS}
/usr/local/intel/mkl60/mkl60/lib/64
/usr/local/intel/mkl/lib/32
/opt/intel/mkl/lib/32
)
MESSAGE(STATUS "Looking for intel/mkl library in ${MKL_PATHS}")
# IF($ENV{MKL}) MATCHES "mkl")
# MESSAGE(STATUS "Using intel/mkl library: $ENV{MKL}")
# SET(LAPACK_LIBRARY $ENV{MKL})
# SET(BLAS_LIBRARY " ")
# SET(LAPACK_LIBRARY_INIT 1)
# ENDIF($ENV{MKL}) MATCHES "mkl")
IF(NOT LAPACK_LIBRARY_INIT)
FIND_LIBRARY(LAPACK_LIBRARY
NAMES mkl_lapack
PATHS ${MKL_PATHS}
)
FIND_LIBRARY(BLAS_LIBRARY
NAMES mkl mkl_itp
PATHS ${MKL_PATHS}
)
FIND_LIBRARY(BLAS_EXTRA_LIBRARY
NAMES guide
PATHS ${MKL_PATHS}
)
IF(LAPACK_LIBRARY MATCHES "mkl")
MESSAGE(STATUS "Found intel/mkl library")
SET(LAPACK_LIBRARY_INIT 1 CACHE BOOL "lapack is initialized")
ENDIF(LAPACK_LIBRARY MATCHES "mkl")
ENDIF(NOT LAPACK_LIBRARY_INIT)
ENDIF(INTEL_COMPILER)
IF(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
SET(ELIB essl)
SET(LLIB lapack-SP4_32)
IF(ENABLE_OMP)
SET(ELIB esslsmp)
ENDIF(ENABLE_OMP)
FIND_LIBRARY(LAPACK_LIBRARY ${LLIB}
/usr/apps/math/lapack/LAPACK
)
FIND_LIBRARY(BLAS_LIBRARY ${ELIB}
/usr/lib
)
SET(LAPACK_LIBRARY_INIT 1 CACHE BOOL "lapack is initialized")
MESSAGE(STATUS "Found lapack/blas on AIX system")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
IF(NOT LAPACK_LIBRARY_INIT)
FIND_LIBRARY(LAPACK_LIBRARY NAMES lapack lapack_gnu
PATHS /usr/apps/math/lapack
/usr/lib
/opt/lib
/usr/local/lib
/sw/lib
)
FIND_LIBRARY(BLAS_LIBRARY NAMES blas blas_gnu
PATHS /usr/apps/math/lapack
/usr/lib
/opt/lib
/usr/local/lib
/sw/lib
)
IF(LAPACK_LIBRARY AND BLAS_LIBRARY)
MESSAGE(STATUS "Found netlib lapack/blas library")
IF(APPLE)
SET(BLAS_LIBRARY ${BLAS_LIBRARY} ${BLAS_EXTRA_LIBRARY} " -lcblas -latlas")
ENDIF(APPLE)
SET(LAPACK_LIBRARY_INIT 1 CACHE BOOL "lapack is initialized")
ENDIF(LAPACK_LIBRARY AND BLAS_LIBRARY)
ENDIF(NOT LAPACK_LIBRARY_INIT)
### BRANDT
### MOVED BECAUSE OF SCOPE PROBLEM
### PROBABLY SHOULD BE FIXED
SET(BLAS_LIBRARY ${BLAS_LIBRARY} ${BLAS_EXTRA_LIBRARY})
MARK_AS_ADVANCED(LAPACK_LIBRARY BLAS_LIBRARY BLAS_EXTRA_LIBRARY)
#LINK_LIBRARIES(${LAPACK_LIBRARY} ${BLAS_LIBRARY})

28
CMake/addSPRNG.cmake Normal file
View File

@ -0,0 +1,28 @@
#
# this module look for HDF5 (http://hdf.ncsa.uiuc.edu) support
# it will define the following values
#
# HDF5_INCLUDE_PATH = where hdf5.h can be found
# HDF5_LIBRARY = the library to link against (hdf5 etc)
#
FIND_LIBRARY(SPRNG_LIBRARY
sprng
/usr/local/lib
/sw/lib
)
FIND_PATH(SPRNG_INCLUDE_PATH
sprng.h
/usr/local/include
/usr/include
/sw/lib
)
IF(SPRNG_LIBRARY)
MESSAGE(STATUS "Found SPRNG library")
INCLUDE_DIRECTORIES(${SPRNG_INCLUDE_PATH})
ENDIF(SPRNG_LIBRARY)
LINK_LIBRARIES(${SPRNG_LIBRARY})
ADD_DEFINITIONS(-DUSE_SPRNG)

110
CMakeLists.txt Normal file
View File

@ -0,0 +1,110 @@
PROJECT(qmcPlusPlus)
#define the paths for library and executable for out-of-soruce compilation
SET (LIBRARY_OUTPUT_PATH ${qmcPlusPlus_BINARY_DIR}/lib CACHE PATH "Single output directory for building all libraries.")
SET (EXECUTABLE_OUTPUT_PATH ${qmcPlusPlus_BINARY_DIR}/bin CACHE PATH "Single output directory for building all executables.")
#list of options to determine libraries. First, try to use libraries available
SET(INTEL_COMPILER 0)
SET(ENABLE_OPENMP 0)
SET(HAVE_MPI 0)
SET(HAVE_OOMPI 0)
SET(HAVE_LIBXML2 0)
SET(HAVE_LIBXMLPP 0)
SET(HAVE_LIBHDF5 0)
SET(HAVE_LIBSPRNG 0)
SET(HAVE_LIBBLITZ 0)
SET(HAVE_LIBGSL 0)
OPTION(QMC_SPRNG "Eanble SPRNG random number generation library" OFF)
OPTION(QMC_BLITZ "Eanble blitz++ library" ON)
######################################################################
#important settings for QMC simulations to instantiate template classes
#OHMMS_* is to reuse Ohmms class libraries
#OHMMS_DIM = dimension of the problem
#OHMMS_INDEXTYPE = type of index
#OHMMS_PRECISION = base precision, float, double etc
#QMC_FASTWALKER = true, when operation is faster for each walker
#QMC_APPS = an application to compile
######################################################################
SET(OHMMS_DIM 3)
SET(OHMMS_INDEXTYPE int)
SET(OHMMS_PRECISION double)
SET(QMC_FASTWALKER 1)
SET(QMCAPPS MolecuApps)
######################################################################
#experimental settings for optimization
######################################################################
SET(INTEL_COMPILER 0)
SET (PROJECT_CMAKE ${qmcPlusPlus_SOURCE_DIR}/CMake)
######################################################
#COMPILER choose one of the cmake files to customize the compiler options
#If nothing is chosen, default settings by cmake will be used.
######################################################
#INCLUDE(${PROJECT_CMAKE}/Intel8.cmake)
#INCLUDE(${PROJECT_CMAKE}/Intel7.cmake)
INCLUDE(${PROJECT_CMAKE}/GNUCompilers.cmake)
#INCLUDE(${PROJECT_CMAKE}/IBMCompilers.cmake)
#INCLUDE(${PROJECT_CMAKE}/KCCCompilers.cmake)
#INCLUDE(${PROJECT_CMAKE}/Compilers.cmake)
INCLUDE(${CMAKE_ROOT}/Modules/FindThreads.cmake)
#check external libraries: required
INCLUDE(${PROJECT_CMAKE}/FindLibxml2.cmake)
#INCLUDE(${PROJECT_CMAKE}/FindLibxmlpp.cmake)
INCLUDE(${PROJECT_CMAKE}/FindLapack.cmake)
INCLUDE(${PROJECT_CMAKE}/FindHDF5.cmake)
INCLUDE(${PROJECT_CMAKE}/FindGSL.cmake)
INCLUDE(${PROJECT_CMAKE}/FindBlitz++.cmake)
IF(FOUND_LIBXML2)
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
LINK_LIBRARIES(${LIBXML2_LIBRARY})
SET(HAVE_LIBXML2 1)
ENDIF(FOUND_LIBXML2)
#IF(FOUND_LIBXMLPP)
# INCLUDE_DIRECTORIES(${LIBXMLPP_INCLUDE_DIR})
# LINK_LIBRARIES(${LIBXMLPP_LIBRARY})
# SET(HAVE_LIBXMLPP 1)
#ENDIF(FOUND_LIBXMLPP)
IF(FOUND_HDF5)
SET(HAVE_LIBHDF5 1)
INCLUDE_DIRECTORIES(${HDF5_INCLUDE_DIR})
LINK_LIBRARIES(${HDF5_LIBRARY})
ENDIF(FOUND_HDF5)
IF(FOUND_GSL)
SET(HAVE_LIBGSL 1)
INCLUDE_DIRECTORIES(${GSL_INCLUDE_DIR})
LINK_LIBRARIES(${GSL_LIBRARY})
ENDIF(FOUND_GSL)
#check optional external libraries: enable only when the libraroes are found
IF(FOUND_BLITZ)
INCLUDE_DIRECTORIES(${BLITZ_INCLUDE_DIR})
SET(HAVE_LIBBLITZ 1)
ENDIF(FOUND_BLITZ)
#IF(QMC_BLITZ)
#ENDIF(QMC_BLITZ)
IF(QMC_MPI)
INCLUDE(${PROJECT_SOURCE_DIR}/CMake/addMPI.cmake)
ENDIF(QMC_MPI)
IF(QMC_SPRNG)
INCLUDE(${PROJECT_SOURCE_DIR}/CMake/addSPRNG.cmake)
ENDIF(QMC_SPRNG)
INCLUDE_DIRECTORIES(
${qmcPlusPlus_SOURCE_DIR}/src
${qmcPlusPlus_BINARY_DIR}/src
)
ADD_DEFINITIONS(-DHAVE_CONFIG_H)
SUBDIRS(src)

52
LICENSE Normal file
View File

@ -0,0 +1,52 @@
Important Notice for qmcplusplus developers and end-users:
i) The original programs developed by Jeongnim Kim and her collaborators
are distributed under UIUC/NCSA Open Source License (below).
ii) Some packages/features are not available under open source license and require
separate license agreements with the authors. Contact the responsible authors.
iii) autoconf/automake scripts are distributed under GPL (see COPYING).
iv) The sources derived from any package distributed under GPL contain
explicit acknowledgments of the original works and are distributed under GPL.
-------------
University of Illinois/NCSA Open Source License
Copyright (c) 2003, University of Illinois Board of Trustees.
All rights reserved.
Developed by:
Jeongnim Kim
Condensed Matter Physics,
National Center for Supercomputing Applications, University of Illinois
Materials computation Center, University of Illinois
http://www.mcc.uiuc.edu/qmcplusplus/
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
``Software''), to deal with the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimers in
the documentation and/or other materials provided with the
distribution.
* Neither the names of the NCSA, the MCC, the University of Illinois,
nor the names of its contributors may be used to endorse or promote
products derived from this Software without specific prior written
permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS WITH THE SOFTWARE.

12
README Normal file
View File

@ -0,0 +1,12 @@
Wed Sep 3 20:47:26 CDT 2003
Creating app to compile the main application qmc using cmake
Creating Data for input/output examples
Adding files for cmake (usage: cmake; make)
CMake directory contains modules to handle libraries.
i) FindBlitz++.cmake
ii) FindHDF5.cmake
iii) FindLibxml.cmake

3729
orbitalbuilder.xmi Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
PROJECT(hf)
#CONFIGURE_FILE(${hf_SOURCE_DIR}/../Configuration.h.in
# ${hf_SOURCE_DIR}/../Configuration.h)
SET(HFSRCS
../Utilities/OhmmsInform.cpp
../OhmmsApp/ProjectData.cpp
../Platforms/sysutil.cpp
../AtomicHF/Clebsch_Gordan.cpp
../AtomicHF/RadialPotential.cpp
../AtomicHF/HartreeFock.cpp
)
LINK_LIBRARIES(${FORTRAN_LIBS})
ADD_EXECUTABLE(hf ${HFSRCS})
TARGET_LINK_LIBRARIES(hf qmcbase)

View File

@ -0,0 +1,136 @@
// -*- C++ -*-
/*! \author Jordan Vincent
* \author Curry Taylor
* \note The original Prim was written in F90 by Tim Wilkens.
*/
// The Clebsch_Gordan class
//
// Contains the Clebsch-Gordan Coefficients in the array cg
// in the following form:
//
// < l1 m1; l2 m2 | L m1+m2 > <---> cg[l1][l2][L][m1+6][m2+6]
//
// The "+6" offsets are due to the need to index arrays from 0 to
// whatever in C++. Therefore, for example, in the case of
// m1 = m2 = 0, the last two indices to the cg array are both *6*.
//
// This routine was adopted from a FORTRAN 77 algorithm taken from
// Rose's 'Elementary Theory of Angular Momentum', p. 39, Wigner's
// formula. Those coefficients listed are only those for which
// l1 >= l2. Coeffienents known to be zero (because of either the
// L or M selection rules) are *not* computed, and these should not
// be sought.
//
// Note: As the main routine is statically defined (hard-coded),
// l values greater than 6 are not allowed and will cause error.
//
#include <math.h>
#include <stdlib.h>
#include "AtomicHF/Clebsch_Gordan.h"
#include <iostream>
/*!\fn Clebsch_Gordan::Clebsch_Gordan(const int lmax)
* \param lmax the maximum angular momentum
* \brief Constructs all the Clebsch-Gordan coefficients
for \f$ l1 <= l_{max} \f$. This routine was adopted
from a FORTRAN 77 algorithm taken from Rose's 'Elementary
Theory of Angular Momentum', p. 39, Wigner's formula. Those
coefficients listed are only those for which l1 >= l2.
Coeffienents known to be zero (because of either the
L or M selection rules) are *not* computed, and these should not
be sought.
Note: the indexing of the array is as follows:
\f[ cg(l1,l2,L,m1+Lmax,m2+Lmax) \f]
this is due to the need to index arrays from 0 to N-1
in C++.
Note: As the main routine is statically defined (hard-coded),
l values greater than 6 are not allowed and will cause error.
*
*/
Clebsch_Gordan::Clebsch_Gordan(const int lmax):Lmax(lmax){
int l1 = Lmax+1;
int l2 = 2*Lmax+1;
cg.resize(l1,l1,l2,l2,l2);
// std::cout << cg.shape() << std::endl;
cg = 0.0;
build_coefficients();
}
Clebsch_Gordan::~Clebsch_Gordan() { cg.free(); }
/*!
* \fn void Clebsch_Gordan::build_coefficients()
*
* \brief Calculates the Clebsch-Gordan coefficients and stores
them in a 5-dimensional Blitz++ array.
*
*/
void Clebsch_Gordan::build_coefficients() {
double si[33], fa[33], sum, prefactor;
int lmin, i, l1, l2, l3, m1, m2, m3, nmin, nmax;
// lmax = maximum(n, size);
si[0] = 1.0;
fa[0] = 1.0;
for(i=1; i<=32; i++) {
si[i] = -si[i-1];
fa[i] = (double)i * fa[i-1];
}
for(l1=0; l1<=Lmax; l1++) {
for(l2=0; l2<=l1; l2++) {
for(m1=-l1; m1<=l1; m1++) {
for(m2=-l2; m2<=l2; m2++) {
m3 = m1 + m2;
lmin = abs(l1-l2);
if(lmin < abs(m3)) { lmin = abs(m3); }
for(l3=lmin; l3<=l1+l2; l3++) {
prefactor = 2.0*l3 + 1.0;
prefactor *= fa[l3+l1-l2] / fa[l1+l2+l3+1];
prefactor *= fa[l3-l1+l2] / fa[l1-m1];
prefactor *= fa[l1+l2-l3] / fa[l1+m1];
prefactor *= fa[l3+m3] / fa[l2-m2];
prefactor *= fa[l3-m3] / fa[l2+m2];
prefactor = sqrt(prefactor);
nmax = l3 - l1 + l2;
if(l3+m3 < nmax) { nmax = l3+m3; }
nmin = 0;
if(l1-l2-m3 < nmin) { nmin = -(l1-l2-m3); }
sum = 0;
for(i=nmin; i<=nmax; i++) {
sum += (si[i+l2+m2]/fa[i]) * fa[l2+l3+m1-i] * fa[l1-m1+i]
/ fa[l3-l1+l2-i] / fa[l3+m3-i] / fa[i+l1-l2-m3];
}
cg(l1,l2,l3,m1+Lmax,m2+Lmax) = prefactor*sum;
cg(l2,l1,l3,m2+Lmax,m1+Lmax) = si[l1+l2+l3]*prefactor*sum;
}
}
}
}
}
}
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,45 @@
// -*- C++ -*-
/*! \author Jordan Vincent
* \author Curry Taylor
* \note The original Prim was written in F90 by Tim Wilkens.
*/
#ifndef CLEBSCH_GORDAN_H2
#define CLEBSCH_GORDAN_H2
#include <blitz/array.h>
/**class Clebsch_Gordan
*\brief Calculates the Clebsch-Gordan coefficients
*/
class Clebsch_Gordan {
public:
Clebsch_Gordan(const int lmax);
///destructor
~Clebsch_Gordan();
///maximum angular momentum
int Lmax;
///array to store the Clebsch-Gordan coefficients
blitz::Array<double,5> cg;
///returns \f$c_g(l1,l2,l3,m1,m2) \f$
inline double operator()(int l1, int l2, int l3, int m1, int m2) const {
return cg(l1,l2,l3,m1+Lmax,m2+Lmax);
}
private:
/// default constructor not implemented
Clebsch_Gordan() { }
void build_coefficients();
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,36 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_ATOMICHARTREEFOCK_TYPES_H
#define OHMMS_ATOMICHARTREEFOCK_TYPES_H
#include "AtomicHF/YlmRnlSet.h"
/**@namespace ohmmshf
*@brief Define basic data types for the applications.
* In order to reduce complier-time complexity and to enable switching
* between C++ libraries for array and expression template,
* basic data types are defined.
*/
namespace ohmmshf {
typedef YlmRnlSet<double> HFAtomicOrbitals;
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,46 @@
#ifndef OHMMS_MAIN_HFCONFIGURATION_H
#define OHMMS_MAIN_HFCONFIGURATION_H
#include <iostream>
// #if !defined(LOGMSG)
// #define LOGMSG(msg) {std::cout << "HF: " << msg << std::endl;}
// #endif
// #if !defined(DEBUGMSG)
// #define DEBUGMSG(msg) {std::cout << "DEBUG: " << msg << std::endl;}
// #endif
// #if !defined(ERRORMSG)
// #define ERRORMSG(msg) {std::cout << "ERROR: " << msg << std::endl;}
// #endif
// int Z = 0;
#if !defined(LOGMSG)
#define LOGMSG(msg) {std::cout<< "QMC " << msg << std::endl;}
#endif
#if !defined(WARNMSG)
#define WARNMSG(msg) {std::cout<< "WARNING " << msg << std::endl;}
#endif
#if !defined(DEBUGMSG)
#if defined(PRINT_DEBUG)
#define DEBUGMSG(msg) {std::cout<< "DEBUG " << msg << std::endl;}
#else
#define DEBUGMSG(msg)
#endif
#endif
#if !defined(ERRORMSG)
#define ERRORMSG(msg) {std::cout<< "ERROR " << msg << std::endl;}
#endif
#if !defined(XMLReport)
//#if defined(PRINT_DEBUG)
#define XMLReport(msg) {std::cout<< "XML " << msg << std::endl;}
//#else
//#define XMLReport(msg)
//#endif
#endif
#endif

View File

@ -0,0 +1,340 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim and Jordan Vincent
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#include "AtomicHF/HFConfiguration.h"
#include "AtomicHF/Clebsch_Gordan.h"
#include "AtomicHF/HartreeFock.h"
#include "AtomicHF/fillshells.h"
#include "OhmmsData/OhmmsElementBase.h"
#include "OhmmsPETE/OhmmsMatrix.h"
#include "Utilities/OhmmsSpecies.h"
#include <fstream>
#include <libxml/xpath.h>
namespace ohmmshf {
bool parseXMLFile(RadialPotentialSet& Pot, HFAtomicOrbitals& Psi,
string& name,string& pottype,string& gridtype,
const xmlpp::Node* root) {
using namespace xmlpp;
int nshells = 0;
OneDimGridBase<double>* grid;
NodeSet aset = root->find("//Atom");
if(aset.empty()){
ERRORMSG("Must include atomic information.")
return false;
} else {
Element* cur = dynamic_cast<Element*>(aset[0]);
Attribute* att1 = cur->get_attribute("name");
Attribute* att2 = cur->get_attribute("num_closed_shells");
if(att1){
name = att1->get_value();
XMLReport("Name = " << name)
} else {
ERRORMSG("Must specify name.")
return false;
}
if(att2){
nshells = atoi(att2->get_value().c_str());
XMLReport("Number of Closed Shells = " << nshells)
} else {
WARNMSG("Number of Closed Shells = " << nshells)
}
NodeSet gset = aset[0]->find("./Grid");
if(gset.empty()){
ERRORMSG("No grid information")
return false;
} else {
Element* p = dynamic_cast<Element*>(gset[0]);
Element::AttributeList atts = p->get_attributes();
Element::AttributeList::iterator it = atts.begin();
double scale = 1.0;
double min = 0.001;
double max = 1000.0;
int npts = 2001;
while(it != atts.end()) {
const string& aname = (*it)->get_name();
if(aname == "type") {
gridtype = (*it)->get_value();
} else if(aname == "scale") {
scale = atof((*it)->get_value().c_str());
}
it++;
}
XMLReport("Grid type = " << gridtype)
NodeSet gpset = gset[0]->find("./Parameter");
if(gpset.empty()){
WARNMSG("Using default grid values")
} else {
for(int i=0; i<gpset.size(); i++){
Element* cur = dynamic_cast<Element*>(gpset[i]);
Attribute* att = cur->get_attribute("name");
if(att) {
const string& aname = att->get_value();
xmlNode* curc = cur->cobj();
if(aname == "min") putContent(min,curc);
else if(aname == "max") putContent(max,curc);
else if(aname == "npts") putContent(npts,curc);
}
}
}
if(gridtype == "log"){
grid = new LogGrid<double>;
min/=scale;
max/=sqrt(scale);
grid->set(min,max,npts);
XMLReport("rmin = " << min << ", rmax = " << max
<< ", dh = " << grid->dh() << ", npts = " << npts)
} else if(gridtype == "linear"){
grid = new LinearGrid<double>;
min/=scale;
max/=sqrt(scale);
grid->set(min,max,npts);
XMLReport("rmin = " << min << ", rmax = " << max
<< ", dh = " << grid->dh() << ", npts = " << npts)
} else {
ERRORMSG("Grid Type Options: Log or Linear.")
return false;
}
}
// pass grid to wavefunction
Psi.m_grid = grid;
// class to generate Clebsh Gordan coeff.
Clebsch_Gordan* CG_coeff;
NodeSet potset = aset[0]->find("./Potential");
if(potset.empty()){
ERRORMSG("Must provide potential information.")
return false;
} else {
Element* cur = dynamic_cast<Element*>(potset[0]);
Attribute* att = cur->get_attribute("type");
if(att){
pottype = att->get_value();
NodeSet oset = aset[0]->find("./OrbitalSet");
if(oset.empty()){
ERRORMSG("Must specify OrbitalSet")
return false;
} else {
Element* cur = dynamic_cast<Element*>(oset[0]);
Attribute* att = cur->get_attribute("rest_type");
if(att) Psi.Restriction = att->get_value();
XMLReport("Orbital restriction type = " << Psi.Restriction)
xmlNode* curc = cur->cobj();
if(pottype == "Harmonic"){
if(nshells) FillShellsHarmPot(Psi,nshells);
} else {
if(nshells) FillShellsNucPot(Psi,nshells);
}
Psi.put(curc);
Pot.initialize(Psi);
LOGMSG("No of Orbs = " << Psi.size());
LOGMSG("Orbital | Orbital ID");
for(int j=0; j < Psi.size(); j++){
LOGMSG(j << " " << Psi.ID[j]);
}
LOGMSG("ID | IDcount");
for(int j=0; j < Psi.NumUniqueOrb; j++){
LOGMSG(j << " " << Psi.IDcount[j]);
}
}
XMLReport("Potential Type = " << pottype)
} else {
ERRORMSG("Must provide Potential Type.")
return false;
}
if(pottype == "Nuclear"){
XMLReport("Creating a Nuclear Potential.")
double Z;
NodeSet gpset = potset[0]->find("./Parameter");
if(gpset.empty()){
Z = Psi.NumOrb;
WARNMSG("Default: Z = " << Z)
} else {
for(int i=0; i<gpset.size(); i++){
Element* cur = dynamic_cast<Element*>(gpset[i]);
Attribute* att = cur->get_attribute("name");
if(att) {
const string& aname = att->get_value();
xmlNode* curc = cur->cobj();
if(aname == "Z") putContent(Z,curc);
XMLReport("Z = " << Z)
}
}
}
// determine maximum angular momentum
int lmax = 0;
for(int i=0; i<Psi.L.size(); i++)
if(Psi.L[i] > lmax) lmax = Psi.L[i];
XMLReport("Maximum Angular Momentum = " << lmax)
CG_coeff = new Clebsch_Gordan(lmax);
Pot.add(new ZOverRFunctor(Z));
Pot.add(new HartreePotential(CG_coeff));
Pot.add(new ExchangePotential(CG_coeff));
Psi.CuspParam = Z;
Psi.EigenBoundParam = Z;
} // if Nuclear
else if(pottype == "Harmonic"){
XMLReport("Creating a Harmonic Potential.")
double Omega;
NodeSet gpset = potset[0]->find("./Parameter");
if(gpset.empty()){
Omega = Psi.NumOrb;
WARNMSG("Default: Omega = " << Omega)
} else {
for(int i=0; i<gpset.size(); i++){
Element* cur = dynamic_cast<Element*>(gpset[i]);
Attribute* att = cur->get_attribute("name");
if(att) {
const string& aname = att->get_value();
xmlNode* curc = cur->cobj();
if(aname == "Omega") putContent(Omega,curc);
else if(aname == "Z") putContent(Omega,curc);
XMLReport("Omega = " << Omega)
}
}
}
// determine maximum angular momentum
int lmax = 0;
for(int i=0; i<Psi.L.size(); i++)
if(Psi.L[i] > lmax) lmax = Psi.L[i];
lmax++; // increment by 1
XMLReport("Maximum Angular Momentum = " << lmax)
CG_coeff = new Clebsch_Gordan(lmax);
Pot.add(new HarmonicFunctor(Omega));
Pot.add(new HartreePotential(CG_coeff));
Pot.add(new ExchangePotential(CG_coeff));
Psi.CuspParam = 0.0;
Psi.EigenBoundParam = Omega;
} // if Harmonic
else if(pottype == "Nuclear_Scalar_Rel"){
XMLReport("Creating a Nuclear Scalar Relativistic Potential.")
double Z;
NodeSet gpset = potset[0]->find("./Parameter");
if(gpset.empty()){
Z = Psi.NumOrb;
WARNMSG("Default: Z = " << Z)
} else {
for(int i=0; i<gpset.size(); i++){
Element* cur = dynamic_cast<Element*>(gpset[i]);
Attribute* att = cur->get_attribute("name");
if(att) {
const string& aname = att->get_value();
xmlNode* curc = cur->cobj();
if(aname == "Z") putContent(Z,curc);
XMLReport("Z = " << Z)
}
}
}
// determine maximum angular momentum
int lmax = 0;
for(int i=0; i<Psi.L.size(); i++)
if(Psi.L[i] > lmax) lmax = Psi.L[i];
XMLReport("Maximum Angular Momentum = " << lmax)
CG_coeff = new Clebsch_Gordan(lmax);
Pot.add(new ZOverRFunctor(Z));
Pot.add(new HartreePotential(CG_coeff));
Pot.add(new ExchangePotential(CG_coeff));
Psi.CuspParam = Z;
Psi.EigenBoundParam = Z;
} // if Nuclear_Scalar_Rel
else if(pottype == "Pseudo"){
XMLReport("Creating a Starkloff-Joannopoulos Pseudo-Potential.")
double rc, lambda, Zeff;
NodeSet gpset = potset[0]->find("./Parameter");
if(gpset.empty()){
ERRORMSG("Must Provide core radius and decay for PseudoPotential.")
return false;
} else {
for(int i=0; i<gpset.size(); i++){
Element* cur = dynamic_cast<Element*>(gpset[i]);
Attribute* att = cur->get_attribute("name");
if(att) {
const string& aname = att->get_value();
xmlNode* curc = cur->cobj();
if(aname == "rc"){
putContent(rc,curc);
XMLReport("Core radius = " << rc)
} else if(aname == "lambda"){
putContent(lambda,curc);
XMLReport("Decay = " << lambda)
} else if(aname == "Zeff"){
putContent(Zeff,curc);
XMLReport("Effective core charge = " << Zeff)
}
}
}
}
// determine maximum angular momentum
int lmax = 0;
for(int i=0; i<Psi.L.size(); i++)
if(Psi.L[i] > lmax) lmax = Psi.L[i];
XMLReport("Maximum Angular Momentum = " << lmax)
CG_coeff = new Clebsch_Gordan(lmax);
Pot.add(new PseudoPotential(Zeff,rc,lambda));
Pot.add(new HartreePotential(CG_coeff));
Pot.add(new ExchangePotential(CG_coeff));
Psi.CuspParam = 0.0;
Psi.EigenBoundParam = 2.0*Zeff/rc;
} // if Pseudo
}
}
return true;
}
}
int main(int argc, char **argv) {
using namespace ohmmshf;
using namespace xmlpp;
DomParser parser;
parser.parse_file(argv[1]);
Node* root
= parser.get_document()->get_root_node(); //deleted by DomParser.
string element;
string pottype;
string gridtype;
RadialPotentialSet Pot;
HFAtomicOrbitals Psi;
parseXMLFile(Pot,Psi,element,pottype,gridtype,root);
HartreeFock HFSolver(Pot,Psi,root);
HFSolver.solve(pottype,gridtype,Psi.size());
Psi.print(element);
return 1;
}
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

170
src/AtomicHF/HartreeFock.h Normal file
View File

@ -0,0 +1,170 @@
#ifndef OHMMS_ATOMICHF_HARTREEFOCK_H
#define OHMMS_ATOMICHF_HARTREEFOCK_H
#include "AtomicHF/HFConfiguration.h"
#include "AtomicHF/HFAtomicOrbitals.h"
#include "AtomicHF/RadialPotentialSet.h"
#include "Numerics/RnlRelTransform.h"
#include "Numerics/RnlTransform.h"
#include "Numerics/HarmTransform.h"
#include "Numerics/Numerov.h"
#include "Numerics/RadialFunctorUtility.h"
#include "OhmmsData/libxmldefs.h"
#include <libxml++/libxml++.h>
#include <ofstream>
namespace ohmmshf {
struct HartreeFock {
typedef HFAtomicOrbitals::value_type value_type;
typedef HFAtomicOrbitals::RadialOrbital_t RadialOrbital_t;
int maxiter;
value_type eig_tol, scf_tol, ratio;
RadialPotentialSet& Pot;
HFAtomicOrbitals& Psi;
HartreeFock(RadialPotentialSet& pot, HFAtomicOrbitals& psi,
const xmlpp::Node* root):
Pot(pot), Psi(psi), maxiter(1000), eig_tol(1e-12),
scf_tol(1e-8), ratio(0.35) { put(root); }
bool put(const xmlpp::Node* q){
using namespace xmlpp;
NodeSet eset = q->find("./EigenSolve");
if(eset.empty()){
WARNMSG("Using default values for eigensolver.")
XMLReport("maximum iterations = " << maxiter)
XMLReport("eigentolerance = " << eig_tol)
XMLReport("scftolerance = " << scf_tol)
XMLReport("ratio = " << ratio)
} else {
NodeSet pset = eset[0]->find("./Parameter");
for(int i=0; i<pset.size(); i++){
Element* cur = dynamic_cast<Element*>(pset[i]);
Attribute* att = cur->get_attribute("name");
if(att) {
const string& aname = att->get_value();
xmlNode* ccur = cur->cobj();
if(aname == "max_iter"){
putContent(maxiter,ccur);
XMLReport("maximum iterations = " << maxiter)
} else if(aname == "eig_tol"){
putContent(eig_tol,ccur);
XMLReport("eigentolerance = " << eig_tol)
} else if(aname == "en_tol"){
putContent(scf_tol,ccur);
XMLReport("scftolerance = " << scf_tol)
} else if(aname == "mix_ratio"){
putContent(ratio,ccur);
XMLReport("ratio = " << ratio)
}
}
}
}
}
template<class Transform_t>
void run_hf(Transform_t* fake, int norb) {
typedef Numerov<Transform_t, RadialOrbital_t> Numerov_t;
value_type Vtotal,KEnew, KEold,E;
vector<value_type> energy(Pot.size()), epsilon(norb);
value_type lowerbound, upperbound;
int iter = 0;
Vtotal = Pot.evaluate(Psi,energy,norb);
Pot.mix(0.0);
KEnew = Pot.calcKE(Psi,0,norb);
string label("spdf");
ofstream log_stream("atomicHF.log");
log_stream.precision(8);
do {
KEold = KEnew;
value_type eigsum = 0.0;
///loop over the orbitals
for(int ob=0; ob < norb; ob++){
///set up the transformer
Transform_t es(Pot.V[ob], Psi.N[ob], Psi.L[ob],
Psi.CuspParam, Psi.EigenBoundParam);
///initialize the numerov solver
Numerov_t numerov(es,Psi(ob));
///calculate the lower and upper bounds for the eigenvalue
es.EnergyBound(lowerbound,upperbound);
///perform the numerov algorithm
///calculate the eigenvalue and the corresponding orbital
eigsum += (epsilon[ob] =
numerov.solve(lowerbound, upperbound, eig_tol));
log_stream << Psi.N[ob]<< label[Psi.L[ob]] << '\t' << epsilon[ob] << endl;
}
log_stream << endl;
///normalize the orbitals
Psi.normalize(norb);
///restrict the orbitals
Psi.applyRestriction(norb);
///calculate the new kinetic energy
KEnew = Pot.calcKE(Psi,eigsum,norb);
///the total energy
E = KEnew + Vtotal;
///for the new orbitals Psi, calculate the new SCF potentials
Vtotal = Pot.evaluate(Psi,energy,norb);
Pot.applyRestriction(Psi);
Pot.mix(ratio);
log_stream.precision(10);
log_stream << "Iteration #" << iter+1 << endl;
log_stream << "KE = " << setw(15) << KEnew
<< " PE = " << setw(15) << Vtotal << endl;
log_stream << "PE/KE = " << setw(15) << Vtotal/KEnew
<< " Energy = " << setw(15) << E << endl;
log_stream << endl;
iter++;
///continue the loop until the kinetic energy converges
}while(fabs(KEnew-KEold)>scf_tol && iter<maxiter);
}
inline void solve(string pottype, string gridtype, int norb) {
if(pottype == "Harmonic"){
if(gridtype == "linear"){
HarmLinearTransform<RadialOrbital_t> *afake=NULL;
run_hf(afake,norb);
} else if(gridtype == "log"){
HarmLogTransform<RadialOrbital_t> *afake=NULL;
run_hf(afake,norb);
}
} else if(pottype == "Nuclear_Scalar_Rel"){
if(gridtype == "linear"){
RnlRelLinearTransform<RadialOrbital_t> *afake=NULL;
run_hf(afake,norb);
} else if(gridtype == "log"){
RnlRelLogTransform<RadialOrbital_t> *afake=NULL;
run_hf(afake,norb);
}
} else if(pottype == "Nuclear"){
if(gridtype == "linear"){
RnlLinearTransform<RadialOrbital_t> *afake=NULL;
run_hf(afake,norb);
} else if(gridtype == "log"){
RnlLogTransform<RadialOrbital_t> *afake=NULL;
run_hf(afake,norb);
}
} else if(pottype == "Pseudo"){
if(gridtype == "linear"){
RnlLinearTransform<RadialOrbital_t> *afake=NULL;
run_hf(afake,norb);
} else if(gridtype == "log"){
RnlLogTransform<RadialOrbital_t> *afake=NULL;
run_hf(afake,norb);
}
} else return;
}
};
}
#endif

47
src/AtomicHF/Makefile Normal file
View File

@ -0,0 +1,47 @@
##########################################################
# OHMMS application makefile stub for suite: linuxicc
# Created Sat Mar 29 15:39:36 CST 2003 by jnkim on bach
# Generated by configure --arch linuxicc --tb
##########################################################
include makefile.linuxicc
#CDIR = ../Common/IO
.SUFFIXES: .cpp .F .o
.f.o:
$(F77) $(F77FLAGS) -c $< -o $(ODIR)/$@
.cpp.o:
$(CXX) $(CXXFLAGSAPP) $(OHMMSINC) -c $< -o $@
BASEOBJS = $(ODIR)/OhmmsObject.o $(ODIR)/OhmmsInform.o $(ODIR)/OhmmsInfo.o $(ODIR)/Communicate.o $(ODIR)/CommCreate.o
COMMONOBJS = $(CDIR)/InputOutput.o $(CDIR)/InputOutputASCII.o $(CDIR)/InputOutputHDF5.o
HFOBJS = $(BASEOBJS) $(ODIR)/RadialPotential.o $(ODIR)/Clebsch_Gordan.o
hartreefock.x: HartreeFock.cpp $(HFOBJS)
$(CXX) $(CXXLDFLAGS) $(OHMMSINC) -o $(ODIR)/hartreefock.x HartreeFock.cpp $(HFOBJS) $(OHMMSLIBS)
#PASS_DEFS = "CC=${CXX} -c" "LD=${CXX}" "CCFLAGS=${CXXFLAGSAPP}" "DEFS=${DEFS}" "INCL=${OHMMSINC}" "LIBS=${OHMMSLIBS}"
#MAKE_ALL = $(MAKE) all $(PASS_DEFS)
#MAKE_NEWMAKE = $(MAKE) -f template.make newmake $(PASS_DEFS)
#Common_obj: Common_newmake
# cd ../Common; ${MAKE_ALL}
#Common_newmake:
# cd ../Common; $(MAKE_NEWMAKE)
#Common_clean:
# cd ../Common; ${MAKE} clean
#clean:
# rm -rf *.o hartreefock.x
include $(OHMMSDIR)/src/Utilities/Makefile
include $(OHMMSDIR)/src/Message/Makefile
include $(OHMMSDIR)/src/AtomicHF/Makefile
#include $(HFDIR)/src/Particle/Makefile
# ---------------------------------------------------
# $RCSfile$Author: jnkim $
# $Revision$Date: 2003/08/27 14:19:23 $
# ---------------------------------------------------

View File

@ -0,0 +1,349 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim and Jordan Vincent
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#include <math.h>
#include "AtomicHF/RadialPotential.h"
#include "AtomicHF/Clebsch_Gordan.h"
#include "Numerics/RadialFunctorUtility.h"
using namespace ohmmshf;
/*!
* \fn ZOverRFunctor::ZOverRFunctor(value_type z)
* \param z the charge of the Nuclear Potential
* \brief The Constructor for the Nuclear Potential
*
*/
ZOverRFunctor::ZOverRFunctor(value_type z): Z(z) { }
/*! RadialPotentialBase::value_type
PseudoPotential::evaluate(const HFAtomicOrbitals& psi,
RadialOrbitalSet_t& V, int norb)
* \param psi the wavefunction
* \param V the potential
* \param norb the number of orbitals
* \return The sum of the Nuclear Potential matrix
elements (energy): \f[
\langle i|V(r)|i \rangle = \sum_{k=0}^{N_{orb}}
\int_0^{\infty} dr\psi_k^*(r)V(r)\psi_k(r) \f]
* \brief Calculates and assigns the values of the Nuclear
Potential for each orbital. The Nuclear Potential: \f[
V_{Nuclear}(r) = -\frac{Z}{r} \f]
*
*/
RadialPotentialBase::value_type
ZOverRFunctor::evaluate(const HFAtomicOrbitals& psi,
RadialOrbitalSet_t& V, int norb){
RadialOrbital_t integrand(psi(0));
for(int ig=0; ig < psi.m_grid->size(); ig++) {
value_type t = -Z/psi.m_grid->r(ig);
value_type sum = 0.0;
for(int o=0; o < norb; o++) {
V[o](ig) += t;
sum += pow(psi(o,ig),2);
}
integrand(ig) = t*sum;
}
return integrate_RK2(integrand);
}
/*!
* \fn HarmonicFunctor::HarmonicFunctor(value_type omega)
* \param omega
* \brief The Constructor for the Harmonic Potential
*
*/
HarmonicFunctor::HarmonicFunctor(value_type omega):
Omega(omega) { }
/*! RadialPotentialBase::value_type
PseudoPotential::evaluate(const HFAtomicOrbitals& psi,
RadialOrbitalSet_t& V, int norb)
* \param psi the wavefunction
* \param V the potential
* \param norb the number of orbitals
* \return The sum of the Harmonic Potential matrix
elements (energy): \f[
\langle i|V(r)|i \rangle = \sum_{k=0}^{N_{orb}}
\int_0^{\infty} dr\psi_k^*(r)V(r)\psi_k(r) \f]
* \brief Calculates and assigns the values of the Harmonic
Potential for each orbital. The Harmonic Potential: \f[
V_{Harmonic}(r) = \frac{1}{2}\omega^2 r^2 \f]
*
*/
RadialPotentialBase::value_type
HarmonicFunctor::evaluate(const HFAtomicOrbitals& psi,
RadialOrbitalSet_t& V, int norb) {
RadialOrbital_t integrand(psi(0));
for(int ig=0; ig < psi.m_grid->size(); ig++) {
value_type v = 0.5*Omega*Omega*psi.m_grid->r(ig)*psi.m_grid->r(ig);
value_type sum = 0.0;
for(int o=0; o < norb; o++) {
V[o](ig) += v;
sum += pow(psi(o,ig),2);
}
integrand(ig) = v*sum;
}
return integrate_RK2(integrand);
}
/*!
* \fn PseudoPotential::PseudoPotential(VarRegistry<value_type>& vreg,
value_type zeff, value_type r_c,
value_type lambda)
* \param vreg a registry for the optimizable variables
\f$r_c\$f and \f$\lambda\f$
* \param zeff \f$Z_{Eff}\f$ the effective charge of the core
* \param r_c \f$r_c\$f the core-radius
* \param lambda \f$\lambda\f$ the decay parameter
* \brief The Constructor for the Joanappoulos-Starkloff
pseudopotential
*
*/
PseudoPotential::PseudoPotential(VarRegistry<value_type>& vreg,
value_type zeff, value_type r_c,
value_type lambda):
Zeff(zeff), rc(r_c), SJ_lambda(lambda) {
vreg.add("SJ_lambda",&SJ_lambda);
vreg.add("r_core",&rc);
}
PseudoPotential::PseudoPotential(value_type zeff, value_type r_c,
value_type lambda):
Zeff(zeff), rc(r_c), SJ_lambda(lambda) { }
/*! RadialPotentialBase::value_type
PseudoPotential::evaluate(const HFAtomicOrbitals& psi,
RadialOrbitalSet_t& V, int norb)
* \param psi the wavefunction
* \param V the potential
* \param norb the number of orbitals
* \return The sum of the PseudoPotential matrix elements: \f[
\langle i|V_{PP}(r)|i \rangle = \sum_{k=0}^{N_{orb}}
\int_0^{\infty} dr\psi_k^*(r)V_{PP}(r)\psi_k(r) \f]
* \brief Calculates and assigns the values of the pseudopotential
for each orbital. The Starkloff-Joannapoulos pseudopotential: \f[
V_{PP}(r) = -\frac{Z_{Eff}}{r}\frac{1-e^{-\lambda r}}
{1-e^{-\lambda (r-r_c)}} \f]
*
*/
RadialPotentialBase::value_type
PseudoPotential::evaluate(const HFAtomicOrbitals& psi,
RadialOrbitalSet_t& V, int norb) {
RadialOrbital_t integrand(psi(0));
for(int ig=0; ig < psi.m_grid->size(); ig++) {
value_type r = psi.m_grid->r(ig);
value_type SJ_num = 1.0-exp(-SJ_lambda*r);
value_type SJ_den = 1.0+exp(-SJ_lambda*(r-rc));
value_type v = -Zeff/r*SJ_num/SJ_den;
value_type sum = 0.0;
for(int o=0; o < norb; o++) {
V[o](ig) += v;
sum += pow(psi(o,ig),2);
}
integrand(ig) = v*sum;
}
return integrate_RK2(integrand);
}
/*!
* \fn HartreePotential::HartreePotential(Clebsch_Gordan* cg)
* \param cg The Clebsch-Gordan matrix elements
* \brief The Constructor for the HartreePotential
*
*/
HartreePotential::HartreePotential(Clebsch_Gordan* cg):
CG_coeff(cg) { }
/*!
* \fn RadialPotentialBase::value_type
HartreePotential::evaluate(const HFAtomicOrbitals& psi,
RadialOrbitalSet_t& V, int norb)
* \param psi The wavefuntion
* \param V The potential
* \param norb The number of orbitals
* \return The sum of the Hartree matrix elements: \f[
\langle ij|\frac{1}{r_{12}}|ij \rangle = \sum_{k=0}^{max(2l_i,2l_j)}
c^k(l_i,m_i;l_i,m_i)c^k(l_j,m_j;l_j,m_j)R^k(i,j;i,j) \f]
*
* \brief Calculates and assigns the values for the Hartree potential
for each orbital. The Hartree potential: \f[ V_{Hartree}(r) =
\sum_j\sum_{k=0}^{max(2l_i,2l_j)} (-1)^{m_i+m_j}
\frac{(2l_i+1)(2l_j+1)}{(2k+1)^2}c_g(l_i,l_j,k,0,0)
c_g(l_j,l_j,k,0,0)c_g(l_i,l_i,k,-m_i,m_i)
c_g(l_i,l_i,k,-m_j,m_j)\frac{ Y_k(n_jl_j,n_jl_j/r)}{r} \f]
*
*/
RadialPotentialBase::value_type
HartreePotential::evaluate(const HFAtomicOrbitals& psi,
RadialOrbitalSet_t& V, int norb) {
int kmax, k;
int pt;
value_type coeff, ith_orb_coeff, jth_orb_coeff, energy_coeff = 0;
value_type Ehartree=0;
RadialOrbital_t Ykii_r(psi(0));
RadialOrbital_t Ykjj_r(psi(0));
RadialOrbital_t Psisq_x_Yk(psi(0));
int npts = psi.m_grid->size();
for(int i=0; i < norb; i++) {
int mi = psi.M[i];
int li = psi.L[i];
int two_li_plus_one = 2*li + 1;
for(int j=i; j < norb; j++) {
int mj = psi.M[j];
int lj = psi.L[j];
int two_lj_plus_one = 2*lj + 1;
int kmax = (li > lj) ? 2*lj : 2*li;
for(int k=kmax; k >= 0; k -= 2) {
int two_k_plus_one = 2*k+1;
int lmax = CG_coeff->Lmax;
coeff = static_cast<value_type>(two_li_plus_one*two_lj_plus_one)/
static_cast<value_type>(two_k_plus_one)/static_cast<value_type>(two_k_plus_one)
* CG_coeff->cg(li,li,k,0+lmax,0+lmax) * CG_coeff->cg(lj,lj,k,0+lmax,0+lmax)
* CG_coeff->cg(li,li,k,mi+lmax,-mi+lmax) * CG_coeff->cg(lj,lj,k,mj+lmax,-mj+lmax)
* pow(-1.0, mi+mj);
if(i == j) coeff /= 2.0;
ith_orb_coeff = psi.Occ[i] * coeff;
jth_orb_coeff = psi.Occ[j] * coeff;
energy_coeff = psi.Occ[j] * psi.Occ[i] * coeff;
Ykofr(Ykii_r, psi(i), psi(i), k);
Ykofr(Ykjj_r, psi(j), psi(j), k);
for(int gp=0; gp<npts; gp++){
V[i](gp) += jth_orb_coeff*Ykjj_r(gp);
V[j](gp) += ith_orb_coeff*Ykii_r(gp);
}
Ehartree += Phisq_x_Yk(Ykjj_r, psi(i), psi(i), 0.5*energy_coeff);
Ehartree += Phisq_x_Yk(Ykii_r, psi(j), psi(j), 0.5*energy_coeff);
}
}
}
return Ehartree;
}
/*!
* \fn ExchangePotential::ExchangePotential(Clebsch_Gordan* cg)
* \param cg The Clebsch-Gordan matrix elements
* \brief The Constructor for the ExchangePotential
*
*/
ExchangePotential::ExchangePotential(Clebsch_Gordan* cg):
CG_coeff(cg) { }
/*!
* \fn RadialPotentialBase::value_type
ExchangePotential::evaluate(const HFAtomicOrbitals& psi,
RadialOrbitalSet_t& V, int norb)
* \param psi The wavefuntion
* \param V The potential
* \param norb The number of orbitals
* \return The sum of the Exchange matrix elements: \f[ \langle
ij|\frac{1}{r_{12}}|ji \rangle =
\sum_{k=|l_i-l_j|}^{l_i+l_j}c^k(l_i,m_i;l_j,m_j)R^k(ij;ji) \f]
* \brief Calculates and assigns the values for the exchange potential
for each orbital. The exchange potential: \f[ V_{exchange}(r) =
\sum_j\delta(s_i,s_j)\sum_{k=|l_i-l_j|}^{l_i+l_j}
\frac{(2l_i+1)(2l_j+1)}{(2k+1)^2}c_g(l_i,l_j,k,0,0)^2
c_g(l_i,l_j,k,-m_i,m_j)^2\frac{ Y_k(n_il_i,n_jl_j/r)}{r} \f] is
non-local.
*/
RadialPotentialBase::value_type
ExchangePotential::evaluate(const HFAtomicOrbitals& psi,
RadialOrbitalSet_t& V, int norb) {
value_type ith_orb_coeff, jth_orb_coeff, coeff;
value_type energy_coeff=0;
value_type Eexchange=0;
/// zero_all_orbitals(); V is reset before entering
RadialOrbital_t Ykij_r(psi(0));
// Loop over all pairs of electrons once
for(int i=0; i < norb; i++) {
int si = psi.S[i];
int mi = psi.M[i];
int li = psi.L[i];
int two_li_plus_one = 2*li + 1;
for(int j=i; j < norb; j++) {
int sj = psi.S[j];
int mj = psi.M[j];
int lj = psi.L[j];
int two_lj_plus_one = 2*lj + 1;
int kmax = li + lj;
int kmin = abs(li - lj);
if( si == sj ) {
for(int k=kmax; k >= kmin; k-=2) {
int two_k_plus_one = 2*k + 1;
int lmax = CG_coeff->Lmax;
coeff = static_cast<value_type>(two_li_plus_one * two_lj_plus_one) /
static_cast<value_type>(two_k_plus_one*two_k_plus_one)
* CG_coeff->cg(li,lj,k,0+lmax,0+lmax) * CG_coeff->cg(li,lj,k,-mi+lmax,mj+lmax)
* CG_coeff->cg(li,lj,k,0+lmax,0+lmax) * CG_coeff->cg(li,lj,k,-mi+lmax,mj+lmax);
if(i == j) coeff /= 2.0;
ith_orb_coeff = psi.Occ[i] * coeff;
jth_orb_coeff = psi.Occ[j] * coeff;
energy_coeff = psi.Occ[j] * psi.Occ[i] * coeff;
Ykofr(Ykij_r, psi(i), psi(j), k); /// Ykofr_phi1_phi2
Make_Loc_Pot(V[i], Ykij_r, psi(i), psi(j),jth_orb_coeff);
Make_Loc_Pot(V[j], Ykij_r, psi(j), psi(i),ith_orb_coeff);
Eexchange -= Phisq_x_Yk(Ykij_r, psi(i), psi(j), energy_coeff);
}
}
}
}
return Eexchange;
}
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,121 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim and Jordan Vincent
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMSHF_RADIALPOTENTIALBASE_H
#define OHMMSHF_RADIALPOTENTIALBASE_H
#include "AtomicHF/HFAtomicOrbitals.h"
#include "Optimize/VarList.h"
/*! \author Jeongnim Kim
* \author Jordan Vincent
* \note The original Prim was written in F90 by Tim Wilkens.
*/
class Clebsch_Gordan;
namespace ohmmshf {
/**class RadialPotentialBase
*\brief An abstract class to build grid potentials
*/
struct RadialPotentialBase {
typedef HFAtomicOrbitals::value_type value_type;
typedef HFAtomicOrbitals::RadialGrid_t RadialGrid_t;
typedef HFAtomicOrbitals::RadialOrbital_t RadialOrbital_t;
typedef HFAtomicOrbitals::RadialOrbitalSet_t RadialOrbitalSet_t;
///constructor
RadialPotentialBase() {}
///destructor
virtual ~RadialPotentialBase() { }
/*! \fn virtual
value_type evaluate(const HFAtomicOrbitals& mo,
RadialOrbitalSet_t& V, int norb)
* \param psi the wavefunction
* \param V the potential
* \param norb the number of orbitals
*/
virtual
value_type evaluate(const HFAtomicOrbitals& mo,
RadialOrbitalSet_t& V, int norb) = 0;
};
/**class ZOverRFunctor
*\brief Implements the Nuclear potential
*/
struct ZOverRFunctor: public RadialPotentialBase {
value_type Z;
ZOverRFunctor(value_type z);
value_type evaluate(const HFAtomicOrbitals& mo,
RadialOrbitalSet_t& V, int norb);
};
/**class HarmonicFunctor
*\brief Implements the Harmonic potential
*/
struct HarmonicFunctor: public RadialPotentialBase {
value_type Omega;
HarmonicFunctor(value_type omega);
value_type evaluate(const HFAtomicOrbitals& mo,
RadialOrbitalSet_t& V, int norb);
};
/**class PseudoPotential
*\brief Implements the Starkloff-Joanappoulos
pseudopotential
*/
struct PseudoPotential: public RadialPotentialBase {
value_type Zeff, SJ_lambda, rc;
PseudoPotential(VarRegistry<value_type>&,value_type,
value_type,value_type);
PseudoPotential(value_type,value_type,value_type);
value_type evaluate(const HFAtomicOrbitals& mo,
RadialOrbitalSet_t&V, int norb);
};
/**class HartreePotential
*\brief Implements the Hartree potential
*/
struct HartreePotential: public RadialPotentialBase {
Clebsch_Gordan *CG_coeff;
HartreePotential(Clebsch_Gordan*);
value_type evaluate(const HFAtomicOrbitals& mo,
RadialOrbitalSet_t& V, int norb);
};
/**class ExchangePotential
*\brief Implements the exchange potential
*/
struct ExchangePotential: public RadialPotentialBase {
Clebsch_Gordan *CG_coeff;
ExchangePotential(Clebsch_Gordan*);
value_type evaluate(const HFAtomicOrbitals& mo,
RadialOrbitalSet_t& V, int norb);
};
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,197 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim and Vincent Jordan
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_RADIALPOTENTIALSET_H
#define OHMMS_RADIALPOTENTIALSET_H
#include "AtomicHF/RadialPotential.h"
#include "Numerics/OneDimIntegration.h"
namespace ohmmshf {
struct RadialPotentialSet {
typedef RadialPotentialBase::value_type value_type;
typedef RadialPotentialBase::RadialOrbital_t RadialOrbital_t;
typedef RadialPotentialBase::RadialGrid_t RadialGrid_t;
///the grid potentials for each orbital
RadialPotentialBase::RadialOrbitalSet_t V;
///the grid potentials for each orbital
RadialPotentialBase::RadialOrbitalSet_t Vsave;
///the Self Consistent Fields
vector<RadialPotentialBase*> SCF;
///constructor
RadialPotentialSet() { }
///destructor
~RadialPotentialSet() {
for(int i=0; i<SCF.size(); i++) delete SCF[i];
}
///add a new Self Consistent Field to the list
void add(RadialPotentialBase* a) { SCF.push_back(a);}
///return the number of Self Consistent Fields
inline int size() const {return SCF.size();}
///create a grid potential for each orbital in the wavefunction
void initialize(HFAtomicOrbitals& psi) {
for(int i=0; i < psi.size(); i++)
V.push_back(RadialOrbital_t(psi.m_grid));
for(int i=0; i<psi.size(); i++)
Vsave.push_back(RadialOrbital_t(psi.m_grid));
}
///reset the grid potentials to zero
void reset(HFAtomicOrbitals& psi) {
for(int i=0; i<V.size(); i++){
V[i].m_Y = 0.0;
Vsave[i].m_Y = 0.0;
}
}
/*! \fn inline value_type evaluate(HFAtomicOrbitals& psi,
vector<value_type>& Energy,
int norb)
* \param psi the wavefunction
* \param Energy vector to store the sum of each SCF of
the SCF matrix elements
* \param norb number of orbitals
* \brief Loop over all the SCFs to generate a new
potential for each orbital.
*/
inline value_type evaluate(HFAtomicOrbitals& psi,
vector<value_type>& Energy,
int norb) {
value_type sum = 0.0;
for(int i=0; i < V.size(); i++)
V[i].m_Y = 0.0;
for(int ip=0; ip<SCF.size(); ip++)
sum += (Energy[ip] = SCF[ip]->evaluate(psi,V,norb));
return sum;
}
/*! \fn inline void mix(value_type x)
* \param x the mixing ratio
* \brief Mix the old potential with the new
potential: \f[ V_{New}(r) = (1-x)V_{New}(r) +
x V_{Old}(r). \f] This is for convergence purposes, so
that the convergence is "smoother" and decreases the
possibility of having dramatic changes in the potential.
*/
inline void mix(value_type x) {
value_type y = 1-x;
for(int ob=0; ob < V.size(); ob++) {
V[ob].m_Y = y*V[ob].m_Y + x*Vsave[ob].m_Y;
Vsave[ob].m_Y = V[ob].m_Y;
}
}
/*! \fn inline value_type calcKE(HFAtomicOrbitals& psi,
value_type eigsum,
int norb)
* \param psi the wavefunction
* \param eigsum the sum of the eigenvalues
* \param norb the number of orbitals
* \return the total kinetic energy
* \brief Calculates the total kinetic energy:
\f[ KE = \sum_i^{Norb} \left\{ \epsilon_i - \int_0^{\infty}
dr \psi_i V(r) \psi_i \right\}. \f] This is true because
\f[ \langle \psi_i | -\frac{1}{2} \nabla^2 | \psi_i \rangle
= -\frac{1}{2r^2}\frac{d}{dr}\left( r^2 \frac{d}{dr} -
\frac{l(l+1)}{2r^2} = (\epsilon - V(r)) \f]
*/
inline value_type calcKE(HFAtomicOrbitals& psi,
value_type eigsum,
int norb){
value_type sum=0.0;
RadialOrbital_t integrand(psi(0));
for(int ob=0; ob < norb; ob++) {
for(int i=0; i < integrand.size(); i++){
integrand(i) = V[ob](i)*psi(ob,i)*psi(ob,i);
}
sum+=integrate_RK2(integrand);
}
return eigsum-sum;
}
/*! \fn void applyRestriction(HFAtomicOrbitals& psi)
* \param psi the wavefunction
* \brief Restrict the potential. Normally each orbital
\f$ \psi_i \f$ in the wavefunction has its own unique
potential, but we want to restrict the potential to be
the same for orbitals with the same quantum numbers,
such as \f$ (n,l) \f$. What this function does is
assign the average potential to all the orbitals that
are restricted to be the same.
*/
void applyRestriction(HFAtomicOrbitals& psi){
static vector<value_type> sum;
if(sum.empty()){
sum.resize(psi.m_grid->size());
for(int ig=0; ig < psi.m_grid->size(); ig++)
sum[ig] = 0.0;
}
///index of starting orbital index
int o_start = 0;
///index of ending orbital index
int o_end = 0;
///orbital index
int orb = 0;
while (orb < psi.size()) {
///loop over unique orbitals
for(int uorb=0; uorb < psi.NumUniqueOrb; uorb++){
///for each unique orbital, loop over all
///identical orbitals
for(int i=0; i < psi.IDcount[uorb]; i++){
///add all the orbitals together for averaging
for(int ig=0; ig < psi.m_grid->size(); ig++){
sum[ig] += V[orb](ig);
}
///increment the orbital index
orb++;
}
int o_end = o_start+psi.IDcount[uorb];
///assign the average back to the orbitals
for(int o = o_start; o < o_end; o++){
for(int ig=0; ig < psi.m_grid->size(); ig++){
V[o](ig) = sum[ig]/psi.IDcount[uorb];
}
}
o_start = o_end;
///reset the sum for the next average
for(int ig=0; ig < psi.m_grid->size(); ig++) sum[ig] = 0.0;
}
}
}
};
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

327
src/AtomicHF/YlmRnlSet.IO.h Normal file
View File

@ -0,0 +1,327 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim and Jordan Vincent
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
/*@author Jeongnim Kim and Jordan Vincent
*/
#ifndef OHMMS_YLMRNLSET_ONGRID_IO_H
#define OHMMS_YLMRNLSET_ONGRID_IO_H
#include "Numerics/HDFNumericAttrib.h"
#include "Numerics/Transform2GridFunctor.h"
/**@brief Print \f$ r R_{nl}(r)\f$ */
template<class GT>
bool YlmRnlSet<GT>::get(std::ostream& os) {
os.precision(12);
os.setf(ios::scientific, ios::floatfield);
for(int i=0; i < m_grid->size(); i++) {
os << setw(20) << m_grid->r(i);
for(int ob=0; ob < psi.size(); ob++) {
os << setw(20) << psi[ob](i);
}
os << endl;
}
return true;
}
/*! \fn template<class GT>
bool YlmRnlSet<GT>::put(xmlNodePtr cur)
* \param cur
* \return true if succeeds
* \brief Loops through the XML tree to find all the orbitals,
checks to see if the orbital has not already been added,
and adds any new orbitals to the orbital list.
*/
template<class GT>
bool YlmRnlSet<GT>::put(xmlNodePtr cur){
int n;
int l;
int m;
int s;
value_type occ;
cur = cur->xmlChildrenNode;
while(cur != NULL) {
if (!(xmlStrcmp(cur->name, (const xmlChar *) "Orbital"))) {
LOGMSG("Found Orbital");
n = atoi((const char*)xmlGetProp(cur, (const xmlChar *) "n"));
if(n < 0) {
ERRORMSG("Invalid value for n");
return false;
}
l = atoi((const char*)xmlGetProp(cur, (const xmlChar *) "l"));
if(l < 0) {
ERRORMSG( "Invalid value for l");
return false;
}
m = atoi((const char*)xmlGetProp(cur, (const xmlChar *) "m"));
if(m < -l && m > 1) {
ERRORMSG( "Invalid value for m");
return false;
}
s = atoi((const char*)xmlGetProp(cur, (const xmlChar *) "s"));
if(s != 1 && s != -1) {
ERRORMSG( "Invalid value for spin");
return false;
}
occ = atof((const char*)xmlGetProp(cur, (const xmlChar *) "c"));
if(static_cast<int>(occ) !=0 && static_cast<int>(occ) != 1) {
ERRORMSG( "Invalid value for occupation");
return false;
}
NLMSIndex nlms(n,l,m,s);
NLMS_Map_t::iterator it = OccNo.find(nlms);
if(it == OccNo.end()) {
add(n,l,m,s,occ);
LOGMSG("Adding Orbital: n=" << n << ", l=" << l <<
", m=" << m << ", s=" << s << ", occ=" << occ);
// OccNo[nlmn] = Num-1;
OccNo[nlms] = 1;
} else {
ERRORMSG( "Error, orbital " << n << l << m << s
<< " already occupied");
return false;
}
}
cur = cur->next;
}
return true;
}
/*! \fn template<class GT>
bool YlmRnlSet<GT>::print(const std::string& elementName)
* \param elementName name of the element
* \return true if succeeds
* \brief The output files produced by this function are
for use in a Quantum Monte Carlo code and for graphical
purposes only. Prints the grid and orbital information to an HDF5
file named "elementName.h5". Also prints the basis information
to a file named "elementName.basis.xml" and the individual
orbitals to ASCII files named "ORB.N.L.(M).(S).elementName",
where N,L,M,S are the quantum numbers (M,S are only printed
if the orbitals are unrestricted). In the ASCII files, the
orbitals are first interpolated onto a linear grid of 500
points for reasons of disk-space.
*/
template<class GT>
bool YlmRnlSet<GT>::print(const std::string& elementName){
/// print to file fname
string HDFfname = elementName + ".h5";
hid_t afile = H5Fcreate(HDFfname.c_str(),H5F_ACC_TRUNC,
H5P_DEFAULT,H5P_DEFAULT);
OneDimGridBase<double>* reduced_grid;
reduced_grid = new LinearGrid<double>;
ofstream* out;
int orbindex = 0;
/// main group
hid_t group_id = H5Gcreate(afile,"radial_basis_states",0);
/// output grid information
hid_t group_id_grid = H5Gcreate(group_id,"grid",0);
Vector<int> grid_type(1);
Vector<double> grid_params(3);
grid_params[0] = m_grid->rmin();
grid_params[1] = m_grid->rmax();
grid_params[2] = static_cast<double>(m_grid->size());
// if(gridtype == "linear")
// grid_type[0] = 1;
// else if(gridtype == "log")
grid_type[0] = 2;
//HDFAttribIO<string> GridHDFTypeOut(gridtype);
//GridHDFTypeOut.write(group_id_grid,"grid_type");
HDFAttribIO<Vector<int> > GridHDFTypeOut(grid_type);
GridHDFTypeOut.write(group_id_grid,"grid_type");
HDFAttribIO<Vector<double> > GridHDFParamOut(grid_params);
GridHDFParamOut.write(group_id_grid,"params");
H5Gclose(group_id_grid);
/// output orbital information
/// output only unique radial functions
for(int orb=0; orb<NumUniqueOrb; orb++){
char grpname[128];
sprintf(grpname,"orbital%04d",orb);
hid_t group_id_orb = H5Gcreate(group_id,grpname,0);
Vector<int> Power(1);
Power[0] = 1+L[orbindex];
HDFAttribIO<Vector<int> > PowerHDFOut(Power);
PowerHDFOut.write(group_id_orb,"power");
Vector<int> QuantumNo(3);
QuantumNo[0] = N[orbindex];
QuantumNo[1] = L[orbindex];
// only single-zeta basis
QuantumNo[2] = 1;
HDFAttribIO<Vector<int> > QuantumNoHDFOut(QuantumNo);
QuantumNoHDFOut.write(group_id_orb,"quantum_numbers");
///vector to store the radial orbital
Vector<double> rad_orb;
///create the ASCII file
char sfname[128];
if(Restriction == "none")
sprintf(sfname,"ORB.%01d.%01d.%01d.%01d.%01s",N[orbindex],L[orbindex],
M[orbindex],S[orbindex],elementName.c_str());
else
sprintf(sfname,"ORB.%01d.%01d.%01s",N[orbindex],L[orbindex],
elementName.c_str());
out = new ofstream(sfname);
int max_rad = m_grid->size()-1;
while(fabs(psi[orbindex](max_rad)) < 1e-12) max_rad--;
max_rad += 2;
rad_orb.resize(max_rad);
reduced_grid->set(0.0,m_grid->r(max_rad),max_rad);
RadialOrbital_t temp_orb(reduced_grid);
for(int i=0; i<rad_orb.size(); i++)
rad_orb(i) = psi[orbindex](i);
///calculate the boundary conditions
int imin = 0;
value_type deriv = (psi[orbindex](imin+1) - psi[orbindex](imin))/m_grid->dr(imin);
psi[orbindex].spline(imin,deriv,max_rad,0.0);
Transform2GridFunctor<OneDimGridFunctor<double>,OneDimGridFunctor<double> >
transform(psi[orbindex],temp_orb);
transform.generate();
for(int j=0; j<reduced_grid->size(); j++)
*out << setw(15) << temp_orb.r(j) << setw(15) << temp_orb(j) << endl;
out->close();
HDFAttribIO<Vector<double> > RadOrbOut(rad_orb);
RadOrbOut.write(group_id_orb,"radial_orbital");
H5Gclose(group_id_orb);
orbindex += IDcount[orb];
}
H5Gclose(group_id);
H5Fclose(afile);
/// create input for qmc
int nUp = 0;
int nDn = 0;
int nBasis = 0;
ofstream* osXML;
string fnameXML = elementName + ".basis.xml";
osXML = new ofstream(fnameXML.c_str());
*osXML << "<DeterminantSet type=\"MolecularOrbital\">" << endl;
*osXML << "<BasisSet>" << endl;
*osXML << "<Basis type=\"HFNG\" species=\"" << elementName
<< "\" file=\"" << HDFfname << "\">" << endl;
if(Restriction == "none"){
for(int orb=0; orb<size(); orb++){
(S[orb] == 1) ? nUp++ : nDn++;
nBasis++;
char idname[128];
sprintf(idname,"R%03d",ID[orb]);
*osXML << "<psi id=\"" << idname << "\" n=\"" << N[orb]
<< "\" l=\"" << L[orb] << "\" m=\"" << M[orb]
<< "\" s=\"" << S[orb] << "\" zeta=\"1\"/>" << endl;
}
} else {
for(int orb=0; orb<size(); orb++){
(S[orb] == 1) ? nUp++ : nDn++;
if(S[orb] == 1){
nBasis++;
char idname[128];
sprintf(idname,"R%03d",ID[orb]);
*osXML << "<psi id=\"" << idname << "\" n=\"" << N[orb]
<< "\" l=\"" << L[orb] << "\" m=\"" << M[orb]
<< "\" s=\"" << S[orb] << "\" zeta=\"1\"/>" << endl;
}
}
}
*osXML << "</Basis>" << endl;
*osXML << "</BasisSet>" << endl;
*osXML << "<SlaterDeterminant>" << endl;
*osXML << "<Determinant spin=\"1\" orbitals=\"" << nUp << "\">" << endl;
*osXML << "<Var type=\"Array\">" << endl;
Matrix<double> M_Up(nUp,nBasis);
if(Restriction == "none"){
int row = 0;
orbindex = 0;
for(int j=0; j<M_Up.cols(); j++){
if(S[orbindex] == 1){
M_Up(row,j) = 1.0;
row++;
}
orbindex += IDcount[j];
}
} else {
int row = 0;
int col = 0;
while(row < M_Up.rows()){
M_Up(row,col) = 1.0;
row++; col++;
}
}
*osXML << M_Up;
*osXML << "</Var>" << endl;
*osXML << "</Determinant>" << endl;
*osXML << "<Determinant spin=\"-1\" orbitals=\"" << nDn << "\">" << endl;
*osXML << "<Var type=\"Array\">" << endl;
Matrix<double> M_Dn(nDn,nBasis);
if(Restriction == "none"){
orbindex = 0;
int row = 0;
for(int j=0; j<M_Dn.cols(); j++){
if(S[orbindex] == -1){
M_Dn(row,j) = 1.0;
row++;
}
orbindex += IDcount[j];
}
} else {
int row = 0;
int col = 0;
while(row < M_Dn.rows()){
M_Dn(row,col) = 1.0;
row++; col++;
}
}
*osXML << M_Dn;
*osXML << "</Var>" << endl;
*osXML << "</Determinant>" << endl;
*osXML << "</SlaterDeterminant>" << endl;
*osXML << "</DeterminantSet>" << endl;
delete osXML;
return true;
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

157
src/AtomicHF/YlmRnlSet.cpp Normal file
View File

@ -0,0 +1,157 @@
#ifndef OHMMS_YLMRNLSET_ONGRID_CPP_H
#define OHMMS_YLMRNLSET_ONGRID_CPP_H
/*! \fn template<class GT>
bool YlmRnlSet<GT>::add(int n, int l, int m, int s, value_type occ)
* \param n principal quantum number
* \param l angular momentum
* \param m z-component of angular momentum
* \param s spin
* \param occ occupation
* \return true if succeeds
* \brief Add a new orbital with quantum numbers \f$ (n,l,m,s) \f$ to
the list of orbitals. The orbitals are sorted by their restriction
type, i.e. if the restriction type is \f$ (n,l) \f$ "spin+space" then
all the orbitals with the same \f$ (n,l) \f$ are grouped together.
Each orbital is assigned an id, with the possibility of several
orbitals sharing the same id if they are restricted.
*/
template<class GT>
bool YlmRnlSet<GT>::add(int n, int l, int m, int s, value_type occ) {
if(Restriction == "spin+space") {
NLIndex nl(n,l);
NL_Map_t::iterator it = NL.find(nl);
///if the orbital is new add it to the end of the list
if(it == NL.end()) {
///assign the orbital a new id
ID.push_back(NumUniqueOrb);
///the id counter is set to 1
IDcount.push_back(1);
///add a new element to the map
NL[nl] = NumUniqueOrb;
///increment the number of unique orbitals
NumUniqueOrb++;
///now add the radial grid orbital
psi.push_back(RadialOrbital_t(m_grid));
///add the quantum numbers to the list
N.push_back(n);
L.push_back(l);
M.push_back(m);
S.push_back(s);
Occ.push_back(occ);
} else {
///if an orbital of the same restriction type has already
///been added, add the orbital such that all the
///orbitals with the same restriction type are grouped
///together
///increment the id counter
IDcount[(*it).second]++;
///locate the position in the array where the orbital
///will be added
// IDmap.resize(IDcount.size());
vector<int> IDmap(IDcount.size());
IDmap[0] = 0;
int sum = 0;
for(int i=1; i < IDmap.size(); i++){
sum += IDcount[i-1];
IDmap[i] = sum;
}
ID.insert(ID.begin()+IDmap[(*it).second],(*it).second);
psi.insert(psi.begin()+IDmap[(*it).second],RadialOrbital_t(m_grid));
N.insert(N.begin()+IDmap[(*it).second],n);
L.insert(L.begin()+IDmap[(*it).second],l);
M.insert(M.begin()+IDmap[(*it).second],m);
S.insert(S.begin()+IDmap[(*it).second],s);
Occ.insert(Occ.begin()+IDmap[(*it).second],occ);
IDmap.clear();
}
}
if(Restriction == "spin") {
NLMIndex nlm(n,l,m);
NLM_Map_t::iterator it = NLM.find(nlm);
if(it == NLM.end()) {
ID.push_back(NumUniqueOrb);
IDcount.push_back(1);
NLM[nlm] = NumUniqueOrb;
NumUniqueOrb++;
psi.push_back(RadialOrbital_t(m_grid));
N.push_back(n);
L.push_back(l);
M.push_back(m);
S.push_back(s);
Occ.push_back(occ);
} else {
IDcount[(*it).second]++;
vector<int> IDmap(IDcount.size());
// IDmap.resize(IDcount.size());
IDmap[0] = 0;
int sum = 0;
for(int i=1; i < IDmap.size(); i++){
sum += IDcount[i-1];
IDmap[i] = sum;
}
ID.insert(ID.begin()+IDmap[(*it).second],(*it).second);
psi.insert(psi.begin()+IDmap[(*it).second],RadialOrbital_t(m_grid));
N.insert(N.begin()+IDmap[(*it).second],n);
L.insert(L.begin()+IDmap[(*it).second],l);
M.insert(M.begin()+IDmap[(*it).second],m);
S.insert(S.begin()+IDmap[(*it).second],s);
Occ.insert(Occ.begin()+IDmap[(*it).second],occ);
IDmap.clear();
}
}
if(Restriction == "none") {
///add the orbital at the end of the list
ID.push_back(NumUniqueOrb);
IDcount.push_back(1);
NumUniqueOrb++;
psi.push_back(RadialOrbital_t(m_grid));
N.push_back(n);
L.push_back(l);
M.push_back(m);
S.push_back(s);
Occ.push_back(occ);
}
return true;
}
template<class GT>
void YlmRnlSet<GT>::applyRestriction(int norb){
static vector<value_type> sum;
if(sum.empty()){
sum.resize(m_grid->size());
for(int ig=0; ig < m_grid->size(); ig++)
sum[ig] = 0.0;
}
int o_start = 0;
int o_end = 0;
int orb = 0;
while (orb < norb) {
for(int uorb=0; uorb < NumUniqueOrb; uorb++){
for(int i=0; i < IDcount[uorb]; i++){
for(int ig=0; ig < m_grid->size(); ig++){
sum[ig] += psi[orb](ig);
}
orb++;
}
int o_end = o_start+IDcount[uorb];
for(int o = o_start; o < o_end; o++){
for(int ig=0; ig < m_grid->size(); ig++){
psi[o](ig) = sum[ig]/IDcount[uorb];
}
}
o_start = o_end;
for(int ig=0; ig < m_grid->size(); ig++) sum[ig] = 0.0;
}
}
}
#endif

215
src/AtomicHF/YlmRnlSet.h Normal file
View File

@ -0,0 +1,215 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim and Jordan Vincent
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
/*@author Jeongnim Kim and Jordan Vincent
*/
#ifndef OHMMS_YLMRNLSET_ONGRID_H
#define OHMMS_YLMRNLSET_ONGRID_H
#include <map>
#include <set>
#include <vector>
#include <stdlib.h>
#include "OhmmsData/OhmmsElementBase.h"
#include "Numerics/OneDimGridFunctor.h"
#include "Numerics/OneDimCubicSpline.h"
#include "Numerics/OneDimIntegration.h"
#include "OhmmsPETE/TinyVector.h"
struct ltnlm {
bool operator()(const TinyVector<int,3>& a,
const TinyVector<int,3>& b) const {
if(a[0] > b[0])
return false;
else if(a[0] == b[0]){
// return a[1] < b[1];
if (a[1] < b[1]) return true;
else if(a[1] == b[1])
return a[2] < b[2];
else return true;
}
else {
return true;
}
}
};
struct ltnl {
bool operator()(const TinyVector<int,2>& a,
const TinyVector<int,2>& b) const {
if(a[0] > b[0])
return false;
else if(a[0] == b[0]){
return a[1] < b[1];
}
else {
return true;
}
}
};
template<unsigned D>
struct equal_nlms {
bool operator()(const TinyVector<int,D>& a,
const TinyVector<int,D>& b) const {
int i=0;
while(i<D) {
if(a[i]!= b[i]) return true;
i++;}
return false;
}
};
template<class T>
struct YlmRnlSet {
typedef T value_type;
typedef OneDimGridBase<value_type> RadialGrid_t;
typedef OneDimCubicSpline<value_type,value_type> RadialOrbital_t;
typedef vector<RadialOrbital_t> RadialOrbitalSet_t;
typedef TinyVector<int,2> NLIndex;
typedef TinyVector<int,3> NLMIndex;
typedef TinyVector<int,4> NLMSIndex;
typedef std::map<NLIndex,int,ltnl > NL_Map_t;
typedef std::map<NLMIndex,int,ltnlm > NLM_Map_t;
typedef std::map<NLMSIndex,int,equal_nlms<4> > NLMS_Map_t;
///constructor
YlmRnlSet(): m_grid(NULL), NumOrb(0),
NumUniqueOrb(0), Restriction("none"), CuspParam(0.0),
EigenBoundParam(0.0) { }
bool add(int n, int l, int m, int s, value_type occ);
void applyRestriction(int norb);
///normailize all the orbitals
void normalize(int norb){
for(int i=0; i < norb; i++) normalize_RK2(psi[i]);
}
///assigns orbital \f$ \psi_{iorb}(r) \f$
inline RadialOrbital_t& operator()(int iorb) {
return psi[iorb];
}
///returns a reference to orbital \f$ \psi_{iorb}(r) \f$
inline const RadialOrbital_t& operator()(int iorb) const {
return psi[iorb];
}
///return the number of orbitals
inline int size() const { return psi.size(); }
///return \f$ \psi_{iorb}(r_j) \f$
inline value_type operator()(int iorb, int j) const{
return psi[iorb](j);
}
///assigns orbital \f$ \psi_{iorb}(r_j) \f$
inline value_type& operator()(int iorb, int j){
return psi[iorb](j);
}
inline const value_type dR0(int iorb){
return psi[iorb].yprime0;
}
inline const value_type dRN(int iorb){
return psi[iorb].yprimeN;
}
///reset the values of orbitals
void reset() {
for(int i=0; i < psi.size(); i++) psi[i].m_Y = 0.0;
}
///restriction type;
string Restriction;
///number of orbitals
int NumOrb;
///number of unique orbitals
int NumUniqueOrb;
///a common grid
RadialGrid_t* m_grid;
/**@defgroup QuantumNumber
* Quantum numbers of an orbital.
* The i-th orbital is represented by (N[i],L[i],M[i],S[i])
*@{n = Principal quantum number
*/
vector<int> N;
/*@ l = angular momentum */
vector<int> L;
/*@ M = z-angular momentum */
vector<int> M;
/*@ S = spin in unit of 1/2 */
vector<int> S;
/**@}*///end of group QuantumNumber
///coefficient for each orbtial (1 if occupied, 0 if not)
vector<value_type> Occ;
///parameter for calculating orbital cusp conditions
value_type CuspParam;
///parameter for calculating orbital cusp conditions
value_type EigenBoundParam;
///map for nl quantum numbers
NL_Map_t NL;
///map for nlm quantum numbers
NLM_Map_t NLM;
///map for occupation number
NLMS_Map_t OccNo;
///assign an id for each orbital
vector<int> ID;
///keeps track of the number of orbitals with the same id
vector<int> IDcount;
// vector<int> IDmap;
///the radial grid orbitals
vector<RadialOrbital_t> psi;
bool put(xmlNodePtr cur);
bool get(std::ostream& os);
// bool getqmc(std::ostream& os);
// bool getsiesta(std::ostream& os, int orb);
bool print(const std::string&);
};
#include "AtomicHF/YlmRnlSet.cpp"
#include "AtomicHF/YlmRnlSet.IO.h"
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

657
src/AtomicHF/fillshells.h Normal file
View File

@ -0,0 +1,657 @@
#ifndef ATOMICHF_FILLSHELLS_H
#define ATOMICHF_FILLSHELLS_H
#include "AtomicHF/HFAtomicOrbitals.h"
using namespace ohmmshf;
inline void FillShellsNucPot(HFAtomicOrbitals& mo,
int nmax) {
// vector<int>& cs,
// vector<double>& cratio){
int up=1;
int dn=-1;
switch(nmax) {
case(1):
mo.add(1,0,0,up,1.0);
mo.add(1,0,0,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
break;
case(2):
mo.add(1,0, 0,up,1.0);
mo.add(1,0, 0,dn,1.0);
mo.add(2,0, 0,up,1.0);
mo.add(2,0, 0,dn,1.0);
mo.add(2,1,-1,up,1.0);
mo.add(2,1,-1,dn,1.0);
mo.add(2,1, 0,up,1.0);
mo.add(2,1, 0,dn,1.0);
mo.add(2,1, 1,up,1.0);
mo.add(2,1, 1,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
// cs[2] = 10;
// cratio[2] = 0.35;
break;
case(3):
mo.add(1,0, 0,up,1.0);
mo.add(1,0, 0,dn,1.0);
mo.add(2,0, 0,up,1.0);
mo.add(2,0, 0,dn,1.0);
mo.add(2,1,-1,up,1.0);
mo.add(2,1,-1,dn,1.0);
mo.add(2,1, 0,up,1.0);
mo.add(2,1, 0,dn,1.0);
mo.add(2,1, 1,up,1.0);
mo.add(2,1, 1,dn,1.0);
mo.add(3,0, 0,up,1.0);
mo.add(3,0, 0,dn,1.0);
mo.add(3,1,-1,up,1.0);
mo.add(3,1,-1,dn,1.0);
mo.add(3,1, 0,up,1.0);
mo.add(3,1, 0,dn,1.0);
mo.add(3,1, 1,up,1.0);
mo.add(3,1, 1,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
// cs[2] = 10;
// cratio[2] = 0.35;
// cs[3]=18;
// cratio[2] = 0.4;
break;
case(4):
mo.add(1,0, 0,up,1.0);
mo.add(1,0, 0,dn,1.0);
mo.add(2,0, 0,up,1.0);
mo.add(2,0, 0,dn,1.0);
mo.add(2,1,-1,up,1.0);
mo.add(2,1,-1,dn,1.0);
mo.add(2,1, 0,up,1.0);
mo.add(2,1, 0,dn,1.0);
mo.add(2,1, 1,up,1.0);
mo.add(2,1, 1,dn,1.0);
mo.add(3,0, 0,up,1.0);
mo.add(3,0, 0,dn,1.0);
mo.add(3,1,-1,up,1.0);
mo.add(3,1,-1,dn,1.0);
mo.add(3,1, 0,up,1.0);
mo.add(3,1, 0,dn,1.0);
mo.add(3,1, 1,up,1.0);
mo.add(3,1, 1,dn,1.0);
mo.add(3,2,-2,up,1.0);
mo.add(3,2,-2,dn,1.0);
mo.add(3,2,-1,up,1.0);
mo.add(3,2,-1,dn,1.0);
mo.add(3,2, 0,up,1.0);
mo.add(3,2, 0,dn,1.0);
mo.add(3,2, 1,up,1.0);
mo.add(3,2, 1,dn,1.0);
mo.add(3,2, 2,up,1.0);
mo.add(3,2, 2,dn,1.0);
mo.add(4,0, 0,up,1.0);
mo.add(4,0, 0,dn,1.0);
mo.add(4,1,-1,up,1.0);
mo.add(4,1,-1,dn,1.0);
mo.add(4,1, 0,up,1.0);
mo.add(4,1, 0,dn,1.0);
mo.add(4,1, 1,up,1.0);
mo.add(4,1, 1,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
// cs[2] = 10;
// cratio[2] = 0.35;
// cs[3]=18;
// cratio[2] = 0.4;
// cs[4] = 36;
// cratio[4] = 0.45;
break;
case(5):
mo.add(1,0, 0,up,1.0);
mo.add(1,0, 0,dn,1.0);
mo.add(2,0, 0,up,1.0);
mo.add(2,0, 0,dn,1.0);
mo.add(2,1,-1,up,1.0);
mo.add(2,1,-1,dn,1.0);
mo.add(2,1, 0,up,1.0);
mo.add(2,1, 0,dn,1.0);
mo.add(2,1, 1,up,1.0);
mo.add(2,1, 1,dn,1.0);
mo.add(3,0, 0,up,1.0);
mo.add(3,0, 0,dn,1.0);
mo.add(3,1,-1,up,1.0);
mo.add(3,1,-1,dn,1.0);
mo.add(3,1, 0,up,1.0);
mo.add(3,1, 0,dn,1.0);
mo.add(3,1, 1,up,1.0);
mo.add(3,1, 1,dn,1.0);
mo.add(3,2,-2,up,1.0);
mo.add(3,2,-2,dn,1.0);
mo.add(3,2,-1,up,1.0);
mo.add(3,2,-1,dn,1.0);
mo.add(3,2, 0,up,1.0);
mo.add(3,2, 0,dn,1.0);
mo.add(3,2, 1,up,1.0);
mo.add(3,2, 1,dn,1.0);
mo.add(3,2, 2,up,1.0);
mo.add(3,2, 2,dn,1.0);
mo.add(4,0, 0,up,1.0);
mo.add(4,0, 0,dn,1.0);
mo.add(4,1,-1,up,1.0);
mo.add(4,1,-1,dn,1.0);
mo.add(4,1, 0,up,1.0);
mo.add(4,1, 0,dn,1.0);
mo.add(4,1, 1,up,1.0);
mo.add(4,1, 1,dn,1.0);
mo.add(4,2,-2,up,1.0);
mo.add(4,2,-2,dn,1.0);
mo.add(4,2,-1,up,1.0);
mo.add(4,2,-1,dn,1.0);
mo.add(4,2, 0,up,1.0);
mo.add(4,2, 0,dn,1.0);
mo.add(4,2, 1,up,1.0);
mo.add(4,2, 1,dn,1.0);
mo.add(4,2, 2,up,1.0);
mo.add(4,2, 2,dn,1.0);
mo.add(5,0, 0,up,1.0);
mo.add(5,0, 0,dn,1.0);
mo.add(5,1,-1,up,1.0);
mo.add(5,1,-1,dn,1.0);
mo.add(5,1, 0,up,1.0);
mo.add(5,1, 0,dn,1.0);
mo.add(5,1, 1,up,1.0);
mo.add(5,1, 1,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
// cs[2] = 10;
// cratio[2] = 0.35;
// cs[3]=18;
// cratio[2] = 0.4;
// cs[4] = 36;
// cratio[4] = 0.45;
// cs[5] = 54;
// cratio[5] = 0.5;
break;
case(6):
mo.add(1,0, 0,up,1.0);
mo.add(1,0, 0,dn,1.0);
mo.add(2,0, 0,up,1.0);
mo.add(2,0, 0,dn,1.0);
mo.add(2,1,-1,up,1.0);
mo.add(2,1,-1,dn,1.0);
mo.add(2,1, 0,up,1.0);
mo.add(2,1, 0,dn,1.0);
mo.add(2,1, 1,up,1.0);
mo.add(2,1, 1,dn,1.0);
mo.add(3,0, 0,up,1.0);
mo.add(3,0, 0,dn,1.0);
mo.add(3,1,-1,up,1.0);
mo.add(3,1,-1,dn,1.0);
mo.add(3,1, 0,up,1.0);
mo.add(3,1, 0,dn,1.0);
mo.add(3,1, 1,up,1.0);
mo.add(3,1, 1,dn,1.0);
mo.add(3,2,-2,up,1.0);
mo.add(3,2,-2,dn,1.0);
mo.add(3,2,-1,up,1.0);
mo.add(3,2,-1,dn,1.0);
mo.add(3,2, 0,up,1.0);
mo.add(3,2, 0,dn,1.0);
mo.add(3,2, 1,up,1.0);
mo.add(3,2, 1,dn,1.0);
mo.add(3,2, 2,up,1.0);
mo.add(3,2, 2,dn,1.0);
mo.add(4,0, 0,up,1.0);
mo.add(4,0, 0,dn,1.0);
mo.add(4,1,-1,up,1.0);
mo.add(4,1,-1,dn,1.0);
mo.add(4,1, 0,up,1.0);
mo.add(4,1, 0,dn,1.0);
mo.add(4,1, 1,up,1.0);
mo.add(4,1, 1,dn,1.0);
mo.add(4,2,-2,up,1.0);
mo.add(4,2,-2,dn,1.0);
mo.add(4,2,-1,up,1.0);
mo.add(4,2,-1,dn,1.0);
mo.add(4,2, 0,up,1.0);
mo.add(4,2, 0,dn,1.0);
mo.add(4,2, 1,up,1.0);
mo.add(4,2, 1,dn,1.0);
mo.add(4,2, 2,up,1.0);
mo.add(4,2, 2,dn,1.0);
mo.add(5,0, 0,up,1.0);
mo.add(5,0, 0,dn,1.0);
mo.add(5,1,-1,up,1.0);
mo.add(5,1,-1,dn,1.0);
mo.add(5,1, 0,up,1.0);
mo.add(5,1, 0,dn,1.0);
mo.add(5,1, 1,up,1.0);
mo.add(5,1, 1,dn,1.0);
mo.add(4,3,-3,up,1.0);
mo.add(4,3,-3,dn,1.0);
mo.add(4,3,-2,up,1.0);
mo.add(4,3,-2,dn,1.0);
mo.add(4,3,-1,up,1.0);
mo.add(4,3,-1,dn,1.0);
mo.add(4,3, 0,up,1.0);
mo.add(4,3, 0,dn,1.0);
mo.add(4,3, 1,up,1.0);
mo.add(4,3, 1,dn,1.0);
mo.add(4,3, 2,up,1.0);
mo.add(4,3, 2,dn,1.0);
mo.add(4,3, 3,up,1.0);
mo.add(4,3, 3,dn,1.0);
mo.add(5,2,-2,up,1.0);
mo.add(5,2,-2,dn,1.0);
mo.add(5,2,-1,up,1.0);
mo.add(5,2,-1,dn,1.0);
mo.add(5,2, 0,up,1.0);
mo.add(5,2, 0,dn,1.0);
mo.add(5,2, 1,up,1.0);
mo.add(5,2, 1,dn,1.0);
mo.add(5,2, 2,up,1.0);
mo.add(5,2, 2,dn,1.0);
mo.add(6,0, 0,up,1.0);
mo.add(6,0, 0,dn,1.0);
mo.add(6,1,-1,up,1.0);
mo.add(6,1,-1,dn,1.0);
mo.add(6,1, 0,up,1.0);
mo.add(6,1, 0,dn,1.0);
mo.add(6,1, 1,up,1.0);
mo.add(6,1, 1,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
// cs[2] = 10;
// cratio[2] = 0.35;
// cs[3]=18;
// cratio[2] = 0.4;
// cs[4] = 36;
// cratio[4] = 0.45;
// cs[5] = 54;
// cratio[5] = 0.5;
// cs[6] = 86;
// cratio[6] = 0.55;
break;
}
}
inline void FillShellsHarmPot(HFAtomicOrbitals& mo,
int nmax) {
// vector<int>& cs,
// vector<double>& cratio){
int up=1;
int dn=-1;
switch(nmax) {
case(1):
mo.add(0,0,0,up,1.0);
mo.add(0,0,0,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
break;
case(2):
mo.add(0,0,0,up,1.0);
mo.add(0,0,0,dn,1.0);
mo.add(0,1,-1,up,1.0);
mo.add(0,1,-1,dn,1.0);
mo.add(0,1, 0,up,1.0);
mo.add(0,1, 0,dn,1.0);
mo.add(0,1, 1,up,1.0);
mo.add(0,1, 1,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
// cs[2] = 10;
// cratio[2] = 0.35;
break;
case(3):
mo.add(0,0,0,up,1.0);
mo.add(0,0,0,dn,1.0);
mo.add(0,1,-1,up,1.0);
mo.add(0,1,-1,dn,1.0);
mo.add(0,1, 0,up,1.0);
mo.add(0,1, 0,dn,1.0);
mo.add(0,1, 1,up,1.0);
mo.add(0,1, 1,dn,1.0);
mo.add(0,2,-2,up,1.0);
mo.add(0,2,-2,dn,1.0);
mo.add(0,2,-1,up,1.0);
mo.add(0,2,-1,dn,1.0);
mo.add(0,2, 0,up,1.0);
mo.add(0,2, 0,dn,1.0);
mo.add(0,2, 1,up,1.0);
mo.add(0,2, 1,dn,1.0);
mo.add(0,2, 2,up,1.0);
mo.add(0,2, 2,dn,1.0);
mo.add(1,0, 0,up,1.0);
mo.add(1,0, 0,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
// cs[2] = 10;
// cratio[2] = 0.35;
// cs[3]=18;
// cratio[2] = 0.4;
break;
case(4):
mo.add(0,0,0,up,1.0);
mo.add(0,0,0,dn,1.0);
mo.add(0,1,-1,up,1.0);
mo.add(0,1,-1,dn,1.0);
mo.add(0,1, 0,up,1.0);
mo.add(0,1, 0,dn,1.0);
mo.add(0,1, 1,up,1.0);
mo.add(0,1, 1,dn,1.0);
mo.add(0,2,-2,up,1.0);
mo.add(0,2,-2,dn,1.0);
mo.add(0,2,-1,up,1.0);
mo.add(0,2,-1,dn,1.0);
mo.add(0,2, 0,up,1.0);
mo.add(0,2, 0,dn,1.0);
mo.add(0,2, 1,up,1.0);
mo.add(0,2, 1,dn,1.0);
mo.add(0,2, 2,up,1.0);
mo.add(0,2, 2,dn,1.0);
mo.add(1,0, 0,up,1.0);
mo.add(1,0, 0,dn,1.0);
mo.add(0,3,-3,up,1.0);
mo.add(0,3,-3,dn,1.0);
mo.add(0,3,-2,up,1.0);
mo.add(0,3,-2,dn,1.0);
mo.add(0,3,-1,up,1.0);
mo.add(0,3,-1,dn,1.0);
mo.add(0,3, 0,up,1.0);
mo.add(0,3, 0,dn,1.0);
mo.add(0,3, 1,up,1.0);
mo.add(0,3, 1,dn,1.0);
mo.add(0,3, 2,up,1.0);
mo.add(0,3, 2,dn,1.0);
mo.add(0,3, 3,up,1.0);
mo.add(0,3, 3,dn,1.0);
mo.add(1,1,-1,up,1.0);
mo.add(1,1,-1,dn,1.0);
mo.add(1,1, 0,up,1.0);
mo.add(1,1, 0,dn,1.0);
mo.add(1,1, 1,up,1.0);
mo.add(1,1, 1,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
// cs[2] = 10;
// cratio[2] = 0.35;
// cs[3]=18;
// cratio[2] = 0.4;
// cs[4] = 36;
// cratio[4] = 0.45;
break;
case(5):
mo.add(0,0,0,up,1.0);
mo.add(0,0,0,dn,1.0);
mo.add(0,1,-1,up,1.0);
mo.add(0,1,-1,dn,1.0);
mo.add(0,1, 0,up,1.0);
mo.add(0,1, 0,dn,1.0);
mo.add(0,1, 1,up,1.0);
mo.add(0,1, 1,dn,1.0);
mo.add(0,2,-2,up,1.0);
mo.add(0,2,-2,dn,1.0);
mo.add(0,2,-1,up,1.0);
mo.add(0,2,-1,dn,1.0);
mo.add(0,2, 0,up,1.0);
mo.add(0,2, 0,dn,1.0);
mo.add(0,2, 1,up,1.0);
mo.add(0,2, 1,dn,1.0);
mo.add(0,2, 2,up,1.0);
mo.add(0,2, 2,dn,1.0);
mo.add(1,0, 0,up,1.0);
mo.add(1,0, 0,dn,1.0);
mo.add(0,3,-3,up,1.0);
mo.add(0,3,-3,dn,1.0);
mo.add(0,3,-2,up,1.0);
mo.add(0,3,-2,dn,1.0);
mo.add(0,3,-1,up,1.0);
mo.add(0,3,-1,dn,1.0);
mo.add(0,3, 0,up,1.0);
mo.add(0,3, 0,dn,1.0);
mo.add(0,3, 1,up,1.0);
mo.add(0,3, 1,dn,1.0);
mo.add(0,3, 2,up,1.0);
mo.add(0,3, 2,dn,1.0);
mo.add(0,3, 3,up,1.0);
mo.add(0,3, 3,dn,1.0);
mo.add(1,1,-1,up,1.0);
mo.add(1,1,-1,dn,1.0);
mo.add(1,1, 0,up,1.0);
mo.add(1,1, 0,dn,1.0);
mo.add(1,1, 1,up,1.0);
mo.add(1,1, 1,dn,1.0);
mo.add(0,4,-4,up,1.0);
mo.add(0,4,-4,dn,1.0);
mo.add(0,4,-3,up,1.0);
mo.add(0,4,-3,dn,1.0);
mo.add(0,4,-2,up,1.0);
mo.add(0,4,-2,dn,1.0);
mo.add(0,4,-1,up,1.0);
mo.add(0,4,-1,dn,1.0);
mo.add(0,4, 0,up,1.0);
mo.add(0,4, 0,dn,1.0);
mo.add(0,4, 1,up,1.0);
mo.add(0,4, 1,dn,1.0);
mo.add(0,4, 2,up,1.0);
mo.add(0,4, 2,dn,1.0);
mo.add(0,4, 3,up,1.0);
mo.add(0,4, 3,dn,1.0);
mo.add(0,4, 4,up,1.0);
mo.add(0,4, 4,dn,1.0);
mo.add(2,0, 0,up,1.0);
mo.add(2,0, 0,dn,1.0);
mo.add(1,2,-2,up,1.0);
mo.add(1,2,-2,dn,1.0);
mo.add(1,2,-1,up,1.0);
mo.add(1,2,-1,dn,1.0);
mo.add(1,2, 0,up,1.0);
mo.add(1,2, 0,dn,1.0);
mo.add(1,2, 1,up,1.0);
mo.add(1,2, 1,dn,1.0);
mo.add(1,2, 2,up,1.0);
mo.add(1,2, 2,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
// cs[2] = 10;
// cratio[2] = 0.35;
// cs[3]=18;
// cratio[2] = 0.4;
// cs[4] = 36;
// cratio[4] = 0.45;
// cs[5] = 54;
// cratio[5] = 0.5;
break;
case(6):
mo.add(0,0,0,up,1.0);
mo.add(0,0,0,dn,1.0);
mo.add(0,1,-1,up,1.0);
mo.add(0,1,-1,dn,1.0);
mo.add(0,1, 0,up,1.0);
mo.add(0,1, 0,dn,1.0);
mo.add(0,1, 1,up,1.0);
mo.add(0,1, 1,dn,1.0);
mo.add(0,2,-2,up,1.0);
mo.add(0,2,-2,dn,1.0);
mo.add(0,2,-1,up,1.0);
mo.add(0,2,-1,dn,1.0);
mo.add(0,2, 0,up,1.0);
mo.add(0,2, 0,dn,1.0);
mo.add(0,2, 1,up,1.0);
mo.add(0,2, 1,dn,1.0);
mo.add(0,2, 2,up,1.0);
mo.add(0,2, 2,dn,1.0);
mo.add(1,0, 0,up,1.0);
mo.add(1,0, 0,dn,1.0);
mo.add(0,3,-3,up,1.0);
mo.add(0,3,-3,dn,1.0);
mo.add(0,3,-2,up,1.0);
mo.add(0,3,-2,dn,1.0);
mo.add(0,3,-1,up,1.0);
mo.add(0,3,-1,dn,1.0);
mo.add(0,3, 0,up,1.0);
mo.add(0,3, 0,dn,1.0);
mo.add(0,3, 1,up,1.0);
mo.add(0,3, 1,dn,1.0);
mo.add(0,3, 2,up,1.0);
mo.add(0,3, 2,dn,1.0);
mo.add(0,3, 3,up,1.0);
mo.add(0,3, 3,dn,1.0);
mo.add(1,1,-1,up,1.0);
mo.add(1,1,-1,dn,1.0);
mo.add(1,1, 0,up,1.0);
mo.add(1,1, 0,dn,1.0);
mo.add(1,1, 1,up,1.0);
mo.add(1,1, 1,dn,1.0);
mo.add(0,4,-4,up,1.0);
mo.add(0,4,-4,dn,1.0);
mo.add(0,4,-3,up,1.0);
mo.add(0,4,-3,dn,1.0);
mo.add(0,4,-2,up,1.0);
mo.add(0,4,-2,dn,1.0);
mo.add(0,4,-1,up,1.0);
mo.add(0,4,-1,dn,1.0);
mo.add(0,4, 0,up,1.0);
mo.add(0,4, 0,dn,1.0);
mo.add(0,4, 1,up,1.0);
mo.add(0,4, 1,dn,1.0);
mo.add(0,4, 2,up,1.0);
mo.add(0,4, 2,dn,1.0);
mo.add(0,4, 3,up,1.0);
mo.add(0,4, 3,dn,1.0);
mo.add(0,4, 4,up,1.0);
mo.add(0,4, 4,dn,1.0);
mo.add(2,0, 0,up,1.0);
mo.add(2,0, 0,dn,1.0);
mo.add(1,2,-2,up,1.0);
mo.add(1,2,-2,dn,1.0);
mo.add(1,2,-1,up,1.0);
mo.add(1,2,-1,dn,1.0);
mo.add(1,2, 0,up,1.0);
mo.add(1,2, 0,dn,1.0);
mo.add(1,2, 1,up,1.0);
mo.add(1,2, 1,dn,1.0);
mo.add(1,2, 2,up,1.0);
mo.add(1,2, 2,dn,1.0);
mo.add(0,5,-5,up,1.0);
mo.add(0,5,-5,dn,1.0);
mo.add(0,5,-4,up,1.0);
mo.add(0,5,-4,dn,1.0);
mo.add(0,5,-3,up,1.0);
mo.add(0,5,-3,dn,1.0);
mo.add(0,5,-2,up,1.0);
mo.add(0,5,-2,dn,1.0);
mo.add(0,5,-1,up,1.0);
mo.add(0,5,-1,dn,1.0);
mo.add(0,5, 0,up,1.0);
mo.add(0,5, 0,dn,1.0);
mo.add(0,5, 1,up,1.0);
mo.add(0,5, 1,dn,1.0);
mo.add(0,5, 2,up,1.0);
mo.add(0,5, 2,dn,1.0);
mo.add(0,5, 3,up,1.0);
mo.add(0,5, 3,dn,1.0);
mo.add(0,5, 4,up,1.0);
mo.add(0,5, 4,dn,1.0);
mo.add(0,5, 5,up,1.0);
mo.add(0,5, 5,dn,1.0);
mo.add(1,3,-3,up,1.0);
mo.add(1,3,-3,dn,1.0);
mo.add(1,3,-2,up,1.0);
mo.add(1,3,-2,dn,1.0);
mo.add(1,3,-1,up,1.0);
mo.add(1,3,-1,dn,1.0);
mo.add(1,3, 0,up,1.0);
mo.add(1,3, 0,dn,1.0);
mo.add(1,3, 1,up,1.0);
mo.add(1,3, 1,dn,1.0);
mo.add(1,3, 2,up,1.0);
mo.add(1,3, 2,dn,1.0);
mo.add(1,3, 3,up,1.0);
mo.add(1,3, 3,dn,1.0);
mo.add(2,1,-1,up,1.0);
mo.add(2,1,-1,dn,1.0);
mo.add(2,1, 0,up,1.0);
mo.add(2,1, 0,dn,1.0);
mo.add(2,1, 1,up,1.0);
mo.add(2,1, 1,dn,1.0);
// cs[1] = 2;
// cratio[1] = 0.3;
// cs[2] = 10;
// cratio[2] = 0.35;
// cs[3]=18;
// cratio[2] = 0.4;
// cs[4] = 36;
// cratio[4] = 0.45;
// cs[5] = 54;
// cratio[5] = 0.5;
// cs[6] = 86;
// cratio[6] = 0.55;
break;
}
}
#endif

View File

@ -0,0 +1,56 @@
##########################################################
# OHMMS application makefile stub for suite: linuxicc
# Created Sat Mar 29 15:39:36 CST 2003 by jnkim on bach
# Generated by configure --arch linuxicc --tb
##########################################################
#include /home/common/Codes/Make.include
OHMMSDIR = $(HOME)/Projects/qmcPlusPlus
HFDIR = $(HOME)/Projects/qmcPlusPlus
ODIR = icc
OHMMSARCH = ia32
OHMMS_SRCDIR = $(OHMMSDIR)/src
OHMMS_BINDIR = $(OHMMSDIR)/bin
OHMMS_LIBDIR = $(OHMMSDIR)/lib
OHMMS_LIBNAME = Ohmms-icc
OHMMS_LIBEXT =
OHMMS_LIBRARY = lib$(OHMMS_LIBNAME).$(OHMMS_LIBEXT)
BLITZINC = -I/usr/apps/tools/blitz
HDF5INC = -I/usr/local/include
HDF5LIB = -lhdf5
### names of applications
CXX = icc
CC = icc
F77 = ifc
LD = icc
LD_PARALLEL = 1
### flags for applications
CXXOPTFLAGS = -DADD_ -O3 -restrict -unroll
CXXDEBUGFLAGS = -DADD_ -g -restrict
CCOPTFLAGS = -DADD_ -O3 -restrict -unroll
CCDEBUGFLAGS = -DADD_ -g -restrict
F77OPTFLAGS = -fpp2 -O3
F77DEBUGFLAGS = -fpp2 -g
OHMMSINC = -I$(HFDIR)/src -I/usr/include/libxml2 -I/usr/local/include $(BLITZINC) $(HDF5INC)
#OHMMSDEF = -DOHMMS_DIM=3 -DENABLE_TB -DENABLE_LIBXML2 -DUSE_BLITZ
OHMMSDEF = -DOHMMS_DIM=3 -DENABLE_TB -DENABLE_LIBXML2 -MMD -DPRINT_DEBUG -DUSE_HDF5
OHMMSLIBS = -lxml2 $(BLITZLIB) $(HDF5LIB)
#CXXFLAGSAPP = $(OHMMSDEF) $(CXXOPTFLAGS)
#CXXLDFLAGS = $(OHMMSDEF) $(CXXOPTFLAGS)
CXXFLAGSAPP = $(OHMMSDEF) $(CXXDEBUGFLAGS)
CXXLDFLAGS = $(OHMMSDEF) $(CXXDEBUGFLAGS)
F77FLAGS = $(F77OPTFLAGS)
AR = icc cr
F77AR = ar cr
RANLIB = ranlib
##########################################################
# End of user makefile stub file lib/makefile.linuxicc
##########################################################

71
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,71 @@
#CONFIGURE_FILE(${qmcPlusPlus_SOURCE_DIR}/src/Configuration.h.in
# ${qmcPlusPlus_BINARY_DIR}/src/Configuration.h)
CONFIGURE_FILE(${qmcPlusPlus_SOURCE_DIR}/src/ohmms-config.h.cmake.in
${qmcPlusPlus_BINARY_DIR}/src/ohmms-config.h)
SET(UTILITIES
Utilities/RandRandom.cpp
Utilities/RandomGenerator.cpp
Utilities/OhmmsObject.cpp
Utilities/SpeciesSet.cpp
Utilities/SimpleParser.cpp
Utilities/OhmmsInform.cpp
Utilities/OhmmsInfo.cpp
OhmmsApp/ProjectData.cpp
OhmmsApp/RandomNumberControl.cpp
Platforms/sysutil.cpp
)
SET(PARTICLE
Particle/ParticleSet.cpp
Particle/MCWalkerConfiguration.cpp
Particle/DistanceTable.cpp
Particle/HDFWalkerIO.cpp
)
SET(PARTICLEIO
ParticleTags.cpp
ParticleIO/ParticleLayoutIO.cpp
ParticleIO/XMLParticleIO.cpp
ParticleIO/HDFParticleIO.cpp
)
SET(MESSAGE
Message/Communicate.cpp
)
SET(OPTIMIZE
Optimize/Minimize.cpp
)
SET(HAMILTONIAN
QMCHamiltonians/QMCHamiltonianBase.cpp
QMCHamiltonians/LocalPPotential.cpp
)
SET(WFSBASE
QMCWaveFunctions/JastrowBuilder.cpp
QMCWaveFunctions/TrialWaveFunction.cpp
)
#Only basic packages common for both AtomicHF and QMC
SET(BASEDIR
${UTILITIES}
${MESSAGE}
)
ADD_LIBRARY(qmcbase ${BASEDIR})
#QMC-related package, build qmc
SET(QMCBASEDIR
${PARTICLE}
${PARTICLEIO}
${OPTIMIZE}
${HAMILTONIAN}
${WFSBASE}
)
#SUBDIRS(SQD)
ADD_LIBRARY(qmc ${QMCBASEDIR})
SUBDIRS(QMC)

85
src/Configuration.h Normal file
View File

@ -0,0 +1,85 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_QMC_TRAITS_H
#define OHMMS_QMC_TRAITS_H
#include "ohmms-config.h"
#include <string>
#include <vector>
#include <map>
#include "OhmmsPETE/TinyVector.h"
#include "OhmmsPETE/Tensor.h"
#include "OhmmsData/OhmmsElementBase.h"
#include "Lattice/UniformGridLayout.h"
#include "ParticleBase/ParticleAttrib.h"
#include "ParticleBase/ParticleBase.h"
namespace ohmmsqmc {
/** traits for the common particle attributes
*
*This is an alternative to the global typedefs.
*/
struct PtclAttribTraits {
typedef int Index_t;
typedef ParticleAttrib<Index_t> ParticleIndex_t;
typedef ParticleAttrib<OHMMS_PRECISION> ParticleScalar_t;
typedef ParticleAttrib<TinyVector<OHMMS_PRECISION, OHMMS_DIM> > ParticlePos_t;
typedef ParticleAttrib<Tensor<OHMMS_PRECISION, OHMMS_DIM> > ParticleTensor_t;
};
/** traits for QMC variables
*
*typedefs for the QMC data types
*/
struct QMCTraits {
enum {DIM = OHMMS_DIM};
typedef OHMMS_INDEXTYPE IndexType;
typedef OHMMS_PRECISION RealType;
typedef OHMMS_PRECISION ValueType;
typedef TinyVector<RealType,DIM> PosType;
typedef TinyVector<ValueType,DIM> GradType;
};
/** Particle traits to use UniformGridLayout for the ParticleLayout.
*/
struct PtclOnLatticeTraits {
typedef UniformGridLayout<OHMMS_PRECISION,OHMMS_DIM> ParticleLayout_t;
typedef int Index_t;
typedef ParticleLayout_t::Scalar_t Scalar_t;
typedef ParticleLayout_t::SingleParticleIndex_t SingleParticleIndex_t;
typedef ParticleLayout_t::SingleParticlePos_t SingleParticlePos_t;
typedef ParticleLayout_t::Tensor_t Tensor_t;
typedef ParticleAttrib<Index_t> ParticleIndex_t;
typedef ParticleAttrib<Scalar_t> ParticleScalar_t;
typedef ParticleAttrib<SingleParticlePos_t> ParticlePos_t;
typedef ParticleAttrib<Tensor_t> ParticleTensor_t;
};
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,208 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003- by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_QMC_LOCALENERGYESTIMATOR_H
#define OHMMS_QMC_LOCALENERGYESTIMATOR_H
#include <fstream>
#include "OhmmsData/libxmldefs.h"
#include "Estimators/ScalarEstimatorBase.h"
namespace ohmmsqmc {
/*** A class to evaluate the local energy
*
*The LocalEnergyEstimator evaluates
<ul>
<li> LocalEnergy
<li> Variance of the LocalEnergy
</ul>
and the values of each QHCHamiltonianBase elements added by an application.
Typical local energies are
<li> Kinetic Energy
<li> External Potential Energy
<li> Electron-Electron Energy
<li> Ion-Ion Energy (for molecules only)
<li> Conserved Quantity (VMC only)
</ul>
The method of evaluating the estimators is as follows
\f[
\langle O \rangle = \frac{\sum_{i=1}^N w_i O_i}{\sum_{i=1}^N w_i}
\f]
where the sum runs over the total number of accumulated walkers
and \f$ w_i \f$ is the weight of the \f$ ith \f$ walker.
*
*The formula for the LocalEnergy
\f[ E_L({\bf R}) = \frac{\hat{H} \Psi({\bf R})}{ \Psi({\bf R})} \f]
*/
template<class T>
class LocalEnergyEstimator: public ScalarEstimatorBase<T> {
///locator of the first data this object handles
int LocalEnergyIndex;
///local data
T energy_sum, energy_sq_sum;
///vector to contain the names of all the constituents of the local energy
std::vector<string> elocal_name;
///vector to contain all the constituents of the local energy
std::vector<T> elocal;
public:
typedef typename ScalarEstimatorBase<T>::Walker_t Walker_t;
LocalEnergyEstimator(QMCHamiltonian& h):energy_sum(0.0),
energy_sq_sum(0.0) {
int nterms=h.size();
elocal.resize(nterms);
elocal_name.resize(nterms+2);
elocal_name[0] = "LocalEnergy";
elocal_name[1] = "Variance";
int ii=2;
for(int i=0; i < nterms; i++, ii++) elocal_name[ii] = h.getName(i);
}
/**
@param record a container class for storing scalar records (name,value)
@brief add the local energy, variance and all the constituents
of the local energy to the scalar record container
*/
void add2Record(RecordNamedProperty<T>& record) {
LocalEnergyIndex = record.add(elocal_name[0].c_str());
for(int i=1; i<elocal_name.size(); i++)
record.add(elocal_name[i].c_str());
}
inline void accumulate(const Walker_t& awalker, T wgt) {
T e = awalker.Properties(LocalEnergy);
energy_sum += wgt*e; energy_sq_sum += wgt*e*e;
for(int i=0, ii=0; i<elocal.size(); i++) {
elocal[i] += wgt*(awalker.E[i]);
}
}
///reset all the cumulative sums to zero
inline void reset() {
energy_sum = T(); energy_sq_sum = T();
for(int i=0; i<elocal.size(); i++) {
elocal[i] = T();
}
}
/*!
*\param record a container class for storing scalar records (name,value)
*\param wgtinv the inverse weight
*\brief calculate the averages and reset to zero
*/
inline void report(RecordNamedProperty<T>& record, T wgtinv) {
b_average = energy_sum*wgtinv;
b_variance = energy_sq_sum*wgtinv-b_average*b_average;
register int ir=LocalEnergyIndex;
record[ir++] = b_average;
record[ir++] = b_variance;
for(int i=0; i<elocal.size(); i++) {
record[ir++] = elocal[i]*wgtinv;
elocal[i] = T();
}
energy_sum = T(); energy_sq_sum = T();
}
};
// template<class T>
// class LocalEnergyEstimator: public EstimatorBase<T> {
// std::string RootName;
// std::ofstream fout;
// std::vector<std::string> elocal_name;
// std::vector<T> elocal;
// public:
// LocalEnergyEstimator(QMCHamiltonian& h) {
// int nterms=h.size();
// elocal.resize(nterms);
// elocal_name.resize(nterms+2);
// elocal_name[0] = "LocalEnergy";
// elocal_name[1] = "Variance";
// int ii=2;
// for(int i=0; i < nterms; i++, ii++) elocal_name[ii] = h.getName(i);
// }
// inline void resetReportSettings(const string& aname) {
// if(RootName != aname) {
// finalize();
// }
// RootName = aname;
// string fname(aname);
// fname.append(".e.dat");
// fout.open(fname.c_str());
// fout.setf(ios::right,ios::scientific);
// fout << "# index ";
// for(int i=0; i < elocal_name.size(); i++)
// fout << setw(14) << elocal_name[i];
// fout << endl;
// fout<<setprecision(8);
// }
// inline void finalize() {
// if(fout.is_open()) fout.close();
// }
// inline void accumulate(const MCWalkerConfiguration& W) {
// for(MCWalkerConfiguration::const_iterator it = W.begin();
// it != W.end(); it++){
// T w = (*it)->Properties(Weight);
// for(int i=0; i<elocal.size(); i++) {
// elocal[i] += w*((*it)->E[i]);
// }
// add(w,(*it)->Properties(LocalEnergy));
// }
// }
// inline void report(int iter){
// if(iter%stride == 0) {
// register T winv = 1.0/d_v[WEIGHT];
// register T eavg = d_v[VALUE]*winv;
// register T evar = d_v[VALUE_SQ]*winv-eavg*eavg;
// fout << setw(10) << iter;
// fout << setw(15) << eavg << setw(15) << evar;
// for(int i=0; i<elocal.size(); i++) {
// fout << setw(15) << elocal[i]*winv; elocal[i]=0.0;
// }
// fout << endl;
// d_v =0.0;
// d_v[AVERAGE]=eavg;
// d_v[VARIANCE]=evar;
// }
// }
// bool get(ostream& os) const {return true;}
// bool put(istream& is) {return true;}
// bool put(xmlNodePtr cur) {return true;}
// };
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,83 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2004- by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_QMC_SCALAR_ESTIMATORBASE_H
#define OHMMS_QMC_SCALAR_ESTIMATORBASE_H
#include "Configuration.h"
#include "OhmmsData/RecordProperty.h"
#include "OhmmsPETE/TinyVector.h"
#include "Particle/MCWalkerConfiguration.h"
namespace ohmmsqmc {
/** Abstract class for an estimator of an operator.
*
*@note derived classes should provide virtual functions of
ScalarEstimatorBase
*
* void add2Record(RecordNameProperty<T>& record);
*
* void accumulate(const MCWalkerConfiguration&);
*
* void report(RecordNameProperty<T>& record);
*/
template<class T>
struct ScalarEstimatorBase {
typedef typename MCWalkerConfiguration::Walker_t Walker_t;
T b_average;
T b_variance;
ScalarEstimatorBase():b_average(T()), b_variance(T()){}
inline T average() const { return b_average;}
inline T variance() const { return b_variance;}
/** add the content of the scalar estimator to the record
*\param record scalar data list
*
*Each ScalarEstimatorBase object adds a number of scalar data to record.
*/
virtual void add2Record(RecordNamedProperty<T>& record) = 0;
/** a virtual function to accumulate expectation values
*\param awalker a single walker
*\param wgt the weight
*/
virtual void accumulate(const Walker_t& awalker, T wgt) = 0;
/** a virtual function to report the scalar estimator
*@param record
*
*Evalaute the block-average and flush the internal data for new averages
*/
virtual void report(RecordNamedProperty<T>& record, T wgtinv) = 0;
/// a virtual function to flush the internal data to start a new block average
virtual void reset() = 0;
};
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,197 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003- by Jeongnim Kim and Jordan Vincent
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#include "Particle/MCWalkerConfiguration.h"
#include "QMCHamiltonians/QMCHamiltonianBase.h"
#include "Estimators/ScalarEstimatorManager.h"
#include "Estimators/LocalEnergyEstimator.h"
using namespace ohmmsqmc;
ScalarEstimatorManager::ScalarEstimatorManager(QMCHamiltonian& h):
Stride(1000), WeightSum(0.0), H(h), RootName("estimator"),
OutStream(NULL) { }
ScalarEstimatorManager::~ScalarEstimatorManager(){
Estimators.erase(Estimators.begin(), Estimators.end());
if(OutStream) delete OutStream;
}
int
ScalarEstimatorManager::add(EstimatorType* newestimator, const string& aname) {
std::map<string,int>::iterator it = EstimatorMap.find(aname);
if(it == EstimatorMap.end()) {
int n = Estimators.size();
Estimators.push_back(newestimator);
EstimatorMap[aname] = n;
//newestimator->add2Record(BlockAverages);
return n;
} else {
cout << "Already added estimator " << aname << endl;
return (*it).second;
}
}
/**
@brief reset the internal data of all the estimators for new averages
*/
void
ScalarEstimatorManager::reset() {
WeightSum = 0.0;
for(int i=0; i< Estimators.size(); i++) Estimators[i]->reset();
}
/**
@brief accumulate data for all the estimators
*/
void
ScalarEstimatorManager::accumulate(const MCWalkerConfiguration& W) {
for(MCWalkerConfiguration::const_iterator it = W.begin();
it != W.end(); it++){
RealType wgt = (*it)->Properties(Weight);
WeightSum += wgt;
for(int i=0; i< Estimators.size(); i++)
Estimators[i]->accumulate(**it,wgt);
}
}
/**
@brief compute the averages for all the estimators and reset
*/
void ScalarEstimatorManager::flush(){
RealType wgtinv = 1.0/WeightSum;
for(int i=0; i<Estimators.size(); i++)
Estimators[i]->report(BlockAverages,wgtinv);
BlockAverages[WeightIndex] = WeightSum;
WeightSum = 0.0;
}
/**
@param iter the interval
@brief print the averages for all the estimators to a file
*/
void ScalarEstimatorManager::report(int iter){
if(iter%Stride == 0) {
(*OutStream) << setw(10) << iter;
for(int i=0; i<BlockAverages.size();i++)
(*OutStream) << setw(16) << BlockAverages[i];
(*OutStream) << endl;
}
}
/**
@param iter the interval
@brief combines the functionality of flush and report
*/
void ScalarEstimatorManager::flushreport(int iter){
if(iter%Stride == 0) {
RealType wgtinv = 1.0/WeightSum;
for(int i=0; i<Estimators.size(); i++)
Estimators[i]->report(BlockAverages,wgtinv);
BlockAverages[WeightIndex] = WeightSum;
WeightSum = 0.0;
(*OutStream) << setw(10) << iter;
for(int i=0; i<BlockAverages.size();i++)
(*OutStream) << setw(16) << BlockAverages[i];
(*OutStream) << endl;
}
}
void
ScalarEstimatorManager::resetReportSettings(const string& aname) {
//at least have local energy
if(Estimators.empty()) {
add(new LocalEnergyEstimator<RealType>(H),"elocal");
}
//update the weight index
for(int i=0; i<Estimators.size(); i++)
Estimators[i]->add2Record(BlockAverages);
WeightIndex = BlockAverages.add("WeightSum");
if(aname != RootName) {
RootName = aname;
string fname(aname);
fname.append(".scalar.dat");
if(OutStream) delete OutStream;
OutStream = new ofstream(fname.c_str());
OutStream->setf(ios::scientific, ios::floatfield);
OutStream->setf(ios::left,ios::adjustfield);
}
for(int i=0; i<BlockAverages.size();i++) BlockAverages[i] = 0.0;
}
/**
@brief print the header to the output file
*/
void
ScalarEstimatorManager::reportHeader() {
*OutStream << "# index ";
for(int i=0; i<BlockAverages.size(); i++)
(*OutStream) << setw(16) << BlockAverages.Name[i];
(*OutStream) << endl;
OutStream->setf(ios::right,ios::adjustfield);
}
/**
@brief closes the stream to the output file
*/
void
ScalarEstimatorManager::finalize() {
if(OutStream) delete OutStream;
OutStream = NULL;
}
/**
@param istride an inverval of reportting/flushing the cummulative quantities
@brief set the stride of all the estimators to istride
*/
void
ScalarEstimatorManager::setStride(int istride) {
Stride = istride;
}
ScalarEstimatorManager::EstimatorType*
ScalarEstimatorManager::getEstimator(const string& a) {
std::map<string,int>::iterator it = EstimatorMap.find(a);
if(it == EstimatorMap.end()) {
return NULL;
} else {
return Estimators[(*it).second];
}
}
bool ScalarEstimatorManager::put(xmlNodePtr cur) {
//if(Estimators.empty()) {
// add(new LocalEnergyEstimator<RealType>(H),"elocal");
//}
return true;
}
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,107 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003- by Jeongnim Kim and Jordan Vincent
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim and Jordan Vincent
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_QMC_SCALAR_ESTIMATORMANAGER_H
#define OHMMS_QMC_SCALAR_ESTIMATORMANAGER_H
#include "Configuration.h"
#include "Estimators/ScalarEstimatorBase.h"
namespace ohmmsqmc {
class MCWalkerConifugration;
class QMCHamiltonian;
/**Class to manage a set of ScalarEstimators */
class ScalarEstimatorManager: public QMCTraits {
public:
typedef ScalarEstimatorBase<RealType> EstimatorType;
ScalarEstimatorManager(QMCHamiltonian& h);
~ScalarEstimatorManager();
///return the number of ScalarEstimators
inline int size() const { return Estimators.size();}
///process xml tag associated with estimators
bool put(xmlNodePtr cur);
void accumulate(const MCWalkerConfiguration& W);
void resetReportSettings(const string& aname);
void reportHeader();
void flushreport(int iter);
void report(int iter);
void flush();
void finalize();
void reset();
/*!\return the index of the named column
*\brief add a column with the name
*/
inline int addColumn(const char* aname) {
return BlockAverages.add(aname);
}
///add the value of the i-th column with a value v
inline void setColumn(int i, RealType v) {
BlockAverages[i] = v;
}
/*!\return the index of the newestimator
*\brief add a new estimator with name aname
*/
int add(EstimatorType* newestimator, const string& aname);
///set the stride for all the estimators
void setStride(int istride);
///return a pointer to the estimator aname
EstimatorType* getEstimator(const string& a);
///return the average for estimator i
inline RealType average(int i) const {
return Estimators[i]->average();
}
///returns a variance for estimator i
inline RealType variance(int i) const {
return Estimators[i]->variance();
}
private:
string RootName;
int Stride;
int WeightIndex;
ostream* OutStream;
RealType WeightSum;
QMCHamiltonian& H;
RecordNamedProperty<RealType> BlockAverages;
std::map<string,int> EstimatorMap;
vector<EstimatorType*> Estimators;
};
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,251 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
/**@file CrystalLattice.cpp
*@brief Member function definitions of CrystalLattice<T,D>, included by CrystalLattice.h
*/
#include "Lattice/MakeCrystalLattice.h"
/*! \fn CrystalLattice::CrystalLattice()
* Default constructor. Initialized to a \p 1x1x1 cubic supercell.
*/
template<class T, unsigned D>
CrystalLattice<T,D>::CrystalLattice() {
R.diagonal(1e10);
G = R;
M = R;
Volume = 1;
for(int i=0; i<D; i++) BoxBConds[i] = 1;
reset();
}
template<class T, unsigned D>
CrystalLattice<T,D>::CrystalLattice(const CrystalLattice<T,D>& rhs) {
R = rhs.R;
BConds = rhs.BConds;
for(int idir=0; idir<D; idir++) {
BoxBConds[idir] = rhs.BoxBConds[idir];//!< Bonundary Condition
}
reset();
}
template<class T, unsigned D>
void CrystalLattice<T,D>::set(int argc, char **argv) {
vector<string> opt;
for(int i=0; i<argc; i++) opt.push_back(argv[i]);
set(opt);
}
template<class T, unsigned D>
void CrystalLattice<T,D>::set(vector<string>& argv) {
makelattice<CrystalLattice<T,D> >::apply(*this, argv);
}
template<class T, unsigned D>
void CrystalLattice<T,D>::set(const Tensor<T,D>& lat) {
R = lat;
reset();
}
template<class T, unsigned D>
void CrystalLattice<T,D>::set(T sc, T* lat) {
if(lat) {
int ii=0;
for(int i=0; i<D; i++)
for(int j=0; j<D; j++)
R(i,j) = lat[ii++];
R *= sc;
} else {
R = 0.0e0;
R.diagonal(sc);
}
reset();
}
template<class T, unsigned D>
void
CrystalLattice<T,D>::set(const CrystalLattice<T,D>& oldlat, int *uc) {
R = oldlat.R;
BConds = oldlat.BConds;
for(int idir=0; idir<D; idir++) {
BoxBConds[idir] = oldlat.BoxBConds[idir];//!< Bonundary Condition
}
if(uc) {
for(int i=0; i<D; i++)
for(int j=0; j<D; j++) R(i,j) *= static_cast<T>(uc[i]);
}
reset();
}
template<class T, unsigned D>
void CrystalLattice<T,D>::reset() {
G = inverse(R); //G = transpose(Inverse(R));
Volume = fabs(det(R));
//M = dot(transpose(R),R);
M = dot(R,transpose(R));
T t = pow(TWOPI,2.0);
Mg = t*dot(transpose(G),G);
for(int i=0; i<D; i++)
for(int j=0; j<D; j++)
Rv[i][j] = R(i,j);
for(int i=0; i<D; i++)
for(int j=0; j<D; j++)
Gv[i][j] = G(j,i);
}
/*! \fn CrystalLattice<T,D>::operator=(const CrystalLattice<T,D>& rhs)
* \param rhs a CrystalLattice to be copied
* \brief Copy all the properties of the lattice,
* including boundary conditions and grid paritions.
*/
template<class T, unsigned D>
CrystalLattice<T,D>&
CrystalLattice<T,D>::operator=(const CrystalLattice<T,D>& rhs) {
R = rhs.R;
BConds = rhs.BConds;
for(int idir=0; idir<D; idir++) {
BoxBConds[idir] = rhs.BoxBConds[idir];//!< Bonundary Condition
}
reset();
return *this;
}
/*! \fn CrystalLattice<T,D>::operator=(const Tensor<T,D>& rhs)
* \param rhs a Tensor to be copied
*/
template<class T, unsigned D>
CrystalLattice<T,D>&
CrystalLattice<T,D>::operator=(const Tensor<T,D>& rhs) {
R = rhs;
reset();
return *this;
}
/*! \fn CrystalLattice<T,D>::operator*=(T sc)
* \param sc A scaling factor.
* \brief Rescale this supercell by a scalar.
*/
template<class T, unsigned D>
CrystalLattice<T,D>&
CrystalLattice<T,D>::operator*=(T sc) {
R *= sc;
reset();
return *this;
}
template<class T, unsigned D>
void CrystalLattice<T,D>::print(ostream& os, int level) const {
/*\note level == 0: print only the lattice vectors
* level == 1: lattice vectors, boundary conditions, grid
* level == 2: + all the internal values
*/
os << "<lattice>" << endl;
for(int i=0; i<D; i++) {
os << Rv[i] << endl;
}
os << "</lattice>" << endl;
if(level > 0) {
os << "<bconds> ";
for(int i=0; i<D; i++) {
if(BoxBConds[i]) os << " p ";
else os << " n ";
}
os << " </bconds>" << endl;
}
if(level > 1) {
os << "Volume (A^3) = " << Volume << endl;
os << "Reciprocal vectors without 2*pi.\n";
for(int i=0; i<D; i++) {
os << "g_"<< i+1<< " = " << Gv[i] << endl;
}
os << "Metric tensor in real-space.\n";
for(int i=0; i<D; i++) {
os << "h_"<< i+1<< " = ";
for(int j=0; j< D; j++) {
os << M(i,j) << " ";
}
os << endl;
}
os << "Metric tensor in g-space.\n";
for(int i=0; i<D; i++) {
os << "h_"<< i+1<< " = ";
for(int j=0; j< D; j++) {
os << Mg(i,j) << " ";
}
os << endl;
}
}
}
template<class T, unsigned D>
inline bool operator==(const CrystalLattice<T,D>& lhs,
const CrystalLattice<T,D>& rhs) {
const double eps = 1e-6;
for(int i=0; i<D*D; i++)
if(abs(lhs.R[i]-rhs.R[i]) > eps) return false;
return true;
}
template<class T, unsigned D>
inline bool operator!=(const CrystalLattice<T,D>& lhs,
const CrystalLattice<T,D>& rhs) {
return !(lhs == rhs);
}
// free function to check if a CrystalLattice is orthorhombic
template<class T, unsigned D>
inline bool orthorombic(const CrystalLattice<T,D>& a) {
return true;
}
//!< Returns true if the off-diagonal elements of Rm are zero.
template<class T>
bool orthorombic(const CrystalLattice<T,2>& a, T) {
const T eps = 1e-6;
return ((a.R(0,1) < eps) && (a.R(1,0) < eps));
}
//!< Returns true if the off-diagonal elements of Rm are zero.
template<class T>
bool orthorombic(const CrystalLattice<T,3>& a, T) {
const T eps = 1e-6;
return ((a.R(0,1) < eps) && (a.R(0,2) < eps) &&
(a.R(1,0) < eps) && (a.R(1,2) < eps) &&
(a.R(2,0) < eps) && (a.R(2,1) < eps) );
}
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,433 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998- by Jeongnim Kim
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_CRYSTALLATTICE_H
#define OHMMS_CRYSTALLATTICE_H
#include <math.h>
#include "OhmmsPETE/TinyVector.h"
#include "OhmmsPETE/Tensor.h"
#include "Lattice/ParticleBConds.h"
/**@file CrystalLattice.h
*@brief Declaration of CrystalLattice<T,D>
*/
#ifndef TWOPI
#ifndef M_PI
#define TWOPI 6.3661977236758134308E-1
#else
#define TWOPI 2*M_PI
#endif /* M_PI */
#endif /* TWOPI */
/** class to assist copy and unit conversion operations on position vectors
*/
struct PosUnit {
/** enumeraton for the unit of position types.
*/
enum {CartesianUnit=0,/*!< indicates that the values are in Cartesian units*/
LatticeUnit/*!< indicates that the values are in Lattice units*/
};
};
/** a class that defines a supercell in D-dimensional Euclean space.
*
*CrystalLattice handles the physical properties of a supercell, such
*as lattice vectors, reciprocal vectors and metric tensors and provides
*interfaces to access the lattice properties and convert units of
*position vectors or a single-particle position from Cartesian to
*Lattice Unit vice versa.
*
*The indices for R, G and D are chosen to perform
*expression template operations with variable-cell algorithms.
*
*/
template<class T, unsigned D>
struct CrystalLattice{
///enumeration for the dimension of the lattice
enum {DIM = D};
//@{
///the type of scalar
typedef T Scalar_t;
///the type of a D-dimensional position vector
typedef TinyVector<T,D> SingleParticlePos_t;
///the type of a D-dimensional index vector
typedef TinyVector<int,D> SingleParticleIndex_t;
///the type of a D-dimensional Tensor
typedef Tensor<T,D> Tensor_t;
//@}
//@{
/**@brief Physcial properties of a supercell*/
/// Volume of a supercell
T Volume;
///Real-space unit vectors. R(i,j) i=vector and j=x,y,z
Tensor_t R;
///Reciprocal unit vectors. G(j,i) i=vector and j=x,y,z
Tensor_t G;
///Metric tensor
Tensor_t M;
///Metric tensor for G vectors
Tensor_t Mg;
/**@brief Real-space unit vectors.
*
*Introduced to efficiently return one vector at a time.
*Rv[i] is D-dim vector of the ith direction.
*/
TinyVector<SingleParticlePos_t,D> Rv;
/**@brief Reciprocal unit vectors.
*
*Introduced to efficiently return one vector at a time.
*Gv[i] is D-dim vector of the ith direction.
*/
TinyVector<SingleParticlePos_t,D> Gv;
//@}
//@{
/**@brief Parameters defining boundary Conditions */
///Functors that apply boundary conditions on the position vectors
ParticleBConds<T,D> BConds;
///The boundary condition in each direction.
TinyVector<int,D> BoxBConds;
//@}
///default constructor, assign a huge supercell
CrystalLattice();
/** copy constructor
@param rhs An existing SC object is copied to this SC.
*/
CrystalLattice(const CrystalLattice<T,D>& rhs);
///destructor
virtual ~CrystalLattice(){ }
/**@param i the index of the directional vector, \f$i\in [0,D)\f$
*@return The lattice vector of the ith direction
*@brief Provide interfaces familiar to fotran users
*/
inline SingleParticlePos_t a(int i) const {
return Rv[i];
}
/**@param i the index of the directional vector, \f$i\in [0,D)\f$
*@return The reciprocal vector of the ith direction
*@brief Provide interfaces familiar to fotran users
*/
inline SingleParticlePos_t b(int i) const {
return Gv[i];
}
/** Convert a cartesian vector to a unit vector.
* Boundary conditions are not applied.
*/
inline SingleParticlePos_t toUnit(const SingleParticlePos_t &r) const {
return dot(r,G);
}
/** Convert a unit vector to a cartesian vector.
* Boundary conditions are not applied.
*/
inline SingleParticlePos_t toCart(const SingleParticlePos_t &c) const {
return dot(c,R);
}
/** evaluate the cartesian distance
*@param ra a vector in the supercell unit
*@param rb a vector in the supercell unit
*@return Cartesian distance with two vectors in SC unit
*
@note The distance between two cartesian vectors are handled
*by dot function defined in OhmmsPETE/TinyVector.h
*/
inline T Dot(const SingleParticlePos_t &ra,
const SingleParticlePos_t &rb) const {
return dot(ra,dot(M,rb));
}
/** conversion of a reciprocal-vector
*@param kin an input reciprocal vector in the Reciprocal-vector unit
*@return k(reciprocal vector) in cartesian unit
*/
inline SingleParticlePos_t k_cart(const SingleParticlePos_t& kin) const {
return TWOPI*dot(G,kin);
}
/** evaluate \f$k^2\f$
*
*@param kin an input reciprocal vector in reciprocal-vector unit
*@return \f$k_{in}^2\f$
*/
inline T ksq(const SingleParticlePos_t& kin) const {
return dot(kin,dot(Mg,kin));
}
///assignment operator
CrystalLattice<T,D>& operator=(const CrystalLattice<T,D>& rhs);
/** assignment operator
*@param rhs a tensor representing a unit cell
*/
CrystalLattice<T,D>& operator=(const Tensor<T,D>& rhs);
/** scale the lattice vectors by sc. All the internal data are reset.
*@param sc the scaling value
*@return a new CrystalLattice
*/
CrystalLattice<T,D>& operator*=(T sc);
/** set the lattice vector from the command-line options
*@param argc the number of arguments
*@param argv the argument lists
*
*This function is to provide a simple interface for testing.
*/
void set(int argc, char **argv);
/** set the lattice vector from the command-line options stored in a vector
*@param argv the argument lists
*
*This function is to provide a simple interface for testing.
*/
void set(vector<string>& argv);
/** set the lattice vector by an array containing DxD T
*@param sc a scalar to scale the input lattice parameters
*@param lat the starting address of DxD T-elements representing a supercell
*/
void set(T sc, T* lat= NULL);
/** set the lattice vector by a CrystalLattice and expand it by integers
*@param oldlat An input supercell to be copied.
*@param uc An array to expand a supercell.
*/
void set(const CrystalLattice<T,D>& oldlat, int* uc= NULL);
/** set the lattice vector from the command-line options
*@param lat a tensor representing a supercell
*/
void set(const Tensor<T,D>& lat);
/** Evaluate the reciprocal vectors, volume and metric tensor
*/
void reset();
//@{
/* Copy functions with unit conversion*/
template<class PA> void convert(const PA& pin, PA& pout) const;
template<class PA> void convert2Unit(const PA& pin, PA& pout) const;
template<class PA> void convert2Cart(const PA& pin, PA& pout) const;
template<class PA> void convert2Unit(PA& pout) const;
template<class PA> void convert2Cart(PA& pout) const;
//@}
template<class PA> void applyBC(const PA& pin, PA& pout, T del=1.e-6) const;
template<class PA> void applyBC(PA& pos, T del=1.e-6) const;
//! Print out CrystalLattice Data
void print(ostream& , int level=2) const;
};
//including the definitions of the member functions
#include "Lattice/CrystalLattice.cpp"
/** Copy operation pout = pin with the unit checking of the in/out vectors
*
*@param pin an input position array
*@param pout an output position array
*
*@note The units of in/out vectors are conserved.
*/
template<class T, unsigned D>
template<class PA>
inline void CrystalLattice<T,D>::convert(const PA& pin, PA& pout) const
{
if(pin.getUnit() == pout.getUnit()) {
pout = pin;
return;
}
if(pin.getUnit() == PosUnit::LatticeUnit) {
//convert to CartesianUnit
for(int i=0; i<pin.size(); i++) pout[i] = dot(pin[i],R);
} else {
//convert to LatticeUnit
for(int i=0; i<pin.size(); i++) pout[i] = dot(pin[i],G);
}
}
/** Copy operation pout = pin with the unit checking of the in/out vectors
*
*@param pin an input position array
*@param pout an output position array
*
*@note The unit of the out vector is forced to be Cartesian.
*/
template<class T, unsigned D>
template<class PA>
inline void CrystalLattice<T,D>::convert2Cart(const PA& pin, PA& pout) const
{
pout.setUnit(PosUnit::CartesianUnit);
if(pin.getUnit() == PosUnit::CartesianUnit)
pout = pin;
else //need to convert to CartesianUnit
for(int i=0; i<pin.size(); i++) pout[i] = dot(pin[i],R);
}
/** Copy operation pout = pin with the unit checking of the in/out vectors
*
*@param pin an input position array
*@param pout an output position array
*
*@note The unit of the out vector is forced to be Lattice unit.
*/
template<class T, unsigned D>
template<class PA>
inline void CrystalLattice<T,D>::convert2Unit(const PA& pin, PA& pout) const
{
pout.setUnit(PosUnit::LatticeUnit);
if(pin.getUnit() == PosUnit::LatticeUnit)
pout = pin;
else //need to convert to LatticeUnit
for(int i=0; i<pin.size(); i++) pout[i] = dot(pin[i],G);
}
/** Conversion of a position array to Cartesian unit.
*
*@param pos in/out position array
*
*@note The unit of the out vector is forced to be Cartesian. If the unit
*of pos is in Cartesian, no action is taken.
*/
template<class T, unsigned D>
template<class PA>
inline void CrystalLattice<T,D>::convert2Cart(PA& pos) const
{
if(pos.getUnit() == PosUnit::LatticeUnit) {
for(int i=0; i<pos.size(); i++) pos[i] = dot(pos[i],R);
pos.setUnit(PosUnit::CartesianUnit);
}
}
/** Conversion of a position array to Lattice unit.
*
*@param pos in/out position array
*
*@note The unit of the out vector is forced to be in Lattice unit.
*If the unit of pos is in Lattice unit, no action is taken.
*/
template<class T, unsigned D>
template<class PA>
inline void CrystalLattice<T,D>::convert2Unit(PA& pos) const
{
if(pos.getUnit() == PosUnit::CartesianUnit) {
for(int i=0; i<pos.size(); i++) pos[i] = dot(pos[i],G);
pos.setUnit(PosUnit::LatticeUnit);
}
}
/** Copy an in vector to an out vector after applying boundary conditions.
*
*@param pin an input position array
*@param pout an output position array
*@param del a tolerance for wrapping the values within [0,1)
*
*@note The values of pout are all within a bounding box.
*The units of the in/out vectors are preserved. Numerical problems
*can appear by using del=0 due to rounding errors. For instance,
*when the box is partioned by 3x3x3, a terrible thing can happen.
*/
template<class T, unsigned D>
template<class PA>
void
CrystalLattice<T,D>::applyBC(const PA& pin, PA& pout, T del) const
{
int mode = pin.InUnit*2+pout.InUnit;
switch(mode) {
case(0):
for(int i=0; i<pin.size(); i++)
pout[i] = dot(BConds.wrap(dot(pin[i],G)+del),R);
break;
case(1):
for(int i=0; i<pin.size(); i++)
pout[i] = BConds.wrap(dot(pin[i],G)+del);
break;
case(2):
for(int i=0; i<pin.size(); i++) pout[i] = dot(BConds.wrap(pin[i]+del),R);
break;
case(3):
for(int i=0; i<pin.size(); i++) pout[i] = BConds.wrap(pin[i]+del);
break;
}
// switch(mode) {
// case(0):
// for(int i=0; i<pin.size(); i++)
// pout[i] = dot(BConds.wrap(dot(pin[i],G)),R);
// break;
// case(1):
// for(int i=0; i<pin.size(); i++)
// pout[i] = BConds.wrap(dot(pin[i],G));
// break;
// case(2):
// for(int i=0; i<pin.size(); i++) pout[i] = dot(BConds.wrap(pin[i]),R);
// break;
// case(3):
// for(int i=0; i<pin.size(); i++) pout[i] = BConds.wrap(pin[i]);
// break;
// }
}
/** Copy an in vector to an out vector after applying boundary conditions.
*
*@param pos an in/out position array
*@param del a tolerance for wrapping the values within [0,1)
*
*@note The values of pos are all within a bounding box.
*The unit is preserved. Numerical problems can appear
*by using del=0 due to rounding errors.
*/
template<class T, unsigned D>
template<class PA>
void CrystalLattice<T,D>::applyBC(PA& pos, T del) const
{
if(pos.InUnit) {
for(int i=0; i<pos.size(); i++) pos[i] = BConds.wrap(pos[i]);
} else {
for(int i=0; i<pos.size(); i++) pos[i] = BConds.wrap(dot(pos[i],G)+del);
pos.InUnit = true;
}
// if(pos.InUnit) {
// for(int i=0; i<pos.size(); i++) pos[i] = BConds.wrap(pos[i]);
// } else {
// for(int i=0; i<pos.size(); i++) pos[i] = BConds.wrap(dot(pos[i],G));
// pos.InUnit = true;
// }
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,149 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2004- by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
/**@file MakeCrystalLattice.h
*@brief Functors to create a lattice with command-line options.
*
*The arguments are stored in std::vector<string>.
*
*/
/** dummy template class to be specialized */
template<class CL>
struct makelattice { };
/** Specialization of makelattice<CL> for CrystalLattice<T,D>
*
* Does nothing but enables specialization for D-dimensional lattice.
*/
template<class T, unsigned D>
struct makelattice<CrystalLattice<T,D> > {
inline static void apply(CrystalLattice<T,D>& , vector<string>& argv) {
}
};
/** Specialization of makelattice<CL> for CrystalLattice<T,1>*/
template<class T>
struct makelattice<CrystalLattice<T,1> > {
inline static
void
apply(CrystalLattice<T,1>& lat, vector<string>& argv) {
int i=0;
int argc = argv.size();
while(i<argc) {
if(argv[i] == "a0") {
lat.R(0,0) = atof(argv[++i].c_str());
}
i++;
}
lat.reset();
}
};
/** Specialization of makelattice<CL> for CrystalLattice<T,2>*/
template<class T>
struct makelattice<CrystalLattice<T,2> > {
inline static
void
apply(CrystalLattice<T,2>& lat, vector<string>& argv) {
T a0 = 1.0e0;
int i=0;
int argc = argv.size();
while(i<argc) {
if(argv[i] == "cubic") {
a0 = atof(argv[++i].c_str());
lat.R.diagonal(1.0);
} else if(argv[i] == "orthorombic") {
lat.R = 0.0e0;
lat.R(0,0) = atof(argv[++i].c_str());
lat.R(1,1) = atof(argv[++i].c_str());
} else if(argv[i] == "general") {
lat.R = 0.0e0;
lat.R(0,0) = atof(argv[++i].c_str());
lat.R(0,1) = atof(argv[++i].c_str());
lat.R(1,0) = atof(argv[++i].c_str());
lat.R(1,1) = atof(argv[++i].c_str());
}
i++;
}
lat.R *= a0;
lat.reset();
}
};
/** Specialization of makelattice<CL> for CrystalLattice<T,3>*/
template<class T>
struct makelattice<CrystalLattice<T,3> > {
/*! \fn makelattic<CrystalLattice<T,3> >
* ::apply(CrystalLattice<T,3>& lattice, vector<string>& argv)
* \param lattice an CrystalLattice to be set
* \param argv input parameters
* \note Keywords to set a speical 3D primitive cell.
* \li \p lattice \p cubic \p a
* \li \p lattice \p fcc \p a
* \li \p lattice \p bcc \p a
* \li \p lattice \p hcp \p a \p [c/a]
*/
inline static
void
apply(CrystalLattice<T,3>& lat, vector<string>& argv) {
T a0 = 1.0e0;
int i=0;
int argc = argv.size();
while(i<argc) {
if(argv[i] == "cubic") {
a0 = atof(argv[++i].c_str());
lat.R.diagonal(1.0);
} else if(argv[i] == "orthorombic") {
lat.R = 0.0e0;
lat.R(0,0) = atof(argv[++i].c_str());
lat.R(1,1) = atof(argv[++i].c_str());
lat.R(2,2) = atof(argv[++i].c_str());
} else if(argv[i] == "fcc") {
a0 = atof(argv[++i].c_str());
lat.R(0,0) = 0.0; lat.R(0,1) = 0.5; lat.R(0,2) = 0.5;
lat.R(1,0) = 0.5; lat.R(1,1) = 0.0; lat.R(1,2) = 0.5;
lat.R(2,0) = 0.5; lat.R(2,1) = 0.5; lat.R(2,2) = 0.0;
} else if(argv[i] == "bcc") {
a0 = atof(argv[++i].c_str());
lat.R(0,0) = -0.5; lat.R(0,1) = 0.5; lat.R(0,2) = 0.5;
lat.R(1,0) = 0.5; lat.R(1,1) = -0.5; lat.R(1,2) = 0.5;
lat.R(2,0) = 0.5; lat.R(2,1) = 0.5; lat.R(2,2) = -0.5;
} else if(argv[i] == "hcp") {
a0 = atof(argv[++i].c_str());
double covera = sqrt(8.0/3.0);
if(argc-i > 1) covera = atof(argv[++i].c_str());
lat.R(0,0) = 0.5*a0; lat.R(0,1) = -sqrt(3.0)*0.5*a0; lat.R(0,2) = 0.0;
lat.R(1,0) = 0.5*a0; lat.R(1,1) = sqrt(3.0)*0.5*a0; lat.R(1,2) = 0.0;
lat.R(2,0) = 0.0; lat.R(2,1) = 0.0; lat.R(2,2) = covera*a0;
a0 = 1.0e0;
}
i++;
}
lat.R *= a0;
lat.reset();
}
};
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,241 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_MULTIGRID_PARTICLE_LAYOUT_H
#define OHMMS_MULTIGRID_PARTICLE_LAYOUT_H
#include <string>
#include <vector>
using std::vector;
#include "Lattice/Region.h"
#include "Lattice/UniformCartesianGrid.h"
//forward declaration
template<class T, unsigned D> class MakeMultiGrid;
/*! \class MultiGridParticleLayout<class T, unsigned D>
* \brief A class for grid layout
*/
template<class T, unsigned D>
struct MultiGridParticleLayout {
typedef UniformCartesianGrid<T,D> PtclGrid_t;
vector<PtclGrid_t*> dGrid;
MultiGridParticleLayout(){ }
~MultiGridParticleLayout() {
for(int i=0; i<dGrid.size(); i++)
delete dGrid[i];
}
inline const PtclGrid_t* getGrid(int level) const {
return dGrid[level]; // return a grid at level
}
/*! \fn makeGrid(int *grid, int igrid=-1)
* \param grid[D] a grid partition
* \param igrid index of an existing grid to make a sub partition
* \return the index of a new grid
* \note if(igrid == -1) a new grid is created
* else a new subgrid based on igrid-th grid is created
*/
int makeGrid(int *grid, int igrid=-1) {
int n=dGrid.size();
dGrid.push_back(new PtclGrid_t);
if(igrid >= 0 && n>0)
MakeMultiGrid<T,D>::refineGrid(*dGrid[n],*dGrid[igrid],grid);
else
MakeMultiGrid<T,D>::makeGrid(*dGrid[n],grid);
return n;
}
void resetGrid(int igrid, int* grid) {
if(igrid == dGrid.size()) {//need to create a new grid
dGrid.push_back(new PtclGrid_t);
}
if(igrid > 0) {
MakeMultiGrid<T,D>::refineGrid(*dGrid[igrid],*dGrid[igrid-1],grid);
} else {
MakeMultiGrid<T,D>::makeGrid(*dGrid[igrid],grid);
}
}
void printGrid(ostream& os) {
for(int i=0; i<dGrid.size(); i++) dGrid[i]->print(os);
}
template<class P> void update(P*, int);
};
template<class T, unsigned D>
struct MakeMultiGrid {};
template<class T>
struct MakeMultiGrid<T,3> {
typedef UniformCartesianGrid<T,3> ThisGrid_t;
static void makeGrid(ThisGrid_t& grid, int* ng) {
int ngtot=ng[0]*ng[1]*ng[2];
grid.set(ng);
grid.NodeID.resize(ngtot);
grid.NodeDist.resize(ngtot+1);
grid.Node.resize(ngtot);
for(int i=0; i<=ngtot; i++) grid.NodeDist[i] = i;
T ri[3];
int ig=0;
for(int ic=0; ic<grid.NP[0]; ic++) {
ri[0] = grid.Delta[0]*static_cast<T>(ic);
for(int jc=0; jc<grid.NP[1]; jc++) {
ri[1] = grid.Delta[1]*static_cast<T>(jc);
for(int kc=0; kc<grid.NP[2]; kc++) {
ri[2] = grid.Delta[2]*static_cast<T>(kc);
grid.NodeID[grid.key(ic,jc,kc)] = ig;
grid.Node[ig].set(ri,grid.Delta);
ig++;
}
}
}
}
static void
refineGrid(ThisGrid_t& subgrid, const ThisGrid_t& biggrid, int *ng) {
int ngbig = biggrid.NP[0]*biggrid.NP[1]*biggrid.NP[2];
int ngsub = ng[0]*ng[1]*ng[2];
int ngtot = ngbig*ngsub;
int ngnew[3];
ngnew[0] = ng[0]*biggrid.NP[0];
ngnew[1] = ng[1]*biggrid.NP[1];
ngnew[2] = ng[2]*biggrid.NP[2];
subgrid.set(ngnew);
subgrid.NodeID.resize(ngtot);
subgrid.Node.resize(ngtot);
T ri[3],orig[3];
subgrid.NodeDist.resize(ngbig+1);
subgrid.NodeDist[0] = 0;
int igrid=0;
for(int ig=0; ig<biggrid.Node.size(); ig++) {
//origin of a mesh
orig[0] = biggrid.Node[ig].Ri[0];
orig[1] = biggrid.Node[ig].Ri[1];
orig[2] = biggrid.Node[ig].Ri[2];
//integer indices of a mesh
subgrid.getcoord(orig,ngnew);
//ngnew[0]*=ng[0]; ngnew[1]*=ng[1]; ngnew[2]*=ng[2];
for(int isub=0; isub<ng[0]; isub++) {
ri[0] = subgrid.Delta[0]*static_cast<T>(isub)+orig[0];
for(int jsub=0; jsub<ng[1]; jsub++) {
ri[1] = subgrid.Delta[1]*static_cast<T>(jsub)+orig[1];
for(int ksub=0; ksub<ng[2]; ksub++) {
ri[2] = subgrid.Delta[2]*static_cast<T>(ksub)+orig[2];
subgrid.NodeID[subgrid.key(ngnew[0]+isub,
ngnew[1]+jsub,
ngnew[2]+ksub)] = igrid;
subgrid.Node[igrid].set(ri,subgrid.Delta);
igrid++;
}
}
}
subgrid.NodeDist[ig+1] = subgrid.NodeDist[ig]+ngsub;
}
}
// //Intended for MPI_Cartesian functions but
// #ifdef USE_MPI
// static void makeMPIGrid(ThisGrid_t& grid, const int* ng, const int* period) {
// int ngtot=ng[0]*ng[1]*ng[2];
// grid.NodeID.resize(ngtot);
// grid.NodeDist.resize(ngtot+1);
// grid.Node.resize(ngtot);
// for(int i=0; i<=ngtot; i++) grid.NodeDist[i] = i;
// gird.set(ng);
// Communicate* Comm = CommCreate::get();
// int numnode = Comm->getNumNodes();
// int nodeid = Comm->getNodeID(),newnode;
// bool reorder = true;
// MPI_Comm cartcomm;
// int MyCoord[3];
// // remapping a MPI grid using MPI_Cart
// MPI_Cart_create(MPI_COMM_WORLD,3,grid.NP,period,reorder,&cartcomm);
// MPI_Cart_map(cartcomm,3,grid.NP,period,&newnode);
// MPI_Cart_get(cartcomm,3,grid.NP,period,MyCoord);
// Comm->setNodeID(newnode);
// Comm->setCommID(cartcomm);
// int MyID = newnode;
// int coord[3],ii=0;
// double ri[3];
// for(int i=0;i<ng[0]; i++) {
// ri[0] = grid.Delta[0]*static_cast<double>(i);
// for(int j=0; j<ng[1]; j++) {
// ri[1] = grid.Delta[1]*static_cast<double>(j);
// for(int k=0; k<ng[2]; k++) {
// coord[0] = i; coord[1] = j; coord[2] = k;
// MPI_Cart_rank(cartcomm,coord,&nodeid);
// ri[2] = grid.Delta[2]*static_cast<double>(k);
// grid.Node[nodeid].set(ri,grid.Delta);
// grid.NodeID[grid.key(i,j,k)] = nodeid;
// }
// }
// }
// }
// #endif
};
template<class T, unsigned D>
template<class P>
void MultiGridParticleLayout<T,D>::update(P* ptcl, int imode) {
// cout << "Calling MultiGridParticleLayout::update" << endl;
// typedef P::ParticlePos_t ParticlePos_t;
// typedef P::ParticleIndex_t ParticleIndex_t;
// ParticlePos_t r;
// ParticlePos_t id;
// r.resize(ptcl->getLocalNum());
// id.resize(ptcl->getLocalNum());
// r = ptcl->R;
// id = ptcl->IonID;
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,282 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
/***************************************************************************
*
* The POOMA Framework
*
* This program was prepared by the Regents of the University of
* California at Los Alamos National Laboratory (the University) under
* Contract No. W-7405-ENG-36 with the U.S. Department of Energy (DOE).
* The University has certain rights in the program pursuant to the
* contract and the program should not be copied or distributed outside
* your organization. All rights in the program are reserved by the DOE
* and the University. Neither the U.S. Government nor the University
* makes any warranty, express or implied, or assumes any liability or
* responsibility for the use of this software
*
* Visit http://www.acl.lanl.gov/POOMA for more details
*
***************************************************************************/
#ifndef PARTICLE_BCONDS_H
#define PARTICLE_BCONDS_H
#include <math.h>
/*! \note Modification of ParticleBConds.h of Pooma r1 to work with
* changed TinyVector classes.
*/
//////////////////////////////////////////////////////////////////////
// particle boundary condition functions ...
// ParticleNoBCond = no action is taken
// ParticlePeriodicBCond = shift the vector withtin [-len/2, len/2)
// ParticlePeriodicWrapBCond = wrap around at endpoints of the interval
// ParticleReflectiveBCond = values bounce back from endpoints
//////////////////////////////////////////////////////////////////////
// null BC; value is not changed
//! \param t A position subject to the boundary condition.
//! \param minval mininum range (ignored)
//! \param maxval maximum range (ignored)
//! \return t
template<class T>
inline T
ParticleNoBCond(const T t, const T /* minval */, const T /* maxval */) {
return t;
}
//! \param t A position subject to the boundary condition.
//! \param minval mininum range (ignored)
//! \param maxval maximum range (ignored)
//! \return t if |t| < (maxval-minval)/2
//! \note This funtion returns the shortest distance of
//! t under periodic boundary condition. minval is ignored for periodic BC.
//! [-maxval/2, maxval/2) is the actual range
template<class T>
inline T
ParticlePeriodicBCond(const T t, const T minval, const T maxval) {
//T t0=fmod(t,maxval);
//return t0 - static_cast<T>(static_cast<int>(t0*2.0*maxval));
if(t < -0.5) return t+1.0;
else if(t>= 0.5) return t-1.0;
else return t;
}
//! \param t A position subject to the boundary condition.
//! \param minval mininum range (ignored)
//! \param maxval maximum range (ignored)
//! \return t
//! \note Poomar1::ParticlePeriodicBCond is ParticlePeriodicWrapBCond
template<class T>
inline T
ParticlePeriodicWrapBCond(const T t, const T minval, const T maxval) {
if (t < minval)
return (maxval - (minval - t));
else if (t >= maxval)
return (minval + (t - maxval));
else
return t;
}
//! \note reflective BC; values bounce back from endpoints
//! Implemented by Poomar1.
template<class T>
inline T
ParticleReflectiveBCond(const T t, const T minval, const T maxval) {
if (t < minval)
return (minval + (minval - t));
else if (t >= maxval)
return (maxval - (t - maxval));
else
return t;
}
//! \note sink BC; particles stick to the selected face
//! Implemented by Poomar1
template<class T>
T ParticleSinkBCond(const T t, const T minval, const T maxval) {
if (t < minval)
return minval;
else if (t >= maxval)
return maxval;
else
return t;
}
////////////////////////////////////////////////////////////////
//
// Fuction classes to apply BC to a TinyVector
//
////////////////////////////////////////////////////////////////
// forward declaration
template<class T, unsigned D> class ParticleBConds;
/*! \class template<class T> struct applyBConds
* \brief Empty class. Specialization of applyBConds with specific
* ParticleBConds is intended.
*/
template<class T>
struct applyBConds {
};
/*!\class template<class T, unsigned D> struct applyBConds<ParticleBConds<T,D> >
* \brief Specialization for ParticleBConds<T,D> defined below.
*/
template<class T, unsigned D>
struct applyBConds<ParticleBConds<T,D> > {
//!< Apply boundary conditions for each direction
static inline TinyVector<T,D>
apply(const ParticleBConds<T,D>& bc, const TinyVector<T,D>& a){
TinyVector<T,D> res;
for(int i=0; i<D; i++) res[i] = bc.apply(a[i],i,1.0);
return res;
}
};
/*!\class template<class T> struct applyBConds<ParticleBConds<T,1> >
* \brief Specialization for ParticleBConds<T,D> defined below.
*/
template<class T>
struct applyBConds<ParticleBConds<T,1> > {
static inline TinyVector<T,1>
apply(const ParticleBConds<T,1>& bc, const TinyVector<T,1>& a){
return
TinyVector<T,1>(bc.apply(a[0],0,1));
}
};
/*!\class template<class T> struct applyBConds<ParticleBConds<T,2> >
* \brief Specialization for ParticleBConds<T,D> defined below.
*/
template<class T>
struct applyBConds<ParticleBConds<T,2> > {
static inline TinyVector<T,2>
apply(const ParticleBConds<T,2>& bc, const TinyVector<T,2>& a){
return
TinyVector<T,2>(bc.apply(a[0],0,1),bc.apply(a[1],1,1));
}
};
/*!\class template<class T> struct applyBConds<ParticleBConds<T,3> >
* \brief Specialization for ParticleBConds<T,D> defined below.
*/
template<class T>
struct applyBConds<ParticleBConds<T,3> > {
static inline TinyVector<T,3>
apply(const ParticleBConds<T,3>& bc, const TinyVector<T,3>& a){
return
TinyVector<T,3>(bc.apply(a[0],0,1),bc.apply(a[1],1,1),bc.apply(a[2],2,1));
}
static inline TinyVector<T,3>
wrap(const ParticleBConds<T,3>& bc, const TinyVector<T,3>& a){
return
TinyVector<T,3>(bc.wrap(a[0],0,1),bc.wrap(a[1],1,1),
bc.wrap(a[2],2,1));
}
};
/*!\class ParticleBConds
* \brief ParticleBConds is a container for a set of particle boundary condition
* functions. Boundary conditions for particles are not objects, but just
* functions which map a position X -> X', given the minimum and maximum
* values of the spatial domain.
***************************************************************************/
//////////////////////////////////////////////////////////////////////
// general container for a set of particle boundary conditions
template<class T, unsigned Dim>
class ParticleBConds {
public:
// typedef for a pointer to boundary condition function
typedef T (*ParticleBCond)(const T, const T, const T);
public:
// constructor: initialize all BC's to periodic ones
ParticleBConds() {
for (int d=(Dim - 1); d >= 0; --d) {
BCList[d] = ParticlePeriodicBCond; // for distance
BCTransList[d] = ParticlePeriodicWrapBCond; // for translation, wrapping
}
}
// operator= to copy values from another container
ParticleBConds<T,Dim>& operator=(const ParticleBConds<T,Dim>& pbc) {
for (int d=(Dim - 1); d >= 0; --d) {
BCList[d] = pbc.BCList[d];
BCTransList[d] = ParticlePeriodicWrapBCond;
}
return *this;
}
// operator[] to get value of Nth boundary condition
inline ParticleBCond& operator[](unsigned d) { return BCList[d]; }
// return a wrpper function for d-direction
inline ParticleBCond& wrapper(unsigned d) { return BCTransList[d]; }
// for the given value in the given dimension over the given NDRegion,
// apply the proper BC and return back the new value
inline T apply(const T t, const unsigned d, const T len) const {
return BCList[d](t,0,len);
}
// for the given value in the given dimension over the given NDRegion,
// apply the proper BC and return back the new value
inline T wrap(const T t, const unsigned d, const T len) const {
return BCTransList[d](t,0,len);
}
// to work with difffent types of data
template<class T1>
inline T1 apply(const T1 t, const unsigned d, const T1 len) const {
return static_cast<T1>(
BCList[d](static_cast<T>(t), 0, static_cast<T>(len)));
}
inline TinyVector<T,Dim> apply(const TinyVector<T,Dim>& x) const {
return applyBConds<ParticleBConds<T,Dim> >::apply(*this,x);
}
inline TinyVector<T,Dim> wrap(const TinyVector<T,Dim>& x) const {
return applyBConds<ParticleBConds<T,Dim> >::wrap(*this,x);
}
private:
// array storing the function pointers
// Note that the size is Dim not 2*Dim
ParticleBCond BCList[Dim];
ParticleBCond BCTransList[Dim];
};
#endif // PARTICLE_BCONDS_H
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,93 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_REGULARMULTIGRID_H
#define OHMMS_REGULARMULTIGRID_H
#include <vector>
using namespace std;
/*! \class RegMultiGrid<class T, unsigned D>
* \brief A class for grid layout using octree
*/
template<class T, unsigned D>
struct RegMultiGrid {
typedef RegMultiGrid<T,D> this_t;
Region<T,D> R;
RegMultiGrid():Up(NULL){ }
~RegMultiGrid();
inline bool root() const { return Up == NULL;}
inline bool empty() const { return Down.empty();}
inline const RegMultiGrid* node() const { return Up;}
inline const RegMultiGrid* child(int i) const {
if(Down.empty()) return NULL;
else return Down[i];
}
void refine();
void remove() {
for(int i=0; i<Down.size(); i++) delete Down[i];
}
template<class pos_t>
inline int node(const pos_t& pos) {
if(R.inside(pos))
return R.inside(pos);
}
this_t* Up;
vector<this_t* > Down;
};
template<class T, unsigned D>
RegMultiGrid<T,D>::~RegMultiGrid() {
for(int i=0; i<Down.size(); i++) delete Down[i];
}
template<class T, unsigned D>
void RegMultiGrid<T,D>::refine() {}
template<class T>
void RegMultiGrid<T,3>::refine() {
if(Down.empty()) {
for(int i=0; i<8; i++) Down.push_back(new RegMultGrid<T,D>);
T dx[D];
dx[0] = R.Rf[0]-R.Ri[0];
dx[1] = R.Rf[1]-R.Ri[1];
dx[2] = R.Rf[2]-R.Ri[2];
for(int idim=0; idim<D; idim++)
dx[idim] = (R.Rf[idim]-R.Ri[dim])*0.5;
}
if(Down.empty()) {
for(int i=0; i<nsub; i++) Down.push_back(new RegMultGrid<T,D>);
}
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

72
src/Lattice/Region.h Normal file
View File

@ -0,0 +1,72 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_REGINON_H
#define OHMMS_REGION_H
/* \class Region defines a spatial region bound by [Ri,Rf)
\brief Defined in unit vectors 0 <= Ri, Rf < 1
*/
template<class T, unsigned D>
struct Region {
typedef T Scalar_t;
enum {DIM = D};
T Ri[D], Rf[D];
Region(){ }
Region(const T* r0, const T* dr) {
set(r0,dr);
}
Region(const Region<T,D>& rg) {
for(int i=0; i<D; i++) Ri[i] = rg.Ri[i];
for(int i=0; i<D; i++) Rf[i] = rg.Rf[i];
}
Region<T,D>& operator=(const Region<T,D>& rg) {
for(int i=0; i<D; i++) Ri[i] = rg.Ri[i];
for(int i=0; i<D; i++) Rf[i] = rg.Rf[i];
return *this;
}
~Region(){ }
inline void set(const T* r0, const T* dr) {
for(int i=0; i<D; i++) Ri[i] = r0[i];
for(int i=0; i<D; i++) Rf[i] = r0[i]+dr[i];
}
template<class Pos_t>
inline bool inside(const Pos_t& r) const {
for(int i=0; i<DIM; i++) {
if(r[i] < Ri[i] || r[i] >= Rf[i]) return false;
}
return true;
}
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,275 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_UNIFORMCARTESIANGRID_H
#define OHMMS_UNIFORMCARTESIANGRID_H
/**@file UniformCartesianGrid.h
*@brief Class declarations for UniformCartesianGrid
*/
#include "Utilities/DistributedIndex.h"
#include "OhmmsPETE/TinyVector.h"
#include <iostream>
/* \class UniformCartesianGrid
* \brief Class to manage a uniform grid.
*
* Does nothing and needs to be specialized.
*/
template<class T, unsigned D>
struct UniformCartesianGrid {};
/** Specialization of UniformCartesianGrid<T,D> to 3-Dim domains.
*
*Regardless of the shape of the domain, the view of UniformCartesianGrid
*is a cubic cell. The 3-D position vector is valid only if \f$v = ([0,1),[0,1),[0,1))\f$.
*
*The main function of this class is to partition a domain defined by
*3 orthogonal axes, \f${\hat x}, {\hat y}\f$ and \f${\hat z}\f$.
*A region or domain is specified by three indices (i,j,k)
*and they satisfy the conditions \f[ i \in [0,NP[0])\f] \f[ j \in
*[0,NP[1])\f] \f[ k \in [0,NP[2])\f] The subdomains are stored in an
*one-dimensional array and key is used to map (i,j,k) to the
*corresponding domain. Member function key is provided in
*anticipation of the need to use a sparse storage of the subdomains
*to handle inhomogeneous systems.
*/
template<class T>
class UniformCartesianGrid<T,3> {
public:
typedef DistributedIndex::iterator iterator;
typedef DistributedIndex::const_iterator const_iterator;
///default constructor
inline UniformCartesianGrid() {
NumGrids = 1;
NP[0] = 1; NP[1] = 1; NP[2] = 1;
Delta[0] = 1; Delta[1] = 1; Delta[2] =1;
InvDelta[0] = 1; InvDelta[1] = 1; InvDelta[2] =1;
}
///copy constructor
inline UniformCartesianGrid(const UniformCartesianGrid<T,3>& gr) {
makeCopy(gr);
}
/**constructor
*@param ng a 3-Dim index vector that sets the partition
*/
template<class IV>
inline UniformCartesianGrid(const IV& ng) {setGrid(ng);}
///destructor
virtual inline ~UniformCartesianGrid() { }
///copy operator
UniformCartesianGrid<T,3>& operator=(const UniformCartesianGrid<T,3>& gr) {
makeCopy(gr);
return *this;
}
///copy function
inline void makeCopy(const UniformCartesianGrid<T,3>& gr) {
setGrid(gr.NP);
}
///return the number of grid in the i-th direction
inline int size(int i) const { return NP[i];}
/**set the parameters to partition a 3-Dim domain
*@param ng a 3-Dim index vector that sets the partition
*/
template<class IV>
void setGrid(const IV& ng) {
NumGrids = ng[0]*ng[1]*ng[2];
NP[0] = ng[0]; NP[1] = ng[1]; NP[2] = ng[2];
InvDelta[0] =static_cast<T>(ng[0]);
InvDelta[1] =static_cast<T>(ng[1]);
InvDelta[2] =static_cast<T>(ng[2]);
Delta[0] =1./InvDelta[0];
Delta[1] =1./InvDelta[1];
Delta[2] =1./InvDelta[2];
}
///return the total number of sub domains/grids
inline int getTotalNum() const { return NumGrids;}
/**get a unique key for a domain(i,j,k)
@param i the index of the first dimension
@param j the index of the second dimension
@param k the index of the third dimension
@return the key for a domain(i,j,k)
*/
inline int key(int i, int j, int k) const {
return k+NP[2]*(j+NP[1]*i);
}
/**get a index of a domain(i,j,k)
@param i the index of the first dimension
@param j the index of the second dimension
@param k the index of the third dimension
@return the storage index of a domain(i,j,k)
*/
inline int loc(int i, int j, int k) const {
return k+NP[2]*(j+NP[1]*i);
}
/**get a domain index of a 3-D vector v(x,y,z)
@param x the position in the first dimension
@param y the position in the second dimension
@param z the position in the third dimension
@return the storage index of a domain whose position is p(x,y,z)
*/
inline int loc(T x, T y, T z) const {
return int(z*InvDelta[2])+NP[2]*(int(y*InvDelta[1])+
NP[1]*int(x*InvDelta[0]));
}
/**get a domain index of a 3-D vector p
@param p a 3-D vector with operator[]
@return the storage index of a domain whose position is p
*/
template<class Pos_t>
inline
int loc(const Pos_t& p) const {
return
int(p[2]*InvDelta[2])
+NP[2]*(int(p[1]*InvDelta[1])+NP[1]*int(p[0]*InvDelta[0]));
}
/**get a 3-D index vector for a position r
*@param r the position
*@return a index vector containing the cell indices in the three directions
*/
inline TinyVector<int,3> index(const TinyVector<T,3>& r) {
return TinyVector<int,3>(static_cast<int>(r[0]*InvDelta[0]),
static_cast<int>(r[1]*InvDelta[1]),
static_cast<int>(r[2]*InvDelta[2]));
}
/**get a center position of a domain(i,j,k)
@param i the index of the first dimension
@param j the index of the second dimension
@param k the index of the third dimension
@return the position of the domain(i,j,k)
*/
inline TinyVector<T,3> center(int i, int j, int k) const {
return TinyVector<T,3>((static_cast<T>(i)+0.5)*Delta[0],
(static_cast<T>(j)+0.5)*Delta[1],
(static_cast<T>(k)+0.5)*Delta[2]);
}
/**distribute the domains over the processors
*@param ntot the total number of processors
*
*The processor can be a MPI node or an OpenMP thread.
*The domains are distributed over the processors as evenly as possible.
*However, the computataionl nodes are not factored in for load balancing.
*/
inline void distribute(int ntot) {
I.distribute(ntot,NumGrids);
}
/**distribute the domains over the processors [first, last)
*@param first iterator for the starting node
*@param last iterator for the ending node
*
*A similar function to the void distribute(int ntot).
*/
template <class _InputIterator>
void distribute(_InputIterator first, _InputIterator last) {
I.distribute(first,last);
}
/**print the domain partition information
*@param os ostream to write to
*
*This is for debug/test only.
*/
void printGrid(std::ostream& os) const {
const int nw = 15;
os << "number of sub regions " << NumGrids << endl;
os << "Attribute distribution = " << endl;
os << "grid spacing = " << setw(nw) << Delta[0] << setw(nw) << Delta[1]
<< setw(nw) << Delta[2] << endl;
TinyVector<T,3> origin;
for(int ig=0; ig<NP[0]; ig++) {
origin[0] = static_cast<T>(ig)*Delta[0];
for(int jg=0; jg<NP[1]; jg++) {
origin[1] = static_cast<T>(jg)*Delta[1];
for(int kg=0; kg<NP[2]; kg++) {
origin[2] = static_cast<T>(kg)*Delta[2];
os << setw(nw) << origin[0] << " | " << setw(nw) << origin[0]+Delta[0]
<< setw(nw) << origin[1] << " | " << setw(nw) << origin[1]+Delta[1]
<< setw(nw) << origin[2] << " | " << setw(nw) << origin[2]+Delta[2]
<< std::endl;
}
}
}
}
/** resize the grouping of domains
*@param ng the number of groups
*/
inline void resizeGroup(int ng) { PID.resize(ng);}
///return the processor ID of the group ig
inline int group(int ig) const { return PID[ig]; }
///assign the processor ID of the group ig
inline int& group(int ig) { return PID[ig];}
inline void createData() { I.create(NumGrids);}
inline void clearData() { I.clear(); }
inline void addData(int ig, int iat) {I.add(ig,iat);}
inline DistributedIndex& getDataSets() { return I;}
inline const DistributedIndex& getDataSets() const { return I;}
inline int getNumData() const {return I.getNumData();}
inline int getMaxDataPerGrid() const {return I.capacity();}
inline int getNumDataSets() const { return I.getNumDataSets();}
inline int firstData(int i) const { return I.M[i];}
inline int lastData(int i) const { return I.M[i+1];}
inline iterator beginData(int i) { return I.begin(i);}
inline iterator endData(int i) { return I.end(i);}
inline const_iterator beginData(int i) const { return I.begin(i);}
inline const_iterator endData(int i) const { return I.end(i);}
void printData(std::ostream& os) const {
I.print(os);
}
protected:
int NumGrids, NP[3];
T Delta[3],InvDelta[3];
DistributedIndex I;
std::vector<int> PID;
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,254 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_GRID_CONNECTION_H
#define OHMMS_GRID_CONNECTION_H
#include <vector>
#include <map>
#include <iostream>
using namespace std;
#include "Lattice/CrystalLattice.h"
/* \class GridConnection
\brief templated over scalar type, dimension and a key to
make connection list, similar to the nearest neighbor lists
*/
template<class T, unsigned D>
struct UniformGridConnection {};
// specialization
template<class T>
struct UniformGridConnection<T,3> {
typedef CrystalLattice<T,3> ParticleLayout_t;
typedef typename ParticleLayout_t::SingleParticlePos_t SingleParticlePos_t;
vector<int> M;
vector<int> ID;
vector<SingleParticlePos_t> BC;
UniformGridConnection() { }
//!< return the first mesh connected to the ig grid
inline int first(int ig) const { return M[ig];}
//!< return the last mesh connected to the ig grid
inline int last(int ig) const { return M[ig+1];}
//!< return the mesh index
inline int id(int j) const { return ID[j];}
//!< return the correction vector according to the boundary conditions
inline SingleParticlePos_t bc(int j) const { return BC[j];}
//!< return the maximum number of connected cells
inline int connect(const CrystalLattice<T,3>& Lattice, T rmax, int glevel) {
const typename ParticleLayout_t::PtclGrid_t& basegrid = *(Lattice.dGrid[glevel]);
SingleParticlePos_t u0(basegrid.Delta[0],0.0,0.0);
SingleParticlePos_t u1(0.0,basegrid.Delta[1],0.0);
SingleParticlePos_t u2(0.0,0.0,basegrid.Delta[2]);
T RmaxSq = rmax*rmax;
///calculate the extend of linked cells
int nx = static_cast<int>(sqrt(RmaxSq/Lattice.Dot(u0,u0)))+1;
int ny = static_cast<int>(sqrt(RmaxSq/Lattice.Dot(u1,u1)))+1;
int nz = static_cast<int>(sqrt(RmaxSq/Lattice.Dot(u2,u2)))+1;
M.resize(basegrid.getTotalNum()+1);
int ntot = basegrid.getTotalNum()*nx*ny*nz;
if(ID.size() < ntot) ID.reserve(ntot);
if(BC.size() < ntot) BC.reserve(ntot);
M[0] = 0;
int maxnc = 0;
SingleParticlePos_t dx(basegrid.Delta[0], basegrid.Delta[1], basegrid.Delta[2]);
///for each grid, search for connected grids
for(int ig=0; ig<basegrid.getTotalNum(); ig++) {
SingleParticlePos_t org(basegrid.Node[ig].Ri[0]+0.5*dx[0],
basegrid.Node[ig].Ri[1]+0.5*dx[1],
basegrid.Node[ig].Ri[2]+0.5*dx[2]),d;
T x,y,z;
int nconnected = 0;
for(int ix=-nx; ix<=nx; ix++) {
d[0] = x = org[0]+double(ix)*dx[0];
if(Lattice.BoxBConds[0]) {
x = fmod(d[0],1.0); if(x<0) x += 1.0;
}
if(x<0 || x>=1) continue;
d[0] -= x;
for(int jx=-ny; jx<=ny; jx++) {
d[1] = y = org[1]+double(jx)*dx[1];
if(Lattice.BoxBConds[1]) {
y = fmod(d[1],1.0); if(y<0) y += 1.0;
}
if(y<0 || y>=1) continue;
d[1] -= y;
for(int kx=-nz; kx<=nz; kx++) {
///exclude itself
if(ix == 0 && jx == 0 && kx == 0) continue;
d[2] = z = org[2]+double(kx)*dx[2];
if(Lattice.BoxBConds[2]) {
z = fmod(d[2],1.0); if(z<0) z += 1.0;
}
if(z<0 || z>=1) continue;
d[2] -= z;
ID.push_back(basegrid.loc(x,y,z));
BC.push_back(Lattice.toCart(d));
nconnected++;
}
}
}
M[ig+1] = M[ig]+nconnected;
maxnc = max(maxnc,nconnected);
}
// //for each grid, search for connected grid
// for(int ig=0; ig<basegrid.getTotalNum(); ig++) {
// cout << ig << " has " << M[ig+1]-M[ig] << endl;
// for(int j=M[ig]; j<M[ig+1]; j++) {
// cout << ID[j] << " " << BC[j] << endl;
// }
// }
return maxnc; // return the maxmimum number of connected cells
}
/*** Extremely inefficient: using the new method above
inline int connect(const CrystalLattice<T,3>& Lattice, T rmax, int glevel) {
T RmaxSq = rmax*rmax;
SingleParticlePos_t u0(1.0,0.0,0.0);
SingleParticlePos_t u1(0.0,1.0,0.0);
SingleParticlePos_t u2(0.0,0.0,1.0);
int maxx1 = static_cast<int>(sqrt( RmaxSq/Lattice.Dot(u0,u0))) + 1;
int maxx2 = static_cast<int>(sqrt( RmaxSq/Lattice.Dot(u1,u1))) + 1;
int maxx3 = static_cast<int>(sqrt( RmaxSq/Lattice.Dot(u2,u2))) + 1;
if(!Lattice.BoxBConds[0]) maxx1 = 0;
if(!Lattice.BoxBConds[1]) maxx2 = 0;
if(!Lattice.BoxBConds[2]) maxx3 = 0;
// using multimap to sort image cells
multimap<int,SingleParticlePos_t> N;
// add the origin
N.insert(pair<int,SingleParticlePos_t>(0,SingleParticlePos_t(0.0)));
//summation over the direct lattice
for(int ix1=-maxx1; ix1<=maxx1; ix1++) {
for(int ix2=-maxx2; ix2<=maxx2; ix2++) {
for(int ix3=-maxx3; ix3<=maxx3; ix3++) {
if(ix1 == 0 && ix2 == 0 && ix3 == 0) continue;
SingleParticlePos_t xlp(static_cast<T>(ix1),
static_cast<T>(ix2),
static_cast<T>(ix3));
// using ix1^2+ix2^2+ix3^3 as key to sort the image cells
N.insert(pair<int,SingleParticlePos_t>(ix1*ix1+ix2*ix2+ix3*ix3, xlp));
}
}
}
const typename ParticleLayout_t::PtclGrid_t&
basegrid = *(Lattice.dGrid[glevel]);
SingleParticlePos_t dx(1.0/basegrid.Delta[0],
1.0/basegrid.Delta[1],
1.0/basegrid.Delta[2]);
int maxnc = 0;
M.resize(basegrid.getTotalNum()+1);
int ntot = basegrid.getTotalNum()*N.size();
if(ID.size() < ntot) ID.reserve(ntot);
if(BC.size() < ntot) BC.reserve(ntot);
M[0] = 0;
//for each grid, search for connected grid
for(int ig=0; ig<basegrid.getTotalNum(); ig++) {
SingleParticlePos_t org(basegrid.Node[ig].Ri[0],
basegrid.Node[ig].Ri[1],
basegrid.Node[ig].Ri[2]);
typename multimap<int,SingleParticlePos_t>::iterator it = N.begin();
int ibox = 0;
int nconnected = 0;
while(it != N.end()) {
SingleParticlePos_t displ = (*it).second;
for(int jg=0; jg<basegrid.getTotalNum(); jg++) {
if(ibox == 0 && ig == jg) continue; // exclude itself
SingleParticlePos_t nncell(basegrid.Node[jg].Ri[0]+displ[0],
basegrid.Node[jg].Ri[1]+displ[1],
basegrid.Node[jg].Ri[2]+displ[2]);
SingleParticlePos_t dcell = nncell-org;
int icx = int(fabs(dcell[0]*dx[0]));
int icy = int(fabs(dcell[1]*dx[1]));
int icz = int(fabs(dcell[2]*dx[2]));
bool connected = false;
if(icx <= 1 && icy <= 1 && icz <= 1) {
connected = true; // next cells are always included
} else {
if(Lattice.Dot(dcell,dcell) <= 4*RmaxSq) connected = true;
}
if(connected) {
ID.push_back(jg);
BC.push_back(Lattice.toCart(displ));
nconnected++; // number of connected cells for a mesh
}
}
it++; ibox++;
}
maxnc = max(nconnected,maxnc);
M[ig+1] = M[ig] + nconnected;
}
return maxnc; // return the maxmimum number of connected cells
}
*/
void print(ostream& os) {
for(int ig=0; ig<M.size()-1; ig++) {
cout << ig << " has neighboring cell " << M[ig+1]-M[ig]<< endl;
for(int ii=M[ig]; ii<M[ig+1]; ii++) {
cout << ID[ii] << " " << BC[ii] << endl;
}
}
}
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,265 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003- by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_UNIFORMGRIDLAYOUT_H
#define OHMMS_UNIFORMGRIDLAYOUT_H
#include "Lattice/CrystalLattice.h"
#include "Lattice/UniformCartesianGrid.h"
#include <iostream>
/**@file UniformGridLayout.h
*@brief Declaration of UniformGridLayout<T,D>
*/
/** generic UniformGridLayout. Do nothing.
*/
template<class T, unsigned D>
struct UniformGridLayout: public CrystalLattice<T,D>,
public UniformCartesianGrid<T,D>{ };
/** specialization of UniformGridLayout<T,3> for 3-Dim layout
*
*This class represents a supercell and is one of the layout classes
*to define a trait class PT for ParticleBase<PT> (as a matter of fact,
*the only layout class implemented in ohmms).
*
*It is inherited from CrystalLattice<T,3> and
*UniformCartesianGrid<T,3>: CrystalLattice defines a general
*supercell and UniformCartesianGrid defines a cubic-cell view of a
*general supercell. This layout class is intended for typical
*condensed matter or molecular systems, where a uniform grid partition
*works fairly well.
*
*The additional interfaces of UniformGridLayout class are primarily
*for NNEngine classes, which use the parition information to evaluate
*the neighbor lists efficiently.
*
*/
template<class T>
class UniformGridLayout<T,3>: public CrystalLattice<T,3>,
public UniformCartesianGrid<T,3>
{
public:
/**enumeration for grid levels*/
enum {MPI_GRID = 0, /*!< mpi level */
OMP_GRID, /*!< open mp level */
SPATIAL_GRID, /*!< spatial level */
GridLevel = 3 /*!< counter used to tell the number of levels */
};
typedef CrystalLattice<T,3> Base_t;
typedef UniformCartesianGrid<T,3> Grid_t;
typedef UniformGridLayout<T,3> This_t;
typedef typename Base_t::SingleParticlePos_t SingleParticlePos_t;
typedef typename Base_t::SingleParticleIndex_t SingleParticleIndex_t;
/**default constructor
*
*Create 1x1x1 cubic view for a supercell assuming that no
*parallelization is used.
*/
inline UniformGridLayout(){
for(int i=0; i<GridLevel; i++) Grid[i] = SingleParticleIndex_t(1);
SuperGrid.reserve(GridLevel);
for(int i=0; i<GridLevel; i++) SuperGrid.push_back(NULL);
}
inline ~UniformGridLayout(){
for(int i=0; i<SuperGrid.size(); i++)
if(SuperGrid[i]) delete SuperGrid[i];
}
///return the first cell connected to the ig cell
inline int first_connected(int ig) const { return c_offset[ig];}
///return the last cell connected to the ig cell
inline int last_connected(int ig) const { return c_offset[ig+1];}
/// return the cell index
inline int id_connected(int j) const { return c_id[j];}
/// return the correction vector according to the boundary conditions
inline SingleParticlePos_t bc(int j) const { return c_bc[j];}
/// return the total number of paritions
inline int ncontexts() const { return c_offset.size()-1;}
/// return the maximum number of connected cells
int connectGrid(T rmax);
template<class GIM>
inline void makeGrid(const GIM& mgrid) {
if(mgrid.size() < GridLevel) {
Grid[SPATIAL_GRID] = mgrid.back();
} else {
for(int ig=0; ig<GridLevel; ig++) Grid[ig] = mgrid[ig];
}
///first build the spatial grid
setGrid(Grid[SPATIAL_GRID]);
}
inline Grid_t* restrict
addGrid(int glevel, const SingleParticleIndex_t& agrid) {
if(SuperGrid[glevel]) {
SuperGrid[glevel]->setGrid(agrid);
return SuperGrid[glevel];
} else {
Grid_t* g = new Grid_t(agrid);
SuperGrid[glevel] = g;
return g;
}
}
inline Grid_t* restrict getGrid(int glevel) { return SuperGrid[glevel];}
inline const Grid_t* restrict getGrid(int glevel) const {
return SuperGrid[glevel];
}
inline int ngrid(int ig) const { return Grid[SPATIAL_GRID][ig];}
inline int ngrid(int glevel, int ig) const { return Grid[glevel][ig];}
void print(std::ostream& os) const;
inline void update() {
for(int i=0; i<u_bc.size(); i++) c_bc.push_back(u_bc[i]);
}
/** set the lattice vector with a tensor
*@param lat a tensor representing a supercell
*
*In addition to setting the internal parameters, it updates the Cartesian displacement vectors.
*/
inline void update(const Tensor<T,3>& lat) {
CrystalLattice<T,3>::set(lat);
for(int i=0; i<u_bc.size(); i++) c_bc.push_back(u_bc[i]);
}
private:
///Uniform grid partitions at MPI_GRID, OPENMP_GRID, and SPATIAL_GRID levels.
SingleParticleIndex_t Grid[GridLevel];
///UniformCartesianGrid for multi levels.
std::vector<Grid_t*> SuperGrid;
///offsets to determine cell conection
std::vector<int> c_offset;
///cell index connected to each cell
std::vector<int> c_id;
///displacement vectors due to the boundary conditions
std::vector<SingleParticlePos_t> c_bc;
///displacement vectors due to the boundary conditions in the unit-cell unit
std::vector<SingleParticlePos_t> u_bc;
};
template<class T>
int
UniformGridLayout<T,3>::connectGrid(T rmax) {
///create the spatial grid
setGrid(Grid[SPATIAL_GRID]);
SingleParticlePos_t u0(Delta[0],0.0,0.0);
SingleParticlePos_t u1(0.0,Delta[1],0.0);
SingleParticlePos_t u2(0.0,0.0,Delta[2]);
T RmaxSq = rmax*rmax;
///calculate the extend of linked cells
int nx = static_cast<int>(sqrt(RmaxSq/Dot(u0,u0)))+1;
int ny = static_cast<int>(sqrt(RmaxSq/Dot(u1,u1)))+1;
int nz = static_cast<int>(sqrt(RmaxSq/Dot(u2,u2)))+1;
c_offset.resize(NumGrids+1);
int ntot = NumGrids*(2*nx+1)*(2*ny+1)*(2*nz+1);
if(c_id.capacity() < ntot) c_id.reserve(ntot);
if(c_bc.capacity() < ntot) c_bc.reserve(ntot);
if(u_bc.capacity() < ntot) u_bc.reserve(ntot);
int maxnc = 0, gtot = 0;
SingleParticlePos_t dx(Delta[0],Delta[1],Delta[2]),org,d;
c_offset[0] = 0;
for(int ig=0; ig<NP[0]; ig++) {
org[0] = (static_cast<T>(ig)+0.5)*Delta[0];
for(int jg=0; jg<NP[1]; jg++) {
org[1] = (static_cast<T>(jg)+0.5)*Delta[1];
for(int kg=0; kg<NP[2]; kg++) {
org[2] = (static_cast<T>(kg)+0.5)*Delta[2];
T x,y,z;
int nconnected = 0;
for(int ix=-nx; ix<=nx; ix++) {
d[0] = x = org[0]+T(ix)*dx[0];
if(BoxBConds[0]) {
x = fmod(d[0],1.0);
if(x<0.0) x += 1.0;
}
if(x<0 || x>=1) continue;
d[0] -= x;
for(int jx=-ny; jx<=ny; jx++) {
d[1] = y = org[1]+T(jx)*dx[1];
if(BoxBConds[1]) {
y = fmod(d[1],1.0); if(y<0) y += 1.0;
}
if(y<0 || y>=1) continue;
d[1] -= y;
for(int kx=-nz; kx<=nz; kx++) {
d[2] = z = org[2]+T(kx)*dx[2];
if(BoxBConds[2]) {
z = fmod(d[2],1.0); if(z<0) z += 1.0;
}
if(z<0 || z>=1) continue;
d[2] -= z;
int iloc = loc(x,y,z);
if(iloc == gtot && ix == 0 && jx == 0 && kx == 0) continue;
c_id.push_back(iloc);
u_bc.push_back(d);
c_bc.push_back(toCart(d));
nconnected++;
}
}
}
c_offset[gtot+1] = c_offset[gtot]+nconnected; gtot++;
maxnc = max(maxnc,nconnected);
}
}
}
return maxnc; // return the maxmimum number of connected cells
}
template<class T>
void UniformGridLayout<T,3>::print(std::ostream& os) const {
Base_t::print(os);
printGrid(os);
for(int ig=0; ig<c_offset.size()-1; ig++) {
os << ig << " has neighboring cell "
<< c_offset[ig+1]-c_offset[ig]<< std::endl;
for(int ii=c_offset[ig]; ii<c_offset[ig+1]; ii++) {
os << c_id[ii] << " " << c_bc[ii] << std::endl;
}
}
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,49 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#include "Message/CommCreate.h"
// initialize static data members
int TagMaker::CurrentTag = 1000;
Communicate* CommCreate::Comm =0;
Communicate* CommCreate::get() {
if(!Comm) {
Comm = new Communicate;
}
return Comm;
}
Communicate* CommCreate::get(int argc, char **argv) {
if(!Comm) {
Comm = new Communicate(argc,argv);
}
return Comm;
}
void CommCreate::remove() {
if(Comm) delete Comm;
Comm = 0;
}
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

50
src/Message/CommCreate.h Normal file
View File

@ -0,0 +1,50 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_COMMCREATE_H
#define OHMMS_COMMCREATE_H
#include "Message/TagMaker.h"
#include "Message/Communicate.h"
#ifdef USE_MPI
#include <mpi.h>
#endif
/*!\class CommCreate
* \brief Singleton Pattern to create one instance of Communicate
* during a run.
*/
class CommCreate {
public:
static Communicate* get();
static Communicate* get(int, char**);
static void remove();
private:
// factory
CommCreate() { }
~CommCreate() { }
static Communicate* Comm;
};
#endif // OHMMS_COMMCREATE_H
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

100
src/Message/Communicate.cpp Normal file
View File

@ -0,0 +1,100 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#include "Message/Communicate.h"
#include "Message/TagMaker.h"
//static data of TagMaker::CurrentTag is initialized.
int TagMaker::CurrentTag = 1000;
//Global Communicator is created without initialization
Communicate* OHMMS::Controller = new Communicate;
//default constructor: ready for a serial execution
Communicate::Communicate():d_mycontext(0), d_ncontexts(1), CommID(0){}
Communicate::Communicate(int argc, char **argv){
initialize(argc,argv);
}
//exclusive: OOMPI, MPI or Serial
#ifdef USE_OOMPI
//================================================================
// Implements Communicate with OOMPI library
//================================================================
#include "oompi.h"
Communicate::~Communicate(){ }
void Communicate::initialize(int argc, char **argv){
OOMPI_COMM_WORLD.Init(argc, argv);
d_mycontext = OOMPI_COMM_WORLD.Rank();
d_ncontexts = OOMPI_COMM_WORLD.Size();
CommID = OOMPI_COMM_WORLD.Get_mpi();
}
void Communicate::finalize() {
OOMPI_COMM_WORLD.Finalize();
}
void Communicate::cleanupMessage(void*) { }
#else
#ifdef USE_MPI
//================================================================
// Implements Communicate with standard MPI library
//================================================================
#include <mpi.h>
Communicate::~Communicate(){ }
void Communicate::initialize(int argc, char **argv){
int flag;
MPI_Initialized(&flag);
if(!flag) {
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&d_ncontexts);
MPI_Comm_rank(MPI_COMM_WORLD,&d_mycontext);
CommID = MPI_COMM_WORLD;
}
}
void Communicate::finalize(){
MPI_Finalize();
}
void Communicate::cleanupMessage(void*) { }
#else //USE_MPI
Communicate::~Communicate(){}
void Communicate::initialize(int argc, char **argv){ }
void Communicate::finalize(){ }
void Communicate::cleanupMessage(void*) { }
#endif // !USE_MPI
#endif // !USE_OOMPI
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

84
src/Message/Communicate.h Normal file
View File

@ -0,0 +1,84 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_COMMUNICATE_H
#define OHMMS_COMMUNICATE_H
/**@class Communicate
* @ingroup Message
* @brief
* Wrapping information on parallelism.
* Very limited in functions. Currently, only single-mode or mpi-mode
* is available (mutually exclusive).
* @todo Possibly, make it a general manager class for mpi+openmp, mpi+mpi
*/
class Communicate {
public:
///constructor
Communicate();
///constructor with arguments
Communicate(int argc, char **argv);
/**destructor
* Call proper finalization of Communication library
*/
virtual ~Communicate();
void initialize(int argc, char **argv);
void finalize();
///return the Communicator ID (typically MPI_WORLD_COMM)
inline int getID() const { return CommID;}
///return the rank of this node
inline int getNodeID() const { return d_mycontext;}
inline int mycontext() const { return d_mycontext;}
///return the number of nodes
inline int getNumNodes() const { return d_ncontexts;}
inline int ncontexts() const { return d_ncontexts;}
inline bool master() const { return (d_mycontext == 0);}
void cleanupMessage(void*);
inline void setNodeID(int i) { d_mycontext = i;}
inline void setCommID(int i) { CommID = i;}
protected:
int CommID;
int d_mycontext;
int d_ncontexts;
};
namespace OHMMS {
/** Global Communicator for a process
*/
extern Communicate* Controller;
}
#endif // OHMMS_COMMUNICATE_H
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

7
src/Message/Makefile Normal file
View File

@ -0,0 +1,7 @@
$(ODIR)/Communicate.o: $(OHMMSDIR)/src/Message/Communicate.cpp
$(CXX) $(CXXFLAGSAPP) $(OHMMSINC) -c \
$(OHMMSDIR)/src/Message/Communicate.cpp -o $(ODIR)/Communicate.o
$(ODIR)/CommCreate.o: $(OHMMSDIR)/src/Message/CommCreate.cpp
$(CXX) $(CXXFLAGSAPP) $(OHMMSINC) -c \
$(OHMMSDIR)/src/Message/CommCreate.cpp -o $(ODIR)/CommCreate.o

31
src/Message/OpenMP.h Normal file
View File

@ -0,0 +1,31 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim
//
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_OPENMP_H
#define OHMMS_OPENMP_H
#if defined(USE_OPENMP)
#include <omp.h>
#else
inline int omp_get_thread_num() { return 0;}
#endif
#endif // OHMMS_COMMUNICATE_H
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,307 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
#include <mpi.h>
#include "Message/ReplicaControl.h"
extern "C" {
#include <unistd.h>
#include <sys/types.h>
#include <sys/times.h>
#include <sys/time.h>
}
ReplicaControl::ReplicaControl() {
//MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&NumReplica);
MPI_Comm_rank(MPI_COMM_WORLD,&ReplicaID);
TotMD_t = 0.0e0;
TotHMD_t = 0.0e0;
}
ReplicaControl::ReplicaControl(int argc, char **argv) {
//MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&NumReplica);
MPI_Comm_rank(MPI_COMM_WORLD,&ReplicaID);
TotMD_t = 0.0e0;
TotHMD_t = 0.0e0;
}
void resize(int n) {
if(WallClockTime.size() < n) {
WallClockTime.erase(WallClockTime.begin(), WallClockTime.end());
MDTime.erase(MDTime.begin(), MDTime.end());
HMDTime.erase(HMDTime.begin(), HMDTime.end());
WallClockTime = vector<double>(2*n,0.0e0);
MDTime = vector<double>(2*n,0.0e0);
HMDTime = vector<double>(2*n,0.0e0);
}
}
ReplicaControl::~ReplicaControl() {
}
bool
ReplicaControl::send(ParticlePos_t& p, int node, int btag, bool bcast){
if(bcast) { // broadcasting positions to all the nodes
int size = OHMMS_DIM*newp.size();
int ierr = MPI_Bcast(&p[0][0], size, MPI_DOUBLE, ReplicaID, btag,
MPI_COMM_WORLD);
return true;
} else {
if(node < 0) return true; // do nothing
MPI_Request request;
int size = OHMMS_DIM*p.size();
int errstat = MPI_Isend(&p[0][0], size, MPI_DOUBLE, node, btag,
MPI_COMM_WORLD, &request);
return true;
}
return false;
}
bool
ReplicaControl::recv(ParticlePos_t& p, int& node, int btag) {
{
int size = OHMMS_DIM*p.size();
MPI_Request request;
MPI_Status status;
MPI_Irecv(&p[0][0], size, node, btag, MPI_COMM_WORLD, &request);
bool flag = false;
while (!flag) {
MPI_Test(&request, &flag, &status);
}
return true;
}
bool ReplicaControl::sendDirections(int& inode){
int msg[2];
if(inode < 0) {
msg[0] = PARMD::finalize_tag;
MPI_Bcast(&msg[0], 1, MPI_INT, ReplicaID,PARMD::command_tag,MPI_COMM_WORLD);
return true;
}
MPI_Request request;
MPI_Status status;
msg[0] = PARMD::winner_tag;
msg[1] = PARMD::losers_tag;
bool flag = false;
for(int i=1; i<NumReplica; i++) {
if(i == inode) {
MPI_Isend(&msg[0],1,MPI_INT,i,PARMD::command_tag,
MPI_COMM_WORLD, &request);
} else {
MPI_Isend(&msg[1],1,MPI_INT,i,PARMD::command_tag,
MPI_COMM_WORLD, &request);
}
flag = false;
while (!flag) {
MPI_Test(&request, &flag, &status);
}
}
return true;
}
int ReplicaControl::recvDirections() {
int whattodo;
MPI_Request request;
MPI_Status status;
MPI_Irecv(&whattodo, 1, MPI_INT, 0, PARMD::command_tag,
MPI_COMM_WORLD, &request);
bool flag = false;
while (!flag) {
MPI_Test(&request, &flag, &status);
}
return whatodo;
}
bool ReplicaControl::reportTransition(double drsq){ //slaves
double newdata[2];
MPI_Request request;
newdata[0] = WallClockTime[FrameNum];
newdata[1] = drsq;
MPI_Isend(newdata,2,MPI_DOUBLE,0,PARMD::transition, MPI_COMM_WORLD, &request);
return true;
}
void ReplicaControl::catchTransition(int& remNode, double& wallt, double& rsqmax){ // master
double newdata[2];
static MPI_Request request;
static MPI_Status status;
static bool flag = true;
remNode = -1;
if(flag) { // initiate recv
DEBUGMSG("Open a channel to catch the transition\n");
MPI_Irecv(newdata, 2, MPI_INT, MPI_ANY_SOURCE,
PARMD::transition_tag, MPI_COMM_WORLD, &request);
flag = false;
}
MPI_Test(&request, &flag, &status);
if(flag) { // a transition is reported
wallt = newdata[0];
rsqmax = newdata[1];
remNode = status.MPI_SOURCE; // copy the remote node
}
}
bool ReplicaControl::sendTransitionTime(double t0){
MPI_Bcast(&t0, 1, MPI_DOUBLE, ReplicaID, PARMD::stop_tag, MPI_COMM_WORLD);
return true;
}
bool ReplicaControl::recvTransitionTime(double& t0) {
double trecv = 0;
MPI_Status status;
MPI_Recv(&trecv, 1, MPI_DOUBLE, 0, PARMD::stop_tag, MPI_COMM_WORLD, &status);
t0 = trecv;
return true;
}
bool ReplicaControl::sendExactTime(double wallt, bool havewon) {
int masternode = 0;
double newtime[3];// vector<double> newtime(3);
if(havewon) {
newtime[0] = MDTime[FrameNum];
newtime[1] = WallClockTime[FrameNum];
} else {
int iframe=FrameNum;
while(WallClockTime[iframe] >= wallt && iframe > 0){
iframe--;
}
newtime[0] = MDTime[iframe];
newtime[1] = WallClockTime[iframe];
}
MPI_Request request;
MPI_Isend(newtime,3,MPI_DOUBLE,0,PARMD::exacttime_tag, MPI_COMM_WORLD, &request);
}
void ReplicaControl::collectExactTimes(int itrans, double t0) {
MPI_Status status;
MPI_Request request;
int btag = PARMD::exacttime_tag;
int numrecvd = NumReplica-1;
double newtime[3];
bool flag;
CumMD_t = t0; // constant time to be added to a new cumm. time
while(numrecvd > 0) {
MPI_Irecv(newtime, 3, MPI_DOUBLE, MPI_ANY_SOURCE,
PARMD::exacttime_tag, MPI_COMM_WORLD, &request);
flag = false;
while(!false) {MPI_Test(&request, &flag, &status);}
CumMD_t += newtime[0];
numrecvd--;
}
MDTime[itrans] = CumMD_t;
TotMD_t += CumMD_t;
}
void ReplicaControl::reportTimeData(ostream& os,int i_trans){
os << setw(18) << MDTime[i_trans] << setw(18) << TotMD_t << " ";
}
// bool ReplicaControl::sendNewConfig(ParticlePos_t& newp){
// int size = OHMMS_DIM*newp.size();
// MPI_Bcast(&newp[0][0], size, MPI_DOUBLE, ReplicaID, PARMD_newconfig_tag,
// MPI_COMM_WORLD);
// return true;
// }
// void ReplicaControl::recvNewConfig(ParticlePos_t& newp){
// int btag = PARMD_newconfig_tag;
// int size = OHMMS_DIM*newp.size();
// MPI_Request request;
// MPI_Status status;
// int masternode = 0;
// MPI_Irecv(&newp[0][0], size, masternode, btag, MPI_COMM_WORLD, &request);
// bool flag = false;
// while (!flag) {
// MPI_Test(&request, &flag, &status);
// }
// }
// bool ReplicaControl::sendMinConfig(ParticlePos_t& minp) {
// MPI_Request request;
// MPI_Status status;
// int size = OHMMS_DIM*newp.size();
// int errstat = MPI_Isend(&minp[0][0], size, MPI_DOUBLE, 0, PARMD_minconfig_tag,
// MPI_COMM_WORLD, &request);
// return true;
// }
// void ReplicaControl::recvMinConfig(ParticlePos_t& minp, int& inode) {
// int btag = PARMD_minconfig_tag;
// int size = OHMMS_DIM*newp.size();
// MPI_Request request;
// MPI_Status status;
// MPI_Irecv(&newp[0][0], size, inode, btag, MPI_COMM_WORLD, &request);
// bool flag = false;
// while (!flag) {
// MPI_Test(&request, &flag, &status);
// }
// }
// void ReplicaControl::makeNodeConnection(const char *opt) {
// if(!strcmp(opt,"chain")) {
// RightNode =ReplicaID+1;
// LeftNode = RightNode-2;
// if(RightNode == NumReplica) RightNode = -1; // not periodic
// }
// }
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,133 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// ReplicaControl using MPI
// Responsible for book keeping for parallel replica with or without hmd
// Using timer routines of Parmd7, Art Voter
///////////////////////////////////////////////////////////////////////////
#ifndef OHMMS_REPLICACONTROL_H
#define OHMMS_REPLICACONTROL_H
#include <vector>
using std::vector;
#include "Particle/OhmmsParticle.h"
#include "Message/Communicate.h"
namespace PARMD {
const int transition_tag = 10;
const int exacttime_tag = 11;
const int newconfig_tag = 12;
const int minconfig_tag = 13;
const int command_tag = 14;
const int stop_tag = 15;
const int pluscycle_tag = 16;
const int minuscycle_tag = 17;
const int winner_tag = 1;
const int losers_tag = 0;
const int noevent_tag = -1;
const int finalize_tag = 99;
}
class ReplicaControl {
public:
typedef OHMMS::Particle_t::ParticlePos_t ParticlePos_t;
enum ReplicaTags { NEWPOS, CUMTIME, TRANSITION};
//Communicate* OhmmsComm;
ReplicaControl();
ReplicaControl(int, char**);
~ReplicaControl();
void init(int nproc); // number of processors to
inline int getNumNodes() const {OhmmsComm->getNumNodes();}
inline int getNodeID() const {OhmmsComm->getNodeID();}
inline bool master() const { return OhmmsComm->master();}
// Time-related funtions
inline void saveMDTime(double nowT, double wallt, int iframe){
FrameNum = iframe; // match the frame index
WallClockTime[FrameNum] = wallt;
MDTime[FrameNum] = nowT;
}
inline double getWallClockTime() { return WallClockTime[FrameNum];}
void resetTimer() { // for each transition, reset parameters
FrameNum = 0;
CumMD_t = 0.0e0;
CumHMD_t = 0.0e0;
}
bool send(const ParticlePos_t&, int node, int tag, bool bcast=false);
bool recv(ParticlePos_t&, int& node, int tag);
// // send/recv of new configurations
// bool sendNewConfig(ParticlePos_t& );
// void recvNewConfig(ParticlePos_t& );
// // send/recv of a mininum configurations
// bool sendMinConfig(ParticlePos_t& minp);
// void recvMinConfig(ParticlePos_t& minp, int& inode);
// bool sendNextNode(ParticlePos_t& , int );
// bool recvNextNode(ParticlePos_t& , int );
// send/irecv of the transition time
bool reportTransition(double);
void catchTransition(int& inode, double&, double&);
// send transition time if a transition is detected
// "the" master sends the first-in transition wall-clock time to slaves
bool sendTransitionTime(double );
bool recvTransitionTime(double&);
// sends MD time at the wall-clock time when the winner found a transition
// "the" master collect MD times sent from all other nodes
bool sendExactTime(double, bool havewon = false );
void collectExactTimes(int itrans, double t0);
bool sendDirections(int& winner);
int recvDirections();
void reportTimeData(ostream& ,int itrans);
void resize(int n);
protected:
int NumReplica;
vector<int> ReplicaID;
double CumMD_t, CumHMD_t; // cummulative time over replica
double TotMD_t, TotHMD_t; // total time
int FrameNum;
int LeftNode, RightNode;
vector<double> WallClockTime; // wall-clock time
vector<double> MDTime; // mdtime
vector<double> HMDTime; // hyper time will be added
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* POOMA_VERSION_ID: $Id$
***************************************************************************/

View File

@ -0,0 +1,123 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
#include "Message/ReplicaControl.h"
extern "C" {
#include <unistd.h>
#include <sys/types.h>
#include <sys/times.h>
#include <sys/time.h>
}
// instantiate the Communicator
//Communicate* ReplicaControl::OhmmsComm = new Communicate;
ReplicaControl::ReplicaControl() {
ReplicaID = vector<int>(1);
NumReplica = OhmmsComm->getNumNodes();
ReplicaID[0] = OhmmsComm->getNodeID();
TotMD_t = 0.0e0;
TotHMD_t = 0.0e0;
}
ReplicaControl::ReplicaControl(int argc, char **argv) {
ReplicaID = vector<int>(1);
NumReplica = OhmmsComm->getNumNodes();
ReplicaID[0] = OhmmsComm->getNodeID();
TotMD_t = 0.0e0;
TotHMD_t = 0.0e0;
}
void ReplicaControl::init(int nproc){
if(nproc != ReplicaID.size()) {
ReplicaID = vector<int>(nproc);
for(int i=0; i<nproc; i++) ReplicaID[i] = i;
}
} // number of processors to
void ReplicaControl::resize(int n) {
if(WallClockTime.size() < n) {
WallClockTime.erase(WallClockTime.begin(), WallClockTime.end());
MDTime.erase(MDTime.begin(), MDTime.end());
HMDTime.erase(HMDTime.begin(), HMDTime.end());
WallClockTime = vector<double>(2*n,0.0e0);
MDTime = vector<double>(2*n,0.0e0);
HMDTime = vector<double>(2*n,0.0e0);
}
}
bool ReplicaControl::send(const ParticlePos_t& p, int node, int btag, bool bcast)
{
return true;
}
bool
ReplicaControl::recv(ParticlePos_t& p, int& node, int btag)
{
return true;
}
bool ReplicaControl::sendDirections(int& inode){
return true;
}
int ReplicaControl::recvDirections() {
return 0;
}
bool ReplicaControl::reportTransition(double drsq){ //slaves
return true;
}
void ReplicaControl::catchTransition(int& remNode, double& wallt, double& rsqmax){ // master
}
bool ReplicaControl::sendTransitionTime(double t0){
return true;
}
bool ReplicaControl::recvTransitionTime(double& t0) {
return true;
}
bool ReplicaControl::sendExactTime(double wallt, bool havewon) {
return true;
}
void ReplicaControl::collectExactTimes(int itrans, double t0) {
}
void ReplicaControl::reportTimeData(ostream& os,int i_trans){
os << setw(18) << MDTime[i_trans] << setw(18) << TotMD_t << " ";
}
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* POOMA_VERSION_ID: $Id$
***************************************************************************/

40
src/Message/TagMaker.h Normal file
View File

@ -0,0 +1,40 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_TAG_MAKER_H
#define OHMMS_TAG_MAKER_H
/*!\class TagMaker
* \brief Assign a unique tag whenver TagMaker::TagMaker() is called.
*/
class TagMaker {
public:
TagMaker(){ MyTag = (++CurrentTag);}
~TagMaker() {}
int operator()()const { return MyTag;}
private:
int MyTag;
static int CurrentTag;
};
#endif // OHMMS_TAG_MAKER_H
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

137
src/Numerics/Blasf.h Normal file
View File

@ -0,0 +1,137 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
#ifndef OHMMS_BLAS_FUNCTIONDEFS_H
#define OHMMS_BLAS_FUNCTIONDEFS_H
#include <complex>
using namespace std;
#ifdef ADD_
#define daxpy daxpy_
#define saxpy saxpy_
#define zaxpy zaxpy_
#define dnrm2 dnrm2_
#define snrm2 snrm2_
#define dznrm2 dznrm2_
#define dsymv dsymv_
#define ssymv ssymv_
#define csymv csymv_
#define zsymv zsymv_
#define ddot ddot_
#define sdot sdot_
#define dscal dscal_
#define dcopy dcopy_
#define zcopy zcopy_
#define dsyrk dsyrk_
#define dsymm dsymm_
#define dgemm dgemm_
#define dsyr2k dsyr2k_
#define dgetrf dgetrf_
#define dgetri dgetri_
#define zgetrf zgetrf_
#define zgetri zgetri_
#endif
// declaring Fortran interfaces
extern "C" {
double ddot(const int& n, const double *dx, const int& incx, const double *dy, const int &incy);
float sdot(const int& n, const float *dx, const int& incx, const float *dy, const int &incy);
void daxpy(const int& n, const double& da,
const double *dx, const int& incx, double *dy, const int& incy);
void saxpy(const int& n, const float& da,
const float *dx, const int& incx, float *dy, const int& incy);
void zaxpy(const int& n, const complex<double>& da, const complex<double> *dx,
const int& incx, complex<double> *dy, const int& incy);
double dnrm2(const int& n, const double *dx, const int& incx);
float snrm2(const int& n, const float *dx, const int& incx);
double dznrm2(const int& n, const complex<double> *dx, const int& incx);
double dscal(const int& n, const double&, double* x, const int&);
void dsymv(const char& uplo, const int& n, const double& alpha,
const double& a, const int& lda, const double* x, const int& incx,
const double& beta, double *y, const int& incy);
void ssymv(const char& uplo, const int& n, const float& alpha,
const float& a, const int& lda,
const float* x, const int& incx,
const float& beta, float *y, const int& incy);
void zsymv(const char& uplo, const int& n, const complex<double>& alpha,
complex<double>* a, const int& lda, complex<double>* x,
const int& incx, const complex<double>& beta,
complex<double> *y, const int& incy);
void csymv(const char& uplo, const int& n, const complex<float>& alpha,
complex<float>* a, const int& lda, complex<float>* x,
const int& incx, const complex<float>& beta,
complex<float> *y, const int& incy);
void zcopy(const int& n, const complex<double>* x,
const int& incx, complex<double>* y, const int& incy);
void dcopy(const int& n, const double*, const int& , double *, const int&);
void dsyr2k(const char&, const char&, const int&, const int&,
const double&, const double*, const int&,
const double*, const int&,
const double&, double*, const int&);
void dsymm(const char&, const char&, const int&, const int&, const double&,
const double* A, const int& lda,
const double* B, const int& ldb,
const double& beta, double* C, const int& ldc );
void dgemm(const char&, const char&,
const int&, const int&, const int&,
const double&, const double*, const int&, const double*, const int&,
const double&, double*, const int&);
void dsyrk(const char&, const char&, const int&, const int&,
const double&, const double*, const int&,
const double&, double*,const int&);
void dgetrf(const int& n, const int& m, double* a, const int& n0,
int* piv, int& st);
void zgetrf(const int& n, const int& m, complex<double>* a, const int& n0,
int* piv, int& st);
void dgetri(const int& n, double* a, const int& n0,
int* piv, double* work, const int&, int& st);
void zgetri(const int& n, complex<double>* a, const int& n0,
int* piv, complex<double>* work, const int&, int& st);
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,118 @@
// -*- C++ -*-
/*! \author Jordan Vincent
* \author Curry Taylor
* \note The original Prim was written in F90 by Tim Wilkens.
*/
#include <math.h>
#include <stdlib.h>
#include <iostream>
#include "Numerics/Clebsch_Gordan.h"
/*!\fn Clebsch_Gordan::Clebsch_Gordan(const int lmax)
* \param lmax the maximum angular momentum
* \brief Constructs all the Clebsch-Gordan coefficients
for \f$ 0 \le l_1 \le l_{max}, 0 \le l_2 \le l_1 \f$.
This routine was adopted from a FORTRAN 77 algorithm taken
from Rose's 'Elementary Theory of Angular Momentum', p. 39,
Wigner's formula. The coefficients listed are only those
for which \f$ l_1 \ge l_2 \f$, otherwise the relationship
\f[ \langle l_1 m_1 l_2 m_2 | l_3 m_3 \rangle
= (-1)^{l_1+l_2+l_3} \langle l_2 m_2 l_1 m_1 | l_3 m_3
\rangle \f] applies.
Coeffienents known to be zero (because of either the
L or M selection rules) are not computed, and these should not
be sought.
* \note The indexing of the array is as follows:
\f[ cg(l1,l2,l3,m1+Lmax,m2+Lmax) \f]
this is due to the need to index arrays from 0 to N-1
in C++.
* \note As the main routine is statically defined (hard-coded),
\f$ l \f$ values greater than 6 are not allowed and will cause
error.
*
*/
Clebsch_Gordan::Clebsch_Gordan(const int lmax):Lmax(lmax){
int l1 = Lmax+1;
int l2 = 2*Lmax+1;
cg.resize(l1,l1,l2,l2,l2);
// std::cout << cg.shape() << std::endl;
cg = 0.0;
build_coefficients();
}
Clebsch_Gordan::~Clebsch_Gordan() { cg.free(); }
/*!
* \fn void Clebsch_Gordan::build_coefficients()
*
* \brief Calculates the Clebsch-Gordan coefficients and stores
them in a 5-dimensional Blitz++ array.
*
*/
void Clebsch_Gordan::build_coefficients() {
double si[33], fa[33], sum, prefactor;
int lmin, i, l1, l2, l3, m1, m2, m3, nmin, nmax;
si[0] = 1.0;
fa[0] = 1.0;
for(i=1; i<=32; i++) {
si[i] = -si[i-1];
fa[i] = (double)i * fa[i-1];
}
for(l1=0; l1<=Lmax; l1++) {
for(l2=0; l2<=l1; l2++) {
for(m1=-l1; m1<=l1; m1++) {
for(m2=-l2; m2<=l2; m2++) {
m3 = m1 + m2;
lmin = abs(l1-l2);
if(lmin < abs(m3)) { lmin = abs(m3); }
for(l3=lmin; l3<=l1+l2; l3++) {
prefactor = 2.0*l3 + 1.0;
prefactor *= fa[l3+l1-l2] / fa[l1+l2+l3+1];
prefactor *= fa[l3-l1+l2] / fa[l1-m1];
prefactor *= fa[l1+l2-l3] / fa[l1+m1];
prefactor *= fa[l3+m3] / fa[l2-m2];
prefactor *= fa[l3-m3] / fa[l2+m2];
prefactor = sqrt(prefactor);
nmax = l3 - l1 + l2;
if(l3+m3 < nmax) { nmax = l3+m3; }
nmin = 0;
if(l1-l2-m3 < nmin) { nmin = -(l1-l2-m3); }
sum = 0;
for(i=nmin; i<=nmax; i++) {
sum += (si[i+l2+m2]/fa[i]) * fa[l2+l3+m1-i] * fa[l1-m1+i]
/ fa[l3-l1+l2-i] / fa[l3+m3-i] / fa[i+l1-l2-m3];
}
cg(l1,l2,l3,m1+Lmax,m2+Lmax) = prefactor*sum;
cg(l2,l1,l3,m2+Lmax,m1+Lmax) = si[l1+l2+l3]*prefactor*sum;
}
}
}
}
}
}
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,45 @@
// -*- C++ -*-
/*! \author Jordan Vincent
* \author Curry Taylor
* \note The original Prim was written in F90 by Tim Wilkens.
*/
#ifndef CLEBSCH_GORDAN_H2
#define CLEBSCH_GORDAN_H2
#include <blitz/array.h>
/**class Clebsch_Gordan
*\brief Calculates the Clebsch-Gordan coefficients
*/
class Clebsch_Gordan {
public:
Clebsch_Gordan(const int lmax);
///destructor
~Clebsch_Gordan();
///maximum angular momentum
int Lmax;
///array to store the Clebsch-Gordan coefficients
blitz::Array<double,5> cg;
///returns \f$ \langle l_1 m_1 l_2 m_2 | l_3 (m_1+m_2) \rangle \f$
inline double operator()(int l1, int l2, int l3, int m1, int m2) const {
return cg(l1,l2,l3,m1+Lmax,m2+Lmax);
}
private:
/// default constructor not implemented
Clebsch_Gordan() { }
void build_coefficients();
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

41
src/Numerics/ConstScale.h Normal file
View File

@ -0,0 +1,41 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_CONSTSCALINGSKMODEL_H
#define OHMMS_CONSTSCALINGSKMODEL_H
// SK<T,L1,L2,MID> where MID = 0 for no scaling
// dum scaling function which returns a constant function
struct ConstScale {
double C;
ConstScale(double c=1.0):C(c){ }
~ConstScale() { }
inline double operator()(double r) { return C;}
inline double operator()(double r, double& vr) { vr = C/r; return 0.0e0;}
inline double operator()(double r, double& vr, double& dvr) {
vr = C/r/r; dvr = 0.0e0; return 0.0e0;
}
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* OHMMS_VERSION_ID: $Id$
***************************************************************************/

View File

@ -0,0 +1,130 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_SINECOSINEFUNCTION_H
#define OHMMS_SINECOSINEFUNCTION_H
#include <math.h>
template<class T, class PT>
struct Sine3D
{
typedef T value_type;
typedef PT pos_type;
Sine3D(value_type kx = 0, value_type ky =0, value_type kz = 0) {
set(kx,ky,kz);
}
void set(value_type kx, value_type ky, value_type kz) {
const double twopi = 2.0*M_PI;
Kx = twopi*(kx+0.5);
Ky = twopi*(ky+0.5);
Kz = twopi*(kz+0.5);
Knorm2 = Kx*Kx+Ky*Ky+Kz*Kz;
}
inline value_type evaluate(const PT& r) {
return sin(Kx*r[0])*sin(Ky*r[1])*sin(Kz*r[2]);
}
inline value_type evaluate(const PT& r, PT& gr, value_type& lap) {
value_type v;
gr = gradient(r,v);
lap = -Knorm2*v;
return v;
}
inline PT gradient(const PT& r, value_type& v) {
v = evaluate(r);
return PT(Kx*cos(Kx*r[0])*sin(Ky*r[1])*sin(Kz*r[2]),
Ky*sin(Kx*r[0])*cos(Ky*r[1])*sin(Kz*r[2]),
Kz*sin(Kx*r[0])*sin(Ky*r[1])*cos(Kz*r[2]));
}
// update internal variables and return the funcional value at r
inline value_type laplacian(const PT& r) {
Lap = laplacian(r,Val,Grad);
return Val;
}
inline value_type operator()(const PT& r) {
return evaluate(r);
}
value_type Kx, Ky, Kz, Knorm2;
value_type Val, Lap;
pos_type Grad;
};
template<class T, class PT>
struct Cosine3D
{
typedef T value_type;
typedef PT pos_type;
Cosine3D(value_type kx = 0, value_type ky =0, value_type kz = 0) {
set(kx,ky,kz);
}
void set(value_type kx, value_type ky, value_type kz) {
const double twopi = 2.0*M_PI;
Kx = twopi*(kx+0.5);
Ky = twopi*(ky+0.5);
Kz = twopi*(kz+0.5);
Knorm2 = Kx*Kx+Ky*Ky+Kz*Kz;
}
inline value_type evaluate(const PT& r) {
return cos(Kx*r[0])*cos(Ky*r[1])*cos(Kz*r[2]);
}
inline PT gradient(const PT& r, value_type& v) {
v = evaluate(r);
return PT(-Kx*sin(Kx*r[0])*cos(Ky*r[1])*cos(Kz*r[2]),
-Ky*cos(Kx*r[0])*sin(Ky*r[1])*cos(Kz*r[2]),
-Kz*cos(Kx*r[0])*cos(Ky*r[1])*sin(Kz*r[2]));
}
inline value_type laplacian(const PT& r, value_type& v, PT& gr) {
gr = gradient(r,v);
return -Knorm2*v;
}
// update internal variables
inline value_type laplacian(const PT& r) {
Lap = laplacian(r,Val,Grad);
return Val;
}
inline value_type operator()(const PT& r) {
return evaluate(r);
}
value_type Kx, Ky, Kz, Knorm2;
value_type Val, Lap;
pos_type Grad;
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,307 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef CUBICSPLINE3D_REGULARGRID_H
#define CUBICSPLINE3D_REGULARGRID_H
#include <bitset>
using std::bitset;
/*! \class template<class T> CubicSplineDiff
* \brief spline functions on regular grid [Rmin, Rmax)
*/
template<class grid_type, class pos_type>
class CubicSpline3D {
public:
typedef typename grid_type::value_type value_type;
pos_type Rmin, Rmax, dr, drinv, drinv2, dr2over6, drover6;
bitset<4> xyz[8];
grid_type Y;
//!< default constructor
CubicSpline3D():Y(NULL){
setxyz();
}
//!< default constructor
CubicSpline3D(const CubicSpline3D<grid_type,pos_type>& a) {
setxyz();
Rmin = a.Rmin;
Rmax = a.Rmax;
dr = a.dr;
drinv = a.drinv;
drover6 = a.drover6;
dr2over6 = a.dr2over6;
//Y = a.Y;
}
void setxyz() {
//4-bit to calculate the coefficient indices and sign
//xyz[i](x,y,z,sign): initially, all the bits are set to 0
//xyz[0] = bitset<4>(0,0,0,0); // -1(0) 3*0
xyz[1].flip(2); xyz[1].flip(3); //xyz[1] = bitset<4>(0,0,1,1); // +1(1) 2*0
xyz[2].flip(1); xyz[2].flip(2); //xyz[2] = bitset<4>(0,1,1,0); // -1(0) 1*0
xyz[3].flip(1); xyz[3].flip(3); //xyz[3] = bitset<4>(0,1,0,1); // +1(1) 2*0
xyz[4].flip(0); xyz[4].flip(3); //xyz[4] = bitset<4>(1,0,0,1); // +1(1) 2*0
xyz[5].flip(0); xyz[5].flip(2); //xyz[5] = bitset<4>(1,0,1,0); // -1(0) 1*0
xyz[6].flip(); //xyz[6] = bitset<4>(1,1,1,1); // +1(1) 0*0
xyz[7].flip(0); xyz[7].flip(1); //xyz[7] = bitset<4>(1,1,0,0); // -1(0) 1*0
}
value_type& operator()(int i, int j, int k) {
// all shifted by 1 for the boundary
return Y(i,j,k);
}
value_type operator()(int i, int j, int k) const {
// all shifted by 1 for the boundary
return Y(i,j,k);
}
//!< resize the arrays
void resize(const int l, const int m, const int n) {
Y.resize(l+1,m+1,n+1);
Rmin[0] = 0.0; Rmin[1] = 0.0; Rmin[2] = 0.0;
Rmax[0] = 1.0; Rmax[1] = 1.0; Rmax[2] = 1.0;
drinv[0] = static_cast<value_type>(l);
drinv[1] = static_cast<value_type>(m);
drinv[2] = static_cast<value_type>(n);
drinv2[0] = drinv[0]*drinv[0];
drinv2[1] = drinv[1]*drinv[1];
drinv2[2] = drinv[2]*drinv[2];
dr[0] = 1.0/drinv[0];
dr[1] = 1.0/drinv[1];
dr[2] = 1.0/drinv[2];
drover6[0] = dr[0]/6.0;
drover6[1] = dr[1]/6.0;
drover6[2] = dr[2]/6.0;
dr2over6[0] = dr[0]*drover6[0];
dr2over6[1] = dr[1]*drover6[1];
dr2over6[2] = dr[2]*drover6[2];
}
value_type evaluate(const pos_type& pos) {
// find the location of pos
value_type di = (pos[0]-Rmin[0])*drinv[0];
value_type dj = (pos[1]-Rmin[1])*drinv[1];
value_type dk = (pos[2]-Rmin[2])*drinv[2];
// find the index of pos
int im = static_cast<int>(di);
int jm = static_cast<int>(dj);
int km = static_cast<int>(dk);
// find the index+1 of pos
int ip = im+1;
int jp = jm+1;
int kp = km+1;
// determin L_{nx}, L_{ny}, L_{nz}
//\latex{$$L_{nx} = {R_{min}+nx*dx - x\over dx} = -{x-R_{min}\over dx}+nx$$}
pos_type Lm(static_cast<value_type>(im)-di,
static_cast<value_type>(jm)-dj,
static_cast<value_type>(km)-dk);
// determin L_{nx+1}, L_{ny+1}, L_{nz+1}
//\latex{$$L_{nx+1} = {R_{min}+(nx+1)*dx - x\over dx}
// = -{x-R_{min}\over dx}+nx+1 = L_{nx}+1$$}
pos_type Lp = Lm + 1.0;
// determin C_{nx}, C_{ny}, C_{nz}
pos_type Cm(dr2over6[0]*Lm[0]*(Lm[0]*Lm[0]-1),
dr2over6[1]*Lm[1]*(Lm[1]*Lm[1]-1),
dr2over6[2]*Lm[2]*(Lm[2]*Lm[2]-1));
// determin C_{nx+1}, C_{ny+1}, C_{nz+1}
pos_type Cp(dr2over6[0]*Lp[0]*(Lp[0]*Lp[0]-1),
dr2over6[1]*Lp[1]*(Lp[1]*Lp[1]-1),
dr2over6[2]*Lp[2]*(Lp[2]*Lp[2]-1));
int i, j, k;
value_type Lx, Ly, Lz;
value_type Cx, Cy, Cz;
value_type y, y2x, y2y, y2z;
value_type res = 0.0;
// precalculate d^2 phi/dx^2, d^2 phi/dy^2 and d^2 phi/dz^2
for(int ixyz=0; ixyz<8; ixyz++) {
// get Lx, Cx, Cvx, and index i to get the value
if(xyz[ixyz][0]) { // (1,y,z)
Lx = Lp[0]; Cx = Cp[0]; i = im;
}
else { // (0,y,z)
Lx = Lm[0]; Cx = Cm[0]; i = ip;
}
// get Ly, Cy, Cvy, and index j to get the value
if(xyz[ixyz][1]) { // (x,1,z)
Ly = Lp[1]; Cy = Cp[1]; j = jm;
}
else { // (x,0,z)
Ly = Lm[1]; Cy = Cm[1]; j = jp;
}
// get Lz, Cz, Cvz, and index k to get the value
if(xyz[ixyz][2]) { // (x,y,1)
Lz = Lp[2]; Cz = Cp[2]; k = km;
}
else { // (x,y,0)
Lz = Lm[2]; Cz = Cm[2]; k = kp;
}
y = Y(i,j,k);
//\warning: not protected for negative indices
y2x = (Y(i+1,j,k)+Y(i-1,j,k)-2.0*y)*drinv[0]*drinv[0];
y2y = (Y(i,j+1,k)+Y(i,j-1,k)-2.0*y)*drinv[1]*drinv[1];
y2z = (Y(i,j,k+1)+Y(i,j,k-1)-2.0*y)*drinv[2]*drinv[2];
if(xyz[ixyz][3]) {//positive
res += (Lx*Ly*Lz*y +Cx*Ly*Lz*y2x +Lx*Cy*Lz*y2y+Lx*Ly*Cz*y2z);
} else {
res -= (Lx*Ly*Lz*y +Cx*Ly*Lz*y2x +Lx*Cy*Lz*y2y+Lx*Ly*Cz*y2z);
}
}
return res;
}
value_type laplacian(const pos_type& pos, value_type& value, pos_type& gr) {
// find the location of pos
value_type di = (pos[0]-Rmin[0])*drinv[0];
value_type dj = (pos[1]-Rmin[1])*drinv[1];
value_type dk = (pos[2]-Rmin[2])*drinv[2];
// find the index of pos
int im = static_cast<int>(di);
int jm = static_cast<int>(dj);
int km = static_cast<int>(dk);
// find the index+1 of pos
int ip = im+1;
int jp = jm+1;
int kp = km+1;
// determin L_{nx}, L_{ny}, L_{nz}
//\latex{$$L_{nx} = {R_{min}+nx*dx - x\over dx} = -{x-R_{min}\over dx}+nx$$}
pos_type Lm(static_cast<value_type>(im)-di,
static_cast<value_type>(jm)-dj,
static_cast<value_type>(km)-dk);
// determin L_{nx+1}, L_{ny+1}, L_{nz+1}
//\latex{$$L_{nx+1} = {R_{min}+(nx+1)*dx - x\over dx}
//= -{x-R_{min}\over dx}+nx+1 = L_{nx}+1$$}
pos_type Lp = Lm + 1.0;
// determin C_{nx}, C_{ny}, C_{nz}
pos_type Cm(dr2over6[0]*Lm[0]*(Lm[0]*Lm[0]-1),
dr2over6[1]*Lm[1]*(Lm[1]*Lm[1]-1),
dr2over6[2]*Lm[2]*(Lm[2]*Lm[2]-1));
// determin C_{nx+1}, C_{ny+1}, C_{nz+1}
pos_type Cp(dr2over6[0]*Lp[0]*(Lp[0]*Lp[0]-1),
dr2over6[1]*Lp[1]*(Lp[1]*Lp[1]-1),
dr2over6[2]*Lp[2]*(Lp[2]*Lp[2]-1));
// determine -dC_{nx}/dx, -dC_{ny}/dy, -dC_{nz}/dz
pos_type Cvm(drover6[0]*(3*Lm[0]*Lm[0]-1),
drover6[1]*(3*Lm[1]*Lm[1]-1),
drover6[2]*(3*Lm[2]*Lm[2]-1));
// determin -dC_{nx+1}/dx, -dC_{ny+1}/dy, -dC_{nz+1}/dz
pos_type Cvp(drover6[0]*(3*Lp[0]*Lp[0]-1),
drover6[1]*(3*Lp[1]*Lp[1]-1),
drover6[2]*(3*Lp[2]*Lp[2]-1));
int i,j,k;
value_type Lx, Ly, Lz;
value_type Cx, Cy, Cz;
value_type Cvx, Cvy, Cvz;
value_type lap = 0.0;
value = 0;
// precalculate d^2 phi/dx^2, d^2 phi/dy^2 and d^2 phi/dz^2
for(int ixyz=0; ixyz<8; ixyz++) {
// get Lx, Cx, Cvx, and index i to get the value
if(xyz[ixyz][0]) { // (1,y,z)
Lx = Lp[0]; Cx = Cp[0]; Cvx = Cvp[0]; i = im;
}
else { // (0,y,z)
Lx = Lm[0]; Cx = Cm[0]; Cvx = Cvm[0]; i = ip;
}
// get Ly, Cy, Cvy, and index j to get the value
if(xyz[ixyz][1]) { // (x,1,z)
Ly = Lp[1]; Cy = Cp[1]; Cvy = Cvp[1]; j = jm;
}
else { // (x,0,z)
Ly = Lm[1]; Cy = Cm[1]; Cvy = Cvm[1]; j = jp;
}
// get Lz, Cz, Cvz, and index k to get the value
if(xyz[ixyz][2]) { // (x,y,1)
Lz = Lp[2]; Cz = Cp[2]; Cvz = Cvp[2]; k = km;
}
else { // (x,y,0)
Lz = Lm[2]; Cz = Cm[2]; Cvz = Cvm[2]; k = kp;
}
value_type y = Y(i,j,k);
//\warning: not protected for out-of-bound indices
value_type y2x = (Y(i+1,j, k) +Y(i-1,j, k) -2.0*y)*drinv2[0];
value_type y2y = (Y(i, j+1,k) +Y(i, j-1,k) -2.0*y)*drinv2[1];
value_type y2z = (Y(i, j, k+1)+Y(i, j, k-1)-2.0*y)*drinv2[2];
if(xyz[ixyz][3]) {//positive
value += (Lx*Ly*Lz*y + Cx*Ly*Lz*y2x + Lx*Cy*Lz*y2y + Lx*Ly*Cz*y2z);
lap += Lx*Ly*Lz*(y2x+y2y+y2z);
// negative signs are taken care of here
// Cvx = -dC/dx, Cvy = -dC/dy, and Cvz = -dC/dz
// dL/dx = -1/dx
gr[0] -= (drinv[0]*(Ly*Lz*y+Cy*Lz*y2y+Ly*Cz*y2z) + Cvx*Ly *Lz *y2x);
gr[1] -= (drinv[1]*(Lz*Lx*y+Cz*Lx*y2z+Lz*Cx*y2x) + Lx *Cvy*Lz *y2y);
gr[2] -= (drinv[2]*(Lx*Ly*y+Cx*Ly*y2x+Lx*Cy*y2y) + Lx *Ly *Cvz*y2z);
} else {
value -= (Lx*Ly*Lz*y +Cx*Ly*Lz*y2x + Lx*Cy*Lz*y2y + Lx*Ly*Cz*y2z);
lap -= Lx*Ly*Lz*(y2x+y2y+y2z);
// negative signs are taken care of here
gr[0] += (drinv[0]*(Ly*Lz*y +Cy*Lz*y2y + Ly*Cz*y2z) + Cvx*Ly *Lz *y2x);
gr[1] += (drinv[1]*(Lz*Lx*y +Cz*Lx*y2z + Lz*Cx*y2x) + Lx *Cvy*Lz *y2y);
gr[2] += (drinv[2]*(Lx*Ly*y +Cx*Ly*y2x + Lx*Cy*y2y) + Lx *Ly *Cvz*y2z);
}
}
return lap;
}
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* POOMA_VERSION_ID: $Id$
***************************************************************************/

View File

@ -0,0 +1,353 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef CUBICSPLINE3DCOLLECTION_REGULARGRID_H
#define CUBICSPLINE3DCOLLECTION_REGULARGRID_H
#include <bitset>
using std::bitset;
template<class PosA>
struct CubicSpline3DGrid {
typedef PosA pos_type;
typedef typename PosA::Type_t value_type;
int Npt[3];
value_type reps;
pos_type CurrentPos;
pos_type Rmin, Rmax, dr, drinv, drinv2, dr2over6, drover6;
bitset<4> xyz[8];
pos_type L[8], C[8], dC[8];
int I[8][3];
CubicSpline3DGrid() {
setxyz();
Rmin[0] = 0.0; Rmin[1] = 0.0; Rmin[2] = 0.0;
Rmax[0] = 1.0; Rmax[1] = 1.0; Rmax[2] = 1.0;
resize(1,1,1);
}
CubicSpline3DGrid(const CubicSpline3DGrid<PosA>& g) {
setxyz();
Rmin = g.Rmin;
Rmax = g.Rmax;
resize(g.Npt[0], g.Npt[1], g.Npt[2]);
}
CubicSpline3DGrid<PosA>& operator=(const CubicSpline3DGrid<PosA>& g) {
setxyz();
Rmin = g.Rmin;
Rmax = g.Rmax;
resize(g.Npt[0], g.Npt[1], g.Npt[2]);
return *this;
}
// return 1/dr^2 for the 2nd-derivatives
inline value_type c2(int i) const { return drinv2[i];}
// return 1/dr for the 2nd-derivatives
inline value_type c1(int i) const { return drinv[i];}
void resize(int l, int m, int n) {
Npt[0] = l; Npt[1] =m; Npt[2] = n;
reset();
}
void reset() {
dr[0] = (Rmax[0]-Rmin[0])/static_cast<value_type>(Npt[0]);
dr[1] = (Rmax[1]-Rmin[1])/static_cast<value_type>(Npt[1]);
dr[2] = (Rmax[2]-Rmin[2])/static_cast<value_type>(Npt[2]);
// minimim distance 1/100 th of the distance, to be over written
reps = 1e-6; //rcut2 = dot(dr,dr)/1000000;
CurrentPos = PosA(1000, 1000, 1000);
drinv[0] = 1.0/dr[0];
drinv[1] = 1.0/dr[1];
drinv[2] = 1.0/dr[2];
drinv2[0] = drinv[0]*drinv[0];
drinv2[1] = drinv[1]*drinv[1];
drinv2[2] = drinv[2]*drinv[2];
drover6[0] = dr[0]/6.0;
drover6[1] = dr[1]/6.0;
drover6[2] = dr[2]/6.0;
dr2over6[0] = dr[0]*drover6[0];
dr2over6[1] = dr[1]*drover6[1];
dr2over6[2] = dr[2]*drover6[2];
}
void setxyz(){
//4-bit to calculate the coefficient indices and sign
//xyz[i](x,y,z,sign): initially, all the bits are set to 0
//xyz[0] = bitset<4>(0,0,0,0); // -1(0) 3*0
xyz[1].flip(2); xyz[1].flip(3); //xyz[1] = bitset<4>(0,0,1,1); // +1(1) 2*0
xyz[2].flip(1); xyz[2].flip(2); //xyz[2] = bitset<4>(0,1,1,0); // -1(0) 1*0
xyz[3].flip(1); xyz[3].flip(3); //xyz[3] = bitset<4>(0,1,0,1); // +1(1) 2*0
xyz[4].flip(0); xyz[4].flip(3); //xyz[4] = bitset<4>(1,0,0,1); // +1(1) 2*0
xyz[5].flip(0); xyz[5].flip(2); //xyz[5] = bitset<4>(1,0,1,0); // -1(0) 1*0
xyz[6].flip(); //xyz[6] = bitset<4>(1,1,1,1); // +1(1) 0*0
xyz[7].flip(0); xyz[7].flip(1); //xyz[7] = bitset<4>(1,1,0,0); // -1(0) 1*0
}
inline bool get(const pos_type& pos) {
//how much the gain will be???
//if(dot(CurrentPos,pos) > rcut2) {
if(fabs(CurrentPos[0]-pos[0])>reps
&& fabs(CurrentPos[1]-pos[1])>reps
&& fabs(CurrentPos[2]-pos[2])>reps) {
// find the location of pos
value_type di = (pos[0]-Rmin[0])*drinv[0];
value_type dj = (pos[1]-Rmin[1])*drinv[1];
value_type dk = (pos[2]-Rmin[2])*drinv[2];
// find the index of pos
int im = static_cast<int>(di);
int jm = static_cast<int>(dj);
int km = static_cast<int>(dk);
// find the index+1 of pos
int ip = im+1;
int jp = jm+1;
int kp = km+1;
// determin L_{nx}, L_{ny}, L_{nz}
//\latex{$$L_{nx} = {R_{min}+nx*dx - x\over dx} = -{x-R_{min}\over dx}+nx$$}
pos_type Lm(static_cast<value_type>(im)-di,
static_cast<value_type>(jm)-dj,
static_cast<value_type>(km)-dk);
// determin L_{nx+1}, L_{ny+1}, L_{nz+1}
//\latex{$$L_{nx+1} = {R_{min}+(nx+1)*dx - x\over dx}
//= -{x-R_{min}\over dx}+nx+1 = L_{nx}+1$$}
pos_type Lp = Lm + 1.0;
// determin C_{nx}, C_{ny}, C_{nz}
pos_type Cm(dr2over6[0]*Lm[0]*(Lm[0]*Lm[0]-1),
dr2over6[1]*Lm[1]*(Lm[1]*Lm[1]-1),
dr2over6[2]*Lm[2]*(Lm[2]*Lm[2]-1));
// determin C_{nx+1}, C_{ny+1}, C_{nz+1}
pos_type Cp(dr2over6[0]*Lp[0]*(Lp[0]*Lp[0]-1),
dr2over6[1]*Lp[1]*(Lp[1]*Lp[1]-1),
dr2over6[2]*Lp[2]*(Lp[2]*Lp[2]-1));
// determine -dC_{nx}/dx, -dC_{ny}/dy, -dC_{nz}/dz
pos_type Cvm(drover6[0]*(3*Lm[0]*Lm[0]-1),
drover6[1]*(3*Lm[1]*Lm[1]-1),
drover6[2]*(3*Lm[2]*Lm[2]-1));
// determin -dC_{nx+1}/dx, -dC_{ny+1}/dy, -dC_{nz+1}/dz
pos_type Cvp(drover6[0]*(3*Lp[0]*Lp[0]-1),
drover6[1]*(3*Lp[1]*Lp[1]-1),
drover6[2]*(3*Lp[2]*Lp[2]-1));
CurrentPos = pos; // save input position
for(int ixyz=0; ixyz<8; ixyz++) {
//get Lx, Cx, Cvx, and index i to get the value
if(xyz[ixyz][0]) { //(1,y,z)
L[ixyz][0] = Lp[0];
C[ixyz][0] = Cp[0];
dC[ixyz][0] = Cvp[0];
I[ixyz][0] = im;
}
else { //(0,y,z)
L[ixyz][0] = Lm[0];
C[ixyz][0] = Cm[0];
dC[ixyz][0] = Cvm[0];
I[ixyz][0] = ip;
}
//get Ly, Cy, Cvy, and index j to get the value
if(xyz[ixyz][1]) { //(x,1,z)
L[ixyz][1] = Lp[1];
C[ixyz][1] = Cp[1];
dC[ixyz][1] = Cvp[1];
I[ixyz][1] = jm;
}
else { //(x,0,z)
L[ixyz][1] = Lm[1];
C[ixyz][1] = Cm[1];
dC[ixyz][1] = Cvm[1];
I[ixyz][1] = jp;
}
//get Lz, Cz, Cvz, and index k to get the value
if(xyz[ixyz][2]) { //(x,y,1)
L[ixyz][2] = Lp[2];
C[ixyz][2] = Cp[2];
dC[ixyz][2] = Cvp[2];
I[ixyz][2] = km;
}
else { //(x,y,0)
L[ixyz][2] = Lm[2];
C[ixyz][2] = Cm[2];
dC[ixyz][2] = Cvm[2];
I[ixyz][2] = kp;
}
}
return true; // new values are evaluated
}
else
return false; // position is identical
}
};
/*! \class template<class T> CubicSpline3D
* \brief spline functions on 3D regular grid [Rmin, Rmax)^3
* The number of grids per axis can vary.
* A set of orbitals are associated with a CubicSpline3D.
* This class cannot destroy the orbitals. They have to be provided externally.
*/
template<class grid_type,class orb_type>
struct CubicSpline3D {
typedef typename grid_type::pos_type pos_type;
typedef typename orb_type::value_type value_type;
bool OwnGrid;
value_type Val, Lap;
pos_type Grad;
grid_type* myGrid; // grid
orb_type Orb;
//!< default constructor
CubicSpline3D(): OwnGrid(false) {}
//!< constructor using grid
CubicSpline3D(int l, int m, int n): OwnGrid(true){
myGrid = new grid_type;
myGrid->resize(l,m,n);
resize(l, m, n);
}
//!< copy constructor
CubicSpline3D(const CubicSpline3D<grid_type,orb_type>& a){
OwnGrid = false;
myGrid = a.myGrid;
resize(myGrid->Npt[0], myGrid->Npt[1], myGrid->Npt[2]);
}
void resize(int l, int m, int n) {
Orb.resize(l+1,m+1,n+1);
}
~CubicSpline3D(){
if(OwnGrid) {
cerr << "This CubicSpline3D owns grid. Delete it" << endl;
delete myGrid;
}
}
// assign value at (i,j,k) of iorb-th orbital
value_type& operator()(int i, int j, int k) {
return Orb(i,j,k);
}
// return value at (i,j,k) of iorb-th orbital
value_type operator()(int i, int j, int k) const {
return Orb(i,j,k);
}
// always return the current value
value_type laplacian(const pos_type& pos) {
myGrid->get(pos);
do_evaluate(pos);
return Val;
}
// always return the current value
value_type evaluate(const pos_type& pos) {
myGrid->get(pos);
do_evaluate(pos);
return Val;
}
//!< function to calculate value, gradient and laplacian
//update Val, Grad and Lap
void do_evaluate(const pos_type& pos) {
// using myGrid data members pre-calculated by myGrid.get(pos)
// \li Linear coefficients: Lm, Lp
// \li Cubic coefficients: Cm, Cp
// \li Gradient of Cubic coefficients: Cvm, Cvp
// \li I : index of the (nx,ny,nz)
// \li Ip : index of the (nx+1,ny+1,nz+1)
Val = 0.0;
Lap = 0.0;
Grad = 0.0;
value_type val, lap;
pos_type gr;
// precalculate d^2 phi/dx^2, d^2 phi/dy^2 and d^2 phi/dz^2
for(int ixyz=0; ixyz<8; ixyz++) {
int i = myGrid->I[ixyz][0];
int j = myGrid->I[ixyz][1];
int k = myGrid->I[ixyz][2];
value_type y = Orb(i,j,k);
//\warning: not protected for negative indices
value_type y2x=(Orb(i+1,j,k)+Orb(i-1,j,k)-2.0*y)*myGrid->c2(0);
value_type y2y=(Orb(i,j+1,k)+Orb(i,j-1,k)-2.0*y)*myGrid->c2(1);
value_type y2z=(Orb(i,j,k+1)+Orb(i,j,k-1)-2.0*y)*myGrid->c2(2);
value_type lxy = myGrid->L[ixyz][0]*myGrid->L[ixyz][1];
value_type lyz = myGrid->L[ixyz][1]*myGrid->L[ixyz][2];
value_type lzx = myGrid->L[ixyz][2]*myGrid->L[ixyz][0];
value_type lxyz = lxy*myGrid->L[ixyz][2];
value_type cxx = myGrid->C[ixyz][0]*y2x;
value_type cyy = myGrid->C[ixyz][1]*y2y;
value_type czz = myGrid->C[ixyz][2]*y2z;
val = lxyz*y + cxx*lyz + cyy*lzx + czz*lxy;
lap = lxyz*(y2x+y2y+y2z);
gr[0] = lyz*(myGrid->c1(0)*y+myGrid->dC[ixyz][0]*y2x)
+ myGrid->c1(0)*(cyy*myGrid->L[ixyz][2]+czz*myGrid->L[ixyz][1]);
gr[1] = lzx*(myGrid->c1(1)*y+myGrid->dC[ixyz][1]*y2y)
+ myGrid->c1(1)*(czz*myGrid->L[ixyz][0]+cxx*myGrid->L[ixyz][2]);
gr[2] = lxy*(myGrid->c1(2)*y+myGrid->dC[ixyz][2]*y2z)
+ myGrid->c1(2)*(cxx*myGrid->L[ixyz][1]+cyy*myGrid->L[ixyz][0]);
if(myGrid->xyz[ixyz][3]) {//positive
Val += val;
Lap += lap;
Grad -= gr;
} else {
Val -= val;
Lap -= lap;
Grad += gr;
}
}
}
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* POOMA_VERSION_ID: $Id$
***************************************************************************/

View File

@ -0,0 +1,351 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef CUBICSPLINE3DCOLLECTION_REGULARGRID_H
#define CUBICSPLINE3DCOLLECTION_REGULARGRID_H
template<class PosA>
struct CubicSpline3DGrid {
typedef PosA pos_type;
typedef typename PosA::Type_t value_type;
int Npt[3];
value_type rcut2;
pos_type CurrentPos;
pos_type Rmin, Rmax, dr, drinv, drinv2, dr2over6, drover6;
pos_type Lm, Lp, Cm, Cp, Cvm, Cvp;
int I[3], Ip[3];
CubicSpline3DGrid() {
Rmin[0] = 0.0; Rmin[1] = 0.0; Rmin[2] = 0.0;
Rmax[0] = 1.0; Rmax[1] = 1.0; Rmax[2] = 1.0;
resize(1,1,1);
}
CubicSpline3DGrid(const CubicSpline3DGrid<PosA>& g) {
Rmin = g.Rmin;
Rmax = g.Rmax;
resize(g.Npt[0], g.Npt[1], g.Npt[2]);
}
CubicSpline3DGrid<PosA>& operator=(const CubicSpline3DGrid<PosA>& g) {
Rmin = g.Rmin;
Rmax = g.Rmax;
resize(g.Npt[0], g.Npt[1], g.Npt[2]);
return *this;
}
// return 1/dr^2 for the 2nd-derivatives
inline value_type c2(int i) const { return drinv2[i];}
// return 1/dr for the 2nd-derivatives
inline value_type c1(int i) const { return drinv[i];}
void resize(int l, int m, int n) {
Npt[0] = l; Npt[1] =m; Npt[2] = n;
dr[0] = (Rmax[0]-Rmin[0])/static_cast<value_type>(l);
dr[1] = (Rmax[1]-Rmin[1])/static_cast<value_type>(m);
dr[2] = (Rmax[2]-Rmin[2])/static_cast<value_type>(n);
// minimim distance 1/100 th of the distance, to be over written
rcut2 = dot(dr,dr)/1000000;
CurrentPos = PosA(1000, 1000, 1000);
drinv[0] = 1.0/dr[0];
drinv[1] = 1.0/dr[1];
drinv[2] = 1.0/dr[2];
drinv2[0] = drinv[0]*drinv[0];
drinv2[1] = drinv[1]*drinv[1];
drinv2[2] = drinv[2]*drinv[2];
drover6[0] = dr[0]/6.0;
drover6[1] = dr[1]/6.0;
drover6[2] = dr[2]/6.0;
dr2over6[0] = dr[0]*drover6[0];
dr2over6[1] = dr[1]*drover6[1];
dr2over6[2] = dr[2]*drover6[2];
}
inline bool get(const pos_type& pos) {
//how much the gain will be???
//if(dot(CurrentPos,pos) > rcut2) {
if(fabs(CurrentPos[0]-pos[0])>1e-6
&& fabs(CurrentPos[1]-pos[1])>1e-6 && fabs(CurrentPos[2]-pos[2])>1e-6) {
// find the location of pos
value_type di = (pos[0]-Rmin[0])*drinv[0];
value_type dj = (pos[1]-Rmin[1])*drinv[1];
value_type dk = (pos[2]-Rmin[2])*drinv[2];
// find the index of pos
I[0] = static_cast<int>(di);
I[1] = static_cast<int>(dj);
I[2] = static_cast<int>(dk);
// find the index+1 of pos
Ip[0] = I[0]+1;
Ip[1] = I[1]+1;
Ip[2] = I[2]+1;
// determin L_{nx}, L_{ny}, L_{nz}
//\latex{$$L_{nx} = {R_{min}+nx*dx - x\over dx} = -{x-R_{min}\over dx}+nx$$}
Lm[0] = static_cast<value_type>(I[0])-di;
Lm[1] = static_cast<value_type>(I[1])-dj;
Lm[2] = static_cast<value_type>(I[2])-dk;
// determin L_{nx+1}, L_{ny+1}, L_{nz+1}
//\latex{$$L_{nx+1} = {R_{min}+(nx+1)*dx - x\over dx}
//= -{x-R_{min}\over dx}+nx+1 = L_{nx}+1$$}
Lp = Lm + 1.0;
// determin C_{nx}, C_{ny}, C_{nz}
Cm[0] = dr2over6[0]*Lm[0]*(Lm[0]*Lm[0]-1);
Cm[1] = dr2over6[1]*Lm[1]*(Lm[1]*Lm[1]-1);
Cm[2] = dr2over6[2]*Lm[2]*(Lm[2]*Lm[2]-1);
// determin C_{nx+1}, C_{ny+1}, C_{nz+1}
Cp[0] = dr2over6[0]*Lp[0]*(Lp[0]*Lp[0]-1);
Cp[1] = dr2over6[1]*Lp[1]*(Lp[1]*Lp[1]-1);
Cp[2] = dr2over6[2]*Lp[2]*(Lp[2]*Lp[2]-1);
// determine -dC_{nx}/dx, -dC_{ny}/dy, -dC_{nz}/dz
Cvm[0] = drover6[0]*(3*Lm[0]*Lm[0]-1);
Cvm[1] = drover6[1]*(3*Lm[1]*Lm[1]-1);
Cvm[2] = drover6[2]*(3*Lm[2]*Lm[2]-1);
// determin -dC_{nx+1}/dx, -dC_{ny+1}/dy, -dC_{nz+1}/dz
Cvp[0] = drover6[0]*(3*Lp[0]*Lp[0]-1);
Cvp[1] = drover6[1]*(3*Lp[1]*Lp[1]-1);
Cvp[2] = drover6[2]*(3*Lp[2]*Lp[2]-1);
CurrentPos = pos; // save input position
return true; // new values are evaluated
}
else
return false; // position is identical
}
};
#include <bitset>
using std::bitset;
/*! \class template<class T> CubicSpline3D
* \brief spline functions on 3D regular grid [Rmin, Rmax)^3
* The number of grids per axis can vary.
* A set of orbitals are associated with a CubicSpline3D.
* This class cannot destroy the orbitals. They have to be provided externally.
*/
template<class grid_type,class orb_type>
struct CubicSpline3D {
typedef typename orb_type::value_type value_type;
typedef typename grid_type::pos_type pos_type;
int OrbitalID;
bitset<4> xyz[8]; // \note possible to make it "static const"
grid_type myGrid; // grid
vector<orb_type*> Orb; // a set of orbitals
Vector<value_type> Val,Lap;
Vector<pos_type> Grad;
//!< default constructor
CubicSpline3D(): OrbitalID(-1) {
setxyz(); // set bit operators
myGrid.resize(1,1,1); // set the default variables
}
//!< constructor using grid
CubicSpline3D(int l, int m, int n): OrbitalID(-1){
setxyz(); // set bit operators
myGrid.resize(l,m,n);
}
//!< copy constructor
CubicSpline3D(const CubicSpline3D<grid_type,orb_type>& a): OrbitalID(-1){
setxyz(); // set bit operators
myGrid = a.myGrid;
Val = a.Val;
Lap = a.Lap;
Grad = a.Grad;
Orb.reserve(a.Orb.size());
for(int iorb=0; iorb< a.Orb.size(); iorb++) Orb.push_back(a.Orb[iorb]);
}
~CubicSpline3D(){ }
void setxyz(){
//4-bit to calculate the coefficient indices and sign
//xyz[i](x,y,z,sign): initially, all the bits are set to 0
//xyz[0] = bitset<4>(0,0,0,0); // -1(0) 3*0
xyz[1].flip(2); xyz[1].flip(3); //xyz[1] = bitset<4>(0,0,1,1); // +1(1) 2*0
xyz[2].flip(1); xyz[2].flip(2); //xyz[2] = bitset<4>(0,1,1,0); // -1(0) 1*0
xyz[3].flip(1); xyz[3].flip(3); //xyz[3] = bitset<4>(0,1,0,1); // +1(1) 2*0
xyz[4].flip(0); xyz[4].flip(3); //xyz[4] = bitset<4>(1,0,0,1); // +1(1) 2*0
xyz[5].flip(0); xyz[5].flip(2); //xyz[5] = bitset<4>(1,0,1,0); // -1(0) 1*0
xyz[6].flip(); //xyz[6] = bitset<4>(1,1,1,1); // +1(1) 0*0
xyz[7].flip(0); xyz[7].flip(1); //xyz[7] = bitset<4>(1,1,0,0); // -1(0) 1*0
}
// assign value at (i,j,k) of iorb-th orbital
value_type& operator()(int iorb, int i, int j, int k) {
return Orb[iorb]->operator()(i,j,k);
}
// return value at (i,j,k) of iorb-th orbital
value_type operator()(int iorb, int i, int j, int k) const {
return Orb[iorb]->operator()(i,j,k);
}
//!\fn int add(grid_type* orbital)
//!\param orbital a grid_type to be added to Orb
//!\return the index of the added orbital
//!\warning Assuming that the new orbital is the same kind, i.e., size and grid
int add(orb_type* orbital) {
int id = Orb.size();
Orb.push_back(orbital);
// simply resize it
Val.resize(id+1);
Lap.resize(id+1);
Grad.resize(id+1);
return id;
}
//!< function to calculate value, gradient and laplacian
//\return value[iorb] = value of iorb-th orbial
// gr[iorb] = gradient of iorb-th orbial
// lap[iorb] = laplacian of iorb-th orbial
inline void laplacian(const pos_type& pos) {
//grid returns true, if pos != myGrid.CurrentPos;
if(myGrid.get(pos)) {
get_laplacian(pos, Val, Grad, Lap);// evalulate everything
for(int iorb=0; iorb<Orb.size(); iorb++) {//assign the values, not sure if needed
Orb[iorb]->Val = Val[iorb];
Orb[iorb]->Lap = Lap[iorb];
Orb[iorb]->Grad =Grad[iorb];
}
}
}
template<class ValArray, class PosArray>
inline void laplacian(const pos_type& pos, ValArray& value, PosArray& gr, ValArray& lap) {
if(myGrid.get(pos)) {
get_laplacian(pos, value,gr,lap);
Val = value; Grad = gr; Lap = lap;
}
}
//!< function to calculate value, gradient and laplacian
//\return value[iorb] = value of iorb-th orbial
// gr[iorb] = gradient of iorb-th orbial
// lap[iorb] = laplacian of iorb-th orbial
template<class ValArray, class PosArray>
inline void get_laplacian(const pos_type& pos, ValArray& value, PosArray& gr, ValArray& lap) {
// using myGrid data members pre-calculated by myGrid.get(pos)
// \li Linear coefficients: Lm, Lp
// \li Cubic coefficients: Cm, Cp
// \li Gradient of Cubic coefficients: Cvm, Cvp
// \li I : index of the (nx,ny,nz)
// \li Ip : index of the (nx+1,ny+1,nz+1)
value =0.0; lap = 0.0; gr = 0.0;
int i,j,k;
value_type Lx, Ly, Lz;
value_type Cx, Cy, Cz;
value_type Cvx, Cvy, Cvz;
// precalculate d^2 phi/dx^2, d^2 phi/dy^2 and d^2 phi/dz^2
for(int ixyz=0; ixyz<8; ixyz++) {
// get Lx, Cx, Cvx, and index i to get the value
if(xyz[ixyz][0]) { // (1,y,z)
Lx = myGrid.Lp[0]; Cx = myGrid.Cp[0]; Cvx = myGrid.Cvp[0]; i = myGrid.I[0];
}
else { // (0,y,z)
Lx = myGrid.Lm[0]; Cx = myGrid.Cm[0]; Cvx = myGrid.Cvm[0]; i = myGrid.Ip[0];
}
// get Ly, Cy, Cvy, and index j to get the value
if(xyz[ixyz][1]) { // (x,1,z)
Ly = myGrid.Lp[1]; Cy = myGrid.Cp[1]; Cvy = myGrid.Cvp[1]; j = myGrid.I[1];
}
else { // (x,0,z)
Ly = myGrid.Lm[1]; Cy = myGrid.Cm[1]; Cvy = myGrid.Cvm[1]; j = myGrid.Ip[1];
}
// get Lz, Cz, Cvz, and index k to get the value
if(xyz[ixyz][2]) { // (x,y,1)
Lz = myGrid.Lp[2]; Cz = myGrid.Cp[2]; Cvz = myGrid.Cvp[2]; k = myGrid.I[2];
}
else { // (x,y,0)
Lz = myGrid.Lm[2]; Cz = myGrid.Cm[2]; Cvz = myGrid.Cvm[2]; k = myGrid.Ip[2];
}
value_type lxy = Lx*Ly;
value_type lyz = Ly*Lz;
value_type lzx = Lz*Lx;
value_type lxyz = lxy*Lz;
for(int iorb=0; iorb<Orb.size(); iorb++) {
value_type y = (*Orb[iorb])(i,j,k);
//\warning: not protected for negative indices
value_type y2x=((*Orb[iorb])(i+1,j,k)+(*Orb[iorb])(i-1,j,k)-2.0*y)*myGrid.c2(0);
value_type y2y=((*Orb[iorb])(i,j+1,k)+(*Orb[iorb])(i,j-1,k)-2.0*y)*myGrid.c2(1);
value_type y2z=((*Orb[iorb])(i,j,k+1)+(*Orb[iorb])(i,j,k-1)-2.0*y)*myGrid.c2(2);
if(xyz[ixyz][3]) {//positive
value[iorb] += (lxyz*y + Cx*lyz*y2x + Cy*lzx*y2y + Cz*lxy*y2z);
lap[iorb] += lxyz*(y2x+y2y+y2z);
// negative signs are taken care of here
// Cvx = -dC/dx, Cvy = -dC/dy, and Cvz = -dC/dz
// dL/dx = -1/dx
gr[iorb][0] -= (myGrid.c1(0)*(lyz*y+Cy*Lz*y2y+Ly*Cz*y2z) + Cvx*lyz*y2x);
gr[iorb][1] -= (myGrid.c1(1)*(lzx*y+Cz*Lx*y2z+Lz*Cx*y2x) + Cvy*lzx*y2y);
gr[iorb][2] -= (myGrid.c1(2)*(lxy*y+Cx*Ly*y2x+Lx*Cy*y2y) + Cvz*lxy*y2z);
} else {
value[iorb] -= (lxyz*y + Cx*lyz*y2x + Cy*lzx*y2y + Cz*lxy*y2z);
lap[iorb] -= lxyz*(y2x+y2y+y2z);
// negative signs are taken care of here
// Cvx = -dC/dx, Cvy = -dC/dy, and Cvz = -dC/dz
// dL/dx = -1/dx
gr[iorb][0] += (myGrid.c1(0)*(lyz*y+Cy*Lz*y2y+Ly*Cz*y2z) + Cvx*lyz*y2x);
gr[iorb][1] += (myGrid.c1(1)*(lzx*y+Cz*Lx*y2z+Lz*Cx*y2x) + Cvy*lzx*y2y);
gr[iorb][2] += (myGrid.c1(2)*(lxy*y+Cx*Ly*y2x+Lx*Cy*y2y) + Cvz*lxy*y2z);
}
}
}
}
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* POOMA_VERSION_ID: $Id$
***************************************************************************/

View File

@ -0,0 +1,325 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef CUBICSPLINE3DCOLLECTION_REGULARGRID_H
#define CUBICSPLINE3DCOLLECTION_REGULARGRID_H
#include <bitset>
using std::bitset;
/*! \class template<class T> CubicSpline3D
* \brief spline functions on 3D regular grid [Rmin, Rmax)^3
* The number of grids per axis can vary.
* A set of orbitals are associated with a CubicSpline3D.
* This class cannot destroy the orbitals. They have to be provided externally.
*/
template<class grid_type, class pos_type>
struct CubicSpline3D {
typedef typename grid_type::value_type value_type;
int Npt[3];
int OrbitalID;
pos_type Rmin, Rmax, dr, drinv, drinv2, dr2over6, drover6;
bitset<4> xyz[8]; // \note possible to make it "static const"
pos_type Lm, Lp, Cm, Cp, Cvm, Cvp;
int I[3], J[3];
vector<grid_type*> Orb; // a set of orbitals
//!< default constructor
CubicSpline3D(): OrbitalID(-1) {
setxyz(); // set bit operators
// default bounds [0,1)x[0,1)x[0,1) with 1x1x1 grid
Npt[0] = 1; Npt[1] = 1; Npt[2] = 1;
Rmin[0] = 0.0; Rmin[1] = 0.0; Rmin[2] = 0.0;
Rmax[0] = 1.0; Rmax[1] = 1.0; Rmax[2] = 1.0;
resize(1,1,1); // set the default variables
}
//!< constructor using grid
CubicSpline3D(int l, int m, int n): OrbitalID(-1){
setxyz(); // set bit operators
Rmin[0] = 0.0; Rmin[1] = 0.0; Rmin[2] = 0.0;
Rmax[0] = 1.0; Rmax[1] = 1.0; Rmax[2] = 1.0;
resize(l,m,n);
}
//!< copy constructor
CubicSpline3D(const CubicSpline3D<grid_type,pos_type>& a): OrbitalID(-1){
setxyz(); // set bit operators
Rmin = a.Rmin;
Rmax = a.Rmax;
resize(a.Npt[0], a.Npt[1], a.Npt[2]);
Orb.reserve(a.Orb.size());
for(int iorb=0; iorb< a.Orb.size(); iorb++) Orb.push_back(a.Orb[iorb]);
}
~CubicSpline3D(){ }
void setxyz();
// assign value at (i,j,k) of iorb-th orbital
value_type& operator()(int iorb, int i, int j, int k) {
return Orb[iorb]->operator()(i,j,k);
}
// return value at (i,j,k) of iorb-th orbital
value_type operator()(int iorb, int i, int j, int k) const {
return Orb[iorb]->operator()(i,j,k);
}
//!\fn int add(grid_type* orbital)
//!\param orbital a grid_type to be added to Orb
//!\return the index of the added orbital
//!\warning Assuming that the new orbital is the same kind, i.e., size and grid
int add(grid_type* orbital) {
int id = Orb.size();
Orb.push_back(orbital);
return id;
}
//!< resize the arrays
void resize(const int l, const int m, const int n);
//!< function to calculate value, gradient and laplacian
//\return value[iorb] = value of iorb-th orbial
// gr[iorb] = gradient of iorb-th orbial
// lap[iorb] = laplacian of iorb-th orbial
template<class ValArray, class PosArray>
void laplacian(const pos_type& pos, ValArray& value, PosArray& gr, ValArray& lap);
inline void get_grid(const pos_type& pos) {
// find the location of pos
value_type di = (pos[0]-Rmin[0])*drinv[0];
value_type dj = (pos[1]-Rmin[1])*drinv[1];
value_type dk = (pos[2]-Rmin[2])*drinv[2];
// find the index of pos
I[0] = static_cast<int>(di);
I[1] = static_cast<int>(dj);
I[2] = static_cast<int>(dk);
// find the index+1 of pos
J[0] = I[0]+1;
J[1] = I[1]+1;
J[2] = I[2]+1;
// determin L_{nx}, L_{ny}, L_{nz}
//\latex{$$L_{nx} = {R_{min}+nx*dx - x\over dx} = -{x-R_{min}\over dx}+nx$$}
Lm[0] = static_cast<value_type>(I[0])-di;
Lm[1] = static_cast<value_type>(I[1])-dj;
Lm[2] = static_cast<value_type>(I[2])-dk;
// determin L_{nx+1}, L_{ny+1}, L_{nz+1}
//\latex{$$L_{nx+1} = {R_{min}+(nx+1)*dx - x\over dx}
//= -{x-R_{min}\over dx}+nx+1 = L_{nx}+1$$}
Lp = Lm + 1.0;
// determin C_{nx}, C_{ny}, C_{nz}
Cm[0] = dr2over6[0]*Lm[0]*(Lm[0]*Lm[0]-1);
Cm[1] = dr2over6[1]*Lm[1]*(Lm[1]*Lm[1]-1);
Cm[2] = dr2over6[2]*Lm[2]*(Lm[2]*Lm[2]-1);
// determin C_{nx+1}, C_{ny+1}, C_{nz+1}
Cp[0] = dr2over6[0]*Lp[0]*(Lp[0]*Lp[0]-1);
Cp[1] = dr2over6[1]*Lp[1]*(Lp[1]*Lp[1]-1);
Cp[2] = dr2over6[2]*Lp[2]*(Lp[2]*Lp[2]-1);
// determine -dC_{nx}/dx, -dC_{ny}/dy, -dC_{nz}/dz
Cvm[0] = drover6[0]*(3*Lm[0]*Lm[0]-1);
Cvm[1] = drover6[1]*(3*Lm[1]*Lm[1]-1);
Cvm[2] = drover6[2]*(3*Lm[2]*Lm[2]-1);
// determin -dC_{nx+1}/dx, -dC_{ny+1}/dy, -dC_{nz+1}/dz
Cvp[0] = drover6[0]*(3*Lp[0]*Lp[0]-1);
Cvp[1] = drover6[1]*(3*Lp[1]*Lp[1]-1);
Cvp[2] = drover6[2]*(3*Lp[2]*Lp[2]-1);
}
};
template<class grid_type, class pos_type>
void
CubicSpline3D<grid_type,pos_type>::resize(const int l, const int m, const int n) {
Npt[0] = l; Npt[1] = m; Npt[2] = n;
dr[0] = (Rmax[0]-Rmin[0])/static_cast<value_type>(l);
dr[1] = (Rmax[1]-Rmin[1])/static_cast<value_type>(m);
dr[2] = (Rmax[2]-Rmin[2])/static_cast<value_type>(n);
drinv[0] = 1.0/dr[0];
drinv[1] = 1.0/dr[1];
drinv[2] = 1.0/dr[2];
drinv2[0] = drinv[0]*drinv[0];
drinv2[1] = drinv[1]*drinv[1];
drinv2[2] = drinv[2]*drinv[2];
drover6[0] = dr[0]/6.0;
drover6[1] = dr[1]/6.0;
drover6[2] = dr[2]/6.0;
dr2over6[0] = dr[0]*drover6[0];
dr2over6[1] = dr[1]*drover6[1];
dr2over6[2] = dr[2]*drover6[2];
}
template<class grid_type, class pos_type>
template<class ValArray, class PosArray>
void
CubicSpline3D<grid_type,pos_type>::laplacian(const pos_type& pos,
ValArray& value, PosArray& gr,
ValArray& lap) {
get_grid(pos);
// // find the location of pos
// value_type di = (pos[0]-Rmin[0])*drinv[0];
// value_type dj = (pos[1]-Rmin[1])*drinv[1];
// value_type dk = (pos[2]-Rmin[2])*drinv[2];
// // find the index of pos
// int im = static_cast<int>(di);
// int jm = static_cast<int>(dj);
// int km = static_cast<int>(dk);
// // find the index+1 of pos
// int ip = im+1;
// int jp = jm+1;
// int kp = km+1;
// // determin L_{nx}, L_{ny}, L_{nz}
// //\latex{$$L_{nx} = {R_{min}+nx*dx - x\over dx} = -{x-R_{min}\over dx}+nx$$}
// pos_type Lm(static_cast<value_type>(im)-di,
// static_cast<value_type>(jm)-dj,
// static_cast<value_type>(km)-dk);
// // determin L_{nx+1}, L_{ny+1}, L_{nz+1}
// //\latex{$$L_{nx+1} = {R_{min}+(nx+1)*dx - x\over dx}
// //= -{x-R_{min}\over dx}+nx+1 = L_{nx}+1$$}
// pos_type Lp = Lm + 1.0;
// // determin C_{nx}, C_{ny}, C_{nz}
// pos_type Cm(dr2over6[0]*Lm[0]*(Lm[0]*Lm[0]-1),
// dr2over6[1]*Lm[1]*(Lm[1]*Lm[1]-1),
// dr2over6[2]*Lm[2]*(Lm[2]*Lm[2]-1));
// // determin C_{nx+1}, C_{ny+1}, C_{nz+1}
// pos_type Cp(dr2over6[0]*Lp[0]*(Lp[0]*Lp[0]-1),
// dr2over6[1]*Lp[1]*(Lp[1]*Lp[1]-1),
// dr2over6[2]*Lp[2]*(Lp[2]*Lp[2]-1));
// // determine -dC_{nx}/dx, -dC_{ny}/dy, -dC_{nz}/dz
// pos_type Cvm(drover6[0]*(3*Lm[0]*Lm[0]-1),
// drover6[1]*(3*Lm[1]*Lm[1]-1),
// drover6[2]*(3*Lm[2]*Lm[2]-1));
// // determin -dC_{nx+1}/dx, -dC_{ny+1}/dy, -dC_{nz+1}/dz
// pos_type Cvp(drover6[0]*(3*Lp[0]*Lp[0]-1),
// drover6[1]*(3*Lp[1]*Lp[1]-1),
// drover6[2]*(3*Lp[2]*Lp[2]-1));
int i,j,k;
value_type Lx, Ly, Lz;
value_type Cx, Cy, Cz;
value_type Cvx, Cvy, Cvz;
// precalculate d^2 phi/dx^2, d^2 phi/dy^2 and d^2 phi/dz^2
for(int ixyz=0; ixyz<8; ixyz++) {
// get Lx, Cx, Cvx, and index i to get the value
if(xyz[ixyz][0]) { // (1,y,z)
Lx = Lp[0]; Cx = Cp[0]; Cvx = Cvp[0]; i = I[0];
}
else { // (0,y,z)
Lx = Lm[0]; Cx = Cm[0]; Cvx = Cvm[0]; i = J[0];
}
// get Ly, Cy, Cvy, and index j to get the value
if(xyz[ixyz][1]) { // (x,1,z)
Ly = Lp[1]; Cy = Cp[1]; Cvy = Cvp[1]; j = I[1];
}
else { // (x,0,z)
Ly = Lm[1]; Cy = Cm[1]; Cvy = Cvm[1]; j = J[1];
}
// get Lz, Cz, Cvz, and index k to get the value
if(xyz[ixyz][2]) { // (x,y,1)
Lz = Lp[2]; Cz = Cp[2]; Cvz = Cvp[2]; k = I[2];
}
else { // (x,y,0)
Lz = Lm[2]; Cz = Cm[2]; Cvz = Cvm[2]; k = J[2];
}
for(int iorb=0; iorb<Orb.size(); iorb++) {
value_type y = (*Orb[iorb])(i,j,k);
//\warning: not protected for negative indices
value_type y2x = ((*Orb[iorb])(i+1,j,k)+(*Orb[iorb])(i-1,j,k)-2.0*y)*drinv2[0];
value_type y2y = ((*Orb[iorb])(i,j+1,k)+(*Orb[iorb])(i,j-1,k)-2.0*y)*drinv2[1];
value_type y2z = ((*Orb[iorb])(i,j,k+1)+(*Orb[iorb])(i,j,k-1)-2.0*y)*drinv2[2];
if(xyz[ixyz][3]) {//positive
value[iorb] += (Lx*Ly*Lz*y + Cx*Ly*Lz*y2x + Lx*Cy*Lz*y2y + Lx*Ly*Cz*y2z);
lap[iorb] += Lx*Ly*Lz*(y2x+y2y+y2z);
// negative signs are taken care of here
// Cvx = -dC/dx, Cvy = -dC/dy, and Cvz = -dC/dz
// dL/dx = -1/dx
gr[iorb][0] -= (drinv[0]*(Ly*Lz*y+Cy*Lz*y2y+Ly*Cz*y2z) + Cvx*Ly *Lz *y2x);
gr[iorb][1] -= (drinv[1]*(Lz*Lx*y+Cz*Lx*y2z+Lz*Cx*y2x) + Lx *Cvy*Lz *y2y);
gr[iorb][2] -= (drinv[2]*(Lx*Ly*y+Cx*Ly*y2x+Lx*Cy*y2y) + Lx *Ly *Cvz*y2z);
} else {
value[iorb] -= (Lx*Ly*Lz*y +Cx*Ly*Lz*y2x + Lx*Cy*Lz*y2y + Lx*Ly*Cz*y2z);
lap[iorb] -= Lx*Ly*Lz*(y2x+y2y+y2z);
// negative signs are taken care of here
gr[iorb][0] += (drinv[0]*(Ly*Lz*y +Cy*Lz*y2y + Ly*Cz*y2z) + Cvx*Ly *Lz *y2x);
gr[iorb][1] += (drinv[1]*(Lz*Lx*y +Cz*Lx*y2z + Lz*Cx*y2x) + Lx *Cvy*Lz *y2y);
gr[iorb][2] += (drinv[2]*(Lx*Ly*y +Cx*Ly*y2x + Lx*Cy*y2y) + Lx *Ly *Cvz*y2z);
}
}
}
}
template<class grid_type, class pos_type>
void
CubicSpline3D<grid_type,pos_type>::setxyz() {
//4-bit to calculate the coefficient indices and sign
//xyz[i](x,y,z,sign): initially, all the bits are set to 0
//xyz[0] = bitset<4>(0,0,0,0); // -1(0) 3*0
xyz[1].flip(2); xyz[1].flip(3); //xyz[1] = bitset<4>(0,0,1,1); // +1(1) 2*0
xyz[2].flip(1); xyz[2].flip(2); //xyz[2] = bitset<4>(0,1,1,0); // -1(0) 1*0
xyz[3].flip(1); xyz[3].flip(3); //xyz[3] = bitset<4>(0,1,0,1); // +1(1) 2*0
xyz[4].flip(0); xyz[4].flip(3); //xyz[4] = bitset<4>(1,0,0,1); // +1(1) 2*0
xyz[5].flip(0); xyz[5].flip(2); //xyz[5] = bitset<4>(1,0,1,0); // -1(0) 1*0
xyz[6].flip(); //xyz[6] = bitset<4>(1,1,1,1); // +1(1) 0*0
xyz[7].flip(0); xyz[7].flip(1); //xyz[7] = bitset<4>(1,1,0,0); // -1(0) 1*0
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* POOMA_VERSION_ID: $Id$
***************************************************************************/

View File

@ -0,0 +1,252 @@
// -*- C++ -*-
template<class T>
T
CubicSpline<T>::operator()(T r) {
const T onesixth = 0.16666666666666666667e0;
int klo,khi,k;
T h,b,a;
if(r>X[1] && r < X[Npt]) { //NR part
klo=1;
khi=Npt;
while (khi-klo > 1) {
k=(khi+klo) >> 1;
if (X[k] > r) khi=k;
else klo=k;
}
h=X[khi]-X[klo];
if (h == 0.0) {
// ERRORMSG("splint called with x = %lf\n",x);
};
a=(X[khi]-r)/h;
b=(r-X[klo])/h;
return a*Y[klo]+b*Y[khi]+
(a*(a*a-1.e0)*Y2[klo]+b*(b*b-1.0e0)*Y2[khi])*(h*h)*onesixth;
} else { // Extrapolation past endpoints
if(r<=X[1]) {
return Y[1] + Yp1 * (r - X[1]);
}
else{
return Y[Npt] + Ypn * (r - X[Npt]);
}
}
}
template<class T>
T
CubicSpline<T>::operator()(T r, T& val) {
const T onesixth = 0.16666666666666666667e0;
int klo,khi,k;
T h,b,a;
if(r>X[1] && r < X[Npt]) { //NR part
klo=1;
khi=Npt;
while (khi-klo > 1) {
k=(khi+klo) >> 1;
if (X[k] > r) khi=k;
else klo=k;
}
h=X[khi]-X[klo];
if (h == 0.0) {
//ERRORMSG("splint called with r = " << r << endl);
};
a=(X[khi]-r)/h;
b=(r-X[klo])/h;
val=a*Y[klo]+b*Y[khi]+
(a*(a*a-1.e0)*Y2[klo]+b*(b*b-1.0e0)*Y2[khi])*(h*h)*onesixth;
val /= r;
return -(1/h)*(Y[klo]-Y[khi] + ((h*h)*onesixth)*((3*a*a-1)*Y2[klo] -
(3*b*b-1)*Y2[khi]) );
} else { // Extrapolation past endpoints
if(r<=X[1]) {
val =(Y[1] + Yp1 * (r - X[1]))/r;
return Yp1;
}
else{
val= (Y[Npt] + Ypn * (r - X[Npt]))/r;
return Ypn;
}
}
}
template<class T>
T
CubicSpline<T>::operator()(T r, T& val, T& yp) {
const T onesixth = 0.16666666666666666667e0;
int klo,khi,k;
T h,b,a;
T rinv = 1.0/r;
if(r>X[1] && r < X[Npt]) { //NR part
klo=1;
khi=Npt;
while (khi-klo > 1) {
k=(khi+klo) >> 1;
if (X[k] > r) khi=k;
else klo=k;
}
h=X[khi]-X[klo];
if (h == 0.0) {
//ERRORMSG("splint called with r = " << r << endl);
};
T hinv = 1/h;
a=(X[khi]-r)*hinv;
b=(r-X[klo])*hinv;
val=a*Y[klo]+b*Y[khi]+
(a*(a*a-1.e0)*Y2[klo]+b*(b*b-1.0e0)*Y2[khi])*(h*h)*onesixth;
val *= (rinv*rinv);
yp = -rinv*hinv*(Y[klo]-Y[khi] +
(h*h*onesixth)*((3*a*a-1)*Y2[klo] -(3*b*b-1)*Y2[khi]) );
return a*Y2[klo]+b*Y2[khi];
} else { // Extrapolation past endpoints
if(r<=X[1]) {
val =(Y[1] + Yp1 * (r - X[1]))*rinv*rinv;
yp = Yp1*rinv;
return 0.0e0;
}
else{
val= (Y[Npt] + Ypn * (r - X[Npt]))*rinv*rinv;
yp = Ypn*rinv;
return 0.0e0;
}
}
}
template<class T>
void CubicSpline<T>::spline() {
//This is just a modified version of the Numerical Recipes routine spline,
//which generates spline coefficients given a set of spline parameters.
int i,k;
T p,qn,sig,un;
vector<T> u(Npt+1);
if (Yp1 > 0.99e30)
Y2[1]=u[1]=0.0;
else {
Y2[1] = -0.5;
u[1]=(3.0/(X[2]-X[1]))*((Y[2]-Y[1])/(X[2]-X[1])-Yp1);
}
for (i=2;i<=Npt-1;i++) {
sig=(X[i]-X[i-1])/(X[i+1]-X[i-1]);
p=sig*(Y2[i-1])+2.0;
Y2[i]=(sig-1.0)/p;
u[i]=(Y[i+1]-Y[i])/(X[i+1]-X[i]) - (Y[i]-Y[i-1])/(X[i]-X[i-1]);
u[i]=(6.0*u[i]/(X[i+1]-X[i-1])-sig*u[i-1])/p;
}
if (Ypn > 0.99e30) qn=un=0.0;
else {
qn=0.5;
un=(3.0/(X[Npt]-X[Npt-1]))*(Ypn-(Y[Npt]-Y[Npt-1])/(X[Npt]-X[Npt-1]));
}
Y2[Npt]=(un-qn*u[Npt-1])/(qn*(Y2[Npt-1])+1.0);
for(k=Npt-1;k>=1;k--) Y2[k]= (Y2[k]*(Y2[k+1]))+u[k];
}
////////////////////////////////////////////////////////////////////////
// Regular spacing
///////////////////////////////////////////////////////////////////////
template<class T>
T
RegCubicSpline<T>::operator()(T r) {
if(r<Xmin) {
return Y[1] + Yp1 * (r - Xmin);
} else if(r<Xmax) {
int i = static_cast<int>((r-Xmin)*DxInv+1);
int ip = i+1;
T rhi = static_cast<T>(i)*Dx+Xmin;
T a=(rhi-r)*DxInv;
T b=(r-rhi+Dx)*DxInv;
return
a*Y[i]+b*Y[ip]+(a*(a*a-1.e0)*Y2[i]+b*(b*b-1.0e0)*Y2[ip])*h2over6;
} else {
return Y[Npt] + Ypn * (r - Xmax);
}
}
template<class T>
T
RegCubicSpline<T>::operator()(T r, T& val) {
if(r<Xmin) {
val =(Y[1] + Yp1 * (r - Xmin))/r;
return Yp1;
} else if(r<Xmax) {
int i = static_cast<int>((r-Xmin)*DxInv+1);
int ip = i+1;
T rhi = static_cast<T>(i)*Dx+Xmin;
T a=(rhi-r)*DxInv;
T b=(r-rhi+Dx)*DxInv;
val = (a*Y[i]+b*Y[ip]+(a*(a*a-1.e0)*Y2[i]+b*(b*b-1.0e0)*Y2[ip])*h2over6)/r;
return -DxInv*(Y[i] -Y[ip] + h2over6*((3*a*a-1)*Y2[i]-(3*b*b-1)*Y2[ip]));
} else {
val= (Y[Npt] + Ypn * (r - Xmax))/r;
return Ypn;
}
}
template<class T>
T
RegCubicSpline<T>::operator()(T r, T& val, T& yp) {
T rinv = 1.0/r;
if(r<Xmin) {
val =(Y[1] + Yp1 * (r - Xmin))*rinv*rinv;
yp = Yp1*rinv;
return 0;
} else if(r<Xmax) {
int i = static_cast<int>((r-Xmin)*DxInv+1);
int ip = i+1;
T rhi = static_cast<T>(i)*Dx+Xmin;
T a=(rhi-r)*DxInv;
T b=(r-rhi+Dx)*DxInv;
val = (a*Y[i]+b*Y[ip]
+(a*(a*a-1.e0)*Y2[i]+b*(b*b-1.0e0)*Y2[ip])*h2over6)*rinv*rinv;
yp = -rinv*DxInv*
(Y[i] -Y[ip] + h2over6*((3*a*a-1)*Y2[i]-(3*b*b-1)*Y2[ip]));
return a*Y2[i]+b*Y2[ip];
} else {
val= (Y[Npt] + Ypn * (r - Xmax))*rinv*rinv;
yp = Ypn*rinv;
return 0;
}
}
template<class T>
void
RegCubicSpline<T>::spline() {
//This is just a modified version of the Numerical Recipes routine spline,
//which generates spline coefficients given a set of spline parameters.
int i,k;
T p,qn,sig,un;
vector<T> u(Npt+1);
if (Yp1 > 0.99e30)
Y2[1]=u[1]=0.0;
else {
Y2[1] = -0.5;
u[1]=(3.0*DxInv)*((Y[2]-Y[1])*DxInv-Yp1);
}
sig=0.5;
for (i=2;i<=Npt-1;i++) {
p=sig*(Y2[i-1])+2.0;
Y2[i]=(sig-1.0)/p;
u[i]=(Y[i+1]+Y[i-1]-2*Y[i])*DxInv;
u[i]=(3.0*u[i]*DxInv-sig*u[i-1])/p;
}
if (Ypn > 0.99e30) qn=un=0.0;
else {
qn=0.5;
un=(3.0*DxInv)*(Ypn-(Y[Npt]-Y[Npt-1])*DxInv);
}
Y2[Npt]=(un-qn*u[Npt-1])/(qn*(Y2[Npt-1])+1.0);
for(k=Npt-1;k>=1;k--) Y2[k]= (Y2[k]*(Y2[k+1]))+u[k];
}
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* POOMA_VERSION_ID: $Id$
***************************************************************************/

View File

@ -0,0 +1,102 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
/***************************************************************************
* This class implements the orthogonal tight-binding model
* for Si proposed by Lenosky, Kress, Kwon, Voter, Edwards, Richards
* Yang, and Adams in PRB 55 (1997) p.1528 using cubic splines
* to parameterize hopping terms and pair-potential.
* Implemented by D. Trinkle July '98 on TBMD
* Implemented by Jeongnim Kim Sep '99
***************************************************************************/
#ifndef CUBICSPLINEFUNCTIONS_H
#define CUBICSPLINEFUNCTIONS_H
#include <vector>
using std::vector;
template<class T>
class CubicSpline{
public:
int Npt;
T Yp1, Ypn;
vector<T> X, Y, Y2;
CubicSpline() { }
inline CubicSpline(const int n) { resize(n);}
inline void resize(const int n) {
Npt = n;
X = vector<T>(n+1); Y = vector<T>(n+1); Y2= vector<T>(n+1);
}
T operator()(T x0);
T operator()(T x0, T& yval);
T operator()(T x0, T& yval, T& yp);
void spline();
void spline(const int n, T* x, T* y, const T yp1, const T ypn){
resize(n);
X[0] = 0.0e0; Y[0] = 0.0e0; // not needed
for(int i=1; i<=n; i++) X[i] = x[i-1];
for(int i=1; i<=n; i++) Y[i] = y[i-1];
Yp1 = yp1; Ypn = ypn;
spline();
}
};
template<class T>
class RegCubicSpline{
int Npt;
T Xmin, Xmax, Dx, DxInv;
T Yp1, Ypn, h2over6;
vector<T> Y, Y2;
public:
RegCubicSpline() { }
inline RegCubicSpline(const int n) { resize(n);}
inline void resize(const int n) {
Npt = n;
Y = vector<T>(n+1); Y2= vector<T>(n+1);
}
T operator()(T x0);
T operator()(T x0, T& yval);
T operator()(T x0, T& yval, T& yp);
void spline();
void spline(const int n, const T x0, const T dx, const T yp1, const T ypn, T* y) {
resize(n);
Dx = dx; DxInv = 1/dx;
h2over6 = dx*dx*0.16666666666666666667e0;
Xmin = x0; Xmax = static_cast<T>(n-1)*dx+x0;
Y[0] = 0;
for(int i=1; i<=n; i++) Y[i] = y[i-1];
Yp1 = yp1;
Ypn = ypn;
spline();
}
};
#include "ScaleFunctors/CubicSplineFunctions.cpp"
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* POOMA_VERSION_ID: $Id$
***************************************************************************/

View File

@ -0,0 +1,161 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
#ifndef OHMMS_NUMERIC_DETERMINANT_H
#define OHMMS_NUMERIC_DETERMINANT_H
#include <algorithm>
#include "OhmmsPETE/OhmmsVector.h"
#include "OhmmsPETE/OhmmsMatrix.h"
#include "Numerics/Blasf.h"
inline void LUFactorization(const int& n, const int& m, double* a, const int& n0,
int* piv) {
int status;
dgetrf(n,m,a,n0,piv,status);
}
inline void LUFactorization(const int& n, const int& m, complex<double>* a, const int& n0,
int* piv) {
int status;
zgetrf(n,m,a,n0,piv,status);
}
inline void InvertLU(const int& n, double* a, const int& n0,
int* piv, double* work, const int& n1){
int status;
dgetri(n,a,n0,piv,work,n1,status);
}
inline double Invert(double* x, int n, int m) {
double detvalue;
if(n == 1) {
detvalue = x[0];
x[0]=1.0/detvalue;
} else {
vector<double> work(n);
vector<int> pivot(n);
LUFactorization(n,m,x,n,&pivot[0]);
detvalue = x[0];
for (int i=1; i<m; ++i) detvalue *= x[i*m+i];
InvertLU(n,x, n, &pivot[0], &work[0], n);
}
/*
switch(n) {
case(1):
detvalue = x[0];
x[0]=1.0/detvalue;break;
case(2):
detvalue = x[0] * x[3] - x[1] * x[2];
double deti = 1.0/detvalue;
x[0] = deti*x[3];
x[1]*=-deti;
x[2]*=-deti;
x[3] = deti*x[0];
break;
defaults:
cout << "using generic inversion " << endl;
vector<double> work(n);
vector<int> pivot(n);
LUFactorization(n,m,x,n,&pivot[0]);
for (int i=1; i<m; ++i) detvalue *= x[i*m+i];
InvertLU(n,x, n, &pivot[0], &work[0], n);
break;
}
*/
// if(n == 1) {
// x[0]=1.0/detvalue;
// } else {
// vector<double> work(n);
// vector<int> pivot(n);
// LUFactorization(n,m,x,n,&pivot[0]);
// for (int i=1; i<m; ++i) detvalue *= x[i*m+i];
// InvertLU(n,x, n, &pivot[0], &work[0], n);
// }
return detvalue;
}
/*!\fn invert_matrix(MatrixA& M, bool getdet)
* \param MatrixA, a matrix to be inverted
* \param bool, if true, calculate the determinant
* \return the determinant
*/
template<class MatrixA>
inline double
invert_matrix(MatrixA& M, bool getdet=true) {
typedef typename MatrixA::value_type value_type;
Vector<int> pivot(M.rows());
Vector<value_type> work(M.rows());
int status;
dgetrf(M.rows(), M.cols(), M.data(), M.rows(), pivot.data(), status);
value_type det0 = 1.0;
if(getdet) {// calculate determinant
int sign = 1;
for(int i=0; i<M.rows(); ++i){
if(pivot[i] != i+1) sign *= -1;
det0 *= M(i,i);
}
det0 *= static_cast<value_type>(sign);
}
dgetri(M.rows(), M.data(), M.rows(), pivot.data(), work.data(),
M.rows(), status);
return det0;
}
template<class MatA, class Iter>
inline
typename MatA::value_type
DetRatio(const MatA& Minv, Iter newrow, int rowchanged) {
typename MatA::value_type res = 0.0;
for(int j=0; j<Minv.cols(); j++,newrow++)
res += Minv(rowchanged,j)*(*newrow);
return res;
}
template<class T, unsigned D>
inline TinyVector<T,D>
dot(const T* a, const TinyVector<T,D>* b, int n) {
TinyVector<T,D> res;
for(int i=0; i<n; i++) res += a[i]*b[i];
return res;
}
template<class T>
inline T dot(const T* restrict a, const T* restrict b, int n) {
T res = 0.0;
for(int i=0; i<n; i++) res += a[i]*b[i];
return res;
}
// template<class T1, class T2>
// inline T2
// dot(const T1* restrict a, const T2* restrict b, int n) {
// T2 res;
// for(int i=0; i<n; i++) res += a[i]*b[i];
// return res;
// }
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,64 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003- by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_SLATERTYPEORBITAL_H
#define OHMMS_SLATERTYPEORBITAL_H
#include <math.h>
/**class for Gaussian-type orbitals
*@f[
*\Psi_{n,l,m}({\bf R}) =N \frac{\exp{-\sigma r^2}}{r^l} \times r^l Y_{lm}(\theta,\phi)
*@f]
*/
template<class T>
struct RadialGaussian {
int L;
T Sigma;
T Norm;
RadialGaussian(): L(0), Sigma(1.0), Norm(1.0) { }
RadialGaussian(int l, double sig, double norm=1.0): L(l), Sigma(sig),Norm(norm) { }
inline void setgrid(T r) { }
inline void evaluate(T r, T rinv) {
Y = evaluate(r,rinv,dY,d2Y);
}
inline T evaluate(T r, T rinv, T& drnl, T& d2rnl) {
if(L) {
T oneoverrl = pow(rinv,L);
T rnl = Norm*exp(-Sigma*r*r)*oneoverrl;
T x = 2.0*Sigma*r+L*rinv;
drnl = -rnl*x;
d2rnl = rnl*(x*x-2.0*Sigma+L*rinv*rinv);
return rnl;
} else {
T rnl = Norm*exp(-Sigma*r*r);
T x = 2.0*Sigma*r;
drnl = -rnl*x;
d2rnl = rnl*(x*x-2.0*Sigma);
return rnl;
}
}
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,316 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_HDF_NUMERICATTRIBIO_H
#define OHMMS_HDF_NUMERICATTRIBIO_H
#include "OhmmsData/HDFAttribIO.h"
#include "OhmmsPETE/OhmmsVector.h"
#include "OhmmsPETE/TinyVector.h"
#include "OhmmsPETE/OhmmsMatrix.h"
#include <blitz/array.h>
/** Specialization for hsize_t */
template<>
struct HDFAttribIO<hsize_t>: public HDFAttribIOBase {
hsize_t& ref;
HDFAttribIO<hsize_t>(hsize_t& a):ref(a) { }
inline void write(hid_t grp, const char* name) {
hsize_t dim = 1;
hid_t dataspace = H5Screate_simple(1, &dim, NULL);
hid_t dataset =
H5Dcreate(grp, name, H5T_NATIVE_INT, dataspace, H5P_DEFAULT);
hid_t ret =
H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,&ref);
H5Sclose(dataspace);
H5Dclose(dataset);
}
inline void read(hid_t grp, const char* name) {
hid_t h1 = H5Dopen(grp, name);
hid_t ret = H5Dread(h1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &ref);
H5Dclose(h1);
}
};
/*
template<unsigned D>
struct HDFAttribIO<TinyVector<double,D> >: public HDFAttribIOBase {
typedef TinyVector<double,D> data_type;
data_type& ref;
HDFAttribIO<data_type>(data_type& a):ref(a) { }
inline void write(hid_t grp, const char* name) {
hsize_t dim = D;
hid_t dataspace = H5Screate_simple(1, &dim, NULL);
hid_t dataset =
H5Dcreate(grp, name, H5T_NATIVE_DOUBLE, dataspace, H5P_DEFAULT);
hid_t ret =
H5Dwrite(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT,&(ref[0]));
H5Sclose(dataspace);
H5Dclose(dataset);
}
inline void read(hid_t grp, const char* name) {
hid_t h1 = H5Dopen(grp, name);
hid_t ret = H5Dread(h1, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &(ref[0]));
H5Dclose(h1);
}
};
*/
/** Specialization for Vector<double> */
template<>
struct HDFAttribIO<Vector<double> >: public HDFAttribIOBase {
typedef Vector<double> ArrayType_t;
ArrayType_t& ref;
HDFAttribIO<ArrayType_t>(ArrayType_t& a):ref(a) { }
inline void write(hid_t grp, const char* name) {
hsize_t dim = ref.size();
hid_t dataspace = H5Screate_simple(1, &dim, NULL);
hid_t dataset =
H5Dcreate(grp, name, H5T_NATIVE_DOUBLE, dataspace, H5P_DEFAULT);
hid_t ret =
H5Dwrite(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref.data());
H5Sclose(dataspace);
H5Dclose(dataset);
}
inline void read(hid_t grp, const char* name) {
hid_t h1 = H5Dopen(grp, name);
hid_t dataspace = H5Dget_space(h1);
hsize_t dims_out[1];
int rank = H5Sget_simple_extent_ndims(dataspace);
int status_n = H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
if(ref.size() != int(dims_out[0])){
ref.resize(int(dims_out[0]));
}
hid_t ret = H5Dread(h1, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, ref.data());
H5Sclose(dataspace);
H5Dclose(h1);
}
};
/** Specialization for Vector<int> */
template<>
struct HDFAttribIO<Vector<int> >: public HDFAttribIOBase {
typedef Vector<int> ArrayType_t;
ArrayType_t& ref;
HDFAttribIO<ArrayType_t>(ArrayType_t& a):ref(a) { }
inline void write(hid_t grp, const char* name) {
hsize_t dim = ref.size();
hid_t dataspace = H5Screate_simple(1, &dim, NULL);
hid_t dataset =
H5Dcreate(grp, name, H5T_NATIVE_INT, dataspace, H5P_DEFAULT);
hid_t ret =
H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref.data());
H5Sclose(dataspace);
H5Dclose(dataset);
}
inline void read(hid_t grp, const char* name) {
hid_t h1 = H5Dopen(grp, name);
hid_t dataspace = H5Dget_space(h1);
hsize_t dims_out[1];
int rank = H5Sget_simple_extent_ndims(dataspace);
int status_n = H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
if(ref.size() != int(dims_out[0])){
ref.resize(int(dims_out[0]));
}
hid_t ret = H5Dread(h1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, ref.data());
H5Sclose(dataspace);
H5Dclose(h1);
}
};
/** Specialization for Matrix<double> */
template<>
struct HDFAttribIO<Matrix<double> >: public HDFAttribIOBase {
typedef Matrix<double> ArrayType_t;
ArrayType_t& ref;
HDFAttribIO<ArrayType_t>(ArrayType_t& a):ref(a) { }
inline void write(hid_t grp, const char* name) {
hsize_t dim = ref.size();
hid_t dataspace = H5Screate_simple(1, &dim, NULL);
hid_t dataset =
H5Dcreate(grp, name, H5T_NATIVE_DOUBLE, dataspace, H5P_DEFAULT);
hid_t ret =
H5Dwrite(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref.data());
H5Sclose(dataspace);
H5Dclose(dataset);
}
inline void read(hid_t grp, const char* name) {
hid_t h1 = H5Dopen(grp, name);
hid_t ret = H5Dread(h1, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, ref.data());
H5Dclose(h1);
}
};
/** Specialization for blitz::Array<TinyVector<double,D>,2> */
template<unsigned D>
struct HDFAttribIO<blitz::Array<TinyVector<double,D>,2> >: public HDFAttribIOBase {
typedef blitz::Array<TinyVector<double,D>,2> ArrayType_t;
ArrayType_t& ref;
HDFAttribIO<ArrayType_t>(ArrayType_t& a):ref(a) { }
inline void write(hid_t grp, const char* name) {
int rank = 3;
hsize_t dim[rank];
dim[0] = ref.extent(0);
dim[1] = ref.extent(1);
dim[2] = D;
hid_t dataspace = H5Screate_simple(rank, dim, NULL);
hid_t dataset =
H5Dcreate(grp, name, H5T_NATIVE_DOUBLE, dataspace, H5P_DEFAULT);
hid_t ret =
H5Dwrite(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref.data());
H5Sclose(dataspace);
H5Dclose(dataset);
}
inline void read(hid_t grp, const char* name) {
hid_t h1 = H5Dopen(grp, name);
hid_t dataspace = H5Dget_space(h1);
hsize_t dims_out[3];
int rank = H5Sget_simple_extent_ndims(dataspace);
int status_n = H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
if((ref.extent(0) != (unsigned long)dims_out[0]) || (ref.extent(1) != (unsigned long)dims_out[1])){
// cout << "dimensions not equal" << endl;
ref.resize(dims_out[0],dims_out[1]);
}
hid_t ret = H5Dread(h1, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, ref.data());
H5Dclose(h1);
}
};
/** Specialization for Vector<TinyVector<double,D> > */
template<unsigned D>
struct HDFAttribIO<Vector<TinyVector<double,D> > >: public HDFAttribIOBase {
typedef Vector<TinyVector<double,D> > ArrayType_t;
ArrayType_t& ref;
HDFAttribIO<ArrayType_t>(ArrayType_t& a):ref(a) { }
inline void write(hid_t grp, const char* name) {
hsize_t dim[2] = {ref.size(), D};
hid_t dataspace = H5Screate_simple(2, dim, NULL);
hid_t dataset =
H5Dcreate(grp, name, H5T_NATIVE_DOUBLE, dataspace, H5P_DEFAULT);
hid_t ret =
H5Dwrite(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref.data());
H5Sclose(dataspace);
H5Dclose(dataset);
}
inline void read(hid_t grp, const char* name) {
hid_t h1 = H5Dopen(grp, name);
hid_t dataspace = H5Dget_space(h1);
hsize_t dims_out[2];
int rank = H5Sget_simple_extent_ndims(dataspace);
int status_n = H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
if(ref.size() != (unsigned long)dims_out[0]){
// cout << "dimensions not equal" << endl;
ref.resize(dims_out[0]);
}
hid_t ret = H5Dread(h1, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, ref.data());
H5Dclose(h1);
}
};
/** Specialization for string */
template<>
struct HDFAttribIO<string>: public HDFAttribIOBase {
typedef string ArrayType_t;
ArrayType_t& ref;
hid_t str80;
HDFAttribIO<ArrayType_t>(ArrayType_t& a): ref(a) {
str80 = H5Tcopy(H5T_C_S1);
H5Tset_size(str80,80);
}
inline void write(hid_t grp, const char* name) {
hsize_t dim = 1;
hid_t dataspace = H5Screate_simple(1, &dim, NULL);
hid_t dataset =
// H5Dcreate(grp, name, H5T_NATIVE_CHAR, dataspace, H5P_DEFAULT);
H5Dcreate(grp, name, str80, dataspace, H5P_DEFAULT);
hid_t ret =
// H5Dwrite(dataset, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref.data());
H5Dwrite(dataset, str80, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref.data());
H5Sclose(dataspace);
H5Dclose(dataset);
}
inline void read(hid_t grp, const char* name) {
hid_t h1 = H5Dopen(grp, name);
hid_t dataspace = H5Dget_space(h1);
hsize_t dims_out[1];
// int rank = H5Sget_simple_extent_ndims(dataspace);
// int status_n = H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
// if(ref.size() != (unsigned long)dims_out[0]){
// cout << "dimensions not equal" << endl;
// ref.resize(dims_out[0]);
// }
hid_t ret = H5Dread(h1, str80, H5S_ALL, H5S_ALL, H5P_DEFAULT, &ref);
H5Dclose(h1);
}
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,46 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 1998-2002 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_LIBXML_NUMERICATTRIBIO_H
#define OHMMS_LIBXML_NUMERICATTRIBIO_H
#include "OhmmsData/libxmldefs.h"
#include "OhmmsPETE/OhmmsVector.h"
#include "OhmmsPETE/OhmmsMatrix.h"
/*!\fn bool putContent(std::Matrix<T>& a, xmlNodePtr cur)
*\brief assign vector<T> from a node. Create a temporary vector and make assignment.
*\param a reference vector<T>
*\param cur current node to which a content is copied
*\return ture if successful
*/
template<class T>
inline bool
putContent(Matrix<T>& a, xmlNodePtr cur){
std::istringstream
stream((const char*)
(xmlNodeListGetString(cur->doc, cur->xmlChildrenNode, 1)));
int i=0;
while(!stream.eof()){ stream >> a(i++);}
return true;
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

84
src/Numerics/MatGrid1D.h Normal file
View File

@ -0,0 +1,84 @@
#ifndef GUARD_MATGRID1D_H
#define GUARD_MATGRID1D_H
#include <vector>
#include "Numerics/Spline3D/Config.h"
#include "Numerics/Spline3D/Grid1D.h"
class MatGrid1D{
public:
/// number of different grid density sections (regions)
int nsecs_m;
/// starting coordinate of grid
int ix0_m;
/// the axis of the grid: namely the z direction z = 2;
int iaxis;
/// the vector containing the intervals and properties
std::vector<int> d_ivals;
std::vector<int> prior_m;
std::vector<double> prop_m;
std::vector<double> dx_ivals;
/// the constructor
MatGrid1D(int nsections){
nsecs_m = nsections;
d_ivals.resize(nsecs_m+1);
dx_ivals.resize(nsecs_m+1);
prop_m.resize(nsecs_m);
prior_m.resize(nsecs_m);
cout << "material Grid:" << nsecs_m << endl;
}
/// initialise with the entire data from input
inline void init(const Grid1D& aGrid1D,
const std::vector<int>& ix,
const std::vector<int>& prior,
const std::vector<double>& props){
d_ivals[0] = 0; dx_ivals[0] = aGrid1D.d_x[d_ivals[0]];
for( int isec = 0; isec < prop_m.size(); isec++){
d_ivals[isec+1] = ix[isec+1];
dx_ivals[isec+1] = aGrid1D.d_x[d_ivals[isec+1]];
prop_m[isec] = props[isec];
prior_m[isec] = prior[isec];
}
}
/// get the property of the material
inline double prop(double x){
double property; bool flag=true;
for(int isec = 0; isec < nsecs_m; isec++){
double xsec = dx_ivals[isec+1];
if( flag && x < xsec ){
property = prop_m[isec]; flag = false;
} else if( flag && x == xsec ){
int jsec = (prior_m[isec+1] > prior_m[isec]) ? isec + 1 : isec;
property = prop_m[jsec];
flag = false;
}
}
return property;
}
};
#endif

View File

@ -0,0 +1,57 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_NR_CUBICSPLINE_H
#define OHMMS_NR_CUBICSPLINE_H
/**template function: converted from Numerical Recipe spline.c
*note that the range of data is [0,n) instead of [1,n]
*/
template<class T>
inline void
NRCubicSpline(const T* x, const T* y, int n, T yp1, T ypn, T* y2) {
int i,k;
T p,qn,sig,un;
vector<T> u(n);
if (yp1 > 0.99e30)
y2[0]=u[0]=0.0;
else {
y2[0] = -0.5;
u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yp1);
}
for (i=1;i<n-1;i++) {
sig=(x[i]-x[i-1])/(x[i+1]-x[i-1]);
p=sig*y2[i-1]+2.0;
y2[i]=(sig-1.0)/p;
u[i]=(y[i+1]-y[i])/(x[i+1]-x[i]) - (y[i]-y[i-1])/(x[i]-x[i-1]);
u[i]=(6.0*u[i]/(x[i+1]-x[i-1])-sig*u[i-1])/p;
}
if (ypn > 0.99e30)
qn=un=0.0;
else {
qn=0.5;
un=(3.0/(x[n-1]-x[n-2]))*(ypn-(y[n-1]-y[n-2])/(x[n-1]-x[n-2]));
}
y2[n-1]=(un-qn*u[n-2])/(qn*y2[n-2]+1.0);
for (k=n-2;k>=0;k--)
y2[k]=y2[k]*y2[k+1]+u[k];
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

287
src/Numerics/Numerov.h Normal file
View File

@ -0,0 +1,287 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim and Jordan Vincent
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef NUMEROVCLASS_H
#define NUMEROVCLASS_H
/**@defgroup NumerovTransform
*@brief Transform functors which provide interfaces to Numerov<ST,FT>.
*
*The prototype: "template<class SourceType> ATransformFunctor",
*where SourceType encapsulates the form of an external potential.
*
*For examples, the RegularLinearTransform is implemented to solve
*Radial Schrodinger equation
*\f[ \frac{d^2R_{nl}}{dr^2}+k^2(r) R_{nl} = 0, \f] where
*\f[k^2(r)=2[\varepsilon-\frac{L(L+1)}{2r^2}-V(r)], \f] and
*\f$ V(r) \f$ is a radial potential on a linear grid.
*
*/
/** Generic class to solve eigen problems using the Numerov
*Integration Algorithm.
*
*Solve second order differential equations of the form
\f[\frac{d^2y}{dx^2} + k^2(x)y = S(x)\f]
using the Numerov algorithm
\f[
(1+\frac{h^2}{12}k^2_{n+2})y_{n+2} -
2(1-\frac{5h^2}{12}k^2_{n+1})y_{n+1} + (1+\frac{h^2}{12}k^2_n)y_n =
\frac{h^2}{12}(S_{n+2}+10S_{n+1}+S_n) + \mathcal{O}(h^6), \f] by
solving for \f$y_{n+2}\f$ and recursively integrating forward in x.
The boundary conditons being \f$y_0 = y(x_0)\f$ and \f$y_1 = y(x_1).\f$
*
* Two template parameters are required:
- ST: source functor type, e.g., the transform functors in
\ref NumerovTransform.
- FT: grid functor type for the solution \f$y(x)\f$ and \f$V(x)\f$
for \f$k^2(\epsilon,V(x))\f$.
*
*See \ref numerov_sec "Numerov algorihm".
*
*Specifically, the source functor should implement
- value_type ST::setCusp(int i, value_type& z0, value_type& z1)
- int ST::first() the first valid index for the grid
- value_type ST::ke(i)
- value_type ST::convert(value_type Z(x), x)
*
*/
template<class ST, class FT>
class Numerov {
public:
enum {lower_energy=-1, nothing, raise_energy};
typedef typename FT::value_type value_type;
typedef typename FT::data_type data_type;
///constructor with source V(x) and target solution f(x) and TransForm y
Numerov(ST& y, FT& f): Y(y), Target(f) {
Z.resize(Target.size());
//save the derivate of the first grid
Y.setCusp(Y.first(), Target0, Target1);
}
int evaluate(value_type e);
/**
*\param lowerin lower bound for the eigen energy
*\param upperin upper bound for the eigen energy
*\param etol the energy tolerance
*\return the eigen energy
*\brief Solve for the eigen energy and eigen function self
consistently.
*/
inline value_type solve(value_type lowerin, value_type upperin,
value_type etol) {
value_type lower = lowerin;
value_type upper = upperin;
value_type trialenergy=0.5*(lower+upper);
value_type oldenergy = upper;
int modifier = nothing;
do{
modifier = evaluate(trialenergy);
if(modifier == raise_energy) lower = trialenergy;
if(modifier == lower_energy) upper = trialenergy;
oldenergy = trialenergy;
trialenergy=0.5*(lower+upper);
} while((fabs(trialenergy-oldenergy))>etol);
return trialenergy;
}
/**
*\param e reference eigenvalue
*\brief Reset the reference eigen energy for \f$k^2(\epsilon, V(x))\f$
*and the classical TurningPoint \f$i\f$, where
*\f$k^2(\epsilon,V(x_{i})) < 0\f$ and \f$k^2(\epsilon,V(x_{i-1})) > 0\f$
*/
inline void reset(value_type e) {
Target.m_Y = 0.0;
TurningPoint = 0;
Y.reset(e);
int i=Target.size()-2;
while(i > 1 && Y.ke(i)<0) {
i--;
}
TurningPoint = i;
}
private:
///engine that takes care of the transformation of variables
ST& Y;
///real function that holds solution
FT& Target;
///solution by Numerov Target <-> TransForm::convert(Z)
data_type Z;
///cusp condition
value_type Target0, Target1;
///the maximum size of physical data
int TurningPoint;
///index reserved to truncate the data
int Current;
};
/**
*\param e reference eigen energy for \f$k^2(\epsilon, V(x))\f$
*\return integer flag for the change of the reference eigen energy
*/
template<class TransForm, class FT>
inline
int Numerov<TransForm,FT>::evaluate(value_type e) {
reset(e);
const value_type MAX_VALUE = 1000;
value_type dh2 = Target.dh()*Target.dh();
value_type tentwelfth = 0.8333333333333333333333333333333333333333333333*dh2;
value_type onetwelfth = 0.0833333333333333333333333333333333333333333333*dh2;
//get the first index
int first = Y.first();
int second = first+1;
Z[first] = Target0;
Z[second] = Target1;
value_type r0 = Target.r(first);
value_type r1 = Target.r(second);
value_type ke_m2 = Y.ke(first);
value_type ke_m = Y.ke(second);
value_type y_m2 = Z[first];
value_type y_m = Z[second];
//set the wave function
Target(first) = Y.convert(y_m2,r0);
Target(second) = Y.convert(y_m,r1);
int num_nodes = 0;
int nodes_to_find = Y.nodes();
//not meaningful turning point, raise the energy
if(TurningPoint == 1) return raise_energy;
int e_mode =nothing;
int i=first+2;
while(i<=TurningPoint+2) {
//get the radius of the current index
r0 = Target.r(i);
//get k^2
value_type ke = Y.ke(i);
value_type y =
((2.0-tentwelfth*ke_m)*y_m -
(1.0+onetwelfth*ke_m2)*y_m2)/(1.0+onetwelfth*ke);
Z[i] = y;
//avoid exponential solution
if(fabs(y)>MAX_VALUE) {
value_type yinv = 1.0/y;
for(int j=0; j<=i; j++) Z[j]*=yinv;
y_m2*=yinv;
y_m*=yinv;
y = 1.0;
}
//check the node
if(y_m*y < 0.0) {
num_nodes++;
if( num_nodes > nodes_to_find) {
return lower_energy;
}
}
ke_m2 = ke_m;
ke_m = ke;
y_m2 = y_m;
y_m = y;
Target(i) = Y.convert(Z[i],r0);
i++;
}
if(e_mode == nothing) {
i = TurningPoint+3;
while(i<=Target.size()-2) {
r0 = Target.r(i);
//get k^2
value_type ke = Y.ke(i);
value_type y
= ((2.0-tentwelfth*ke_m)*y_m - (1.0+onetwelfth*ke_m2)*y_m2)
/(1.0+onetwelfth*ke);
Z[i] = y;
//growing beyond the turning point
if(y/y_m > 1) {
return raise_energy;
}
if(fabs(y)>MAX_VALUE) {
value_type yinv = 1.0/y;
for(int j=0; j<=i; j++) Z[j]*=yinv;
y_m2*=yinv;
y_m*=yinv;
y = 1.0;
}
if(y_m*y < 0.0) {
num_nodes++;
if(num_nodes > nodes_to_find) return lower_energy;
}
//assign numerov value to the real function
ke_m2 = ke_m;
ke_m = ke;
y_m2 = y_m;
y_m = y;
Target(i) = Y.convert(Z[i],r0);
i++;
}
}
if( num_nodes < nodes_to_find )
return raise_energy;
else
return nothing;
}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,223 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_GRID_FUNCTOR_CUBIC_SPLINE_H
#define OHMMS_GRID_FUNCTOR_CUBIC_SPLINE_H
#include "Numerics/OneDimGridFunctor.h"
#include "Numerics/NRSplineFunctions.h"
/**Perform One-Dimensional Cubic Spline Interpolation.
*
Given a function evaluated on a grid \f$ \{x_i\},
i=1\ldots N, \f$ such that \f$ y_i = y(x_i), \f$ we would like to
interpolate for a point \f$ x \f$ in the interval \f$ [x_j,x_{j+1}]. \f$
The linear interpolation formula
\f[
y = Ay_j + By_{j+1}
\f]
where
\f[
A = \frac{x_{j+1}-x}{x_{j+1}-x_j} \;\;\;\;\;\;\;\;\;\;\;\;\;
B = 1-A = \frac{x-x_{j+1}}{x_{j+1}-x_j}
\f]
Satisfies the conditions at the endpoints \f$ x_j \mbox{ and } x_{j+1},\f$
but suffers from some major drawbacks. The problem with this approach is
that over the range of the function \f$ [x_1,x_N] \f$ we have a series of
piecewise linear equations with a zero second derivative within each interval
and an undefined or infinite second derivative at the interval boundaries,
the grid points \f$ \{x_i\}. \f$ Ideally we would like to construct an
interpolation function with a smooth first derivate and a continuous second
derivative both within the intervals and at the the grid points.
By adding a cubic polynomial to the linear interpolation equation within
each interval, we can construct an interpolation function that varies
linearly in the second derivative. Assume for a moment that we have the
values of the second derivative evaluated at each grid point,
\f$ y_i'' = d^2y(x_i)/dx^2, i=1\ldots N. \f$ Now we can construct a cubic
polynomial that has the correct second derivatives \f$y_j'' \mbox{ and }
y_{j+1}''\f$ at the endpoints and also evaluates to zero at the endpoints.
The reason the polynomial must be zero at the endpoints is to not spoil
the agreement that is already built into the linear function. A function
constructed from these principals is given by the equation
\f[
y = Ay_j + By_{j+1} + Cy_j'' + Dy_{j+1}''
\f]
where
\f[
C = \frac{1}{6}(A^3-A)(x_{j+1}-x_j)^2 \;\;\;\;\;\;\;
D = \frac{1}{6}(B^3-B)(x_{j+1}-x_j)^2.
\f]
To explictly check that this function does indeed satisfy the conditions
at the endpoints take the derivatives
\f[
\frac{dy}{dx} = \frac{y_{j+1}-y_j}{x_{j+1}-x_j}
- \frac{3A^2-1}{6}(x_{j+1}-x_j)y_j''
+ \frac{3B^2-1}{6}(x_{j+1}-x_j)y_{j+1}''
\f]
and
\f[
\frac{d^2y}{dx^2} = Ay_j'' + By_{j+1}''.
\f]
The second derivative is continuous across the boundary between two
intervals, e.g. \f$ [x_{j-1},x_j] \f$ and \f$ [x_j,x_{j+1}], \f$ and
obeys the conditions at the endpoints since at \f$ x=x_j, (A=1,B=0) \f$
and at \f$ x=x_{j+1}, (A=0,B=1). \f$
We had made the assumption that the values of the second derivative are
known at the grid points, which they are not. By imposing the condition
that the first derivative is smooth and continuous across the boundary
between two intervals it is possible to derive a set of equations to
generate the \f$ y_i''\f$'s. Evaluate the equation for the first
derivative at \f$x=x_j\f$ in the inverval \f$ [x_{j-1},x_j] \f$ and set
it equal to the same equation evaluated at \f$x=x_j\f$ in the inverval
\f$ [x_j,x_{j+1}]; \f$ rearranging the terms
\f[
\frac{x_j-x_{j+1}}{6}y_{j+1}'' + \frac{x_{j+1}-x_{j-1}}{3}y_j''
+ \frac{x_{j+1}-x_j}{6}y_{j+1}'' = \frac{y_{j+1}-y_j}{x_{j+1}-x_j}
- \frac{y_j-y_{j+1}}{x_j-x_{j+1}},
\f]
where \f$ j=2\ldots N-1.\f$ To generate a unique solution for the system
of \f$N-2\f$ equations we have to impose boundary conditions at \f$x_1
\mbox{ and } x_N,\f$ the possibilities being either to set \f$y_1''
\mbox{ and } y_N''\f$ to zero, the natural cubic spline, or, if you want
to make the first derivative at the boundaries to have a specified value,
use \f$y_1' \mbox{ and } y_N'\f$ to calculate the second derivatives at
the endpoints using equation.
*
*/
template <class Td,
class Tg = double,
class CTd= Vector<Td>,
class CTg= Vector<Tg> >
class OneDimCubicSpline: public OneDimGridFunctor<Td,Tg,CTd,CTg> {
public:
typedef OneDimGridFunctor<Td,Tg,CTd,CTg> base_type;
typedef typename base_type::value_type value_type;
typedef typename base_type::point_type point_type;
typedef typename base_type::data_type data_type;
typedef typename base_type::grid_type grid_type;
point_type r_min;
point_type r_max;
value_type first_deriv;
value_type last_deriv;
OneDimCubicSpline(grid_type* gt = NULL):base_type(gt) { }
template<class VV>
OneDimCubicSpline(grid_type* gt, const VV& nv):
base_type(gt),first_deriv(0.0),last_deriv(0.0)
{
m_Y.resize(nv.size());
std::copy(nv.begin(), nv.end(), m_Y.data());
}
/*
OneDimCubicSpline(grid_type* gt,
const std::vector<Td>& nv):
base_type(gt),first_deriv(0.0),last_deriv(0.0)
{
m_Y.resize(nv.size());
std::copy(nv.begin(), nv.end(), m_Y.data());
}
*/
/**
*@param r the radial distance
*@param du return the derivative
*@param d2u return the 2nd derivative
*@return the value of the function
*@brief Use the formula for the Cubic Spline
*Interpolation to evaluate the function and its
*derivatives.
*@note Must first call the function setgrid to
*determine the interval on the grid which contains r.
*/
inline value_type
splint(point_type r, value_type& du, value_type& d2u) {
if(r<r_min) {
//linear-extrapolation returns y[0]+y'*(r-r[0])
du = first_deriv;
d2u = 0.0;
return m_Y[0]+first_deriv*(r-r_min);
}
if(r<r_max) {
const double onesixth = 1.0/6.0;
//first set Loc for the grid
int klo = m_grid->Loc;
int khi = klo+1;
point_type h = m_grid->dr(klo);
point_type hinv = 1.0/h;
point_type h6 = h*onesixth;
point_type hh6 = h6*h;
point_type A = (m_grid->r(khi)-r)*hinv;
point_type dA = -hinv;
point_type B = (r-m_grid->r(klo))*hinv;
point_type dB = hinv;
point_type C = A*(A*A-1.0)*hh6;
point_type dC = -h6*(3*A*A-1.0);
point_type D = B*(B*B-1.0)*hh6;
point_type dD = h6*(3*B*B-1.0);
du = dA*m_Y[klo]+dB*m_Y[khi]+ dC*m_Y2[klo] + dD*m_Y2[khi];
d2u = A*m_Y2[klo] + B*m_Y2[khi];
return A*m_Y[klo]+B*m_Y[khi]+C*m_Y2[klo]+D*m_Y2[khi];
} else {
du = 0.0; d2u = 0.0; return 1e-20;
}
}
/**
*\param imin the index of the first valid data point
*\param yp1 the derivative at the imin-th grid point
*\param imax the index of the last valid data point
*\param ypn the derivative at the imax-th grid point
*\brief Evaluate the 2nd derivate on the grid points for
*splint given the boundary conditions.
*
*In general, a grid is shared by several OneDimCubicSpline objects
*and each object can have its own range of valid grid points.
*r_min and r_max are used to specify the range.
*/
inline
void spline(int imin, value_type yp1, int imax, value_type ypn) {
first_deriv = yp1;
last_deriv = ypn;
r_min = m_grid->r(imin);
r_max = m_grid->r(imax);
m_Y2.resize(size());
m_Y2 = 0.0;
NRCubicSpline(m_grid->data()+imin, m_Y.data()+imin,
size()-imin, yp1, ypn, m_Y2.data()+imin);
}
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,211 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_ONEDIMGRID_BASE
#define OHMMS_ONEDIMGRID_BASE
/**@file OneDimGridBase.h
*@brief Decalaration of One-Dimesional grids
*/
#include <algorithm>
#include "OhmmsPETE/OhmmsVector.h"
/** An abstract base class to implement a One-Dimensional grid */
template <class T, class CT=Vector<T> >
struct OneDimGridBase {
typedef T value_type;
typedef CT Array_t;
///the current index of the grid
int Loc;
///differential spacing of the grid
T Delta;
///array to store the radial grid data
Array_t X;
///assign a value
inline T& operator[](int i) { return X[i];}
///assign a value
inline T& operator()(int i) { return X[i];}
///return a value
inline T operator[](int i) const { return X[i];}
///return a value
inline T operator()(int i) const { return X[i];}
inline const T* restrict data() const { return &(X[0]);}
inline T* restrict data() { return &(X[0]);}
///return the differential spacing of the grid
inline T dh() const { return Delta;}
///returns \f$r(i)\f$
inline T r(int i) const {return X[i];}
///returns \f$r(i+1)-r(i)\f$
inline T dr(int i) const { return X[i+1]-X[i];}
///returns the size of the grid
inline int size() const { return X.size();}
///return the first grid point
inline T rmin() const { return X[0];}
///return the last grid point
inline T rmax() const { return X[X.size()-1];}
///assign and return the index for radial point r
virtual int index(T r) = 0;
/**
*@param ri initial grid point
*@param rf final grid point
*@param n number of grid points
*@brief Set the grid given the parameters.
*/
virtual void set(T ri, T rf, int n) = 0;
};
/** One-Dimensional linear-grid.
*
* The analytic form \f[ r_i = r_0 +
* i\left( \frac{r_f - r_0}{N-1} \right), \f]
* where \f$ N \f$ is the number of points and the index
* \f$ i \f$ runs from 0 to \f$ N-1 \f$
*/
template <class T, class CT=Vector<T> >
struct LinearGrid: public OneDimGridBase<T,CT> {
// T Delta;
T DeltaInv;
inline int index(T r) {
return Loc = static_cast<int>((r-X[0])*DeltaInv);
}
inline void set(T ri, T rf, int n) {
// Delta is the differential spacing
X.resize(n);
Delta = (rf-ri)/static_cast<T>(n-1);
DeltaInv = 1.0/Delta;
X[0] = ri;
for(int i=0; i<n-1; i++) X[i+1] = X[i]+Delta;
}
};
/** One-Dimensional logarithmic-grid.
*
* The analytic form \f[ r_i = r_0
* \left( \frac{r_f}{r_0} \right) ^{\frac{i}{N-1}}, \f]
* where \f$ N \f$ is the number of points and the index
* \f$ i \f$ runs from 0 to \f$ N-1 \f$
*/
template <class T, class CT=Vector<T> >
struct LogGrid: public OneDimGridBase<T,CT> {
// T Delta;
T OneOverLogDelta;
inline int index(T r){
return Loc = static_cast<int>(log(r/X[0])*OneOverLogDelta);
}
inline void set(T ri, T rf, int n) {
// r(i) = ri*(rf/ri)^(i/(n-1))
// this expression is equal to:
// r(i) = ri*exp(dlog_ratio*i)
// where dlog_ratio = (1/(n-1))*log(rf/ri)
// dlog_ratio is the differential spacing
T ratio = rf/ri;
T log_ratio = log(ratio);
T dlog_ratio = log_ratio/static_cast<T>(n-1);
T expdr = exp(dlog_ratio);
X.resize(n);
X[0] = ri;
for(int i=0; i < n-1; i++) {
X[i+1] = X[i]*expdr;
}
Delta = dlog_ratio;
OneOverLogDelta = 1.0/Delta;
}
};
/**One-Dimensional logarithmic-grid starting at the
*origin (Used in Siesta).
*
* The analytic form \f[ r_i = B
* \left[ \exp(Ai)-1 \right] , \f]
* where the number of points is \f$ N \f$ and the index
* \f$ i \f$ runs from 0 to \f$ N-1 \f$
*/
template <class T, class CT=Vector<T> >
struct LogGridZero: public OneDimGridBase<T,CT> {
T OneOverA;
T OneOverB;
inline int index(T r){
return Loc = static_cast<int>(log(r*OneOverB+1.0)*OneOverA);
}
inline void set(T a, T b, int n) {
OneOverA = 1.0/a;
OneOverB = 1.0/b;
X.resize(n);
for(int i=0; i<n; i++)
X[i] = b*exp(a*i)-b;
Delta = 0.0;
}
};
/** One-Dimensional numerical grid with arbitrary grid spacings.
*
* Non-Analytic grid, uses an array of values
* (typically read in from a file).
*/
template <class T, class CT=Vector<T> >
struct NumericalGrid: public OneDimGridBase<T,CT> {
template<class VA>
NumericalGrid(const VA& nv) {
// NumericalGrid(const std::vector<T>& nv) {
X.resize(nv.size());
std::copy(nv.begin(), nv.end(), X.data());
}
int index(T r){
int k;
int klo=0;
int khi=size()-1;
while(khi-klo > 1){
k=(khi+klo) >> 1;
if(X[k] > r) khi=k;
else klo=k;
}
return Loc = klo;
}
inline void set(T ri, T rf, int n) {
X.resize(n);
Delta = 0.0;
}
};
template<class T>
ostream& operator<<(ostream& out, const OneDimGridBase<T>& rhs)
{
for(int i=0; i<rhs.size(); i++)
out << i << " " << rhs.r(i) << " " << rhs.dr(i)<< endl;
return out;
}
#endif

View File

@ -0,0 +1,183 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003 by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_GRID_FUNCTOR_H
#define OHMMS_GRID_FUNCTOR_H
#include "Numerics/OneDimGridBase.h"
template<class T, unsigned D>
struct FunctorBase { };
/** Implement One-Dimensional function on a radial grid.
*\brief Store the values of the function for the
*cooresponding grid points, \f$ y_i = y(x_i) \f$.
*/
template <class Td,
class Tg = double,
class CTd= Vector<Td>,
class CTg= Vector<Tg> >
struct OneDimGridFunctor//: public FunctorBase<Td,1> {
{
typedef Td value_type;
typedef Tg point_type;
typedef CTd data_type;
typedef OneDimGridBase<Tg,CTg> grid_type;
typedef OneDimGridFunctor<Td,Tg,CTd,CTg> this_type;
/**constructor
*@param gt the radial grid
*/
OneDimGridFunctor(grid_type* gt = NULL): m_grid(gt) {
if(m_grid) resize(m_grid->size());
}
///copy constructor
OneDimGridFunctor(const this_type& a): m_grid(a.m_grid) {
if(m_grid) resize(m_grid->size());
}
///assignment operator
const this_type& operator=(const this_type& a) {
m_grid = a.m_grid;
m_Y = a.m_Y;
m_Y2 = a.m_Y2;
return *this;
}
template<class T1>
const this_type& operator=(const T1& x) {
Y = x;
return *this;
}
///set the number of nodes
inline void setNumOfNodes(int n) { NumNodes = n;}
///return the number of nodes
inline int getNumOfNodes() const { return NumNodes;}
///return the grid data
inline value_type* data() { return &(m_Y[0]);}
///assign the grid data
inline const value_type* data() const { return &(m_Y[0]);}
///return the number of data points
inline int size() const { return m_Y.size();}
///resize the number of data points
inline void resize(int n) { m_Y.resize(n);}
///return the radial grid
inline const grid_type& grid() const { return *m_grid;}
///assign a radial grid
inline grid_type& grid() { return *m_grid;}
///set the index of the grid for radius r
inline int setgrid(point_type r) {
return m_grid->index(r);
}
/**return the differntial spacing for the grid
*@warning only for LinearGrid and LogGrid
*/
inline point_type dh() const { return m_grid->dh();}
///return \f$r(i)\f$ the grid point at index i
inline point_type r(int i) const { return m_grid->r(i);}
///return \f$r(i+1)-r(i)\f$
inline point_type dr(int i) const { return m_grid->dr(i);}
/**
*@param r radial distance
*@return the value of the function
*@brief Evaluate the function and its derivatives, store the
*values of the derivatives.
*@note This should not be called frequently: only for the
*transform function (Transform2GridFunctor)
*/
inline value_type f(point_type r) {
setgrid(r);
return splint(r,dY,d2Y);
}
/**
*@param r radial distance
*@return the derivative of the function
*@brief Evaluate the function and its derivatives, store the
*values of the derivatives.
*@note This should not be called frequently: only for the
*transform function (Transform2GridFunctor)
*/
inline value_type df(point_type r) {
setgrid(r);
splint(r,dY,d2Y);
return dY;
}
///returns a value
inline value_type operator()(int i) const { return m_Y[i];}
///assign a value
inline value_type& operator()(int i) { return m_Y[i];}
/**Evaluate the function and its derivatives.
*@note Must first call the function setgrid to
*determine the interval on the grid which contains r.
*/
inline value_type evaluate(point_type r, point_type rinv) {
return Y = splint(r,dY,d2Y);
}
virtual
value_type
splint(point_type r, value_type& du, value_type& d2u) { return 0.0; }
virtual void spline(int imin, value_type yp1, int imax, value_type ypn) { }
/**
*@param r radial distance
*@param rinv inverse of radial distance
*@param du return derivative
*@param d2u return 2nd derivative
*@return the value of the function
*@brief Evaluate the function and its derivatives.
*/
inline value_type
evaluate(point_type r, point_type rinv, value_type& du, value_type& d2u) {
return splint(r,du,d2u);
}
///pointer to the radial grid
grid_type* m_grid;
///store the value of the function
value_type Y;
///store the derivative of the function
value_type dY;
///store the second derivative of the function
value_type d2Y;
///data for the function on the grid
data_type m_Y;
///data for the 2nd derivative on the grid
data_type m_Y2;
///the number of nodes
int NumNodes;
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,209 @@
#ifndef ONEDIMINTEGRATION_H
#define ONEDIMINTEGRATION_H
/*! \fn template<class GF>
inline
typename GF::value_type
integrate_RK2(const GF& f, GF& g)
* \param f the integrand
* \param g the integral of f
* \return the numerical integral of f
* \brief Performs the second order Runge-Kutta
algorithm to evaluate the integral of a radial
grid function
\f$ f(r) \f$: \f[ g(r) = \int_a^r dr' f(r') \f]
*/
template<class GF>
inline
typename GF::value_type
integrate_RK2(const GF& f, GF& g){
typedef typename GF::value_type value_type;
// value_type ysum = 0.0;
value_type yold=0.0;
value_type ynew=0.0;
g(0) = 0.0;
for(int i=0; i < f.size()-1; i++){
// ysum += 0.5*f.dr(i)*(f(i)+f(i+1));
ynew=yold+0.5*f.dr(i)*(f(i)+f(i+1));
// g(i+1) = ysum;
g(i+1) = ynew;
yold = ynew;
}
// return ysum;
return yold;
}
/*! \fn template<class GF>
inline
typename GF::value_type
integrate_RK2_forward(const GF& f, GF& g)
* \param f the integrand
* \param g the integral of f
* \return the numerical integral of f
* \brief Performs the second order Runge-Kutta
algorithm to evaluate the integral (in the
forward direction) of a radial grid function
\f$ f(r) \f$: \f[ g(r) = \int_a^r dr' f(r') \f]
*/
template<class GF>
inline
typename GF::value_type
integrate_RK2_forward(const GF& f, GF& g){
return integrate_RK2(f,g);
}
/*! \fn template<class GF>
inline
typename GF::value_type
integrate_RK2_backward(const GF& f, GF& g)
* \param f the integrand
* \param g the integral of f
* \return the numerical integral of f
* \brief Performs the Runge-Kutta algorithm to
evaluate the integral (in the backwards direction)
of a radial grid function
\f$ f(r) \f$: \f[ g(x) = \int_x^b dx' f(x') \f]
*/
template<class GF>
inline
typename GF::value_type
integrate_RK2_backward(const GF& f, GF& g){
// typedef typename GF::value_type value_type;
// int last = min(f.size(),g.size())-1;
// value_type ysum=0.0;
// g(last) = 0.0;
// for(int i=last; i > 0; i--){
// ysum += 0.5*f.dr(i)*(f(i)+f(i-1));
// g(i)=ysum;
// }
// return ysum;
typedef typename GF::value_type value_type;
int last = min(f.size(),g.size())-1;
value_type yold = 0.0;
value_type ynew = 0.0;
g(last) = 0.0;
for(int i=last; i > 0; i--){
ynew = yold+0.5*f.dr(i-1)*(f(i)+f(i-1));
g(i-1)=ynew;
yold = ynew;
}
return yold;
}
/*! \fn template<class GF>
inline
typename GF::value_type
integrate_RK2(const GF& f)
* \param f the integrand
* \return the numerical integral of f
* \brief Performs the second order Runge-Kutta
algorithm to evaluate the integral of a radial
grid function
\f$ f(r) \f$: \f[ y = \int_a^b dr' f(r') \f]
*/
template<class GF>
inline
typename GF::value_type
integrate_RK2(const GF& f){
typedef typename GF::value_type value_type;
value_type sum = 0.0;
for(int i=0; i < f.size()-1; i++){
sum += f.dr(i)*(f(i)+f(i+1));
}
return 0.5*sum;
}
/*! \fn template<class GF>
inline
void normalize_RK2(GF& f)
* \param f the integrand
* \brief Normalizes the function \f$ f(r) \f$:
\f[ f(r) = \frac{1}{\sqrt{C}} f(r) \f] where
\f[ C = \int_a^b dr f^2(r) \f]
*/
template<class GF>
inline
void normalize_RK2(GF& f){
typedef typename GF::value_type value_type;
value_type sum = 0.0;
for(int i=0; i < f.size()-1; i++){
sum += f.dr(i)*(pow(f(i),2)+pow(f(i+1),2));
}
value_type norm = 1.0/sqrt(0.5*sum);
for(int i=0; i < f.size(); i++) f(i) *= norm;
}
template<class GT, class Fn>
inline
typename Fn::value_type
integrate_RK2(const GT& grid, const Fn& a){
typedef typename GT::value_type value_type;
value_type sum = 0.0;
for(int i=0; i < f.size()-1; i++){
sum += grid.dr(i)*(a(grid.r(i)) + a(grid.r(i+1)));
}
return 0.5*sum;
}
template<class GF>
typename GF::value_type
integrate(const GF& f) {
typedef typename GF::value_type value_type;
const value_type one_third = 0.33333333333333333333333333333333;
const value_type three_eighths = 0.375;
const value_type BODES_FACTOR = 0.0444444444444444444444444444444;
value_type sum = 0.0;
int NumIntervals = f.size() - 1;
int rem = NumIntervals % 4;
///f.func(int i) return dr(i)*f(i)
switch ( rem ) {
case 0:
sum += 0.0;
break;
case 1:
sum += 0.5 * (f.func(0)+ f.func(1));
break;
case 2:
sum += one_third * (f.func(0)+ 4.0 * f.func(1) + f.func(2));
break;
case 3:
sum += three_eighths * (f.func(0)+3.0*f.func(1)
+ 3.0*f.func(2) + f.func(3));
break;
}
for(int i = 0; i < f.size()-1; i+=4) {
// std::cout << i << '\n';
int pt0=(i+0);
int pt1=(i+1);
int pt2=(i+2);
int pt3=(i+3);
int pt4=(i+4);
sum += 7.0 * f.func(pt0) +
32.0 * f.func(pt1) +
12.0 * f.func(pt2) +
32.0 * f.func(pt3) +
7.0 * f.func(pt4);
}
return BODES_FACTOR * sum;
}
#endif

View File

@ -0,0 +1,151 @@
// -*- C++ -*-
#ifndef RADIALFUNCTIONUTILITY_H
#define RADIALFUNCTIONUTILITY_H
#ifndef ONEDIMINTEGRATION_H
#include "Numerics/OneDimIntegration.h"
#endif
/**@file RadialFunctorUtility.h
@brief Utility functions for atomic Hartree-fock solutions
@authors Jeongnim Kim, Jordan Vincent
@note The original Prim was written in F90 by Tim Wilkens.
*/
/*!\fn
* \param g \f$Y_k(n_al_a;n_bl_b/r)\f$
* \param a \f$psi_a\f$
* \param b \f$\psi_b\f$
* \param prefactor The scaling constant (simple multiplication factor)
* \return double The result of the calculation after integration
*
* \brief Calculates \f$\int_0^{\infty} dr \psi_a(r) \psi_b(r)
Y_k(n_al_a,n_bl_b/r) \psi_b(r) \f$ with appropriate scaling.
*/
template<class T, class GF>
inline T Phisq_x_Yk(const GF& g, const GF& a,
const GF& b, T prefactor) {
GF t(g);
for(int i=0; i < t.size(); i++) {
t(i) = prefactor * g(i)*a(i)*b(i);
}
return integrate_RK2(t);
}
/*! \fn
* \param g return
* \param a \f$psi_a\f$
* \param b \f$\psi_b\f$
* \param k the integer parameter.
*
* \brief Calculates the function:
\f[
\frac{{\cal Y}_k(n_a l_a; n_b l_b/r)}{r}
\f]
*
On Page 17 of "Quantum Theory of Atomic
Structure" Vol 2 by JC Slater. Note: (here we use \f$ u(r) \f$ not \f$ R(r) \f$,
where the relation is \f$ u(r) = rR(r) \f$) this function is used extensively
to calculate the Coulomb and Exchange potentials. The actual
equation is:
\f[
\frac{{\cal Y}_k(n_al_a;n_bl_b/r)}{r} =
\frac{1}{r^{k+1}}
\int_{0}^{r} dr' \: r'^k u_{n_a l_a}(r') u_{n_b l_b}(r')
+ r^{k} \int_{r}^{\infty}dr' \:
r'^{-k-1} u_{n_a l_a}(r') u_{n_b l_b}(r')
\f]
*/
template<class GF>
inline void
Ykofr(GF& g, const GF& a, const GF& b, int k) {
typedef typename GF::value_type value_type;
int n = g.size();
//The integrands of each of the two integrals
GF first_integrand(g);
GF second_integrand(g);
vector<value_type> r_to_k(n);
vector<value_type> r_to_minus_k_plus_one(n);
//Store values for r_to_k and r_to_minus_kplus1
for(int i=0; i < n; ++i) {
value_type r0 = g.r(i)+1e-12;
value_type t = pow(r0,k); // r0^k
r_to_k[i] = t;
r_to_minus_k_plus_one[i] = 1.0/(t*r0); // 1/r0^(k+1)
value_type ab = a(i)*b(i);
first_integrand(i) = r_to_k[i]*ab;
second_integrand(i) = r_to_minus_k_plus_one[i]*ab;
}
//Allow r_1 to range over all the radial grid points.
//Store the value of the integral at each grid point in
//temporary grid objects A and B.
GF A(g), B(g);
integrate_RK2_forward(first_integrand,A);
integrate_RK2_backward(second_integrand,B);
//Too many for loops here *Yk_r = r_to_minus_k_plus_one * A + r_to_k * B;
for(int i=0; i < n; ++i) {
g(i) = r_to_minus_k_plus_one[i]*A(i)+r_to_k[i]*B(i);
}
}
/*! \fn
* \param g the grid function to be returned
* \param y the grid function to be transformed
* \param a \f$\psi_a\f$
* \param b \f$\psi_b\f$
* \param coeff a coefficient
*
* \brief Makes \f$V_{Exchange}\f$ a local function.
*
\f$ V_{Exchange} \f$ is a non-local operator:
\f[
\hat{V}_{Exchange} \psi_a(r) = -\sum_b
\delta_{\sigma_a,\sigma_b}\int dr'
\frac{\psi_b^*(r')\psi_a(r')}{|r-r'|}\psi_b(r),
\f]
It is possible to transform this into a local operator by multiplying
and dividing by $\psi_a(r)$:
\f[
-\sum_b \delta_{\sigma_a,\sigma_b}\int dr'
\frac{\psi_b^* (r')\psi_a(r')\psi_b(r')\psi_b(r)}{\psi_a(r)|r-r'|} \psi_a(r)
\f]
*/
template<class GF>
inline void
Make_Loc_Pot(GF& g, const GF& y, const GF& a, const GF& b,
typename GF::value_type coeff) {
int max_pt, pt=1;
typename GF::value_type ratio;
while(a(pt)/a(pt-1) >= 1.0 && pt<a.size()-1) {
pt++;
}
max_pt = pt;
const double tol = pow(10.0,-10.0);
for(pt=0; pt < g.size(); pt++) {
if(fabs(a(pt)) > tol){
ratio = b(pt)/a(pt);
if(pt >= max_pt && fabs(ratio) > 1000) {ratio = 1000000.0 / ratio;}
g(pt) -= coeff*ratio*y(pt);
}
}
}
//}
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,152 @@
//////////////////////////////////////////////////////////////////
// (c) Copyright 2003- by Jeongnim Kim
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Jeongnim Kim
// National Center for Supercomputing Applications &
// Materials Computation Center
// University of Illinois, Urbana-Champaign
// Urbana, IL 61801
// e-mail: jnkim@ncsa.uiuc.edu
// Tel: 217-244-6319 (NCSA) 217-333-3324 (MCC)
//
// Supported by
// National Center for Supercomputing Applications, UIUC
// Materials Computation Center, UIUC
// Department of Physics, Ohio State University
// Ohio Supercomputer Center
//////////////////////////////////////////////////////////////////
// -*- C++ -*-
#ifndef OHMMS_SLATERTYPEORBITAL_H
#define OHMMS_SLATERTYPEORBITAL_H
#include <math.h>
/**class for Slater-type orbitals
*@f[
*\Psi_{n,l,m}({\bf R}) = N r^{n-1} \exp{-Zr} Y_{lm}(\theta,\phi)
*@f]
*/
template<class T>
struct RadialSTO {
typedef T value_type;
int NminusOne;
T Z;
T Norm;
T Y, dY, d2Y;
RadialSTO(): NminusOne(0), Z(1.0), Norm(1.0) { }
RadialSTO(int n, double z, double norm=1.0):
NminusOne(n-1), Z(z),Norm(norm) { }
inline void setgrid(T r) { }
inline T f(T r) const {
return pow(r,NminusOne)*exp(-Z*r)*Norm;
}
inline T df(T r) const {
T rnl = pow(r,NminusOne)*exp(-Z*r)*Norm;
return (NminusOne/r-Z)*rnl;
}
inline void evaluate(T r, T rinv) {
Y = evaluate(r,rinv,dY,d2Y);
}
inline T evaluate(T r, T rinv, T& drnl, T& d2rnl) {
T rnl = pow(r,NminusOne)*exp(-Z*r)*Norm;
T x = NminusOne*rinv-Z;
drnl = rnl*x;
d2rnl = rnl*(x*x-NminusOne*rinv*rinv);
return rnl;
}
};
/** Generic Slater-Type Orbital
*
*The analytic form
\f[
\chi_{n,\xi}(r) = N r^{n-1} \exp{-\xi r}
\f]
*
*@note For QMC we are interested in
\f[
\frac{\chi_{n,\xi}(r)}{r^l} = N r^{n-l-1} \exp{-\xi r}
/f]
*/
template<class T>
struct GenericSTO {
typedef T value_type;
int ID;
int N;
T Z;
T Norm;
T Y, dY, d2Y;
GenericSTO(): N(-1), Z(1.0), Norm(1.0) { }
GenericSTO(int n, double z, double norm=1.0): N(n), Z(z),Norm(norm) { }
inline void setgrid(T r) { }
inline T f(T r) const {
return exp(-Z*r)*Norm*pow(r,N);
}
inline T df(T r) const {
T rnl = exp(-Z*r)*Norm;
if(N == 0) {
return -Z*rnl;
} else {
return rnl*pow(r,N)*(N/r-Z);
}
}
inline void evaluate(T r, T rinv) {
Y = evaluate(r,rinv,dY,d2Y);
}
inline T evaluate(T r, T rinv, T& drnl, T& d2rnl) {
T rnl = exp(-Z*r)*Norm;
if(N == 0) {
drnl = -Z*rnl;
d2rnl = rnl*Z*Z;
} else {
rnl *= pow(r,N);
T x = N*rinv-Z;
drnl = rnl*x;
d2rnl = rnl*(x*x-N*rinv*rinv);
}
return rnl;
}
};
template<class T>
struct STONorm {
std::vector<T> Factorial;
explicit STONorm(int nmax=1) {
set(nmax);
}
void set(int nmax) {
int n = 2*nmax+2;
Factorial.resize(n+1);
Factorial[0] = 1.0;
for (int i=1;i<n+1;i++) Factorial[i] = Factorial[i-1]*static_cast<T>(i);
}
inline T operator()(int n, T screen) {
return
1.0/sqrt(Factorial[2*n+2]*4.0*(4.0*atan(1.0))/pow(2.0*screen,2*n+3));
}
};
#endif
/***************************************************************************
* $RCSfile$ $Author$
* $Revision$ $Date$
* $Id$
***************************************************************************/

View File

@ -0,0 +1,217 @@
#ifndef __SphericalTensor_h_
#define __SphericalTensor_h_
//#include <valarray>
//#include "Point.h"
/**Class SphericalTensor
* @author John Shumway
* @author Jeongnim Kim
* \brief evaluates the Real Spherical Harmonics
\f[
r^l \Re (Y_l^m(\theta,\phi)).
\f]
*
A list of the real spherical harmonics for the \textit{s},
\textit{p} and \textit{d} states
\f[ \Re (Y_0^0) = \sqrt{\frac{1}{4\pi}} = s \f]
\f[ r\Re (Y_1^{-1}) = -\sqrt{\frac{3}{8\pi}}y = p_y \f]
\f[ r\Re (Y_1^0) = \sqrt{\frac{3}{4\pi}}z = p_z \f]
\f[ r\Re (Y_1^1) = -\sqrt{\frac{3}{8\pi}}x = p_x \f]
\f[ r^2\Re (Y_2^{-2}) = \sqrt{\frac{15}{8\pi}}xy = d_{xy} \f]
\f[ r^2\Re (Y_2^{-1}) = -\sqrt{\frac{15}{8\pi}}yz = d_{yz} \f]
\f[ r^2\Re (Y_2^0) = \sqrt{\frac{5}{16\pi}}(3z^2-r^2) = d_{z^2} \f]
\f[ r^2\Re (Y_2^1) = -\sqrt{\frac{15}{8\pi}}xz = d_{xz} \f]
\f[ r^2\Re (Y_2^2) = \sqrt{\frac{15}{32\pi}}(x^2-y^2) = d_{x^2-y^2} \f]
*
The template parameter T is the value_type, e.g. double, and the
template parameter Point_t is a vector type which must have the
operator[] defined.
*/
template<class T, class Point_t>
class SphericalTensor {
public :
typedef T value_type;
///constructor
explicit SphericalTensor(const int lmax);
///makes a table of \f$ r^{l} \Re (Y_l^m) \f$ and their gradients up to lmax.
void evaluate(const Point_t& p);
///returns the index \f$ l(l+1)+m \f$
inline int index(int l, int m) const {return (l*(l+1))+m;}
///returns the value of \f$ r^{l} \Re (Y_l^m) \f$ given l,m
inline value_type getYlm(int l, int m) const
{return Ylm[index(l,m)];}
///returns the gradient of \f$ r^{l} \Re (Y_l^m) \f$ given l,m
inline Point_t getGradYlm(int l, int m) const
{return gradYlm[index(l,m)];}
///returns the value of \f$ r^{l} \Re (Y_l^m) \f$ given index lm
inline value_type getYlm(int lm) const {return Ylm[lm];}
///returns the gradient of \f$ r^{l} \Re (Y_l^m) \f$ given index lm
inline Point_t getGradYlm(int lm) const {return gradYlm[lm];}
inline int size() const { return Ylm.size();}
inline int lmax() const { return Lmax;}
private :
int Lmax;
vector<value_type> Ylm;
vector<Point_t> gradYlm;
};
template<class T, class Point_t>
SphericalTensor<T, Point_t>::SphericalTensor(const int lmax) : Lmax(lmax){
Ylm.resize((lmax+1)*(lmax+1));
gradYlm.resize((lmax+1)*(lmax+1));
}
template<class T, class Point_t>
void SphericalTensor<T,Point_t>::evaluate(const Point_t& p) {
value_type x=p[0], y=p[1], z=p[2];
const value_type pi = 4.0*atan(1.0);
const value_type pi4 = 4.0*pi;
/* Calculate r, cos(theta), sin(theta), cos(phi), sin(phi) from input
coordinates. Check here the coordinate singularity at cos(theta) = +-1.
This also takes care of r=0 case. */
value_type cphi,sphi,ctheta;
value_type r2xy=x*x+y*y;
value_type r=sqrt(r2xy+z*z);
if (r2xy == 0.0) {
cphi = 0.0;
sphi = 1.0;
ctheta = (z<0)?-1.0:1.0;
} else {
ctheta = z/r;
value_type rxyi = 1.0/sqrt(r2xy);
cphi = x*rxyi;
sphi = y*rxyi;
}
value_type stheta = sqrt(1.0-ctheta*ctheta);
/* Now to calculate the associated legendre functions P_lm from the
recursion relation from l=0 to lmax. Conventions of J.D. Jackson,
Classical Electrodynamics are used. */
Ylm[0] = 1.0;
// calculate P_ll and P_l,l-1
value_type fac = 1.0;
int j = -1;
for (int l=1; l<=Lmax; l++) {
j += 2;
fac *= -j*stheta;
int ll=index(l,l);
int l1=index(l,l-1);
int l2=index(l-1,l-1);
Ylm[ll] = fac;
Ylm[l1] = j*ctheta*Ylm[l2];
}
// Use recurence to get other plm's //
for (int m=0; m<Lmax-1; m++) {
int j = 2*m+1;
for (int l=m+2; l<=Lmax; l++) {
j += 2;
int lm=index(l,m);
int l1=index(l-1,m);
int l2=index(l-2,m);
Ylm[lm] = (ctheta*j*Ylm[l1]-(l+m-1)*Ylm[l2])/(l-m);
}
}
// Now to calculate r^l Y_lm. //
value_type sphim,cphim,fac2,temp;
Ylm[0] = 1.0/sqrt(pi4);
value_type rpow = 1.0;
for (int l=1; l<=Lmax; l++) {
rpow *= r;
fac = rpow*sqrt((2*l+1)/pi4);
int l0=index(l,0);
Ylm[l0] *= fac;
cphim = 1.0;
sphim = 0.0;
for (int m=1; m<=l; m++) {
fac2 = (l+m)*(l+1-m);
fac = fac/sqrt(fac2);
temp = cphim*cphi-sphim*sphi;
sphim = sphim*cphi+cphim*sphi;
cphim = temp;
int lm = index(l,m);
temp = fac*Ylm[lm];
Ylm[lm] = temp*cphim;
lm = index(l,-m);
Ylm[lm] = temp*sphim;
}
}
// Calculating Gradient now//
for (int l=0; l<Lmax+1; l++) {
for (int m=-l; m<l+1; m++) {
int lm = index(l-1,0);
value_type fac = ((value_type) (2*l+1))/(2*l-1);
value_type gx,gy,gz,dpr,dpi,dmr,dmi;
int ma = abs(m);
value_type cp = sqrt(fac*(l-ma-1)*(l-ma));
value_type cm = sqrt(fac*(l+ma-1)*(l+ma));
value_type c0 = sqrt(fac*(l-ma)*(l+ma));
gz = (l > ma) ? c0*Ylm[lm+m]:0.0;
if (l > ma+1) {
dpr = cp*Ylm[lm+ma+1];
dpi = cp*Ylm[lm-ma-1];
} else {
dpr = 0.0;
dpi = 0.0;
}
if (l > 1) {
switch (ma) {
case 0:
dmr = -cm*Ylm[lm+1];
dmi = cm*Ylm[lm-1];
break;
case 1:
dmr = cm*Ylm[lm];
dmi = 0.0;
break;
default:
dmr = cm*Ylm[lm+ma-1];
dmi = cm*Ylm[lm-ma+1];
}
} else {
dmr = (l==1) ? cm*Ylm[lm]:0.0;
dmi = 0.0;
}
if (m < 0) {
gx = 0.5*(dpi-dmi);
gy = -0.5*(dpr+dmr);
} else {
gx = 0.5*(dpr-dmr);
gy = 0.5*(dpi+dmi);
}
lm = index(l,m);
gradYlm[lm] = Point_t(gx,gy,gz);
}
}
}
#endif

View File

@ -0,0 +1,13 @@
#ifndef GUARD_SPLINE3DCONFIGURATION_H
#define GUARD_SPLINE3DCONFIGURATION_H
#include "OhmmsPETE/TinyVector.h"
#include "OhmmsPETE/OhmmsVector.h"
typedef TinyVector<int,3> gridvec_t;
typedef TinyVector<double,3> posvec_t;
typedef Vector<double> scalar_array_t;
typedef Vector<posvec_t> posarray_t;
typedef vector<posvec_t> rarray_t;
#endif

View File

@ -0,0 +1,126 @@
#include "Numerics/Spline3D/CubicSpline.h"
#include <iostream>
using namespace std;
void CubicSpline::Update(){
blitz::Array<double,1> mu(n_x);
F(0)[1] = 1.5 * ( F(1)[0] - F(0)[0] ) * invh;
F(n_x-1)[1] = 1.5 * ( F(n_x-1)[0] - F(n_x-2)[0] ) * invh;
mu(0) = 0.5;
for(int i = 1; i < n_x-1; i++){
double lambda = 0.25;
mu(i) = 0.5 - lambda;
F(i)[1] = 3.0* invh * ( lambda * ( F(i)[0] - F(i-1)[0] ) +
mu(i) * ( F(i+1)[0] - F(i)[0] ) );
double ci = 1.0 - lambda * mu(i-1);
F(i)[1] -= lambda * F(i-1)[1];
mu(i) /= ci;
F(i)[1] /= ci;
}
int i = n_x - 1;
double lambda = 0.5;
mu(i) = 0.5 - lambda;
F(i)[1] = 3.0 * invh * lambda * ( F(i)[0] - F(i-1)[0] );
double ci = 1.0 - lambda * mu(i-1);
F(i)[1] -= lambda * F(i-1)[1];
mu(i) /= ci;
F(i)[1] /= ci;
for( i = n_x - 2; i >= 0; i-- )
F(i)[1] -= mu(i) * F(i+1)[1];
for(int j = 0; j < n_x; j++)
cout << F(j)[0] << '\t' << F(j)[1] << endl;
exit(-1);
UpToDate = true;
return;
}
void CubicSpline::Update(double dfi, double dff){
blitz::Array<double,1> mu(n_x);
F(0)[1] = dfi;
F(n_x-1)[1] = dff;
mu(0) = 0.5;
for(int i = 1; i < n_x-1; i++){
double lambda = 0.25;
mu(i) = 0.5 - lambda;
F(i)[1] = 3.0* invh * ( lambda * ( F(i)[0] - F(i-1)[0] ) +
mu(i) * ( F(i+1)[0] - F(i)[0] ) );
double ci = 1.0 - lambda * mu(i-1);
F(i)[1] -= lambda * F(i-1)[1];
mu(i) /= ci;
F(i)[1] /= ci;
}
for( int i = n_x - 2; i > 0; i-- )
F(i)[1] -= mu(i) * F(i+1)[1];
UpToDate = true;
return;
}
/*
void CubicSpline::Update(){
blitz::Array<double,1> a(n_x),b(n_x),c(n_x),r(n_x);
/// initilaise the coefficient matrix
a(0) = 0.0; b(0) = 2.0; b(n_x-1) = 2; c(n_x-1) = 0.0;
for(int i = 1; i < n_x-1; i++){
a(i) = 1.0; b(i) = 4.0; c(i) = 1.0;
}
/// initialise the right hand side
double fac = 3* invh ;
r(0) = fac*(F(1)[0] - F(0)[0]) - 0.5*d2i;
for(int i = 1; i < n_x-1; i++) r(i) = fac*(F(i+1)[0]-F(i-1)[0]);
r(n_x-1) = fac*(F(n_x-1)[0] - F(n_x-2)[0]) + 0.5*d2f;
blitz::Array<double,1> gamma(n_x);
/// decomposition and forward substitution
double beta=b(0);
F(0)[1] = r(0)/beta;
for(int j = 1; j < n_x; j++){
gamma(j) = c(j-1)/beta;
beta = b(j) - a(j)*gamma(j);
F(j)[1] = (r(j)-a(j)*F(j-1)[1])/beta;
}
/// backsubstitution
for(int j = n_x-2; j >= 0; j--)
F(j)[1] -= gamma(j+1)*F(j+1)[1];
// for(int i = 0; i < n_x-1; i++)
// cout << F(i)[0] << '\t' << F(i)[1] << endl;
// exit(-1);
UpToDate = true;
return;
}
*/

View File

@ -0,0 +1,143 @@
#ifndef GUARD_CUBICSPLINE_H
#define GUARD_CUBICSPLINE_H
#include "Numerics/Spline3D/Config.h"
#include "Numerics/Spline3D/uGrid1D.h"
#include "Numerics/Spline3D/SetSplinePoint.h"
#include <fstream>
#include <blitz/array.h>
/// This is Cubic Splines with natural boundary conditions, i.e.
/// the second derivative vanishes at the boundary, not suitable for
/// functions like sines and cosines.
/// Each point of F contains:
/// 0) F(x,y,z)
/// 1) dF/dx
class CubicSpline{
/// functions which depend on the point where the interpolated value
/// is required. t = (x - xi)/h
inline double p1(double t)
{ return ((t-1.0)*(t-1.0)*(1.0+2.0*t)); }
inline double p2(double t)
{ return (t*t*(3.0-2.0*t)); }
inline double q1(double t)
{ return (t*(t-1.0)*(t-1.0)); }
inline double q2(double t)
{ return (t*t*(t-1.0)); }
inline double dp1(double t)
{ return (6.0*t*(t-1.0)); }
inline double dq1(double t)
{ return ((t-1.0)*(3.0*t-1.0)); }
inline double dp2(double t)
{ return (-dp1(t)); }
inline double dq2 (double t)
{ return ((3.0*t - 2.0)*t); }
inline double d2p1(double t)
{ return (12.0*t-6.0); }
inline double d2q1 (double t)
{ return (6.0*t - 4.0); }
inline double d2p2 (double t)
{ return (-d2p1(t)); }
inline double d2q2 (double t)
{ return (6.0*t - 2.0); }
// dim: Dimension to calculate derivative w.r.t
// source: Function to differentiate
// dest: where to put result
void UpdateX (int source, int dest);
/// whether the first derivatives have been calculated using the
/// m-relations.
bool UpToDate;
int n_x;
double d2i;
double d2f;
double h;
double invh;
public:
typedef double value_type;
/// function and derivatives at each point
blitz::Array<blitz::TinyVector<double,2>,1> F;
uGrid1D* m_grid;
/// constructor
CubicSpline(uGrid1D* agrid){
m_grid = agrid;
n_x = agrid->m_size;
h = agrid->m_h;
invh = 1.0/h;
d2i = 0.0;
d2f = 0.0;
F.resize(n_x);
UpToDate = false;
}
inline void set_bc(double ad2i, double ad2f){
d2i = ad2i;
d2f = ad2f;
return;
}
inline double operator()(int ix) const
{
return (F(ix)[0]);
}
inline double& operator()(int ix)
{
UpToDate = false;
return (F(ix)[0]);
}
/// update the derivatives using the m-relations
void Update();
void Update(double,double);
inline double evaluate(const double x,
double& gradf,
double& lapf){
double val;
//if( !UpToDate ) Update(); /// m-relations
int ix = m_grid->xl(x); /// get the lowest grid-point
double u = (x-m_grid->m_coord[ix])*invh;
double& Y00 = F(ix)[0];
double& Y01 = F(ix)[1];
double& Y10 = F(ix+1)[0];
double& Y11 = F(ix+1)[1];
val = Y00 * p1(u) + Y10 * p2(u) + h* ( Y01 * q1(u) + Y11 * q2(u) );
gradf = invh * ( Y00 * dp1(u) + Y10 * dp2(u) )
+ Y01 * dq1(u) + Y11 * dq2(u) ;
lapf = invh * ( invh * ( Y00 * d2p1(u) + Y10 * d2p2(u) )
+ Y01 * d2q1(u) + Y11 * d2q2(u) );
return val;
}
};
#endif

View File

@ -0,0 +1,102 @@
#include "Numerics/Spline3D/Grid1D.h"
#include <iostream>
using namespace std;
void Grid1D::init(int nsections,
int npts,
double xi,
const vector<int>& nrho,
const vector<double>& dh){
m_size = npts;
m_coord.resize(m_size);
m_sections = nsections;
m_start = xi;
/// assign and initialise arrays
m_h.resize(m_size); m_M.resize(m_size+1); m_M[0] = 0;
for(int isec = 0; isec < m_sections; isec++){
m_h[isec] = dh[isec];
m_M[isec+1] = m_M[isec] + nrho[isec];
}
/// compute the coordinates
int ipt = 0; m_coord[0] = m_start;
for(int isec = 0; isec < m_size; isec++){
for(int ix = m_M[isec]; ix < m_M[isec+1]; ix++){
ipt++; m_coord[ipt] = m_coord[ipt-1] + m_h[isec];
}
}
m_end = m_coord[m_size-1];
return;
}
void Grid1D::init(int xi,
int xf,
const Grid1D& agrid){
m_size = xf - xi + 1;
m_coord.resize(m_size);
int si, sf; /// the indices of the initial and final sections
bool flag1 = true, flag2 = true;
for(int isec = 0; isec < agrid.m_sections; isec++){
if(flag1 && xi <= agrid.m_M[isec+1]) { si = isec; flag1 = false; }
if(flag2 && xf <= agrid.m_M[isec+1]) { sf = isec; flag2 = false; }
}
m_sections = sf - si + 1;
/// assign arrays
m_M.resize(m_size+1); m_h.resize(m_size); m_M[0] = 0;
for(int isec = 1; isec < m_sections; isec++)
m_M[isec] = agrid.m_M[isec+si] - xi;
m_M[m_sections] = xf - xi;
/// the grid spacings
for(int isec = 0; isec < m_sections; isec++)
m_h[isec] = agrid.m_h[si+isec];
/// compute the coordinates
int ipt = 0; m_coord[0] = agrid.m_coord[xi];
for(int isec = 0; isec < m_size; isec++){
for(int ix = m_M[isec]; ix < m_M[isec+1]; ix++){
ipt++; m_coord[ipt] = m_coord[ipt-1] + m_h[isec];
}
}
m_start = m_coord[0]; m_end = m_coord[m_size-1];
return;
}
int Grid1D::xl(double x){
/// the start and end points
int a = 0; int b = m_size-1;
while( b - a > 1 ){
int m = a + ( b - a )/2 ; // divide by 2^{1}
if( x >= m_coord[m] ){
a = m;
} else {
b = m;
}
}
return a;
}
int Grid1D::xn(double x){
int i = xl(x); /// get the lowest Grid point
if( x - m_coord[i] > 0.5*h(i) ) i += 1;
return i;
}

View File

@ -0,0 +1,57 @@
#ifndef GUARD_GRID1D_H
#define GUARD_GRID1D_H
#include <vector>
class Grid1D{
public:
/// number of different Grid density sections (regions)
int m_sections;
/// total number of Grid points : 0 to m_size - 1
int m_size;
/// coordinate of first and last grid points
double m_start;
double m_end;
/// coordinates
std::vector<double> m_coord;
/// the interval points
std::vector<int> m_M;
/// Grid widths
std::vector<double> m_h;
/// Constructor
Grid1D(){}
/// initialise with the entire data from input
void init(int, int, double, const std::vector<int>&,
const std::vector<double>&);
/// initialise from part of a supplied Grid
void init(int, int, const Grid1D&);
/// the lowest Grid-point for coordinate x
int xl(double);
/// the nearest Grid-point for coordinate x
int xn(double);
/// the Grid width for coordinate x
inline double h(double x){ return h(xl(x)); }
/// the Grid width for some Grid point i
inline double h(int i) { return m_coord[i+1] - m_coord[i];}
/// the size of the Grid :
inline int Size() { return m_size; }
};
#endif

View File

@ -0,0 +1,220 @@
#ifndef GUARD_GRID3D_H
#define GUARD_GRID3D_H
#include <vector>
#include "Numerics/Spline3D/Config.h"
#include "Numerics/Spline3D/Grid1D.h"
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
class Grid3D{
public:
/// number of points along each direction
int n_x, n_y, n_z;
/// total number of points in the Grid3D : 0 to m_size-1
int m_size;
/// array of the axes Grid1D
std::vector<Grid1D> m_axis;
/// Constructor :: create the three axes
Grid3D(){ m_axis.resize(3); }
/// initialise an axis with entire data from the input
void init(int idir,
int nsections,
int npts,
double xi,
const std::vector<int>& nrho,
const std::vector<double>& dh){
m_axis[idir].init(nsections,npts,xi,nrho,dh);
return;
}
/// initialise the Grid3D from another Grid3D
void init(const gridvec_t& ri,
const gridvec_t& rf,
const Grid3D* agrid){
for(int idir = 0; idir < 3; idir++)
m_axis[idir].init(ri[idir],rf[idir],agrid->m_axis[idir]);
set_size();
return;
}
void set_size(){
n_x = m_axis[0].Size();
n_y = m_axis[1].Size();
n_z = m_axis[2].Size();
m_size = n_x * n_y * n_z;
return;
}
/// index of a Grid3D point
inline int index(const gridvec_t& ir){
return ir[0] + n_x * ( ir[1] + n_y * ir[2] );
}
/// index of a Grid3D point
inline int index(int ix, int iy, int iz){
return ix + n_x * ( iy + n_y * iz );
}
/// Grid3D point corresponding to index
inline gridvec_t ipt(int index){
gridvec_t ir;
int nxy = n_x * n_y;
ir[2] = index/nxy; index -= nxy*ir[2];
ir[1] = index/n_x; index -= n_x*ir[1];
ir[0] = index;
return ir;
}
/// lowest Grid3D point
inline gridvec_t ptl(const posvec_t& r){
gridvec_t ir;
for(int i = 0; i < 3; i++) ir[i] = m_axis[i].xl(r[i]);
return ir;
}
/// nearest Grid3D point
inline gridvec_t ptn(const posvec_t& r){
gridvec_t ir;
for(int i = 0; i < 3; i++) ir[i] = m_axis[i].xn(r[i]);
return ir;
}
/// r coordinate of a Grid3D point
inline posvec_t ptr(const gridvec_t& ir){
posvec_t r;
for(int i = 0; i < 3; i++) r[i] = m_axis[i].m_coord[ir[i]];
return r;
}
inline posvec_t ptr(int ix, int iy, int iz){
posvec_t r;
r[0] = m_axis[0].m_coord[ix];
r[1] = m_axis[1].m_coord[iy];
r[2] = m_axis[2].m_coord[iz];
return r;
}
double put(xmlNodePtr cur, double epsbym){
double units; /// conversion unit
const double aB = 0.5291772108e-10; /// Bohr radius in meters
const double aBeff = epsbym * aB;
const double u0 = 1.0/aBeff;
/// read in the units
string cname ((const char*)(cur->name));
if( cname == "Grid3D"){
string cunit = (char*)xmlGetProp(cur,(xmlChar*)"unit");
if(cunit == "nm"){
units = u0 * 1.0e-9;
cout << "The input data are expressed in nano-meters. " << endl;
cout << "Using a.u. :: 1nm = " << units << " a_B*, and 1 a_B* = "
<< aBeff << " m" << endl;
} else if(cunit == "A"){
units = u0 * 1.0e-10;
cout << "The input data are expressed in Angstroms. " << endl;
cout << "Using a.u. :: 1A = " << units << " a_B* " << endl;
} else if(cunit == "au"){
units = u0 * aB;
cout << "The input data are expressed in atomic units. " << endl;
cout << "Using a.u. :: 1 a_B = " << units << " a_B* " << endl;
} else {
units = 1.0;
cout << "The input data are expressed in effective au. " << endl;
cout << "Using a.u. :: 1nm = 1 a_B = 5.291772083(19)e-11m" << endl;
}
vector<int> n_rho;
vector<double> d_h;
xmlNodePtr node1 = cur->xmlChildrenNode; /// node1->name = Grid1D
while( node1 != NULL ){
string name1 ((const char*)(node1->name));
if( name1 == "Grid1D" ){
/// axis number
int dir = atoi((char*)xmlGetProp(node1,(xmlChar*)"dir"));
/// number of sections
int nsecs = atoi((char*)xmlGetProp(node1,(xmlChar*)"nsecs"));
/// total number of points
int npts = atoi((char*)xmlGetProp(node1,(xmlChar*)"npts"));
/// coordinate origin
double x0 = units * atof((char*)xmlGetProp(node1,(xmlChar*)"x0"));
/// assign the Grid::initialisation-vectors
n_rho.resize(nsecs); d_h.resize(nsecs);
/// initilaise section to be read in.
int isec = 0;
xmlNodePtr node2 = node1->xmlChildrenNode;
while( node2 != NULL ){
string name2 ((const char*)(node2->name));
if( name2 == "section" ){
n_rho[isec]=atoi((char*)xmlGetProp(node2,(xmlChar*)"nx"));
d_h[isec]=units*atof((char*)xmlGetProp(node2,(xmlChar*)"dx"));
isec++;
}
node2 = node2->next; /// next section if any
}
/// initialise axis
m_axis[dir].init(nsecs,npts,x0,n_rho,d_h);
}
node1 = node1->next; /// next Grid1D if any
}
} else {
cout << "Grid3D not properly supplied. Exiting ... " << endl;
exit(-1);
}
set_size(); /// set all dimension sizes
return units;
}
};
#endif

View File

@ -0,0 +1,66 @@
#include "Numerics/Spline3D/NRCubicSpline.h"
void NRCubicSpline::update(){
double qn, un;
std::vector<double> u(n_x-1);
/// set lower boundary condition
if( y1i > y1max ){
y2[0] = 0.0; u[0] = 0.0;
} else {
y2[0] = -0.5;
u[0] = 3.0 * hin * ( y[1] - y[0] ) / ( h - y1i);
}
/// decomposition loop of the tridiagonal matrix
for(int i = 1; i < n_x - 1; i++){
double sig = 0.5;
double p = sig * y2[i-1] + 2.0;
double pin = 1.0/p;
y2[i] = (sig - 1.0) * pin;
u[i] = hin * ( y[i+1] - 2.0 * y[i] + y[i-1] );
u[i] = pin * ( 3 * hin * u[i] - sig * u[i-1] );
}
if( y1f > y1max ){
qn = 0.0; un = 0.0;
} else {
qn = 0.5;
un = 3.0 * hin * ( y1f - hin * ( y[n_x-1] - y[n_x-2] ) );
}
/// backsubstitution loop
y2[n_x-1] = ( un - qn * u[n_x-2] ) / ( qn * y2[n_x-2] + 1.0 );
for( int i = n_x - 2; i >= 0; i--)
y2[i] = y2[i] * y2[i+1] + u[i];
UpToDate = true;
return;
}
double NRCubicSpline::evaluate( const double x,
double& gradf){
if(! UpToDate ) update();
double onesixth = 1.0/6.0;
int ix = m_grid->xl(x);
double a = hin * ( m_grid->m_coord[ix+1] - x );
double b = hin * ( x - m_grid->m_coord[ix] );
double yval = a * y[ix] + b * y[ix+1] + ( a * ( a * a - 1.0 ) * y2[ix] +
b * ( b * b - 1.0 ) * y2[ix+1] ) *
h * h * onesixth;
gradf = hin * ( y[ix+1] - y[ix] ) + onesixth * h *
( ( 3.0 * b * b - 1.0 ) * y2[ix+1] - ( 3.0 * a * a - 1.0 ) * y2[ix] );
return yval;
}

View File

@ -0,0 +1,61 @@
#ifndef GUARD_NRCUBICSPLINE_H
#define GUARD_NRCUBICSPLINE_H
#include "Numerics/Spline3D/Config.h"
#include "Numerics/Spline3D/uGrid1D.h"
#include <vector>
class NRCubicSpline{
/// default value of y1max
double y1max;
/// initial first derivative
double y1i;
/// final first derivative
double y1f;
/// function value
std::vector<double> y;
/// second derivative
std::vector<double> y2;
void update();
public:
typedef double value_type;
/// uniform Grid1D
uGrid1D* m_grid;
/// Constructor
CubicSpline(uGrid1D* agrid){
m_grid = agrid;
n_x = agrid->m_size;
h = agrid->m_h;
hin = 1.0/h;
y.resize(n_x); y2.resize(n_x);
y1max = 1.e30; y1i = y1max; y1f = y1max;
UpToDate = false;
}
/// set boundary conditions on first derivatives
inline void set_bc(double ypi, double ypf){ y1i = ypi; y1f = ypf; }
inline evaluate(const double, double&);
};
#endif

View File

@ -0,0 +1,67 @@
#ifndef GUARD_SETSPLINEPOINT_H
#define GUARD_SETSPLINEPOINT_H
#include "Numerics/Spline3D/Config.h"
#include "Numerics/Spline3D/Grid3D.h"
class SetSplinePoint{
public:
bool ifout;
int ix,iy,iz;
double h,k,l;
double hinv,kinv,linv;
double u,v,w;
void set_point(const posvec_t& r,
Grid3D* agrid){
gridvec_t ir = agrid->ptl(r);
ix = ir[0];
iy = ir[1];
iz = ir[2];
ifout = false;
if( r[2] < agrid->m_axis[2].m_start || r[0] > agrid->m_axis[0].m_end ||
r[2] > agrid->m_axis[2].m_end || r[0] < agrid->m_axis[0].m_start ||
r[1] < agrid->m_axis[1].m_start || r[1] > agrid->m_axis[1].m_end )
{ ifout = true;
/*
cout << "OUTSIDE" << endl;
cout << r[0] << '\t' << agrid->m_axis[0].m_start << '\t'
<< agrid->m_axis[0].m_end << endl;
cout << r[1] << '\t' << agrid->m_axis[1].m_start << '\t'
<< agrid->m_axis[1].m_end << endl;
cout << r[2] << '\t' << agrid->m_axis[2].m_start << '\t'
<< agrid->m_axis[2].m_end << endl;
*/
}
h = agrid->m_axis[0].h(ix);
k = agrid->m_axis[1].h(iy);
l = agrid->m_axis[2].h(iz);
hinv = 1.0/h;
kinv = 1.0/k;
linv = 1.0/l;
u = (r[0] - agrid->m_axis[0].m_coord[ix])*hinv;
v = (r[1] - agrid->m_axis[1].m_coord[iy])*kinv;
w = (r[2] - agrid->m_axis[2].m_coord[iz])*linv;
}
};
#endif

View File

@ -0,0 +1,361 @@
#include "Numerics/Spline3D/TriCubicSpline.h"
#include <iostream>
using namespace std;
void TriCubicSpline::Update(bool iflap){
UpdateX(0, 1); // Do dF/dx
UpdateY(0, 2); // Do dF/dy
UpdateZ(0, 3); // Do dF/dz
UpdateY(1, 4); // Do d2F/dxdy
UpdateZ(1, 5); // Do d2F/dxdz
UpdateZ(2, 6); // Do d2F/dydz
UpdateZ(4, 7); // Do d3F/dxdydz
if(iflap){
D2F.resize(n_x,n_y,n_z);
/// calculate D2F at all points.
D2FDR2();
UpdateD2X(0, 1); // Do d (D2F) /dx
UpdateD2Y(0, 2); // Do d (D2F) /dy
UpdateD2Z(0, 3); // Do d (D2F) /dy
UpdateD2Y(1, 4); // Do d2 (D2F) /dxdy
UpdateD2Z(1, 5); // Do d2 (D2F) /dxdz
UpdateD2Z(2, 6); // Do d2 (D2F) /dydz
UpdateD2Z(4, 7); // Do d3 (D2F) /dxdydz
}
UpToDate = true;
}
void TriCubicSpline::UpdateX(int source, int dest){
blitz::Array<double,1> mu(n_x);
/// Loop over all y and z
for(int iy = 0; iy < n_y; iy++){
for(int iz = 0; iz < n_z; iz++){
/// set up tridiagonal set of equations : initialise RHS
F(0,iy,iz)[dest] = 1.5 *
( F(1,iy,iz)[source] - F(0,iy,iz)[source] ) / dx(0,0);
F(n_x-1,iy,iz)[dest] = 1.5 *
(F(n_x-1,iy,iz)[source] - F(n_x-2,iy,iz)[source]) / dx(0,n_x-2);
mu(0) = 0.5;
/// solve tri-diagonal set of equations. First eliminate lower elements
for(int j = 1; j < n_x - 1; j++){
double lambda = 0.5*dx(0,j)/(dx(0,j)+dx(0,j-1));
mu(j) = 0.5 - lambda;
F(j,iy,iz)[dest] =
3.0*(lambda*(F(j,iy,iz)[source]-F(j-1,iy,iz)[source])/dx(0,j-1)+
mu(j) *(F(j+1,iy,iz)[source]-F(j,iy,iz)[source])/dx(0,j) );
double cj = 1.0 - lambda * mu(j-1);
F(j,iy,iz)[dest] -= lambda * F(j-1,iy,iz)[dest];
mu(j) /= cj;
F(j,iy,iz)[dest] /= cj;
}
/// last element
int j = n_x - 1;
double lambda = 0.5;
mu(j) = 0.5 - lambda;
F(j,iy,iz)[dest] =
3.0*(lambda*(F(j,iy,iz)[source]-F(j-1,iy,iz)[source])/dx(0,j-1) );
double cj = 1.0 - lambda * mu(j-1);
F(j,iy,iz)[dest] -= lambda * F(j-1,iy,iz)[dest];
mu(j) /= cj;
F(j,iy,iz)[dest] /= cj;
/// now last d/dx is correct, so proceed upward, back substituting
for (j=n_x-2; j>=0; j--)
F(j,iy,iz)[dest] -= mu(j) * F(j+1,iy,iz)[dest];
}
}
}
void TriCubicSpline::UpdateY(int source, int dest){
blitz::Array<double,1> mu(n_y);
/// Loop over all x and z
for(int ix = 0; ix < n_x; ix++){
for(int iz = 0; iz < n_z; iz++){
/// set up tridiagonal set of equations : initialise RHS
F(ix,0,iz)[dest] = 1.5 *
( F(ix,1,iz)[source] - F(ix,0,iz)[source] ) / dx(1,0);
F(ix,n_y-1,iz)[dest] = 1.5 *
(F(ix,n_y-1,iz)[source] - F(ix,n_y-2,iz)[source]) / dx(1,n_y-2);
mu(0) = 0.5;
/// solve tri-diagonal set of equations. First eliminate lower elements
for(int j = 1; j < n_y - 1; j++){
double lambda = 0.5*dx(1,j)/(dx(1,j)+dx(1,j-1));
mu(j) = 0.5 - lambda;
F(ix,j,iz)[dest] =
3.0*(lambda*(F(ix,j,iz)[source]-F(ix,j-1,iz)[source])/dx(1,j-1)+
mu(j) *(F(ix,j+1,iz)[source]-F(ix,j,iz)[source])/dx(1,j) );
double cj = 1.0 - lambda * mu(j-1);
F(ix,j,iz)[dest] -= lambda * F(ix,j-1,iz)[dest];
mu(j) /= cj;
F(ix,j,iz)[dest] /= cj;
}
/// last element
int j = n_y - 1;
double lambda = 0.5;
mu(j) = 0.5 - lambda;
F(ix,j,iz)[dest] =
3.0*(lambda*(F(ix,j,iz)[source]-F(ix,j-1,iz)[source])/dx(1,j-1) );
double cj = 1.0 - lambda * mu(j-1);
F(ix,j,iz)[dest] -= lambda * F(ix,j-1,iz)[dest];
mu(j) /= cj;
F(ix,j,iz)[dest] /= cj;
/// now last d/dx is correct, so proceed upward, back substituting
for (j=n_y-2; j>=0; j--)
F(ix,j,iz)[dest] -= mu(j) * F(ix,j+1,iz)[dest];
}
}
}
void TriCubicSpline::UpdateZ(int source, int dest){
blitz::Array<double,1> mu(n_z);
/// Loop over all x and y
for(int ix = 0; ix < n_x; ix++){
for(int iy = 0; iy < n_y; iy++){
/// set up tridiagonal set of equations : initialise RHS
F(ix,iy,0)[dest] = 1.5 *
( F(ix,iy,1)[source] - F(ix,iy,0)[source] ) / dx(2,0);
F(ix,iy,n_z-1)[dest] = 1.5 *
(F(ix,iy,n_z-1)[source] - F(ix,iy,n_z-2)[source]) / dx(2,n_z-2);
mu(0) = 0.5;
/// solve tri-diagonal set of equations. First eliminate lower elements
for(int j = 1; j < n_z - 1; j++){
double lambda = 0.5*dx(2,j)/(dx(2,j)+dx(2,j-1));
mu(j) = 0.5 - lambda;
F(ix,iy,j)[dest] =
3.0*(lambda*(F(ix,iy,j)[source]-F(ix,iy,j-1)[source])/dx(2,j-1)+
mu(j) *(F(ix,iy,j+1)[source]-F(ix,iy,j)[source])/dx(2,j) );
double cj = 1.0 - lambda * mu(j-1);
F(ix,iy,j)[dest] -= lambda * F(ix,iy,j-1)[dest];
mu(j) /= cj;
F(ix,iy,j)[dest] /= cj;
}
/// last element
int j = n_z - 1;
double lambda = 0.5;
mu(j) = 0.5 - lambda;
F(ix,iy,j)[dest] =
3.0*(lambda*(F(ix,iy,j)[source]-F(ix,iy,j-1)[source])/dx(2,j-1) );
double cj = 1.0 - lambda * mu(j-1);
F(ix,iy,j)[dest] -= lambda * F(ix,iy,j-1)[dest];
mu(j) /= cj;
F(ix,iy,j)[dest] /= cj;
/// now last d/dx is correct, so proceed upward, back substituting
for (j=n_z-2; j>=0; j--)
F(ix,iy,j)[dest] -= mu(j) * F(ix,iy,j+1)[dest];
}
}
return;
}
void TriCubicSpline::UpdateD2X(int source, int dest){
blitz::Array<double,1> mu(n_x);
/// Loop over all y and z
for(int iy = 0; iy < n_y; iy++){
for(int iz = 0; iz < n_z; iz++){
/// set up tridiagonal set of equations : initialise RHS
D2F(0,iy,iz)[dest] = 1.5 *
( D2F(1,iy,iz)[source] - D2F(0,iy,iz)[source] ) / dx(0,0);
D2F(n_x-1,iy,iz)[dest] = 1.5 *
(D2F(n_x-1,iy,iz)[source] - D2F(n_x-2,iy,iz)[source]) / dx(0,n_x-2);
mu(0) = 0.5;
/// solve tri-diagonal set of equations. First eliminate lower elements
for(int j = 1; j < n_x - 1; j++){
double lambda = 0.5*dx(0,j)/(dx(0,j)+dx(0,j-1));
mu(j) = 0.5 - lambda;
D2F(j,iy,iz)[dest] =
3.0*(lambda*(D2F(j,iy,iz)[source]-D2F(j-1,iy,iz)[source])/dx(0,j-1)+
mu(j) *(D2F(j+1,iy,iz)[source]-D2F(j,iy,iz)[source])/dx(0,j) );
double cj = 1.0 - lambda * mu(j-1);
D2F(j,iy,iz)[dest] -= lambda * D2F(j-1,iy,iz)[dest];
mu(j) /= cj;
D2F(j,iy,iz)[dest] /= cj;
}
/// last element
int j = n_x - 1;
double lambda = 0.5;
mu(j) = 0.5 - lambda;
D2F(j,iy,iz)[dest] =
3.0*(lambda*(D2F(j,iy,iz)[source]-D2F(j-1,iy,iz)[source])/dx(0,j-1) );
double cj = 1.0 - lambda * mu(j-1);
D2F(j,iy,iz)[dest] -= lambda * D2F(j-1,iy,iz)[dest];
mu(j) /= cj;
D2F(j,iy,iz)[dest] /= cj;
/// now last d/dx is correct, so proceed upward, back substituting
for (j=n_x-2; j>=0; j--)
D2F(j,iy,iz)[dest] -= mu(j) * D2F(j+1,iy,iz)[dest];
}
}
}
void TriCubicSpline::UpdateD2Y(int source, int dest){
blitz::Array<double,1> mu(n_y);
/// Loop over all x and z
for(int ix = 0; ix < n_x; ix++){
for(int iz = 0; iz < n_z; iz++){
/// set up tridiagonal set of equations : initialise RHS
D2F(ix,0,iz)[dest] = 1.5 *
( D2F(ix,1,iz)[source] - D2F(ix,0,iz)[source] ) / dx(1,0);
D2F(ix,n_y-1,iz)[dest] = 1.5 *
(D2F(ix,n_y-1,iz)[source] - D2F(ix,n_y-2,iz)[source]) / dx(1,n_y-2);
mu(0) = 0.5;
/// solve tri-diagonal set of equations. First eliminate lower elements
for(int j = 1; j < n_y - 1; j++){
double lambda = 0.5*dx(1,j)/(dx(1,j)+dx(1,j-1));
mu(j) = 0.5 - lambda;
D2F(ix,j,iz)[dest] =
3.0*(lambda*(D2F(ix,j,iz)[source]-D2F(ix,j-1,iz)[source])/dx(1,j-1)+
mu(j) *(D2F(ix,j+1,iz)[source]-D2F(ix,j,iz)[source])/dx(1,j) );
double cj = 1.0 - lambda * mu(j-1);
D2F(ix,j,iz)[dest] -= lambda * D2F(ix,j-1,iz)[dest];
mu(j) /= cj;
D2F(ix,j,iz)[dest] /= cj;
}
/// last element
int j = n_y - 1;
double lambda = 0.5;
mu(j) = 0.5 - lambda;
D2F(ix,j,iz)[dest] =
3.0*(lambda*(D2F(ix,j,iz)[source]-D2F(ix,j-1,iz)[source])/dx(1,j-1) );
double cj = 1.0 - lambda * mu(j-1);
D2F(ix,j,iz)[dest] -= lambda * D2F(ix,j-1,iz)[dest];
mu(j) /= cj;
D2F(ix,j,iz)[dest] /= cj;
/// now last d/dx is correct, so proceed upward, back substituting
for (j=n_y-2; j>=0; j--)
D2F(ix,j,iz)[dest] -= mu(j) * D2F(ix,j+1,iz)[dest];
}
}
}
void TriCubicSpline::UpdateD2Z(int source, int dest){
blitz::Array<double,1> mu(n_z);
/// Loop over all x and y
for(int ix = 0; ix < n_x; ix++){
for(int iy = 0; iy < n_y; iy++){
/// set up tridiagonal set of equations : initialise RHS
D2F(ix,iy,0)[dest] = 1.5 *
( D2F(ix,iy,1)[source] - D2F(ix,iy,0)[source] ) / dx(2,0);
D2F(ix,iy,n_z-1)[dest] = 1.5 *
(D2F(ix,iy,n_z-1)[source] - D2F(ix,iy,n_z-2)[source]) / dx(2,n_z-2);
mu(0) = 0.5;
/// solve tri-diagonal set of equations. First eliminate lower elements
for(int j = 1; j < n_z - 1; j++){
double lambda = 0.5*dx(2,j)/(dx(2,j)+dx(2,j-1));
mu(j) = 0.5 - lambda;
D2F(ix,iy,j)[dest] =
3.0*(lambda*(D2F(ix,iy,j)[source]-D2F(ix,iy,j-1)[source])/dx(2,j-1)+
mu(j) *(D2F(ix,iy,j+1)[source]-D2F(ix,iy,j)[source])/dx(2,j) );
double cj = 1.0 - lambda * mu(j-1);
D2F(ix,iy,j)[dest] -= lambda * D2F(ix,iy,j-1)[dest];
mu(j) /= cj;
D2F(ix,iy,j)[dest] /= cj;
}
/// last element
int j = n_z - 1;
double lambda = 0.5;
mu(j) = 0.5 - lambda;
D2F(ix,iy,j)[dest] =
3.0*(lambda*(D2F(ix,iy,j)[source]-D2F(ix,iy,j-1)[source])/dx(2,j-1) );
double cj = 1.0 - lambda * mu(j-1);
D2F(ix,iy,j)[dest] -= lambda * D2F(ix,iy,j-1)[dest];
mu(j) /= cj;
D2F(ix,iy,j)[dest] /= cj;
/// now last d/dx is correct, so proceed upward, back substituting
for (j=n_z-2; j>=0; j--)
D2F(ix,iy,j)[dest] -= mu(j) * D2F(ix,iy,j+1)[dest];
}
}
}
void TriCubicSpline::D2FDR2(){
D2F = 0.0;
for(int ix = 1; ix < n_x - 1; ix++){
for(int iy = 1; iy < n_y - 1; iy++){
for(int iz = 1; iz < n_z - 1; iz++){
posvec_t r = m_grid->ptr(ix,iy,iz);
D2F(ix,iy,iz)[0] = laplacian(r);
}
}
}
return;
}
double TriCubicSpline::delsqf(const gridvec_t& P0, int dir){
double numer, denom;
gridvec_t Pi,Pf;
for(int idim = 0; idim < 3; idim++){
Pi[idim] = P0[idim]; Pf[idim] = P0[idim];
}
Pi[dir] -= 1; Pf[dir] += 1;
double f0 = F(P0[0],P0[1],P0[2])[0];
double fi = F(Pi[0],Pi[1],Pi[2])[0];
double ff = F(Pf[0],Pf[1],Pf[2])[0];
double hi = dx(dir,Pi[dir]);
double h0 = dx(dir,P0[dir]);
numer = hi*(ff-f0) + h0*(fi-f0);
denom = hi*h0*(hi+h0);
return 2.0*numer/(denom+1e-30);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,136 @@
#include "Numerics/Spline3D/TriCubicSplineSet.h"
#include <string>
#include <cstring>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
namespace ohmmsqmc {
using namespace std;
TriCubicSplineSet::TriCubicSplineSet(): DeviceGrid(NULL),
Schr_Grid(NULL),
m_set(NULL){ }
TriCubicSplineSet::~TriCubicSplineSet(){
}
bool TriCubicSplineSet::put(xmlNodePtr cur,
Grid3D* agrid){
/// make these member functions (WHY???)
vector<string> wfile;
vector<int> norbs_t;
DeviceGrid = agrid; /// point to the whole Grid3D
if(!m_set) m_set = new SetSplinePoint; /// create r-point set
xmlNodePtr node = cur->xmlChildrenNode;
while( node != NULL){
string name((char*)node->name);
if(name=="orbitals"){
int n = atoi((char*)xmlGetProp(node,(xmlChar*)"norbs"));
string w((char*)xmlGetProp(node,(xmlChar*)"file"));
norbs_t.push_back(n);
wfile.push_back(w);
}
if(name=="HeteroStructure"){
xmlNodePtr node1 = node->xmlChildrenNode;
while(node1 != NULL){
string cname((const char*)(node1->name));
if(cname=="Grid3D"){
xmlNodePtr node2 = node1->xmlChildrenNode;
while(node2 != NULL){
string qname((const char*)(node2->name));
if(qname=="qGridi"){
ri[0] = atoi((char*)xmlGetProp(node2,(xmlChar*)"x"));
ri[1] = atoi((char*)xmlGetProp(node2,(xmlChar*)"y"));
ri[2] = atoi((char*)xmlGetProp(node2,(xmlChar*)"z"));
}
if(qname=="qGridf"){
rf[0] = atoi((char*)xmlGetProp(node2,(xmlChar*)"x"));
rf[1] = atoi((char*)xmlGetProp(node2,(xmlChar*)"y"));
rf[2] = atoi((char*)xmlGetProp(node2,(xmlChar*)"z"));
}
node2 = node2->next;
}
}
node1 = node1->next;
}
}
node = node->next;
}
/// allocate and initialise the Schr_Grid
if(!Schr_Grid) Schr_Grid = new Grid3D;
Schr_Grid->init(ri,rf,DeviceGrid);
/// read in the input wave-function file
norbs = 0; cout << "Reading Wafefunction file ..." ;
for(int iset=0; iset<wfile.size(); iset++) {
for(int iorb = 0; iorb < norbs_t[iset]; iorb++) {
m_psi.push_back(new TriCubicSpline(m_set,Schr_Grid));
}
readwf(wfile[iset].c_str(),iset,norbs_t[iset]);
}
cout << "done!" << endl;
if(wfile.size() ==1) {
char aname[4];
int num = orbital_map.size();
for(int iorb = 0; iorb < num; iorb++) {
sprintf(aname,"d%d",iorb);
orbital_map[aname]=iorb;
}
}
/// initialise the TriCubicSpline
for(int iorb = 0; iorb < m_psi.size(); iorb++)
m_psi[iorb]->Update(true); /// Laplacian is required so true
return true;
}
void TriCubicSplineSet::readwf(const char* wfile, int ispin, int num){
char aname[4];
int norbs_save = norbs;
for(int iorb = 0; iorb < num; iorb++) {
if(ispin == 0) {
sprintf(aname,"u%d",iorb);
orbital_map[aname]=norbs++;
} else {
sprintf(aname,"d%d",iorb);
orbital_map[aname]=norbs++;
}
}
ifstream infile(wfile, ios_base::in); double x;
for(int i = 0; i < Schr_Grid->m_size; i++){
for(int iorb = norbs_save, j=0; j< num; iorb++,j++) {
infile >>x;
const gridvec_t& ir = Schr_Grid->ipt(i);
(*m_psi[iorb])(ir[0],ir[1],ir[2]) = -x;
}
}
return;
}
void TriCubicSplineSet::evaluate(const posvec_t& r,
scalar_array_t& fval,
posarray_t& gradf,scalar_array_t& lapf){
for(int iorb = 0; iorb < norbs; iorb++)
fval[iorb] = m_psi[iorb]->evaluate(r,gradf[iorb],lapf[iorb]);
return;
}
}

Some files were not shown because too many files have changed in this diff Show More