Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pseudopotentials and numeric orbitals for initial guess #499

Draft
wants to merge 130 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
2b4bcbb
quick and dirty
moritzgubler Apr 16, 2024
e47dd6f
improve code
moritzgubler Apr 16, 2024
49594c4
(un)safe changes
moritzgubler Apr 16, 2024
1766ace
add doc
moritzgubler Apr 16, 2024
267ca95
fix bug reading c
moritzgubler Apr 17, 2024
e271a5f
start on good pp
moritzgubler Apr 29, 2024
7aa5db6
improve pp
moritzgubler Apr 29, 2024
02f5f59
add one to lmax
moritzgubler Apr 29, 2024
9b1b71c
remove old implementation of data type
moritzgubler Apr 29, 2024
6dbdd01
clean up code
moritzgubler Apr 29, 2024
cdc675a
rename stuff
moritzgubler Apr 29, 2024
e9b090f
move files
moritzgubler Apr 29, 2024
0df70dd
add multi elements
moritzgubler Apr 29, 2024
89e6da3
add first draft of projector
moritzgubler Apr 30, 2024
3e1fb50
add exponential factor
moritzgubler Apr 30, 2024
6a9f508
improvements
moritzgubler Apr 30, 2024
5a95eb0
add sketch of projectoroperator
moritzgubler Apr 30, 2024
bd87121
add some docs
moritzgubler Apr 30, 2024
b93f5c2
more docs
moritzgubler Apr 30, 2024
f86b1b0
introduce shift
moritzgubler Apr 30, 2024
0105d49
change types
moritzgubler Apr 30, 2024
64ca5a7
add constructor
moritzgubler Apr 30, 2024
8218550
doc
moritzgubler Apr 30, 2024
0c197c7
fix silly errors
moritzgubler Apr 30, 2024
a8e0fa8
reintroduce old stuff
moritzgubler Apr 30, 2024
df69e9f
minor fix in file format
moritzgubler Apr 30, 2024
44629e6
fix qmfunctionvector naming
moritzgubler May 1, 2024
2475709
improve constructor
moritzgubler May 1, 2024
d3f0613
make parent class public
moritzgubler May 2, 2024
082cd42
start dotting
moritzgubler May 2, 2024
881155d
apply compiles
moritzgubler May 2, 2024
f35b4d6
make it segfault
moritzgubler Aug 12, 2024
f0384bc
add prints
moritzgubler Aug 14, 2024
08e130e
add more prints
moritzgubler Nov 7, 2024
11a546d
more prints
moritzgubler Nov 7, 2024
13e74d1
more prints and fix bugs
moritzgubler Nov 8, 2024
56af19c
single s projector working
moritzgubler Nov 9, 2024
e8ba774
printprintprint
moritzgubler Nov 11, 2024
b323f5b
fix bug
moritzgubler Nov 19, 2024
d5e2478
p orbitals working
moritzgubler Nov 19, 2024
876bf82
add pp section
moritzgubler Nov 20, 2024
9aca579
start python stuff
moritzgubler Nov 20, 2024
3950c63
update params
moritzgubler Nov 20, 2024
fe3188b
first logic done, todo parse psppar
moritzgubler Nov 20, 2024
86ff50b
add parsing of psppar files
moritzgubler Nov 22, 2024
6148ea7
json mess
moritzgubler Nov 22, 2024
fd099eb
small change
moritzgubler Nov 24, 2024
ba36d7c
use different format
moritzgubler Nov 24, 2024
4c0bda3
example in driver working
moritzgubler Nov 24, 2024
3e0d8dc
add getters
moritzgubler Nov 25, 2024
b61a865
integrate pp-data
moritzgubler Nov 25, 2024
2c62a2a
add new constructor to nuclei and add function that checks if a pp ex…
moritzgubler Nov 26, 2024
3956e48
put pp into molecult
moritzgubler Nov 26, 2024
5f22583
add other constructor to get rid of final occurence of set_charge
moritzgubler Nov 26, 2024
10b5a91
update mechanism from pp nucleus
moritzgubler Nov 26, 2024
aa58fb8
mixed sims working
moritzgubler Nov 26, 2024
99b4084
update parser
moritzgubler Nov 26, 2024
719260c
input logic working
moritzgubler Nov 26, 2024
2bd8ad5
compute molecular charge differently
moritzgubler Nov 26, 2024
55b1164
fix bug
moritzgubler Nov 27, 2024
6db00bc
comment a lot of print
moritzgubler Nov 27, 2024
f16da90
make core initial guess work for pps
moritzgubler Nov 27, 2024
069c0fa
add has pp function to molecule
moritzgubler Nov 27, 2024
8b688eb
force core initial guess if pps are used
moritzgubler Nov 27, 2024
9dcc594
remove r^-l factor for numerical stability
moritzgubler Nov 27, 2024
31e1bcf
remove a lot of prints
moritzgubler Nov 27, 2024
1b7adf2
parse nlcc terms
moritzgubler Nov 27, 2024
179c2ad
implement nlcc pps
moritzgubler Nov 27, 2024
98a5882
get rid of numpy dependency
moritzgubler Nov 27, 2024
73588f7
print nlcc data
moritzgubler Nov 29, 2024
b46900b
implement f projectors untested
moritzgubler Dec 1, 2024
972c4d9
remove print
moritzgubler Dec 2, 2024
5a616c9
add getatomic number function
moritzgubler Dec 2, 2024
e992d87
make sad work for pp
moritzgubler Dec 2, 2024
3b87d15
new way to project rho
moritzgubler Dec 2, 2024
4c8c032
clean things up
moritzgubler Dec 2, 2024
af085df
remove more prints
moritzgubler Dec 2, 2024
eff9cf7
speed things up
moritzgubler Dec 2, 2024
e7e74d4
add basis for all elements
moritzgubler Dec 2, 2024
1ae552a
test spherical harmonics
moritzgubler Dec 2, 2024
0c4e72a
make test work or other alphas
moritzgubler Dec 3, 2024
c8eb701
remove writing of user dict for debug purposes
moritzgubler Dec 3, 2024
23f70e7
add a couple of virtual orbitals
moritzgubler Dec 3, 2024
bb8b472
renove virt. orbs
moritzgubler Dec 3, 2024
a781fa8
improve test
moritzgubler Dec 4, 2024
f795cf2
make projector not function
moritzgubler Dec 4, 2024
fd94f4e
deepcopy to be safe
moritzgubler Dec 4, 2024
79bfd7a
debug print
moritzgubler Dec 4, 2024
8161d57
lots of debyug
moritzgubler Dec 4, 2024
2dd1c95
make sure projector is projected
moritzgubler Dec 4, 2024
63b6560
remove some copies
moritzgubler Dec 4, 2024
82359ec
make sure nlcc rho gets projected
moritzgubler Dec 4, 2024
c9221c1
mix it a bit
moritzgubler Dec 5, 2024
767dc0f
move mixing calculation to sad initial guess
moritzgubler Dec 5, 2024
2c3f7f8
new parameters
moritzgubler Dec 6, 2024
bceaa58
calcuclate mixing energies
moritzgubler Dec 6, 2024
fab5143
go to pbe
moritzgubler Dec 6, 2024
304488f
adnjust test
moritzgubler Dec 6, 2024
27520b3
for marco
moritzgubler Dec 6, 2024
b896f69
add orbitals
moritzgubler Dec 6, 2024
14d41ae
read file
moritzgubler Dec 6, 2024
aad1105
make it run again
moritzgubler Dec 6, 2024
83fa2cb
add getter
moritzgubler Dec 6, 2024
747c5a2
improve switch_sperics
moritzgubler Dec 6, 2024
9bc7a44
this does nearly work
moritzgubler Dec 6, 2024
cae9047
fix bug
moritzgubler Dec 9, 2024
d80241a
sp[in changes
moritzgubler Dec 9, 2024
acbf7c2
maybe
moritzgubler Dec 9, 2024
adc56cc
rescale intitial charge
moritzgubler Dec 9, 2024
e363534
more orbitalsfor gold
moritzgubler Dec 10, 2024
3324692
precompute kin and nuc mat
moritzgubler Dec 10, 2024
f66bd3e
remove print
moritzgubler Dec 10, 2024
0e68af4
start migrating stuff
moritzgubler Dec 11, 2024
2038e87
restore sad initial guess
moritzgubler Dec 11, 2024
f674dab
add new initial guess type
moritzgubler Dec 11, 2024
0617c69
parse new mixing parameters
moritzgubler Dec 11, 2024
d87bf15
implement nao intial guess in driver
moritzgubler Dec 11, 2024
4f79cb0
fix bug
moritzgubler Dec 11, 2024
048c275
add timer
moritzgubler Dec 11, 2024
4d0a46a
revert gsf
moritzgubler Dec 11, 2024
d24ea97
revert core
moritzgubler Dec 11, 2024
62bb4a2
fix projection
moritzgubler Dec 11, 2024
9a458e9
better prints
moritzgubler Dec 11, 2024
877c28a
gold has even f orbital
moritzgubler Dec 12, 2024
8537148
update template and helper
moritzgubler Dec 19, 2024
19c85c9
update parser
moritzgubler Dec 19, 2024
41a4ff3
fix typo
moritzgubler Dec 19, 2024
b1ba379
change yet another thing
moritzgubler Dec 19, 2024
8ec14b6
add nao directory logic to mrchem
moritzgubler Dec 19, 2024
ddeaca0
include unoccupied orbitals in nao basis.
moritzgubler Jan 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions doc/users/user_ref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,21 @@ User input reference
**Predicates**
- ``value.lower() in ['point_like', 'point_parabola', 'point_minimal', 'finite_gaussian', 'finite_sphere']``

:Pseudopotential: Define the pseudopotentials.

:red:`Keywords`
:pp_files: Json string of pseudopotential files. The key can be the element symbol or a number. When the key is an element symbol, all atoms of that element will use the given pseudopotential. When the key is a number (index is 1 based), the corresponding atom will use the given pseudopotential. When the value is an empty string, an all electron calculation will be performed for the corresponding atom or element.

**Type** ``str``

**Default** ``{}``

:pp_prec: Precision parameter used in construction of pseudopotentials.

**Type** ``float``

**Default** ``user['world_prec']``

:ZORA: Define required parameters for the ZORA Hamiltonian.

:red:`Keywords`
Expand Down Expand Up @@ -728,14 +743,32 @@ User input reference

**Default** ``-1.0``

:guess_type: Type of initial guess for ground state orbitals. ``chk`` restarts a previous calculation which was dumped using the ``write_checkpoint`` keyword. This will load MRA and electron spin configuration directly from the checkpoint files, which are thus required to be identical in the two calculations. ``mw`` will start from final orbitals in a previous calculation written using the ``write_orbitals`` keyword. The orbitals will be re-projected into the new computational setup, which means that the electron spin configuration and MRA can be different in the two calculations. ``gto`` reads precomputed GTO orbitals (requires extra non-standard input files for basis set and MO coefficients). ``core`` and ``sad`` will diagonalize the Fock matrix in the given AO basis (SZ, DZ, TZ or QZ) using a Core or Superposition of Atomic Densities Hamiltonian, respectively. ``cube`` will start from orbitals saved in cubefiles from external calculations.
:guess_type: Type of initial guess for ground state orbitals. ``chk`` restarts a previous calculation which was dumped using the ``write_checkpoint`` keyword. This will load MRA and electron spin configuration directly from the checkpoint files, which are thus required to be identical in the two calculations. ``mw`` will start from final orbitals in a previous calculation written using the ``write_orbitals`` keyword. The orbitals will be re-projected into the new computational setup, which means that the electron spin configuration and MRA can be different in the two calculations. ``gto`` reads precomputed GTO orbitals (requires extra non-standard input files for basis set and MO coefficients). ``core`` and ``sad`` will diagonalize the Fock matrix in the given AO basis (SZ, DZ, TZ or QZ) using a Core or Superposition of Atomic Densities Hamiltonian, respectively. ``cube`` will start from orbitals saved in cubefiles from external calculations. ``nao`` will start from orbitals saved in NAO format from external calculations. It also allows for some mixing iterations to converge the initial guess within the nao basis.

**Type** ``str``

**Default** ``sad_gto``

**Predicates**
- ``value.lower() in ['mw', 'chk', 'gto', 'core_sz', 'core_dz', 'core_tz', 'core_qz', 'sad_sz', 'sad_dz', 'sad_tz', 'sad_qz', 'sad_gto', 'cube']``
- ``value.lower() in ['mw', 'chk', 'gto', 'core_sz', 'core_dz', 'core_tz', 'core_qz', 'sad_sz', 'sad_dz', 'sad_tz', 'sad_qz', 'sad_gto', 'cube', 'nao']``

:nao_directory: Directory where NAO orbitals are stored for mrchem calculation.

**Type** ``str``

**Default** ``none``

:initial_mixing_steps: Number of mixing iterations to converge the initial guess within the nao basis.

**Type** ``int``

**Default** ``4``

:initial_mixing_step_size: Step size for the mixing iterations to converge the initial guess within the nao basis.

**Type** ``float``

**Default** ``0.4``

:write_checkpoint: Write orbitals to disk in each iteration, file name ``<path_checkpoint>/phi_scf_idx_<0..N>``. Can be used as ``chk`` initial guess in subsequent calculations. Note: must be given in quotes if there are slashes in the path "path/to/checkpoint".

Expand Down Expand Up @@ -12254,4 +12287,4 @@ User input reference
**Type** ``float``

**Default** ``0.00011186082063``


10 changes: 9 additions & 1 deletion python/mrchem/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@

from .helpers import (parse_wf_method, write_rsp_calc, write_scf_fock,
write_scf_guess, write_scf_plot, write_scf_properties,
write_scf_solver)
write_scf_solver, write_pseudo_potential)
from .periodictable import PeriodicTable as PT
from .periodictable import PeriodicTableByZ as PT_Z
from .validators import MoleculeValidator


