Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
77 changes: 50 additions & 27 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
@@ -1,59 +1,82 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Python application
name: Python package

on:
push:
branches: [ Fast_LANCZOS ]
branches: [ master ]
pull_request:
branches: [ Fast_LANCZOS ]
branches: [ master ]

jobs:
build:

runs-on: ubuntu-latest

strategy:
matrix:
python-version: [3.8]

services:
rabbitmq:
image: rabbitmq:latest
ports:
- 5672:5672

steps:
- uses: actions/checkout@v2
- name: Set up Python 3.9

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: 3.9
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
pip install ase spglib==2.2 julia
python -c 'import julia; julia.install()'
pip install flake8 pytest~=6.0 pgtest~=1.3 aiida-core~=2.3 aiida-quantumespresso~=4.3
if [ ${{matrix.python-version}} -eq 2.7 ]; then pip install -r requirements2.txt;
else pip install -r requirements.txt; fi
aiida-pseudo install

- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Prepare the installation

- name: Install
run: |
sudo apt-get update
# Install the fortran compiler with lapack and blas
sudo apt-get install gfortran libblas-dev liblapack-dev build-essential \
mpich libopenmpi-dev libgl1-mesa-glx libglib2.0-0 \
libboost-all-dev
sudo apt-get install git gfortran libblas-dev liblapack-dev mpich

pip install mpi4py


git clone https://github.com/SSCHAcode/CellConstructor.git
cd CellConstructor && python setup.py install --user && cd ..
rm -r CellConstructor

git clone https://github.com/SSCHAcode/python-sscha.git
cd python-sscha && python setup.py install --user && cd ..
rm -r python-sscha

MPICC=mpicc python setup.py install --user

cd CModules; make; cd ..

pip install meson meson-python ninja
pip install mpi4py

cd CellConstructor
pip install --no-build-isolation .
cd ..

# Install the python-sscha
cd python-sscha
pip install --no-build-isolation .
cd ..

# Install the tdscha package
pip install --no-build-isolation .

# Install julia requirements
python -c 'import julia; julia.install()'
- name: Test with pytest
env:
OMP_NUM_THREADS: 1
run: |
pytest
cd tests
rm -rf __pycache__
# Test excluding very long running tests
pytest -v -m "not release"
88 changes: 44 additions & 44 deletions CModules/odd_corr_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,16 @@ static PyObject *ApplyV3ToDyn(PyObject * self, PyObject * args) {
}

// Retrive the pointer to the data from the python object
X = (double*) PyArray_DATA(npy_X);
Y = (double*) PyArray_DATA(npy_Y);
rho = (double*) PyArray_DATA(npy_rho);
w = (double*) PyArray_DATA(npy_omega);
input = (double*) PyArray_DATA(npy_input);
output = (double*) PyArray_DATA(npy_output);
X = (double*) PyArray_DATA((PyArrayObject*)npy_X);
Y = (double*) PyArray_DATA((PyArrayObject*)npy_Y);
rho = (double*) PyArray_DATA((PyArrayObject*)npy_rho);
w = (double*) PyArray_DATA((PyArrayObject*)npy_omega);
input = (double*) PyArray_DATA((PyArrayObject*)npy_input);
output = (double*) PyArray_DATA((PyArrayObject*)npy_output);

// Read the symmetries
symmetries = (double*)PyArray_DATA(npy_symmetries);
n_deg = (int*)PyArray_DATA(npy_n_deg);
symmetries = (double*)PyArray_DATA((PyArrayObject*)npy_symmetries);
n_deg = (int*)PyArray_DATA((PyArrayObject*)npy_n_deg);

