Skip to content

Commit

Permalink
Merge branch 'develop' into rho-pcie
Browse files Browse the repository at this point in the history
  • Loading branch information
dzzz2001 authored Jul 3, 2024
2 parents 0bbe40c + f9c20e5 commit 2135a03
Show file tree
Hide file tree
Showing 91 changed files with 2,314 additions and 2,238 deletions.
43 changes: 43 additions & 0 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,49 @@ To add a unit test:

in the `abacus-develop` directory.

## Adding an integrate test
The integrate test is a test suite for testing the whole ABACUS package. The examples are located in the `tests/integrate` directory. Before adding a new test, please firstly read `README.md` in `tests/integrate` to understand the structure of the integrate test. To add an integrate test:
1. Add a new directory under `tests/integrate` for the new test.
2. Prepare the input files for the new test.
- The input files should be placed in the new directory. Pseudopotential files and orbital files should be placed in `tests/PP_ORB`. You should define the correct `pseudo_dir` and `orb_dir`(if need orbital files) in INPUT with the relative path to the `tests/PP_ORB` directory, and be sure the new test can be run successfully.
- The running time of the new test should not exceed 20 seconds. You can try to reduce the time by below methods (on the premise of ensuring the effectiveness of the test):
- Reduce the number of atoms in the unit cell (1~2 atoms).
- Reduce the number of k-points (`1 1 1` or `2 2 2`).
- Reduce ecutwfc (20~50 Ry).
- Reduce the number of steps for relax or md job (2~3 steps).
- Reduce the basis set for LCAO calculations (DZP orbital and 6 a.u. cutoff).
- For PW calculations, should set `pw_seed 1` in INPUT file to ensure the reproducibility of the test.
3. Generate the reference results for the new test.
- Run the new test with GNU compiler and 4 MPI processes 2 OpenMP threads. The command is `OMP_NUM_THREADS=2 mpirun -np 4 abacus > log.txt`.
- Execute tests/integrate/tools/catch_properties.sh script to generate the reference results. At the new test directory, run `bash ../tools/catch_properties.sh result.ref`.
A `result.ref` file may be like:
```text
etotref -3439.007931317310
etotperatomref -3439.0079313173
totaltimeref 2.78
```
- If you want to test the correctness of some output files, you need to do extra below steps:
1. add the corresponding comparison method in `catch_properties.sh`. For example, to verify whether the output of the SPIN1_CHG.cube file is correct, you need to add the following code in `catch_properties.sh`:
```bash
has_band=$(awk '$1=="out_band" {a=$2} END{print a}' INPUT) # check if the BAND is outputed
if ! test -z "$has_band" && [ $has_band == 1 ]; then # if band is outputed, then check if the band is correct
bandref=refBANDS_1.dat # this file should be prepared in new test directory
bandcal=OUT.autotest/BANDS_1.dat # this file is generated by each run of test
python3 ../tools/CompareFile.py $bandref $bandcal 8 # compare the new band file with the reference file
echo "CompareBand_pass $?" >>$1 # record the comparison result, $? is the return value of last command
fi
```
`CompareFile.py` is used to determine if two files are identical. It accepts three arguments: the first two are the files to be compared, and the third specifies the precision for comparing numerical values. The comparison fails if the difference between any two corresponding numerical values exceeds 1e-{precision} (such as: 1e-8 in previous case). If the files are identical, the script returns 0; otherwise, it returns 1.

2. Add the reference file (such as: `refBANDS_1.dat` in previous case) to the new test directory.

3. Add the reference comparison result to the `result.ref` file. For example, `CompareBand_pass 0` means the comparison of the band file is passed. (This statement should be added before the `totaltimeref` line)
4. Add a `jd` file in the new test directory, which is one setence to describe the new test.
5. Add the new test to `tests/integrate/CASES_CPU.txt` file (or `tests/integrate/CASES_GPU.txt` file if it is for GPU verion).
6. Enter directory tests/integrate and run `bash Autotest.sh -r <the-new-test-name>` to check if the new test can be run successfully.