def translate_input(user_dict):

# get the origin in the desired units of measure
origin = user_dict["world_origin"]
pc = user_dict["Constants"]
Expand All @@ -46,6 +47,13 @@ def translate_input(user_dict):
mra_dict = write_mra(user_dict, mol_dict)
scf_dict = write_scf_calculation(user_dict, origin)
rsp_dict = write_rsp_calculations(user_dict, mol_dict, origin)
pseudo_potential_dict = write_pseudo_potential(user_dict, mol_dict)
mol_dict["pseudopotentials"] = pseudo_potential_dict

if mol_dict["pseudopotentials"]["use_pp"]:
scf_dict["fock_operator"]["pseudopotential"] = {
"pp_prec": mol_dict["pseudopotentials"]["pp_prec"]
}

# piece everything together
program_dict = {
Expand Down
188 changes: 188 additions & 0 deletions python/mrchem/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ def _reaction_operator_handler(user_dict, rsp=False):
def write_scf_guess(user_dict, wf_dict):
guess_str = user_dict["SCF"]["guess_type"].lower()
guess_type = guess_str.split("_")[0]
nmix = user_dict["SCF"]["initial_mixing_steps"]
alpha_mix = user_dict["SCF"]["initial_mixing_step_size"]
nao_directory = user_dict["SCF"]["nao_directory"]
zeta = 0

scf_dict = user_dict["SCF"]
Expand Down Expand Up @@ -249,7 +252,11 @@ def write_scf_guess(user_dict, wf_dict):
"file_CUBE_p": f"{vector_dir}CUBE_p_vector.json",
"file_CUBE_a": f"{vector_dir}CUBE_a_vector.json",
"file_CUBE_b": f"{vector_dir}CUBE_b_vector.json",
"initial_mixing_steps": nmix,
"initial_mixing_step_size": alpha_mix,
}
if nao_directory != "none":
guess_dict["nao_directory"] = nao_directory
return guess_dict


