From 4370d7f889a68b184ea599324dddd155039b8a5d Mon Sep 17 00:00:00 2001 From: lcrippa Date: Thu, 5 Sep 2024 09:05:20 +0200 Subject: [PATCH] Experimental: 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. --- python/edi2py.py | 43 +++++++++++++++++++++++++-------------- python/func_read_input.py | 3 +-- src/ED_INPUT_VARS.f90 | 19 ++++++++--------- src/edi2py/edi2py.f90 | 41 +++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 27 deletions(-) diff --git a/python/edi2py.py b/python/edi2py.py index d2052d88..5ec1af29 100644 --- a/python/edi2py.py +++ b/python/edi2py.py @@ -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 ################################# @@ -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): @@ -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 @@ -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() @@ -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) #################################################################### @@ -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") diff --git a/python/func_read_input.py b/python/func_read_input.py index 08fee58f..181d4bda 100644 --- a/python/func_read_input.py +++ b/python/func_read_input.py @@ -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" \ No newline at end of file + read_input_wrap(c_string) \ No newline at end of file diff --git a/src/ED_INPUT_VARS.f90 b/src/ED_INPUT_VARS.f90 index d6442f4b..58e66b6c 100644 --- a/src/ED_INPUT_VARS.f90 +++ b/src/ED_INPUT_VARS.f90 @@ -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 @@ -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 @@ -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 @@ -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") diff --git a/src/edi2py/edi2py.f90 b/src/edi2py/edi2py.f90 index 70034a26..f0d77127 100644 --- a/src/edi2py/edi2py.f90 +++ b/src/edi2py/edi2py.f90 @@ -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 @@ -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"