## Debugging the codes

For the unexpected results when developing ABACUS, [GDB](https://www.sourceware.org/gdb/) will come in handy.
Expand Down
2 changes: 1 addition & 1 deletion source/Makefile.Objects
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ OBJS_CELL=atom_pseudo.o\
setup_nonlocal.o\
klist.o\
cell_index.o\
check_atomic_stru.o\

OBJS_DEEPKS=LCAO_deepks.o\
LCAO_deepks_fdelta.o\
Expand Down Expand Up @@ -232,7 +233,6 @@ OBJS_GINT=gint.o\
gint_tau.o\
gint_vl.o\
gint_k_env.o\
gint_k_sparse.o\
gint_k_sparse1.o\
gint_k_pvpr.o\
gint_k_pvdpr.o\
Expand Down
66 changes: 32 additions & 34 deletions source/driver_run.cpp
Original file line number Diff line number Diff line change
@@ -1,48 +1,53 @@
#include "driver.h"
#include "module_cell/check_atomic_stru.h"
#include "module_cell/module_neighbor/sltk_atom_arrange.h"
#include "module_hamilt_pw/hamilt_pwdft/global.h"
#include "module_io/input.h"
#include "module_io/para_json.h"
#include "module_io/print_info.h"
#include "module_io/winput.h"
#include "module_md/run_md.h"
#include "module_io/para_json.h"

/**
* @brief This is the driver function which defines the workflow of ABACUS calculations.
* It relies on the class Esolver, which is a class that organizes workflows of single point calculations.
*
* For calculations involving change of configuration (lattice parameter & ionic motion),
* this driver calls Esolver::Run and the configuration-changing subroutine in a alternating manner.
*
* @brief This is the driver function which defines the workflow of ABACUS
* calculations. It relies on the class Esolver, which is a class that organizes
* workflows of single point calculations.
*
* For calculations involving change of configuration (lattice parameter & ionic
* motion), this driver calls Esolver::Run and the configuration-changing
* subroutine in a alternating manner.
*
* Information is passed between the two subroutines by class UnitCell
*
* Esolver::Run takes in a configuration and provides force and stress,
* the configuration-changing subroutine takes force and stress and updates the configuration
*
* Esolver::Run takes in a configuration and provides force and stress,
* the configuration-changing subroutine takes force and stress and updates the
* configuration
*/
void Driver::driver_run(void)
{
void Driver::driver_run() {
ModuleBase::TITLE("Driver", "driver_line");
ModuleBase::timer::tick("Driver", "driver_line");

//! 1: initialize the ESolver
ModuleESolver::ESolver *p_esolver = nullptr;
//! 1: initialize the ESolver
ModuleESolver::ESolver* p_esolver = nullptr;
ModuleESolver::init_esolver(p_esolver);

//! 2: setup cell and atom information

// this warning should not be here, mohan 2024-05-22
#ifndef __LCAO
if(GlobalV::BASIS_TYPE == "lcao_in_pw" || GlobalV::BASIS_TYPE == "lcao")
{
ModuleBase::WARNING_QUIT("driver","to use LCAO basis, compile with __LCAO");
if (GlobalV::BASIS_TYPE == "lcao_in_pw" || GlobalV::BASIS_TYPE == "lcao") {
ModuleBase::WARNING_QUIT("driver",
"to use LCAO basis, compile with __LCAO");
}
#endif

// the life of ucell should begin here, mohan 2024-05-12
// delete ucell as a GlobalC in near future
GlobalC::ucell.setup_cell(GlobalV::stru_file, GlobalV::ofs_running);
Check_Atomic_Stru::check_atomic_stru(GlobalC::ucell,
GlobalV::MIN_DIST_COEF);

//! 3: initialize Esolver and fill json-structure
//! 3: initialize Esolver and fill json-structure
p_esolver->before_all_runners(INPUT, GlobalC::ucell);

// this Json part should be moved to before_all_runners, mohan 2024-05-12
Expand All @@ -52,32 +57,25 @@ void Driver::driver_run(void)

const std::string cal_type = GlobalV::CALCULATION;

//! 4: different types of calculations
if(cal_type == "md")
{
//! 4: different types of calculations
if (cal_type == "md") {
Run_MD::md_line(GlobalC::ucell, p_esolver, INPUT.mdp);
}
else if(cal_type == "scf"
|| cal_type == "relax"
|| cal_type == "cell-relax")
{
} else if (cal_type == "scf" || cal_type == "relax"
|| cal_type == "cell-relax") {
Relax_Driver rl_driver;
rl_driver.relax_driver(p_esolver);
}
else
{
} else {
//! supported "other" functions:
//! nscf(PW,LCAO),
//! get_pchg(LCAO),
//! test_memory(PW,LCAO),
//! nscf(PW,LCAO),
//! get_pchg(LCAO),
//! test_memory(PW,LCAO),
//! test_neighbour(LCAO),
//! get_S(LCAO),
//! get_S(LCAO),
//! gen_bessel(PW), et al.
const int istep = 0;
p_esolver->others(istep);
}


//! 5: clean up esolver
p_esolver->after_all_runners();
ModuleESolver::clean_esolver(p_esolver);
Expand Down
1 change: 1 addition & 0 deletions source/module_cell/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_library(
klist.cpp
parallel_kpoints.cpp
cell_index.cpp
check_atomic_stru.cpp
)

if(ENABLE_COVERAGE)
Expand Down
159 changes: 159 additions & 0 deletions source/module_cell/check_atomic_stru.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#include "check_atomic_stru.h"

#include "module_base/element_covalent_radius.h"

void Check_Atomic_Stru::check_atomic_stru(UnitCell& ucell, double& factor) {
// First we calculate all bond length in the structure,
// and compare with the covalent_bond_length,
// if there has bond length is shorter than covalent_bond_length * factor,
// we think this structure is unreasonable.
const double warning_coef = 0.6;
assert(ucell.ntype > 0);
std::stringstream errorlog;
bool all_pass = true;
bool no_warning = true;
for (int it1 = 0; it1 < ucell.ntype; it1++) {
std::string symbol1 = "";
for (char ch: ucell.atoms[it1].label) {
if (std::isalpha(ch)) {
symbol1.push_back(ch);
}
}
// std::string symbol1 = ucell.atoms[it1].label;
double symbol1_covalent_radius;
if (ModuleBase::CovalentRadius.find(symbol1)
!= ModuleBase::CovalentRadius.end()) {
symbol1_covalent_radius = ModuleBase::CovalentRadius.at(symbol1);
} else {
std::stringstream mess;
mess << "Notice: symbol '" << symbol1
<< "' is not an element symbol!!!! ";
mess << "set the covalent radius to be 0." << std::endl;
GlobalV::ofs_running << mess.str();
std::cout << mess.str();
symbol1_covalent_radius = 0.0;
}

for (int ia1 = 0; ia1 < ucell.atoms[it1].na; ia1++) {
double x1 = ucell.atoms[it1].taud[ia1].x;
double y1 = ucell.atoms[it1].taud[ia1].y;
double z1 = ucell.atoms[it1].taud[ia1].z;

for (int it2 = 0; it2 < ucell.ntype; it2++) {
std::string symbol2 = ucell.atoms[it2].label;
double symbol2_covalent_radius;
if (ModuleBase::CovalentRadius.find(symbol2)
!= ModuleBase::CovalentRadius.end()) {
symbol2_covalent_radius
= ModuleBase::CovalentRadius.at(symbol2);
} else {
symbol2_covalent_radius = 0.0;
}

double covalent_length
= (symbol1_covalent_radius + symbol2_covalent_radius)
/ ModuleBase::BOHR_TO_A;

for (int ia2 = 0; ia2 < ucell.atoms[it2].na; ia2++) {
for (int a = -1; a < 2; a++) {
for (int b = -1; b < 2; b++) {
for (int c = -1; c < 2; c++) {
if (it1 > it2)
continue;
else if (it1 == it2 && ia1 > ia2)
continue;
else if (it1 == it2 && ia1 == ia2 && a == 0
&& b == 0 && c == 0)
continue;

double x2 = ucell.atoms[it2].taud[ia2].x + a;
double y2 = ucell.atoms[it2].taud[ia2].y + b;
double z2 = ucell.atoms[it2].taud[ia2].z + c;

double bond_length
= sqrt(pow((x2 - x1) * ucell.a1.x
+ (y2 - y1) * ucell.a2.x
+ (z2 - z1) * ucell.a3.x,
2)
+ pow((x2 - x1) * ucell.a1.y
+ (y2 - y1) * ucell.a2.y
+ (z2 - z1) * ucell.a3.y,
2)
+ pow((x2 - x1) * ucell.a1.z
+ (y2 - y1) * ucell.a2.z
+ (z2 - z1) * ucell.a3.z,
2))
* ucell.lat0;

if (bond_length < covalent_length * factor
|| bond_length
< covalent_length * warning_coef) {
errorlog.setf(std::ios_base::fixed,
std::ios_base::floatfield);
errorlog << std::setw(3) << ia1 + 1
<< "-th " << std::setw(3)
<< ucell.atoms[it1].label << ", ";
errorlog << std::setw(3) << ia2 + 1
<< "-th " << std::setw(3)
<< ucell.atoms[it2].label;
errorlog << " (cell:" << std::setw(2) << a
<< " " << std::setw(2) << b << " "
<< std::setw(2) << c << ")";
errorlog << ", distance= "
<< std::setprecision(3)
<< bond_length << " Bohr (";
errorlog
<< bond_length * ModuleBase::BOHR_TO_A
<< " Angstrom)" << std::endl;

if (bond_length
< covalent_length * factor) {
all_pass = false;
} else {
no_warning = false;
}
}
} // c
} // b
} // a
} // ia2
} // it2
} // ia1
} // it1

if (!all_pass || !no_warning) {
std::stringstream mess;
mess << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
<< std::endl;
mess << "%%%%%% WARNING WARNING WARNING WARNING WARNING %%%%%%"
<< std::endl;
mess << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
<< std::endl;
mess << "!!! WARNING: Some atoms are too close!!!" << std::endl;
mess << "!!! Please check the nearest-neighbor list in log file."
<< std::endl;
mess << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
<< std::endl;
mess << "%%%%%% WARNING WARNING WARNING WARNING WARNING %%%%%%"
<< std::endl;
mess << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
<< std::endl;

GlobalV::ofs_running << mess.str() << mess.str() << mess.str()
<< errorlog.str();
std::cout << mess.str() << mess.str() << mess.str() << std::endl;

if (!all_pass) {
mess.clear();
mess.str("");
mess << "If this structure is what you want, you can set "
"'min_dist_coef'"
<< std::endl;
mess << "as a smaller value (the current value is " << factor
<< ") in INPUT file." << std::endl;
GlobalV::ofs_running << mess.str();
std::cout << mess.str();
ModuleBase::WARNING_QUIT("Input", "The structure is unreasonable!");
}
}
}
11 changes: 11 additions & 0 deletions source/module_cell/check_atomic_stru.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef CHECK_ATOMIC_STRU_H
#define CHECK_ATOMIC_STRU_H

#include "unitcell.h"

class Check_Atomic_Stru {
public:
static void check_atomic_stru(UnitCell& ucell, double& factor);
};

#endif
1 change: 1 addition & 0 deletions source/module_cell/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ list(APPEND cell_simple_srcs
../read_pp_upf100.cpp
../read_pp_vwr.cpp
../read_pp_blps.cpp
../check_atomic_stru.cpp
)

add_library(cell_info OBJECT ${cell_simple_srcs})
Expand Down
Loading

0 comments on commit 2135a03

Please sign in to comment.