Expand Down Expand Up @@ -499,6 +506,187 @@ def write_rsp_solver(user_dict, wf_dict, d):
return solver_dict


def parse_psppar(filename):
"""
Parses a PSPPAR pseudopotential file and returns the data as a dictionary.

Args:
filename (str): Path to the PSPPAR file.

Returns:
dict: Parsed pseudopotential data.
"""
psppar_data = dict()
psppar_data["local"] = dict()
psppar_data["nonlocal"] = dict()

with open(filename, 'r') as file:
# Skip the first line
next(file)

# Read zion and zeff
line = file.readline().strip()
zion = float(line.split()[0])
zeff = float(line.split()[1])
psppar_data['zion'] = zion
psppar_data['zeff'] = zeff

# Skip the next line
next(file)

# Read rloc, nloc, and c coefficients
line = file.readline().strip()
tokens = line.split()
rloc = float(tokens[0])
nloc = int(tokens[1])
c_coefficients = list(map(float, tokens[2:2+nloc]))

alpha_pp = 1.0 / (sqrt(2.0) * rloc)
psppar_data['local']['rloc'] = rloc
psppar_data['local']['alpha_pp'] = alpha_pp
psppar_data['local']['nloc'] = nloc
psppar_data['local']['c'] = c_coefficients

# Read nsep
line = file.readline().strip()
nsep = int(line.split()[0])
if nsep < 0 or nsep > 4:
raise ValueError("Error: nsep must be between 0 and 4.")
psppar_data['nonlocal']['nsep'] = nsep

