Skip to content

Commit

Permalink
Experimental:
Browse files Browse the repository at this point in the history
add a function to access variables that are assumed-shape arrays.
This works by setting up a fixed-shape "external" array which is
interoperable, and then every time the global variable is accessed by
the python code, update the "internal" fortran array to have the same
value.

it works, but it's also a complication and involves allocating two times
what is effectively the same quantity.
To be discussed.
  • Loading branch information
lcrippa committed Sep 5, 2024
1 parent f744234 commit 4370d7f
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 27 deletions.
43 changes: 28 additions & 15 deletions python/edi2py.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,21 @@
import os,sys
import types


######################################
# Load shared library with C-bindings
######################################

system = sys.platform
libext = '.so'
if(system=='darwin'):
libext = '.dylib'
libpath = os.path.dirname(os.path.realpath(__file__))
sys.path.insert(0, libpath)
libfile = os.path.join(libpath, 'libedi2py'+libext)
libedi2py = CDLL(libfile)


#################################
#AUXILIARY FUNCTIONS
#################################
Expand All @@ -11,6 +26,14 @@
class Link:
def __init__(self,library):
self.library = library

#function that equates the assumed-shape Fortran internal arrays with the fixed-shape c-binding ones

def update_array(name,setget):
wrapper = libedi2py.update_array
wrapper.argtypes = [c_char_p,c_char_p]
wrapper.restypes = None
wrapper(c_char_p(name.encode()),c_char_p(setget.encode()))

#function that will add a variable to the dummy class, will be called in variable definition
def add_global_variable(obj, dynamic_name, target_object, target_attribute):
Expand All @@ -24,7 +47,9 @@ def getter(self):
pass
except: #this is for arrays
if(len(target_object)>1):
return [target_object[x] for x in range(len(target_object))]
update_array(dynamic_name,"get")
aux_norb=c_int.in_dll(libedi2py, "Norb").value
return np.asarray([target_object[x] for x in range(aux_norb)])
return attrib

@getter.setter
Expand All @@ -33,6 +58,7 @@ def setter(self, new_value):
if(len(target_object)>1):
minlength=min(len(target_object),len(new_value))
target_object[0:minlength]=new_value[0:minlength]
update_array(dynamic_name,"set")
except:
try:
new_value = new_value.encode()
Expand All @@ -45,19 +71,6 @@ def setter(self, new_value):
setattr(obj.__class__, dynamic_name, setter)


######################################
# Load shared library with C-bindings
######################################

system = sys.platform
libext = '.so'
if(system=='darwin'):
libext = '.dylib'
libpath = os.path.dirname(os.path.realpath(__file__))
sys.path.insert(0, libpath)
libfile = os.path.join(libpath, 'libedi2py'+libext)
libedi2py = CDLL(libfile)

####################################################################
# Create the global_env class (this is what the python module sees)
####################################################################
Expand All @@ -80,7 +93,7 @@ def setter(self, new_value):
add_global_variable(global_env, "Lpos", c_int.in_dll(libedi2py, "Lpos"), "value")
add_global_variable(global_env, "LOGfile", c_int.in_dll(libedi2py, "LOGfile"), "value")

add_global_variable(global_env, "Uloc", ARRAY(c_double, 5).in_dll(libedi2py, "Uloc"), "value")
add_global_variable(global_env, "Uloc", ARRAY(c_double, 5).in_dll(libedi2py, "Uloc_cbind"), "value")
add_global_variable(global_env, "Ust", c_double.in_dll(libedi2py, "Ust"), "value")
add_global_variable(global_env, "Jh", c_double.in_dll(libedi2py, "Jh"), "value")
add_global_variable(global_env, "Jx", c_double.in_dll(libedi2py, "Jx"), "value")
Expand Down
3 changes: 1 addition & 2 deletions python/func_read_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ def read_input(self,input_string):
read_input_wrap.argtypes = [c_char_p]
read_input_wrap.restype = None
c_string = c_char_p(input_string.encode())
read_input_wrap(c_string)
return "lol"
read_input_wrap(c_string)
19 changes: 9 additions & 10 deletions src/ED_INPUT_VARS.f90
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@ MODULE ED_INPUT_VARS

!input variables
!=========================================================
integer(c_int), bind(c, name="Nbath") :: Nbath !Nbath=# of bath sites (per orbital or not depending on bath_type)
integer(c_int), bind(c, name="Norb") :: Norb !Norb =# of impurity orbitals
integer(c_int), bind(c, name="Nspin") :: Nspin !Nspin=# spin degeneracy (max 2)
integer(c_int),bind(c, name="Nbath") :: Nbath !Nbath=# of bath sites (per orbital or not depending on bath_type)
integer(c_int),bind(c, name="Norb") :: Norb !Norb =# of impurity orbitals
integer(c_int),bind(c, name="Nspin") :: Nspin !Nspin=# spin degeneracy (max 2)