// Build the degeneracy space
good_deg_space = (int **) malloc(sizeof(int*) * N_modes);
Expand All @@ -169,7 +169,7 @@ static PyObject *ApplyV3ToDyn(PyObject * self, PyObject * args) {
for (i = 0; i < N_modes;++i) {
good_deg_space[i] = (int*) malloc(sizeof(int) * n_deg[i]);
for (j = 0; j < n_deg[i]; ++j) {
good_deg_space[i][j] = ((int*) PyArray_DATA(npy_deg_space))[counter++];
good_deg_space[i][j] = ((int*) PyArray_DATA((PyArrayObject*)npy_deg_space))[counter++];
}
}

Expand Down Expand Up @@ -252,16 +252,16 @@ static PyObject *ApplyV3_FT(PyObject * self, PyObject * args) {
}

// Retrive the pointer to the data from the python object
X = (double*) PyArray_DATA(npy_X);
Y = (double*) PyArray_DATA(npy_Y);
rho = (double*) PyArray_DATA(npy_rho);
w = (double*) PyArray_DATA(npy_omega);
input = (double*) PyArray_DATA(npy_input);
output = (double*) PyArray_DATA(npy_output);
X = (double*) PyArray_DATA((PyArrayObject*)npy_X);
Y = (double*) PyArray_DATA((PyArrayObject*)npy_Y);
rho = (double*) PyArray_DATA((PyArrayObject*)npy_rho);
w = (double*) PyArray_DATA((PyArrayObject*)npy_omega);
input = (double*) PyArray_DATA((PyArrayObject*)npy_input);
output = (double*) PyArray_DATA((PyArrayObject*)npy_output);

// Read the symmetries
symmetries = (double*)PyArray_DATA(npy_symmetries);
n_deg = (int*)PyArray_DATA(npy_n_deg);
symmetries = (double*)PyArray_DATA((PyArrayObject*)npy_symmetries);
n_deg = (int*)PyArray_DATA((PyArrayObject*)npy_n_deg);

// Build the degeneracy space
good_deg_space = (int **) malloc(sizeof(int*) * N_modes);
Expand All @@ -275,7 +275,7 @@ static PyObject *ApplyV3_FT(PyObject * self, PyObject * args) {
good_deg_space[i] = (int*) malloc(sizeof(int) * n_deg[i]);
if (DEB) printf("Mode %d -> ", i);
for (j = 0; j < n_deg[i]; ++j) {
good_deg_space[i][j] = ((int*) PyArray_DATA(npy_deg_space))[counter++];
good_deg_space[i][j] = ((int*) PyArray_DATA((PyArrayObject*)npy_deg_space))[counter++];
if (DEB) printf(" %d ", good_deg_space[i][j]);
}
if (DEB) printf("\n");
Expand Down Expand Up @@ -339,12 +339,12 @@ static PyObject *GetWeights(PyObject * self, PyObject * args) {
}

// Retrive the pointer to the data from the python object
X = (double*) PyArray_DATA(npy_X);
R1 = (double*) PyArray_DATA(npy_R1);
Y1 = (double*) PyArray_DATA(npy_Y1);
w = (double*) PyArray_DATA(npy_omega);
X = (double*) PyArray_DATA((PyArrayObject*)npy_X);
R1 = (double*) PyArray_DATA((PyArrayObject*)npy_R1);
Y1 = (double*) PyArray_DATA((PyArrayObject*)npy_Y1);
w = (double*) PyArray_DATA((PyArrayObject*)npy_omega);

weights = (double*) PyArray_DATA(npy_weights);
weights = (double*) PyArray_DATA((PyArrayObject*)npy_weights);

get_weights(X, w, R1, Y1, T, N_modes, N_configs, weights);

Expand Down Expand Up @@ -389,12 +389,12 @@ static PyObject *Get_D2DR2_PertV(PyObject * self, PyObject * args) {
}

// Retrive the pointer to the data from the python object
X = (double*) PyArray_DATA(npy_X);
Y = (double*) PyArray_DATA(npy_Y);
rho = (double*) PyArray_DATA(npy_rho);
w = (double*) PyArray_DATA(npy_omega);
weights = (double*) PyArray_DATA(npy_weights);
d2vdr2 = (double*) PyArray_DATA(npy_d2vdr2);
X = (double*) PyArray_DATA((PyArrayObject*)npy_X);
Y = (double*) PyArray_DATA((PyArrayObject*)npy_Y);
rho = (double*) PyArray_DATA((PyArrayObject*)npy_rho);
w = (double*) PyArray_DATA((PyArrayObject*)npy_omega);
weights = (double*) PyArray_DATA((PyArrayObject*)npy_weights);
d2vdr2 = (double*) PyArray_DATA((PyArrayObject*)npy_d2vdr2);

// Apply the method
get_d2v_dR2_pert(X, Y, w, weights, rho, T, N_modes, N_configs, d2vdr2);
Expand Down Expand Up @@ -578,8 +578,8 @@ static PyObject * Get_Perturb_AveragesSym(PyObject * self, PyObject * args) {
//printf("I'm here, %s:%d\n", __FILE__, __LINE__);

for (i = 0; i < n_blocks; ++i) {
good_deg_space[i] = (int*) PyArray_DATA( PyList_GetItem(sym_basis_list, i)); //malloc(sizeof(int) * n_deg[i]);
good_syms[i] = (double*) PyArray_DATA( PyList_GetItem(sym_list, i)) ; // malloc(sizeof(double) * n_deg[i] * n_deg[i] * N_syms);
good_deg_space[i] = (int*) PyArray_DATA((PyArrayObject*) PyList_GetItem(sym_basis_list, i)); //malloc(sizeof(int) * n_deg[i]);
good_syms[i] = (double*) PyArray_DATA( (PyArrayObject*)PyList_GetItem(sym_list, i)) ; // malloc(sizeof(double) * n_deg[i] * n_deg[i] * N_syms);

/*
printf("Block:\n");
Expand Down Expand Up @@ -1081,9 +1081,9 @@ static PyObject * GetV3(PyObject * self, PyObject * args) {
// Convert the array
//numpy_array = PyArray_FROM_OTF(bare_array, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);

X = (double*) PyArray_DATA(npy_X);
Y = (double*) PyArray_DATA(npy_Y);
v3 = (double*) PyArray_DATA(npy_v3);
X = (double*) PyArray_DATA((PyArrayObject*)npy_X);
Y = (double*) PyArray_DATA((PyArrayObject*)npy_Y);
v3 = (double*) PyArray_DATA((PyArrayObject*)npy_v3);


int i;
Expand Down Expand Up @@ -1169,11 +1169,11 @@ static PyObject * ApplyV4(PyObject * self, PyObject * args) {
// Convert the array
//numpy_array = PyArray_FROM_OTF(bare_array, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);

X = (double*) PyArray_DATA(npy_X);
Y = (double*) PyArray_DATA(npy_Y);
Lambda = (double*) PyArray_DATA(npy_Lambda);
v_in = (double*) PyArray_DATA(npy_vin);
v_out = (double*) PyArray_DATA(npy_vout);
X = (double*) PyArray_DATA((PyArrayObject*)npy_X);
Y = (double*) PyArray_DATA((PyArrayObject*)npy_Y);
Lambda = (double*) PyArray_DATA((PyArrayObject*)npy_Lambda);
v_in = (double*) PyArray_DATA((PyArrayObject*)npy_vin);
v_out = (double*) PyArray_DATA((PyArrayObject*)npy_vout);

int i;
int a, b, c, d;
Expand Down Expand Up @@ -1273,11 +1273,11 @@ static PyObject * GetV4(PyObject * self, PyObject * args) {
// Convert the array
//numpy_array = PyArray_FROM_OTF(bare_array, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);

X = (double*) PyArray_DATA(npy_X);
Y = (double*) PyArray_DATA(npy_Y);
rows = (int*) PyArray_DATA(npy_rows);
cols = (int*) PyArray_DATA(npy_cols);
v4_out = (double*) PyArray_DATA(npy_v4out);
X = (double*) PyArray_DATA( (PyArrayObject*)npy_X);
Y = (double*) PyArray_DATA( (PyArrayObject*)npy_Y);
rows = (int*) PyArray_DATA( (PyArrayObject*)npy_rows);
cols = (int*) PyArray_DATA( (PyArrayObject*)npy_cols);
v4_out = (double*) PyArray_DATA((PyArrayObject*)npy_v4out);

int i;
int a, b, c, d;
Expand Down
2 changes: 1 addition & 1 deletion Modules/DynamicalLanczos.py
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ def prepare_symmetrization(self, no_sym = False, verbose = True, symmetries = No

t1 = time.time()
if symmetries is None:
super_symmetries = CC.symmetries.GetSymmetriesFromSPGLIB(spglib.get_symmetry(super_structure.get_ase_atoms()), False)
super_symmetries = CC.symmetries.GetSymmetriesFromSPGLIB(spglib.get_symmetry(super_structure.get_spglib_cell()), False)

else:
super_symmetries = symmetries
Expand Down
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

# Introduction

## What is TD-SCHA?

TD-SCHA is a theory to simulate quantum nuclear motion in materials with strong anharmonicity.
TD-SCHA stands for Time-Dependent Self-Consistent Harmonic Approximation, and it is the dynamical extension of the SCHA theory, that can describe equilibrium properties of materials accounting for both quantum and dynamical nuclear fluctuations.

The `tdscha` Python library allows performing dynamical linear response calculations on top of the equilibrium results (computed with the `python-sscha` package).

## Why would I need tdscha?

### A Tool for Advanced Material Simulations

**Enhanced Simulation Capabilities**
TD-SCHA is an essential tool for researchers and professionals in material science, particularly for simulating transport or thermal properties of materials, phase diagrams, and phonon-related properties.

**Integration with python-sscha**
Seamless integration with `python-sscha` allows for the inclusion of both thermal and quantum phonon fluctuations in *ab initio* simulations.

**Leveraging the SSCHA Method**

**Quantum and Thermal Fluctuations**
The Stochastic Self-Consistent Harmonic Approximation (SSCHA) is a full-quantum method optimizing the nuclear wave-function or density matrix to minimize free energy, crucial for simulating highly anharmonic systems.

**Efficiency and Cost-Effectiveness**
Despite its full quantum and thermal nature, the computational cost is comparable to classical molecular dynamics, enhanced by the algorithm's ability to exploit crystal symmetries.

**User-Friendly and Versatile**

**Python Library and Stand-alone Software**
Available both as a Python library and stand-alone software, with input scripts sharing syntax with Quantum ESPRESSO.

**Broad Compatibility**
Can couple with any *ab initio* engine and interacts through the Atomic Simulation Environment (ASE) with an interface for automatic job submission on remote clusters.

**Getting Started**

**Easy to Use**
User-friendly with short, readable input files and comprehensive tutorials.

**Download and Explore**
Download and install `python-sscha`, and start exploring the tutorials to enhance your material simulation projects.

# How to install

You need to have installed `python-sscha` and `CellConstructor` to work with `tdscha`.
Please read the installation guide for those packages before proceeding further.
You may find all instructions on the [official website](http://www.sscha.eu).

To install from PyPI, simply type:

```bash
pip install tdscha
```
You can alternatively clone the repository from GitHub and install the package with:

```
pip install .
```


# Quick start
Go to the [tutorials](https://sscha.eu/Tutorials/tutorial_05_ramanir/)

Loading