# Initialize containers for projectors
rl = []
h = []
dim_h = []


for l in range(nsep):
# Read projector radii and dimension
line = file.readline().strip()
tokens = line.split()
rl_l = float(tokens[0])
dim_h_l = int(tokens[1])

rl.append(rl_l)
dim_h.append(dim_h_l)

# Initialize h matrix
h_matrix = []
for _ in range(dim_h_l):
h_matrix.append([0.0] * dim_h_l)
# convert h_matrix to list of lists

for i in range(dim_h_l):
h_matrix[0][i] = float(line.split()[2 + i])
h_matrix[i][0] = h_matrix[0][i]

# Fill in the upper triangle of the h matrix
for i in range(1, dim_h_l):
line = file.readline().strip()
values = list(map(float, line.split()))
for j, value in enumerate(values):
h_matrix[i][i + j] = value
h_matrix[i + j][i] = value

# h_matrix = h_matrix.tolist()
h.append(h_matrix)

# Skip irrelevant SOC lines if l > 0
if l > 0:
for _ in range(dim_h_l):
file.readline()

# check if file is at the end
line = file.readline()
if line: # try to read rcore and qcore
words = line.split()
if len(words) >= 2:
rcore = float(words[0])
qcore = float(words[1])
psppar_data['nlcc'] = dict()
psppar_data['nlcc']['rcore'] = rcore
psppar_data['nlcc']['qcore'] = qcore


