qmcpack/nexus/tests/unit/test_physical_system.py

521 lines
15 KiB
Python

#! /usr/bin/env python3
import numpy as np
import testing
from testing import value_eq,object_eq,object_diff,print_diff
from test_structure import structure_same
def system_same(s1,s2,pseudized=True,tiled=False):
same = True
keys = ('net_charge','net_spin','pseudized','particles')
o1 = s1.obj(keys)
o2 = s2.obj(keys)
qsame = object_eq(o1,o2)
vsame = True
if pseudized:
vsame = s1.valency==s2.valency
#end if
ssame = structure_same(s1.structure,s2.structure)
fsame = True
if tiled:
fsame = system_same(s1.folded_system,s2.folded_system)
#end if
same = qsame and vsame and ssame and fsame
return same
#end def system_same
def test_import():
import physical_system
from physical_system import Matter,Particle,Ion,PseudoIon,Particles
from physical_system import PhysicalSystem,generate_physical_system
#end def test_import
def test_particle_initialization():
from generic import obj
from physical_system import Matter,Particle,Ion,PseudoIon,Particles
from physical_system import PhysicalSystem,generate_physical_system
# empty initialization
Matter()
p = Particle()
i = Ion()
pi = PseudoIon()
Particles()
def check_none(v,vfields):
for f in vfields:
assert(f in v)
assert(v[f] is None)
#end for
#end def check_none
pfields = 'name mass charge spin'.split()
ifields = pfields + 'protons neutrons'.split()
pifields = ifields+['core_electrons']
check_none(p,pfields)
check_none(i,ifields)
check_none(pi,pifields)
# matter
elements = Matter.elements
assert(len(elements)==103)
assert('Si' in elements)
pc = Matter.particle_collection
for e in elements:
assert(e in pc)
#end for
assert('up_electron' in pc)
assert('down_electron' in pc)
u = pc.up_electron
assert(u.name=='up_electron')
assert(value_eq(u.mass,1.0))
assert(u.charge==-1)
assert(u.spin==1)
d = pc.down_electron
assert(d.name=='down_electron')
assert(value_eq(d.mass,1.0))
assert(d.charge==-1)
assert(d.spin==-1)
si = pc.Si
assert(si.name=='Si')
assert(value_eq(si.mass,51197.6459833))
assert(si.charge==14)
assert(si.protons==14)
assert(si.neutrons==14)
# test get_particle
assert(object_eq(pc.get_particle('Si'),si))
si1 = si.copy()
si1.name = 'Si1'
assert(object_eq(pc.get_particle('Si1'),si1))
#end def test_particle_initialization
def test_physical_system_initialization():
import os
from generic import obj
from structure import generate_structure
from physical_system import generate_physical_system
from physical_system import PhysicalSystem
tpath = testing.setup_unit_test_output_directory('physical_system','test_physical_system_initialization')
d2 = generate_structure(
structure = 'diamond',
cell = 'prim',
)
d2_path = os.path.join(tpath,'diamond2.xsf')
d2.write(d2_path)
d8 = generate_structure(
structure = 'diamond',
cell = 'conv',
)
d8_path = os.path.join(tpath,'diamond8.xsf')
d8.write(d8_path)
d8_tile = d2.tile([[ 1, -1, 1],
[ 1, 1, -1],
[-1, 1, 1]])
d8_tile_pos_ref = np.array([
[0. , 0. , 0. ],
[0.25, 0.25, 0.25],
[0.5 , 0.5 , 0. ],
[0.75, 0.75, 0.25],
[0. , 0.5 , 0.5 ],
[0.25, 0.75, 0.75],
[0.5 , 0. , 0.5 ],
[0.75, 0.25, 0.75]])
assert(value_eq(d8_tile.pos_unit(),d8_tile_pos_ref,atol=1e-8))
direct_notile = generate_physical_system(
units = 'A',
axes = [[3.57, 0.00, 0.00],
[0.00, 3.57, 0.00],
[0.00, 0.00, 3.57]],
elem = 8*['C'],
posu = [[0.00, 0.00, 0.00],
[0.25, 0.25, 0.25],
[0.00, 0.50, 0.50],
[0.25, 0.75, 0.75],
[0.50, 0.00, 0.50],
[0.75, 0.25, 0.75],
[0.50, 0.50, 0.00],
[0.75, 0.75, 0.25]],
C = 4,
)
direct_tile = generate_physical_system(
units = 'A',
axes = [[1.785, 1.785, 0. ],
[0. , 1.785, 1.785],
[1.785, 0. , 1.785]],
elem = 2*['C'],
posu = [[0.00, 0.00, 0.00],
[0.25, 0.25, 0.25]],
tiling = [[ 1, -1, 1],
[ 1, 1, -1],
[-1, 1, 1]],
C = 4,
)
struct_notile = generate_physical_system(
structure = d8,
C = 4,
)
struct_tile = generate_physical_system(
structure = d2,
tiling = [[ 1, -1, 1],
[ 1, 1, -1],
[-1, 1, 1]],
C = 4,
)
read_notile = generate_physical_system(
structure = d8_path,
C = 4,
)
read_tile = generate_physical_system(
structure = d2_path,
tiling = [[ 1, -1, 1],
[ 1, 1, -1],
[-1, 1, 1]],
C = 4,
)
gen_notile = generate_physical_system(
lattice = 'cubic', # cubic tetragonal orthorhombic rhombohedral
# hexagonal triclinic monoclinic
cell = 'conventional', # primitive, conventional
centering = 'F', # P A B C I R F
constants = 3.57, # a,b,c,alpha,beta,gamma
units = 'A', # A or B
atoms = 'C', # species in primitive cell
basis = [[0,0,0], # basis vectors (optional)
[.25,.25,.25]],
C = 4,
)
gen_tile = generate_physical_system(
lattice = 'cubic', # cubic tetragonal orthorhombic rhombohedral
# hexagonal triclinic monoclinic
cell = 'primitive', # primitive, conventional
centering = 'F', # P A B C I R F
constants = 3.57, # a,b,c,alpha,beta,gamma
units = 'A', # A or B
atoms = 'C', # species in primitive cell
basis = [[0,0,0], # basis vectors (optional)
[.25,.25,.25]],
tiling = [[ 1, -1, 1],
[ 1, 1, -1],
[-1, 1, 1]],
C = 4,
)
lookup_notile = generate_physical_system(
structure = 'diamond',
cell = 'conv',
C = 4,
)
lookup_tile = generate_physical_system(
structure = 'diamond',
cell = 'prim',
tiling = [[ 1, -1, 1],
[ 1, 1, -1],
[-1, 1, 1]],
C = 4,
)
pref = obj(
C = obj(
charge = 4,
core_electrons = 2,
count = 8,
mass = 21894.7135906,
name = 'C',
neutrons = 6,
protons = 6,
spin = 0,
),
down_electron = obj(
charge = -1,
count = 16,
mass = 1.0,
name = 'down_electron',
spin = -1,
),
up_electron = obj(
charge = -1,
count = 16,
mass = 1.0,
name = 'up_electron',
spin = 1,
),
)
# check direct system w/o tiling
ref = direct_notile
sref = ref.structure
assert(ref.net_charge==0)
assert(ref.net_spin==0)
assert(ref.pseudized)
assert(object_eq(ref.valency,obj(C=4)))
assert(object_eq(ref.particles.to_obj(),pref))
assert(structure_same(sref,d8))
assert(value_eq(sref.axes,3.57*np.eye(3)))
assert(tuple(sref.bconds)==tuple('ppp'))
assert(list(sref.elem)==8*['C'])
assert(value_eq(tuple(sref.pos[-1]),(2.6775,2.6775,0.8925)))
assert(sref.units=='A')
assert(object_eq(ref.particles.get_ions().to_obj(),obj(C=pref.C)))
assert(object_eq(ref.particles.get_electrons().to_obj(),obj(down_electron=pref.down_electron,up_electron=pref.up_electron)))
# check direct system w/ tiling
ref = direct_tile
sref = ref.structure
assert(ref.net_charge==0)
assert(ref.net_spin==0)
assert(ref.pseudized)
assert(object_eq(ref.valency,obj(C=4)))
assert(object_eq(ref.particles.to_obj(),pref))
assert(structure_same(sref,d8_tile))
assert(value_eq(sref.axes,3.57*np.eye(3)))
assert(tuple(sref.bconds)==tuple('ppp'))
assert(list(sref.elem)==8*['C'])
assert(value_eq(tuple(sref.pos[-1]),(2.6775,0.8925,2.6775)))
assert(sref.units=='A')
ref = direct_tile.folded_system
sref = ref.structure
pref.C.count = 2
pref.down_electron.count = 4
pref.up_electron.count = 4
assert(ref.net_charge==0)
assert(ref.net_spin==0)
assert(ref.pseudized)
assert(object_eq(ref.valency,obj(C=4)))
assert(object_eq(ref.particles.to_obj(),pref))
assert(structure_same(sref,d2))
assert(value_eq(sref.axes,1.785*np.array([[1.,1,0],[0,1,1],[1,0,1]])))
assert(tuple(sref.bconds)==tuple('ppp'))
assert(list(sref.elem)==2*['C'])
assert(value_eq(tuple(sref.pos[-1]),(0.8925,0.8925,0.8925)))
assert(sref.units=='A')
ref_notile = direct_notile
ref_tile = direct_tile
assert(system_same(struct_notile,ref_notile))
assert(system_same(read_notile ,ref_notile))
assert(system_same(gen_notile ,ref_notile))
assert(system_same(lookup_notile,ref_notile))
assert(system_same(struct_tile,ref_tile,tiled=True))
assert(system_same(read_tile ,ref_tile,tiled=True))
assert(system_same(gen_tile ,ref_tile,tiled=True))
assert(system_same(lookup_tile,ref_tile,tiled=True))
systems_notile = [
direct_notile,
struct_notile,
read_notile ,
gen_notile ,
lookup_notile,
]
systems_tile = [
direct_tile,
struct_tile,
read_tile ,
gen_tile ,
lookup_tile,
]
systems = systems_notile+systems_tile
for sys in systems:
assert(sys.is_valid())
#end for
# test has_folded
for sys in systems_notile:
assert(not sys.has_folded())
#end for
for sys in systems_tile:
assert(sys.has_folded())
#end for
# test copy
for sys in systems:
c = sys.copy()
assert(id(c)!=id(sys))
assert(c.is_valid())
assert(system_same(c,sys,tiled=sys.has_folded()))
#end for
# test load
for i,sys in enumerate(systems):
path = os.path.join(tpath,'system_{}'.format(i))
sys.save(path)
sys2 = PhysicalSystem()
sys2.load(path)
assert(sys2.is_valid())
assert(system_same(sys2,sys,tiled=sys.has_folded()))
#end for
# test particle counts
p = direct_notile.particles
assert(p.count_ions()==8)
assert(p.count_ions(species=True)==(8,1))
assert(p.count_electrons()==32)
assert(p.electron_counts()==[16,16])
#end def test_physical_system_initialization
def test_change_units():
from physical_system import generate_physical_system
sys = generate_physical_system(
units = 'A',
axes = [[3.57, 0.00, 0.00],
[0.00, 3.57, 0.00],
[0.00, 0.00, 3.57]],
elem = 8*['C'],
posu = [[0.00, 0.00, 0.00],
[0.25, 0.25, 0.25],
[0.00, 0.50, 0.50],
[0.25, 0.75, 0.75],
[0.50, 0.00, 0.50],
[0.75, 0.25, 0.75],
[0.50, 0.50, 0.00],
[0.75, 0.75, 0.25]],
C = 4,
)
s = sys.structure
assert(value_eq(s.pos[-1],np.array([2.6775,2.6775,0.8925])))
sys.change_units('B')
assert(value_eq(s.pos[-1],np.array([5.05974172,5.05974172,1.68658057])))
#end def test_change_units
def test_rename():
from generic import obj
from physical_system import generate_physical_system
sys = generate_physical_system(
units = 'A',
axes = [[1.785, 1.785, 0. ],
[0. , 1.785, 1.785],
[1.785, 0. , 1.785]],
elem = ['C1','C2'],
posu = [[0.00, 0.00, 0.00],
[0.25, 0.25, 0.25]],
tiling = [[ 1, -1, 1],
[ 1, 1, -1],
[-1, 1, 1]],
C1 = 4,
C2 = 4,
)
ref = sys
assert(object_eq(ref.valency,obj(C1=4,C2=4)))
assert(list(ref.structure.elem)==4*['C1','C2'])
assert(ref.particles.count_ions()==8)
assert(ref.particles.count_ions(species=True)==(8,2))
ref = sys.folded_system
assert(object_eq(ref.valency,obj(C1=4,C2=4)))
assert(list(ref.structure.elem)==['C1','C2'])
assert(ref.particles.count_ions()==2)
assert(ref.particles.count_ions(species=True)==(2,2))
sys.rename(C1='C',C2='C')
ref = sys
assert(object_eq(ref.valency,obj(C=4)))
assert(list(ref.structure.elem)==8*['C'])
assert(ref.particles.count_ions()==8)
assert(ref.particles.count_ions(species=True)==(8,1))
ref = sys.folded_system
assert(object_eq(ref.valency,obj(C=4)))
assert(list(ref.structure.elem)==2*['C'])
assert(ref.particles.count_ions()==2)
assert(ref.particles.count_ions(species=True)==(2,1))
#end def test_rename
def test_tile():
from physical_system import generate_physical_system
d2_ref = generate_physical_system(
units = 'A',
axes = [[1.785, 1.785, 0. ],
[0. , 1.785, 1.785],
[1.785, 0. , 1.785]],
elem = 2*['C'],
posu = [[0.00, 0.00, 0.00],
[0.25, 0.25, 0.25]],
C = 4,
)
d8_ref = generate_physical_system(
units = 'A',
axes = [[1.785, 1.785, 0. ],
[0. , 1.785, 1.785],
[1.785, 0. , 1.785]],
elem = 2*['C'],
posu = [[0.00, 0.00, 0.00],
[0.25, 0.25, 0.25]],
tiling = [[ 1, -1, 1],
[ 1, 1, -1],
[-1, 1, 1]],
C = 4,
)
d8 = d2_ref.tile([[ 1, -1, 1],
[ 1, 1, -1],
[-1, 1, 1]])
assert(system_same(d8,d8_ref,tiled=True))
#end def test_tile
def test_kf_rpa():
from test_structure import example_structure_h4
from physical_system import generate_physical_system
s1 = example_structure_h4()
ps = generate_physical_system(
structure = s1,
net_charge = 1,
net_spin = 1,
H = 1
)
kfs = ps.kf_rpa()
assert np.isclose(kfs[0], 1.465, atol=1e-3)
assert np.isclose(kfs[1], 1.465/2**(1./3), atol=1e-3)
#end def test_kf_rpa