Sophie

Sophie

distrib > Mandriva > 2010.2 > i586 > media > contrib-backports > by-pkgid > df29c83ca401d91ec9c00bfcf7fea4ea > files > 254

shedskin-0.8-2mdv2010.2.i586.rpm

#!/usr/bin/python

"""\
  wave_func.py - compute the wave fuction and local energy
"""

# Copyright (C) 2006-2007, Mark Dewing
# http://quameon.sourceforge.net/
# Quameon is covered under the GNU General Public License.  Please see the
# file LICENSE that is part of this distribution.

import box_bc
import math
from jastrow import simple_pade, const_jastrow
#from orbital import floating_gaussian
from orbital import lcao
from coulomb import coulomb_pot
from sum_jastrow import ee_jastrow, en_jastrow
import fermion

# general single determinant wavefunction 

class wave_func_single_det:
  def __init__(self): 
    self.npos = [[0.0,0.0,1.0]]
    self.ee_wv = ee_jastrow()
    self.en_wv = en_jastrow(self.npos)
    self.pot = coulomb_pot(self.npos)
    self.orb =  lcao.LCAO()
    self.fermion = fermion.fermion(self.orb)
    self.vp_size_set = False

  def set_npos(self,npos):
    if self.en_wv:
      self.en_wv.set_npos(npos)
    if self.pot:
      self.pot.set_npos(npos)

#  def set_ee_jastrow(self,new_ee_jastrow):
#    self.ee_wv = new_ee_jastrow

#  def set_en_jastrow(self,new_en_jastrow):
#    self.en_wv = new_en_jastrow
#    self.en_wv.set_npos(npos)

  def set_orbital(self,orb):
    self.orb = orb
    self.fermion.set_orbital(self.orb)

  def get_vp(self):
    ee_vp = self.ee_wv.get_vp()
    self.ee_vp_size = len(ee_vp)
    en_vp = self.en_wv.get_vp()
    self.en_vp_size = len(en_vp)
    orb_vp = self.orb.get_vp()
    self.orb_vp_size = len(orb_vp)
    self.vp_size_set = True
    #vp = ee_vp + en_vp + orb_vp
    #vp = [ee_vp[0],en_vp[0],orb_vp[0]]
    vp = []
    for p in ee_vp:
      vp.append(p)
    for p in en_vp:
      vp.append(p)
    for p in orb_vp:
      vp.append(p)
    # this next line doesn't work sometimes, hence the preceeding mess
    #vp = ee_vp + en_vp + orb_vp
    return vp

  def set_vp(self,vp):
    if not(self.vp_size_set):
      self.get_vp()
    ee_vp = vp[:self.ee_vp_size]
    en_vp = vp[self.ee_vp_size:(self.ee_vp_size + self.en_vp_size)]
    orb_vp = vp[(self.en_vp_size + self.ee_vp_size):]
    self.ee_wv.set_vp(ee_vp)
    self.en_wv.set_vp(en_vp)
    self.orb.set_vp(orb_vp)

#  def satisfies_constraints(self,vp):
#    if not(self.vp_size_set):
#      get_vp()
#    ee_vp = vp[:self.ee_vp_size]
#    en_vp = vp[self.ee_vp_size:(self.ee_vp_size + self.en_vp_size)]
#    orb_vp = vp[(self.en_vp_size + self.ee_vp_size):]
#    okay = True
#    okay = self.ee_wv.satisfies_constraints(ee_vp)
#    if okay:
#      okay = self.en_wv.satisfies_constraints(en_vp)
#    if okay:
#      okay = self.orb.satisfies_constraints(orb_vp)
#    return okay

  def compute_jastrow_log_value(self,epos,p,idx):
    ee_wv = self.ee_wv.compute_value(epos,p,idx)
    en_wv = self.en_wv.compute_value(p)
    return 0.5*ee_wv + en_wv

  def compute_log_ratio(self,epos,p,idx):
    old_psi = self.compute_jastrow_log_value(epos,epos[idx],idx)
    new_psi = self.compute_jastrow_log_value(epos,p,idx)
    det_ratio = self.fermion.compute_log_ratio(epos,p,idx)
    return new_psi - old_psi + det_ratio

  def compute_partial_log_value(self,epos):
    val = 0.0
    for i in range(len(epos)):
      val += self.compute_jastrow_log_value(epos,epos[i],i)
    #val += self.fermion.compute_log_value(epos)
    return val

#  def compute_total_log_value(self,epos):
#    j_val = self.compute_partial_log_value(epos)
#    det_orig = self.fermion.compute_value(epos)
# 
#    try:
#      val = j_val*math.log(abs(det_orig))
#    except OverflowError:
#      val = 0.0
#    return val

  def local_energy(self,epos):
    pot_e = 0.0
    pot_e += self.pot.compute_ee_value(epos)
    pot_e += self.pot.compute_en_value(epos)
    pot_e += self.pot.compute_nn_value()
    kin_e = 0.0
    for i in range(len(epos)):
      del_sq = 0.0
      del_sq += self.ee_wv.compute_del_sq(epos,epos[i],i)
      del_sq += self.en_wv.compute_del_sq(epos[i])
      del_sq += self.fermion.compute_del_sq(epos,i)
      du = self.ee_wv.compute_del(epos,epos[i],i)
      dudu = [0.0,0.0,0.0]
      for j in range(len(dudu)):
        dudu[j] += du[j]
      du = self.en_wv.compute_del(epos[i])
      for j in range(len(dudu)):
        dudu[j] += du[j]

      orb_dot = 0.0
      orb_du = self.fermion.compute_del(epos,i)
      for j in range(len(dudu)):
        orb_dot += dudu[j]*orb_du[j]

      dot = 0.0
      for j in range(len(dudu)):
        dot += dudu[j]*dudu[j]
      kin_e += -.5*del_sq - .5*dot - orb_dot
    loc_e = kin_e + pot_e
    return loc_e,kin_e,pot_e

  def local_energy_num(self,epos,h=1e-4):
     val = 0.0
     pot_e = 0.0
     pot_e += self.pot.compute_ee_value(epos)
     pot_e += self.pot.compute_en_value(epos)
     pot_e += self.pot.compute_nn_value()
     kin_e = 0.0
     for i in range(len(epos)):
       deriv = 0.0
       val = self.compute_partial_log_value(epos)
       det_orig = self.fermion.compute_value(epos)
       for j in range(len(epos[0])):
         epos[i][j] += h
         val_p = self.compute_partial_log_value(epos)
         det_p = self.fermion.compute_value(epos)
         epos[i][j] += -2*h
         val_m = self.compute_partial_log_value(epos)
         det_m = self.fermion.compute_value(epos)
         epos[i][j] += h
         arg_p = val_p - val
         arg_m = val_m - val
         deriv += math.exp(arg_p)*det_p/det_orig + math.exp(arg_m)*det_m/det_orig - 2.0
       kin_e -= deriv/(h*h)/2.0
     num_loc_e = kin_e + pot_e
     return num_loc_e,kin_e,pot_e


#def test_orb_derivs(epos):
#  pass
  

if __name__ == '__main__':
  #npos = [[0.0,0.0,0.0],[0.0,0.0,1.4]]
  npos = [[0.0,0.0,0.0]]
  epos = [[0.0,0.0,0.0],[0.0,0.0,1.0]]
  #cp = coulomb_pot(npos)
  #print cp.compute_nn_value(),1.0/1.4
  #print cp.compute_en_value(epos),-4.0/0.7
  #print cp.compute_ee_value(epos)
  wv = wave_func_single_det()
  print wv.local_energy(epos)
  print wv.local_energy_num(epos)