psppar_data['nonlocal']['rl'] = rl
psppar_data['nonlocal']['dim_h'] = dim_h
psppar_data['nonlocal']['h'] = h

return psppar_data


def write_pseudo_potential(user_dict, mol_dict):
import json

pp_dict_out = {
"use_pp": False,
"pp_prec": user_dict["Pseudopotential"]["pp_prec"],
}

# if "Pseudopotential" not in user_dict:
# return []

pp_dict = json.loads(user_dict['Pseudopotential']['pp_files'])

# loop over keys in pp_dict and convert them to lower case
pp_dict = {k.lower(): v for k, v in pp_dict.items()}
all_elements = {k.lower() for k in user_dict["Elements"]}

int_keys = []
# check if all keys in pp_dict are valid elements and collect the integer keys
for key in pp_dict.keys():
if key not in all_elements:
try:
int_keys.append(int(key))
except ValueError:
raise RuntimeError(
f"Invalid key in pseudopotential dictionary (neither a numeric value or an element): {key}"
)

nat = len(mol_dict["coords"])
atomNames = []
atomNamesSet = set()
for atom in mol_dict["coords"]:
atomNames.append(atom["atom"])
atomNamesSet.add(atom["atom"])

pps = []
for i in range(nat):
key = ''
if i in int_keys:
key = str(i)
# check if the key is an element
elif atomNames[i] in pp_dict.keys():
key = atomNames[i]
# if none of the above, all electron calculation for atom i
else:
pp = {
"use_pp": False,
}
pps.append(pp)