integer(c_int), bind(c, name="Nloop") :: Nloop !max dmft loop variables
integer(c_int), bind(c, name="Nph") :: Nph !max number of phonons allowed (cut off)
real(c_double),dimension(5),bind(c, name="Uloc") :: Uloc !local interactions
integer(c_int),bind(c, name="Nloop") :: Nloop !max dmft loop variables
integer(c_int),bind(c, name="Nph") :: Nph !max number of phonons allowed (cut off)
real(c_double),bind(c, name="Ust") :: Ust !intra-orbitals interactions
real(c_double),bind(c, name="Jh") :: Jh !J_Hund: Hunds' coupling constant
real(c_double),bind(c, name="Jx") :: Jx !J_X: coupling constant for the spin-eXchange interaction term
Expand All @@ -24,7 +23,7 @@ MODULE ED_INPUT_VARS
real(c_double),bind(c, name="beta") :: beta !inverse temperature
!
!
integer(c_int), bind(c, name="Nsuccess") :: Nsuccess !# of repeated success to fall below convergence threshold
integer(c_int),bind(c, name="Nsuccess") :: Nsuccess !# of repeated success to fall below convergence threshold
real(c_double),bind(c, name="dmft_error") :: dmft_error !dmft convergence threshold
real(c_double),bind(c, name="eps") :: eps !broadening
real(c_double),bind(c, name="wini") :: wini !frequency range min
Expand All @@ -34,6 +33,7 @@ MODULE ED_INPUT_VARS
real(c_double),bind(c, name="sb_field") :: sb_field !symmetry breaking field
real(c_double),bind(c, name="nread") :: nread !fixed density. if 0.d0 fixed chemical potential calculation.
!
real(8),dimension(:),allocatable :: Uloc !local interactions
logical :: HFmode !flag for HF interaction form U(n-1/2)(n-1/2) VS Unn
real(8) :: cutoff !cutoff for spectral summation
real(8) :: gs_threshold !Energy threshold for ground state degeneracy loop up
Expand Down Expand Up @@ -159,9 +159,8 @@ subroutine ed_read_input(INPUTunit)
call parse_input_variable(Nph,"NPH",INPUTunit,default=0,comment="Max number of phonons allowed (cut off)")
call parse_input_variable(bath_type,"BATH_TYPE",INPUTunit,default='normal',comment="flag to set bath type: normal (1bath/imp), hybrid(1bath), replica(1replica/imp), general(replica++)")
!
!allocate(Uloc(Norb)) #TODO: put me back!
!call parse_input_variable(uloc,"ULOC",INPUTunit,default=(/( 2d0,i=1,size(Uloc) )/),comment="Values of the local interaction per orbital")
call parse_input_variable(uloc,"ULOC",INPUTunit,default=[2d0,0d0,0d0,0d0,0d0],comment="Values of the local interaction per orbital (max 5)")
allocate(Uloc(Norb))
call parse_input_variable(uloc,"ULOC",INPUTunit,default=(/( 2d0,i=1,size(Uloc) )/),comment="Values of the local interaction per orbital")
call parse_input_variable(ust,"UST",INPUTunit,default=0.d0,comment="Value of the inter-orbital interaction term")
call parse_input_variable(Jh,"JH",INPUTunit,default=0.d0,comment="Hunds coupling")
call parse_input_variable(Jx,"JX",INPUTunit,default=0.d0,comment="S-E coupling")
Expand Down
41 changes: 41 additions & 0 deletions src/edi2py/edi2py.f90
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module edi2py_bindings
use iso_c_binding
implicit none

real(c_double),dimension(5),bind(c, name="Uloc_cbind") :: Uloc_cbind !local interactions

contains

Expand Down Expand Up @@ -50,6 +51,46 @@ subroutine c2f(c_str)
f_str=trim(f_str)
end subroutine c2f

subroutine update_array(c_str1,c_str2) bind(c, name="update_array")
character(kind=c_char), dimension(*),intent(IN) :: c_str1, c_str2
character(len=120), allocatable :: f_str1, f_str2
integer :: length
integer :: i

f_str1=" "
f_str2=" "

length=0
do
if (c_str1(length+1) == C_NULL_CHAR) exit
length = length + 1
end do
do i = 1, length
f_str1(i:i) = c_str1(i)
enddo
f_str1=trim(f_str1)

length=0
do
if (c_str2(length+1) == C_NULL_CHAR) exit
length = length + 1
end do
do i = 1, length
f_str2(i:i) = c_str2(i)
enddo
f_str1=trim(f_str1)

select case (f_str1)
case default
STOP "This variable is not updatable"
case("Uloc")
if(allocated(Uloc))deallocate(Uloc)
allocate(Uloc(Norb))
if(f_str2=="set") Uloc(1:Norb) = Uloc_cbind(1:Norb)
if(f_str2=="get") Uloc_cbind(1:Norb) = Uloc(1:Norb)
end select
end subroutine update_array

!include library functions
include "edi2py_read_input.f90"
include "edi2py_main.f90"
Expand Down

0 comments on commit 4370d7f

Please sign in to comment.