if key != "":
if pp_dict[key].lower() == "none" or pp_dict[key].lower() == "":
pp = {
"use_pp": False,
}
else:
pp = {
"use_pp": True,
"file": pp_dict[key],
}
pp_dict_out["use_pp"] = True
# temp_string = json.dumps(temp_pp, indent=4, cls=NumpyEncoder)
# print("Parsed pseudopotential for element:", key, "\n \n")
# print(temp_string)
# print("\n \n \n")
pp['pseuodopotential'] = parse_psppar(pp["file"])
pps.append(pp)
# print(pps)
pp_dict_out["pp_list"] = pps
return pp_dict_out


def parse_wf_method(user_dict):
method_name = ""
restricted = user_dict["WaveFunction"]["restricted"]
Expand Down
2 changes: 1 addition & 1 deletion python/mrchem/input_parser/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
This file was automatically generated by parselglossy on 2024-08-15
This file was automatically generated by parselglossy on 2024-12-19
Editing is *STRONGLY DISCOURAGED*
2 changes: 1 addition & 1 deletion python/mrchem/input_parser/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-

# This file was automatically generated by parselglossy on 2024-08-15
# This file was automatically generated by parselglossy on 2024-12-19
# Editing is *STRONGLY DISCOURAGED*
20 changes: 18 additions & 2 deletions python/mrchem/input_parser/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

# This file was automatically generated by parselglossy on 2024-08-15
# This file was automatically generated by parselglossy on 2024-12-19
# Editing is *STRONGLY DISCOURAGED*

from copy import deepcopy
Expand Down Expand Up @@ -319,6 +319,13 @@ def stencil() -> JSONDict:
"'finite_sphere']"],
'type': 'str'}],
'name': 'WaveFunction'},
{ 'keywords': [ { 'default': '{}',
'name': 'pp_files',
'type': 'str'},
{ 'default': "user['world_prec']",
'name': 'pp_prec',
'type': 'float'}],
'name': 'Pseudopotential'},
{ 'keywords': [ { 'default': True,
'name': 'include_nuclear',
'type': 'bool'},
Expand Down Expand Up @@ -522,8 +529,17 @@ def stencil() -> JSONDict:
"'sad_tz', "
"'sad_qz', "
"'sad_gto', "
"'cube']"],
"'cube', 'nao']"],
'type': 'str'},
{ 'default': 'none',
'name': 'nao_directory',
'type': 'str'},
{ 'default': 4,
'name': 'initial_mixing_steps',
'type': 'int'},
{ 'default': 0.4,
'name': 'initial_mixing_step_size',
'type': 'float'},
{ 'default': False,
'name': 'write_checkpoint',
'type': 'bool'},
Expand Down
2 changes: 1 addition & 1 deletion python/mrchem/input_parser/cli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

# This file was automatically generated by parselglossy on 2024-08-15
# This file was automatically generated by parselglossy on 2024-12-19
# Editing is *STRONGLY DISCOURAGED*

import argparse
Expand Down
Loading
Loading