From 5610df2afee5243794602d8cee1ccef613b98d4e Mon Sep 17 00:00:00 2001 From: Growl Date: Tue, 12 May 2026 17:31:42 +0800 Subject: [PATCH 1/7] Add an alternative Precommit workflow --- .github/workflows/precommit.yml | 50 ++++ .github/workflows/test.yml | 105 +++++--- tools/precommit/Dockerfile | 16 ++ tools/precommit/README.md | 104 ++++++++ tools/precommit/abacus_clang_format.yaml | 49 ++++ tools/precommit/check_file_properties.py | 302 ++++++++++++++++++++++ tools/precommit/clang_format_wrapper.sh | 28 +++ tools/precommit/cloudbuild.yaml | 31 +++ tools/precommit/deploy.sh | 23 ++ tools/precommit/format_makefile.py | 43 ++++ tools/precommit/install_requirements.sh | 32 +++ tools/precommit/precommit.py | 308 +++++++++++++++++++++++ tools/precommit/precommit_server.py | 101 ++++++++ tools/precommit/requirements.txt | 30 +++ tools/precommit/start_local_server.sh | 11 + 15 files changed, 1193 insertions(+), 40 deletions(-) create mode 100644 .github/workflows/precommit.yml create mode 100644 tools/precommit/Dockerfile create mode 100644 tools/precommit/README.md create mode 100644 tools/precommit/abacus_clang_format.yaml create mode 100755 tools/precommit/check_file_properties.py create mode 100755 tools/precommit/clang_format_wrapper.sh create mode 100644 tools/precommit/cloudbuild.yaml create mode 100755 tools/precommit/deploy.sh create mode 100755 tools/precommit/format_makefile.py create mode 100755 tools/precommit/install_requirements.sh create mode 100755 tools/precommit/precommit.py create mode 100755 tools/precommit/precommit_server.py create mode 100644 tools/precommit/requirements.txt create mode 100755 tools/precommit/start_local_server.sh diff --git a/.github/workflows/precommit.yml b/.github/workflows/precommit.yml new file mode 100644 index 00000000000..5a1a4270df0 --- /dev/null +++ b/.github/workflows/precommit.yml @@ -0,0 +1,50 @@ +name: Precommit + +on: + workflow_dispatch: + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + name: Precommit + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + # We will handle submodules manually after fixing ownership + submodules: 'false' + + - name: Update submodules + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + git submodule update --init --recursive + + - name: Configure precommit server + run: | + cd tools/precommit + ./start_local_server.sh & + + - name: Wait for precommit server + run: | + for i in {1..200}; do + if curl -fs -o /dev/null http://127.0.0.1:8080/ 2>/dev/null; then + echo "precommit server is ready" + exit 0 + fi + sleep 1 + done + echo "precommit server did not become ready" >&2 + exit 1 + + - name: Run precommit + env: + ABACUS_PRECOMMIT_SERVER: "http://127.0.0.1:8080" + run: | + ./tools/precommit/precommit.py --no-cache + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a21d54b2a82..baedd4dfc3b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,214 +32,239 @@ jobs: - name: Install CI tools run: | sudo apt-get update - sudo apt-get install -y ccache ca-certificates python-is-python3 python3-pip - sudo pip install clang-format clang-tidy + sudo apt-get install -y ccache ca-certificates python-is-python3 - name: Configure run: | cmake -B build -DBUILD_TESTING=ON -DENABLE_MLALGO=ON -DENABLE_LIBXC=ON -DENABLE_LIBRI=ON -DENABLE_GOOGLEBENCH=ON -DENABLE_RAPIDJSON=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DENABLE_FLOAT_FFTW=ON -# Temporarily removed because no one maintains this now. -# And it will break the CI test workflow. - -# - uses: pre-commit/action@v3.0.1 -# with: -# extra_args: -# --from-ref ${{ github.event.pull_request.base.sha }} -# --to-ref ${{ github.event.pull_request.head.sha }} -# continue-on-error: true -# - uses: pre-commit-ci/lite-action@v1.0.3 - - name: Build run: | cmake --build build -j8 cmake --install build + - name: Prepare ctest wrapper + run: | + cat > "$RUNNER_TEMP/run_ctest.sh" <<'EOF' + #!/usr/bin/env bash + set +e + + name="$1" + shift + + echo "::group::$name" + ctest --test-dir build -V --timeout 1700 "$@" + status=$? + echo "::endgroup::" + + if [ "$status" -ne 0 ]; then + echo "$name" >> "$RUNNER_TEMP/failed-tests.txt" + echo "::error title=$name failed::ctest exited with status $status" + fi + + exit 0 + EOF + + chmod +x "$RUNNER_TEMP/run_ctest.sh" + - name: Integrated Tests Preparation env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R integrated_test + "$RUNNER_TEMP/run_ctest.sh" "Integrated Tests Preparation" -R integrated_test - name: Module_Base Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_BASE + "$RUNNER_TEMP/run_ctest.sh" "Module_Base Unittests" -R MODULE_BASE - name: Module_IO Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_IO + "$RUNNER_TEMP/run_ctest.sh" "Module_IO Unittests" -R MODULE_IO - name: Module_HSolver Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_HSOLVER -E PERF_MODULE_HSOLVER_KERNELS + "$RUNNER_TEMP/run_ctest.sh" "Module_HSolver Unittests" -R MODULE_HSOLVER -E PERF_MODULE_HSOLVER_KERNELS - name: Module_Cell Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_CELL + "$RUNNER_TEMP/run_ctest.sh" "Module_Cell Unittests" -R MODULE_CELL - name: Module_MD Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_MD + "$RUNNER_TEMP/run_ctest.sh" "Module_MD Unittests" -R MODULE_MD - name: Module_Psi Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_PSI + "$RUNNER_TEMP/run_ctest.sh" "Module_Psi Unittests" -R MODULE_PSI - name: Module_RI Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_RI + "$RUNNER_TEMP/run_ctest.sh" "Module_RI Unittests" -R MODULE_RI - name: Module_Estate Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_ESTATE + "$RUNNER_TEMP/run_ctest.sh" "Module_Estate Unittests" -R MODULE_ESTATE - name: Module_Hamilt Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_HAMILT + "$RUNNER_TEMP/run_ctest.sh" "Module_Hamilt Unittests" -R MODULE_HAMILT - name: Module_PW Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_PW + "$RUNNER_TEMP/run_ctest.sh" "Module_PW Unittests" -R MODULE_PW - name: Module_LCAO Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_LCAO + "$RUNNER_TEMP/run_ctest.sh" "Module_LCAO Unittests" -R MODULE_LCAO - name: Module_AO Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_AO + "$RUNNER_TEMP/run_ctest.sh" "Module_AO Unittests" -R MODULE_AO - name: Module_NAO Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_NAO + "$RUNNER_TEMP/run_ctest.sh" "Module_NAO Unittests" -R MODULE_NAO - name: Module_RELAX Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_RELAX + "$RUNNER_TEMP/run_ctest.sh" "Module_RELAX Unittests" -R MODULE_RELAX - name: Module_LR Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R MODULE_LR + "$RUNNER_TEMP/run_ctest.sh" "Module_LR Unittests" -R MODULE_LR - name: 01_PW Test env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R 01_PW + "$RUNNER_TEMP/run_ctest.sh" "01_PW Test" -R 01_PW - name: 02_NAO_Gamma Test env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R 02_NAO_Gamma + "$RUNNER_TEMP/run_ctest.sh" "02_NAO_Gamma Test" -R 02_NAO_Gamma - name: 03_NAO_multik Test env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R 03_NAO_multik + "$RUNNER_TEMP/run_ctest.sh" "03_NAO_multik Test" -R 03_NAO_multik - name: 04_FF Test env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R 04_FF + "$RUNNER_TEMP/run_ctest.sh" "04_FF Test" -R 04_FF - name: 05_rtTDDFT Test env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R 05_rtTDDFT + "$RUNNER_TEMP/run_ctest.sh" "05_rtTDDFT Test" -R 05_rtTDDFT - name: 06_SDFT Test env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R 06_SDFT + "$RUNNER_TEMP/run_ctest.sh" "06_SDFT Test" -R 06_SDFT - name: 07_OFDFT Test env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R 07_OFDFT + "$RUNNER_TEMP/run_ctest.sh" "07_OFDFT Test" -R 07_OFDFT - name: 08_EXX Test env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R 08_EXX + "$RUNNER_TEMP/run_ctest.sh" "08_EXX Test" -R 08_EXX - name: 09_DeePKS Test env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R 09_DeePKS + "$RUNNER_TEMP/run_ctest.sh" "09_DeePKS Test" -R 09_DeePKS - name: 10_others Test env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -R 10_others + "$RUNNER_TEMP/run_ctest.sh" "10_others Test" -R 10_others - name: Other Unittests env: GTEST_COLOR: 'yes' OMP_NUM_THREADS: '2' run: | - ctest --test-dir build -V --timeout 1700 -E 'integrate_test|01_PW|02_NAO_Gamma|03_NAO_multik|04_FF|05_rtTDDFT|06_SDFT|07_OFDFT|08_EXX|09_DeePKS|10_others|11_PW_GPU|12_NAO_Gamma_GPU|13_NAO_multik_GPU|15_rtTDDFT_GPU|16_SDFT_GPU|MODULE_BASE|MODULE_IO|MODULE_HSOLVER|MODULE_CELL|MODULE_MD|MODULE_PSI|MODULE_ESTATE|MODULE_RI|MODULE_HAMILT|MODULE_PW|MODULE_LCAO|MODULE_AO|MODULE_NAO|MODULE_RELAX|MODULE_LR' + "$RUNNER_TEMP/run_ctest.sh" "Other Unittests" -E 'integrate_test|01_PW|02_NAO_Gamma|03_NAO_multik|04_FF|05_rtTDDFT|06_SDFT|07_OFDFT|08_EXX|09_DeePKS|10_others|11_PW_GPU|12_NAO_Gamma_GPU|13_NAO_multik_GPU|15_rtTDDFT_GPU|16_SDFT_GPU|MODULE_BASE|MODULE_IO|MODULE_HSOLVER|MODULE_CELL|MODULE_MD|MODULE_PSI|MODULE_ESTATE|MODULE_RI|MODULE_HAMILT|MODULE_PW|MODULE_LCAO|MODULE_AO|MODULE_NAO|MODULE_RELAX|MODULE_LR' + + - name: Fail if any test group failed + if: always() + run: | + if [ -s "$RUNNER_TEMP/failed-tests.txt" ]; then + echo "" + echo "The following test groups failed:" + cat "$RUNNER_TEMP/failed-tests.txt" + echo "" + exit 1 + fi + + echo "All test groups passed." diff --git a/tools/precommit/Dockerfile b/tools/precommit/Dockerfile new file mode 100644 index 00000000000..2a8aab17861 --- /dev/null +++ b/tools/precommit/Dockerfile @@ -0,0 +1,16 @@ +FROM ubuntu:24.04 + +# Based on CP2K's tools/precommit/Dockerfile, adapted for ABACUS. + +WORKDIR /opt/abacus-precommit +COPY install_requirements.sh requirements.txt ./ +RUN ./install_requirements.sh +ENV PATH="/opt/venv/bin:/opt/abacus-precommit:$PATH" + +ARG REVISION +ENV REVISION=${REVISION} + +COPY . ./ +CMD ["gunicorn", "--bind=:8080", "--workers=1", "--threads=8", "--timeout=0", "precommit_server:app"] + +# EOF diff --git a/tools/precommit/README.md b/tools/precommit/README.md new file mode 100644 index 00000000000..d5a7db67bd2 --- /dev/null +++ b/tools/precommit/README.md @@ -0,0 +1,104 @@ +# ABACUS Precommit + +This is a CP2K-style precommit system adapted for ABACUS. The local driver is +`tools/precommit/precommit.py`; the formatting tools are provided by a small Flask/gunicorn +precommit server. + +The design intentionally follows CP2K's usage model: + +- one local driver script; +- `obj/precommit/cache.json` mtime cache; +- file-level processing; +- local backup before each tool modifies a file; +- default check-only mode; +- `--allow-modifications` to keep formatter changes; +- remote or local Docker server for external tools. + +## Install Git hook + +From the ABACUS repository root: + +```bash +ln -fs ../../tools/precommit/precommit.py .git/hooks/pre-commit +``` + +## Run checks + +```bash +./tools/precommit/precommit.py +``` + +The default mode does not modify source files. If a formatter would change a file, the driver +restores the original content and prints a unified diff. + +## Apply modifications + +```bash +./tools/precommit/precommit.py --allow-modifications +``` + +Short option: + +```bash +./tools/precommit/precommit.py -m +``` + +## Ignore cache + +```bash +./tools/precommit/precommit.py --no-cache +``` + +Short option: + +```bash +./tools/precommit/precommit.py -a +``` + +## Process selected files + +```bash +./tools/precommit/precommit.py source/module/foo.cpp source/module/foo.h +``` + +## Local server + +Until an ABACUS precommit server is deployed, run the server locally with Docker: + +```bash +cd tools/precommit +./start_local_server.sh +``` + +Then, in another terminal from the repository root: + +```bash +export ABACUS_PRECOMMIT_SERVER="http://127.0.0.1:8080" +./tools/precommit/precommit.py +``` + +## Tools + +The first ABACUS version keeps CP2K's lightweight file-level model and maps it to ABACUS' C++-first +source tree: + +- C/C++/CUDA/HIP/OpenCL: `clang-format` +- Python: `ast.parse` + `black` +- Shell: `shfmt` + `shellcheck` +- Markdown: `mdformat --wrap=100` +- CMake: `cmake-format -i` +- Makefile: local `format_makefile.py` +- all files: local `check_file_properties.py` + +`clang-tidy` and `compile_commands.json` are intentionally not part of this CP2K-style first +version. They are build-level static-analysis concerns, while this precommit driver is a lightweight +file-level formatting and convention gate. + +## Notes for ABACUS maintainers + +The only non-CP2K structural change is that C++ is first-class. CP2K rejects most C++ files; this +ABACUS version formats `.c`, `.cc`, `.cpp`, `.cxx`, `.h`, `.hh`, `.hpp`, `.hxx`, `.cu`, `.cuh`, +`.hip`, and `.cl` files. + +`check_file_properties.py` contains the ABACUS-specific convention checks. The banner/license policy +should be tightened once the exact ABACUS source header is agreed upon. diff --git a/tools/precommit/abacus_clang_format.yaml b/tools/precommit/abacus_clang_format.yaml new file mode 100644 index 00000000000..efc19b0b9fd --- /dev/null +++ b/tools/precommit/abacus_clang_format.yaml @@ -0,0 +1,49 @@ +--- +Language: Cpp +BasedOnStyle: LLVM + +AlwaysBreakTemplateDeclarations: Yes + +ColumnLimit: 120 +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +BinPackArguments: false +BinPackParameters: false + +BreakBeforeTernaryOperators: true + +Cpp11BracedListStyle: true +FixNamespaceComments: true + +IncludeBlocks: Preserve +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' + +IndentWidth: 4 + +DerivePointerAlignment: false +PointerAlignment: Left + +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true + +# ABACUS follows the usual C/C++ convention: control statements use a space +# before parentheses (`if (...)`), but function calls/declarations do not +# (`foo(...)`). GNU style defaults to `Always`, which would rewrite calls as +# `foo (...)` and produce noisy, unidiomatic diffs. +SpaceBeforeParens: ControlStatements + +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceBeforeRangeBasedForLoopColon: false +SpaceInEmptyParentheses: false +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false + +Standard: c++17 +UseTab: Never +... diff --git a/tools/precommit/check_file_properties.py b/tools/precommit/check_file_properties.py new file mode 100755 index 00000000000..cb3f1e557fe --- /dev/null +++ b/tools/precommit/check_file_properties.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python3 + +# Based on CP2K's tools/precommit/check_file_properties.py, adapted for ABACUS. + +import argparse +from functools import lru_cache +import os +import pathlib +import re +import sys +from typing import Iterable, List, Set, Tuple, TypeVar + +T = TypeVar("T") + +# We assume this script is in tools/precommit/. +ABACUS_DIR = pathlib.Path(__file__).resolve().parents[2] + +PORTABLE_FILENAME_RE = re.compile(r"^[a-zA-Z0-9._/#~=+-]*$") +OP_RE = re.compile(r"[\\|()!&><=*/+-]") +NUM_RE = re.compile(r"[0-9]+[ulUL]*") +CMAKE_OPTION_RE = re.compile(r"option\(\s*(\w+)", re.DOTALL) +MERGE_CONFLICT_RE = re.compile( + r"^(<<<<<<<(?: .*)?|\|\|\|\|\|\|\|(?: .*)?|=======$|>>>>>>>(?: .*)?)$", + re.MULTILINE, +) + +C_EXTENSIONS = ( + ".c", + ".cc", + ".cpp", + ".cxx", + ".h", + ".hh", + ".hpp", + ".hxx", + ".cu", + ".cuh", + ".hip", + ".cl", +) +HEADER_EXTENSIONS = (".h", ".hh", ".hpp", ".hxx", ".cuh") +TEXT_EXTENSIONS = C_EXTENSIONS + ( + ".cmake", + ".md", + ".py", + ".sh", + ".txt", + ".yml", + ".yaml", + ".json", +) +WINDOWS_SCRIPT_EXTENSIONS = (".bat", ".cmd") + +# Keep this list intentionally broad. Project-specific additions should be made +# here rather than suppressing warnings at call sites. +FLAG_EXCEPTIONS = ( + r"\$\{.+\}\$", + r"__.+__", + r"_M_.+", + r"_WIN32", + r"_OPENMP", + r"__cplusplus", + r"__GNUC__", + r"__GNUC_MINOR__", + r"__GNUC_PATCHLEVEL__", + r"__clang__", + r"__clang_major__", + r"__INTEL_COMPILER", + r"__INTEL_LLVM_COMPILER", + r"__NVCC__", + r"__CUDACC__", + r"__HIPCC__", + r"CUDA_VERSION", + r"HIP_VERSION", + r"NDEBUG", + r"M_PI", + r"EIGEN_.+", + r"ELPA_.+", + r"FFTW_.+", + r"MPI_.+", + r"MKL_.+", + r"LAPACK_.+", + r"BLAS_.+", + r"OPENBLAS_.+", + r"LIBINT.+", + r"LIBXC.+", + r"CEREAL_.+", + r"GTEST_.+", +) +FLAG_EXCEPTIONS_RE = re.compile(r"|".join(FLAG_EXCEPTIONS)) + + +@lru_cache(maxsize=None) +def get_cmake_sources() -> str: + files: List[pathlib.Path] = [] + root_cmake = ABACUS_DIR / "CMakeLists.txt" + if root_cmake.exists(): + files.append(root_cmake) + for directory in ("cmake", "toolchain", "tools"): + base = ABACUS_DIR / directory + if base.exists(): + files.extend(base.glob("**/*.cmake")) + files.extend(base.glob("**/CMakeLists.txt")) + return "\n".join(read_text_safely(fn) for fn in sorted(set(files))) + + +@lru_cache(maxsize=None) +def get_build_docs() -> str: + docs = ABACUS_DIR / "docs" + if not docs.exists(): + return "" + files = list(docs.glob("**/*.md")) + list(docs.glob("**/*.rst")) + return "\n".join(read_text_safely(fn) for fn in sorted(set(files))) + + +def read_text_safely(path: pathlib.Path) -> str: + try: + return path.read_text(encoding="utf8") + except Exception: + return "" + + +def check_file(path: pathlib.Path) -> List[str]: + """Check one file for ABACUS source-tree convention violations.""" + warnings: List[str] = [] + + fn_ext = path.suffix.lower() + abspath = path.resolve() + basefn = path.name + is_executable = os.access(abspath, os.X_OK) + + if not PORTABLE_FILENAME_RE.match(str(path)): + warnings += [f"Filename '{path}' not portable"] + + if not abspath.exists(): + return warnings + + raw_content = abspath.read_bytes() + if b"\0" in raw_content: + return warnings + + try: + content = raw_content.decode("utf8") + except UnicodeDecodeError: + if fn_ext in TEXT_EXTENSIONS or not fn_ext: + warnings += [f"{path}: is not valid UTF-8"] + return warnings + + if "\r\n" in content and fn_ext.lower() not in WINDOWS_SCRIPT_EXTENSIONS: + warnings += [f"{path}: contains DOS linebreaks"] + + if ( + fn_ext not in (".pot", ".patch", ".diff") + and basefn not in ("Makefile",) + and "\t" in content + ): + warnings += [f"{path}: contains tab character"] + + if MERGE_CONFLICT_RE.search(content): + warnings += [f"{path}: contains merge conflict marker"] + + # check shebang, matching CP2K's behavior for executable Python scripts + PY_SHEBANG = "#!/usr/bin/env python3" + if fn_ext == ".py" and is_executable and not content.startswith(f"{PY_SHEBANG}\n"): + warnings += [f"{path}: Wrong shebang, please use '{PY_SHEBANG}'"] + + # C++ headers should not introduce namespace pollution into downstream TUs. + # Be conservative: only reject a clearly global using-directive. Local + # using-directives inside inline/template functions are not ideal, but they + # do not leak into downstream translation units and should not be a first + # version hard failure. + if fn_ext in HEADER_EXTENSIONS: + for i, line in enumerate(content.splitlines(), start=1): + stripped = line.strip() + if line == stripped and stripped.startswith("using namespace "): + warnings += [ + f"{path}:{i} Do not use '{stripped}' at global scope in a header file" + ] + + # Find likely ABACUS build-controlled preprocessor condition flags and check + # whether ABACUS' CMake files know about them. Unlike CP2K, ABACUS has many + # C/C++ header guards and third-party compatibility macros, so this must not + # treat every uppercase token in #if/#ifdef/#ifndef as a project flag. + if fn_ext in C_EXTENSIONS: + flags = find_preprocessor_flags(content, fn_ext, basefn, path) + cmake_sources = get_cmake_sources() + for flag in sorted(flags): + if flag not in cmake_sources: + warnings += [f"{path}: Flag '{flag}' not mentioned in CMake files"] + + # Check CMake options against docs if docs exist. + if "cmake" in str(path).lower() or basefn == "CMakeLists.txt": + build_docs = get_build_docs() + if build_docs: + options = CMAKE_OPTION_RE.findall(content) + for opt in options: + if opt not in build_docs: + warnings += [f"{path}: CMake option {opt} not mentioned in docs"] + + return warnings + + +BUILD_FLAG_RE = re.compile( + r"^(ENABLE_.+|USE_.+|WITH_.+|ABACUS_.+|__UT_.+|__MPI|__CUDA|__ROCM|__EXX|__LCAO|__OPENMP)$" +) +HEADER_GUARD_RE = re.compile(r"^[A-Z0-9_]+_(H|HH|HPP|HXX|CUH)_?$") +SYSTEM_OR_COMPILER_MACRO_RE = re.compile(r"^__[A-Z0-9_]+$|^__[A-Z0-9_]+__$") + + +def find_preprocessor_flags( + content: str, fn_ext: str, basefn: str, path: pathlib.Path +) -> Set[str]: + flags: Set[str] = set() + line_continuation = False + include_guards = find_include_guards(content) + include_guard = basefn.upper().replace(".", "_") + + for line in content.splitlines(): + line = line.lstrip() + + if not line_continuation: + if not line or line[0] != "#": + continue + if line.split()[0] not in ("#if", "#ifdef", "#ifndef", "#elif"): + continue + + line = line.split("/*", 1)[0] + line = line.split("//", 1)[0] + line_continuation = line.rstrip().endswith("\\") + line = OP_RE.sub(" ", line) + line = line.replace("defined", " ") + + for word in line.split()[1:]: + if NUM_RE.match(word): + continue + if fn_ext in HEADER_EXTENSIONS and ( + word == include_guard + or word in include_guards + or HEADER_GUARD_RE.fullmatch(word) + ): + continue + if FLAG_EXCEPTIONS_RE.fullmatch(word): + continue + if SYSTEM_OR_COMPILER_MACRO_RE.fullmatch(word): + continue + if not BUILD_FLAG_RE.fullmatch(word): + continue + flags.add(word) + + return {flag for flag in flags if not FLAG_EXCEPTIONS_RE.fullmatch(flag)} + + +def find_include_guards(content: str) -> Set[str]: + """Return classic #ifndef/#define include guards found near file starts. + + This catches guards such as BASE_THIRD_PARTY_CUSOLVER_H_, not just the + basename-derived CUSOLVER_H used by the first draft. + """ + guards: Set[str] = set() + lines = content.splitlines()[:50] + for idx, line in enumerate(lines[:-1]): + m_ifndef = re.match(r"\s*#\s*ifndef\s+([A-Za-z_][A-Za-z0-9_]*)\b", line) + if not m_ifndef: + continue + guard = m_ifndef.group(1) + for next_line in lines[idx + 1 : idx + 6]: + m_define = re.match( + r"\s*#\s*define\s+([A-Za-z_][A-Za-z0-9_]*)\b", next_line + ) + if m_define: + if m_define.group(1) == guard: + guards.add(guard) + break + return guards + + +def pairwise(iterable: Iterable[T]) -> Iterable[Tuple[T, T]]: + """itertools.pairwise is not available before Python 3.10.""" + a, b = iter(iterable), iter(iterable) + next(b, None) + return zip(a, b) + + +# ====================================================================================== +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Check the given FILENAME for ABACUS source-tree conventions" + ) + parser.add_argument("files", metavar="FILENAME", type=pathlib.Path, nargs="+") + args = parser.parse_args() + + all_warnings = [] + for fpath in args.files: + all_warnings += check_file(fpath) + + for warning in all_warnings: + print(warning) + + if all_warnings: + sys.exit(1) + +# EOF diff --git a/tools/precommit/clang_format_wrapper.sh b/tools/precommit/clang_format_wrapper.sh new file mode 100755 index 00000000000..57bd0533d8d --- /dev/null +++ b/tools/precommit/clang_format_wrapper.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Based on CP2K's clang_format_wrapper.sh, adapted for ABACUS. + +if (($# != 1)); then + echo "Usage: clang_format_wrapper.sh " + exit 1 +fi + +STYLE_FILE="/opt/abacus-precommit/abacus_clang_format.yaml" +if [[ -f "${STYLE_FILE}" ]]; then + CLANG_FORMAT_STYLE="file:${STYLE_FILE}" +else + CLANG_FORMAT_STYLE="llvm" +fi + +# For some files clang-format can require too much memory. As a work-around we +# use the "clang-format off" marker to disable formatting. To actually reduce +# the memory usage this script hides the offending sections from clang-format. +if csplit --quiet --prefix="section" "$1" "/clang-format off/"; then + clang-format --style="${CLANG_FORMAT_STYLE}" -i section00 + cat section* > "$1" + rm section* +else + clang-format --style="${CLANG_FORMAT_STYLE}" -i "$1" +fi + +# EOF diff --git a/tools/precommit/cloudbuild.yaml b/tools/precommit/cloudbuild.yaml new file mode 100644 index 00000000000..e36f46d6895 --- /dev/null +++ b/tools/precommit/cloudbuild.yaml @@ -0,0 +1,31 @@ +# Based on CP2K's tools/precommit/cloudbuild.yaml, adapted for ABACUS. +# Adjust image name, service name, and region before enabling in production. + +substitutions: + _IMAGE_NAME: "us-central1-docker.pkg.dev/${PROJECT_ID}/misc/img_abacus_precommit" + _REGION: "us-central1" + _SERVICE: "abacus-precommit" + +steps: +- name: 'gcr.io/cloud-builders/docker' + args: ["build", "--build-arg", "REVISION=${SHORT_SHA}", "-t", "${_IMAGE_NAME}:${SHORT_SHA}", "./tools/precommit/"] + +- name: 'gcr.io/cloud-builders/docker' + args: ["push", "${_IMAGE_NAME}:${SHORT_SHA}"] + +- name: 'gcr.io/cloud-builders/docker' + args: ["tag", "${_IMAGE_NAME}:${SHORT_SHA}", "${_IMAGE_NAME}:latest"] + +- name: 'gcr.io/cloud-builders/docker' + args: ["push", "${_IMAGE_NAME}:latest"] + +- name: "gcr.io/cloud-builders/gcloud" + args: + - "run" + - "deploy" + - "${_SERVICE}" + - "--platform=managed" + - "--region=${_REGION}" + - "--image=${_IMAGE_NAME}:${SHORT_SHA}" + +# EOF diff --git a/tools/precommit/deploy.sh b/tools/precommit/deploy.sh new file mode 100755 index 00000000000..0c4e0acbb73 --- /dev/null +++ b/tools/precommit/deploy.sh @@ -0,0 +1,23 @@ +#!/bin/bash -e + +# Based on CP2K's tools/precommit/deploy.sh, adapted for ABACUS. +# Adjust PROJECT/REGISTRY/REGION before using for production deployment. + +set -x + +: "${ABACUS_PRECOMMIT_IMAGE:=abacus-precommit}" +: "${ABACUS_PRECOMMIT_REGISTRY:=gcr.io/abacus-project/img_abacus_precommit}" +: "${ABACUS_PRECOMMIT_REGION:=us-central1}" + +SHORT_SHA=$(git rev-parse --short HEAD) +docker build --build-arg "REVISION=${SHORT_SHA}" -t "${ABACUS_PRECOMMIT_IMAGE}" . + +docker tag "${ABACUS_PRECOMMIT_IMAGE}" "${ABACUS_PRECOMMIT_REGISTRY}:${SHORT_SHA}" +docker tag "${ABACUS_PRECOMMIT_IMAGE}" "${ABACUS_PRECOMMIT_REGISTRY}:latest" +docker push "${ABACUS_PRECOMMIT_REGISTRY}:${SHORT_SHA}" +docker push "${ABACUS_PRECOMMIT_REGISTRY}:latest" + +gcloud run deploy abacus-precommit --platform=managed --region="${ABACUS_PRECOMMIT_REGION}" \ + --image="${ABACUS_PRECOMMIT_REGISTRY}:${SHORT_SHA}" + +# EOF diff --git a/tools/precommit/format_makefile.py b/tools/precommit/format_makefile.py new file mode 100755 index 00000000000..6e4d11f69d7 --- /dev/null +++ b/tools/precommit/format_makefile.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +# author: Ole Schuett + +import sys +from pathlib import Path + + +def main() -> None: + if len(sys.argv) != 2: + print("Usage: format_makefile.py ") + sys.exit(1) + makefile = Path(sys.argv[1]) + + lines_out = [] + continuation = False + for line in makefile.read_text(encoding="utf8").split("\n"): + # Remove trailing whitespaces. + line = line.rstrip() + + # Detect continued lines. + prev_continuation = continuation + continuation = line.endswith("\\") + + # Continued lines are indented 8 spaces. + if prev_continuation: + lines_out.append(" " * 8 + line.strip()) + + # Tabbed lines are indented with exactly one tab. + elif line.startswith("\t"): + lines_out.append("\t" + line.strip()) + + # All other lines are not indented. + else: + lines_out.append(line.strip()) + + makefile.write_text("\n".join(lines_out), encoding="utf8") + + +if __name__ == "__main__": + main() + +# EOF diff --git a/tools/precommit/install_requirements.sh b/tools/precommit/install_requirements.sh new file mode 100755 index 00000000000..ffb641c90cc --- /dev/null +++ b/tools/precommit/install_requirements.sh @@ -0,0 +1,32 @@ +#!/bin/bash -e + +# Based on CP2K's tools/precommit/install_requirements.sh, adapted for ABACUS. + +export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true +apt-get update -qq +apt-get install -qq --no-install-recommends \ + ca-certificates \ + clang-format \ + git \ + less \ + nano \ + python3 \ + python3-venv \ + python3-pip \ + python3-wheel \ + python3-setuptools \ + shellcheck \ + wget +rm -rf /var/lib/apt/lists/* + +python3 -m venv /opt/venv +export PATH="/opt/venv/bin:$PATH" +pip3 install --quiet -r requirements.txt + +# Install shfmt. +wget -q https://github.com/mvdan/sh/releases/download/v3.2.2/shfmt_v3.2.2_linux_amd64 +echo '3a32a69286a19491a81fcd854154f0d886c379ff28d99e32d5594490b8bbef4b shfmt_v3.2.2_linux_amd64' | sha256sum --check +chmod +x shfmt_v3.2.2_linux_amd64 +ln -s /opt/abacus-precommit/shfmt_v3.2.2_linux_amd64 /usr/bin/shfmt + +# EOF diff --git a/tools/precommit/precommit.py b/tools/precommit/precommit.py new file mode 100755 index 00000000000..bb33249a290 --- /dev/null +++ b/tools/precommit/precommit.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python3 + +# Based on CP2K's tools/precommit/precommit.py, adapted for ABACUS. + +import ast +import argparse +import concurrent.futures +from difflib import unified_diff +from http.client import HTTPResponse +import json +import os +from pathlib import Path +import re +from subprocess import PIPE, STDOUT +import subprocess +import shutil +import sys +from time import sleep, time +from typing import cast, Iterator +from urllib.error import HTTPError +from urllib.request import Request, urlopen +import uuid + +SCRATCH_DIR = Path("./obj/precommit") +CACHE_FILE = SCRATCH_DIR / "cache.json" +SERVER = os.environ.get("ABACUS_PRECOMMIT_SERVER", "https://precommit.abacus.org") + +C_CPP_EXT_RE = re.compile(r".*\.(c|cc|cpp|cxx|h|hh|hpp|hxx|cu|cuh|hip|hip.hpp|cl)$") + + +# ====================================================================================== +def main() -> None: + parser = argparse.ArgumentParser( + description="Check source code for formatting and linter problems." + ) + parser.add_argument( + "-a", + "--no-cache", + action="store_true", + help="ignore the cache and check all files", + ) + parser.add_argument( + "-m", + "--allow-modifications", + action="store_true", + help="allow the tools to modify files", + ) + parser.add_argument( + "-j", + "--num_workers", + type=int, + default=min(16, (os.cpu_count() or 0) + 2), + help="number of parallel workers", + ) + parser.add_argument( + "--progressbar-wait", + metavar="SECONDS", + type=int, + default=1, + help="number seconds in between progressbar updates", + ) + parser.add_argument( + "-t", + "--timeout", + type=int, + default=10, + help="server wait timeout in seconds", + ) + parser.add_argument("files", metavar="FILE", nargs="*", help="files to process") + args = parser.parse_args() + + print( + f"Running precommit checks using {args.num_workers} workers and server: {SERVER} " + f"(server wait timeout: {args.timeout} seconds)" + ) + server_hello = ( + urlopen(Request(SERVER + "/"), timeout=args.timeout).read().decode("utf8") + ) + assert server_hello.startswith("abacus precommit server") + + # Store candidates before changing base directory and creating scratch dir. + file_list = [os.path.abspath(fn) for fn in args.files] + base_dir = Path(__file__).resolve().parent.parent.parent + os.chdir(base_dir) + SCRATCH_DIR.mkdir(parents=True, exist_ok=True) + + # Collect candidate files. This intentionally follows CP2K's behavior: + # without explicit file arguments, check git-tracked files first and fall + # back to walking the working tree only if git is not available. + if not file_list: + sys.stdout.write("Searching for files...\r") + sys.stdout.flush() + + walk_list = [] + try: + output = subprocess.check_output(["git", "ls-files"], encoding="utf8") + for line in filter(None, output.split("\n")): + dir_name, file_name = os.path.split(line) + walk_list.append((os.path.join(".", dir_name), [dir_name], [file_name])) + except Exception: + walk_list = [] + + for root, dirs, files in walk_list if walk_list else os.walk("."): + if should_skip_root(root): + continue + file_list += [os.path.join(root, fn) for fn in files] + + # Filter symlinks, backup copies, logs, hidden files, and very large files. + file_list = [fn for fn in file_list if os.path.exists(fn)] + file_list = [fn for fn in file_list if not os.path.isdir(fn)] + file_list = [fn for fn in file_list if not os.path.islink(fn)] + file_list = [fn for fn in file_list if not fn[-1] in ("~", "#")] + file_list = [fn for fn in file_list if not fn.endswith(".log")] + file_list = [fn for fn in file_list if not os.path.basename(fn).startswith(".")] + + # Sort files by size as larger ones will take longer to process. + file_list.sort(reverse=True, key=lambda fn: os.path.getsize(fn)) + + # Load cache. Keep CP2K's mtime-based cache semantics. + should_load_cache = CACHE_FILE.exists() and not args.no_cache + cache = json.loads(CACHE_FILE.read_text()) if should_load_cache else {} + + # Launch async processing of files. + futures = {} + executor = concurrent.futures.ThreadPoolExecutor(max_workers=args.num_workers) + for fn in file_list: + if os.path.getmtime(fn) != cache.get(fn, -1): + futures[fn] = executor.submit(process_file, fn, args.allow_modifications) + num_skipped = len(file_list) - len(futures) + + # Continuously update progressbar, save cache file, and print errors. + failed_files = set() + while True: + num_done = num_skipped + for fn, f in futures.items(): + if f.done(): + num_done += 1 + if not f.exception(): + cache[fn] = os.path.getmtime(fn) + elif fn not in failed_files: + failed_files.add(fn) + print_box(fn, str(f.exception())) + CACHE_FILE.write_text(json.dumps(cache)) + if file_list: + progressbar = "=" * int(60 * num_done / len(file_list)) + sys.stdout.write( + f"[{progressbar:60s}] {num_done} / {len(file_list)} files processed\r" + ) + sys.stdout.flush() + if num_done == len(file_list) or len(failed_files) >= 10: + executor.shutdown(wait=False) + break + sleep(args.progressbar_wait) + + print( + f"Summary: Found {len(file_list)}, " + f"skipped {num_skipped}, " + f"checked {num_done - num_skipped}, " + f"and failed {len(failed_files)} files." + (" " * 50) + ) + print("Status: " + ("FAILED" if failed_files else "OK")) + sys.exit(len(failed_files)) + + +# ====================================================================================== +def should_skip_root(root: str) -> bool: + # Keep the CP2K style: explicit project-local exclusions in the driver. + skipped_prefixes = ( + "./.git", + "./obj", + "./build", + "./cmake-build", + "./CMakeFiles", + "./external", + "./third_party", + "./deps", + "./lib", + "./bin", + "./docs/_build", + "./__pycache__", + ) + if root.startswith(skipped_prefixes): + return True + skipped_fragments = ( + "/.mypy_cache/", + "/.pytest_cache/", + "/__pycache__/", + "/CMakeFiles/", + ) + return any(fragment in root for fragment in skipped_fragments) + + +# ====================================================================================== +def print_box(fn: str, message: str) -> None: + print("+" + "-" * 160 + "+") + print(f"| {fn:^158s} |") + print("+" + "-" * 160 + "+") + for line in message.strip().split("\n"): + print(f"| {line:<158s} |") + print("+" + "-" * 160 + "+\n\n") + + +# ====================================================================================== +def process_file(fn: str, allow_modifications: bool) -> None: + basename = Path(fn).name + orig_content = Path(fn).read_bytes() + bak_fn = SCRATCH_DIR / f"{basename}_{time()}.bak" + shutil.copy2(fn, bak_fn) + + # C, C++, CUDA, HIP, OpenCL: ABACUS is C++-first-class, unlike CP2K. + if C_CPP_EXT_RE.match(fn): + run_remote_tool("clangformat", fn) + + # Python. + if re.match(r".*\.py$", fn): + ast.parse(orig_content, filename=fn) + run_remote_tool("black", fn) + + # Shell. (TODO: Re-enable shellcheck in the future) + # if re.match(r".*\.sh$", fn): + # run_remote_tool("shfmt", fn) + # run_remote_tool("shellcheck", fn) + + # Markdown. + if re.match(r".*\.md$", fn): + run_remote_tool("mdformat", fn) + + # CMake. + if re.match(r"(.*/CMakeLists.txt)|(.*\.cmake)$", fn): + run_remote_tool("cmakeformat", fn) + + # Makefile. + if re.match(r".*/Makefile", fn) or basename == "Makefile": + run_local_tool("./tools/precommit/format_makefile.py", fn) + + # Always run local project convention checks after formatters. + run_check_file_properties(fn) + + new_content = Path(fn).read_bytes() + if new_content == orig_content: + bak_fn.unlink() + elif not allow_modifications: + bak_fn.replace(fn) + diff: Iterator[str] + try: + orig_lines = orig_content.decode("utf8").split("\n") + new_lines = new_content.decode("utf8").split("\n") + diff = unified_diff(orig_lines, new_lines, "before", "after", lineterm="") + except Exception: + diff = iter([]) + raise Exception("File modified:\n" + "\n".join(diff)) + + +# ====================================================================================== +def run_check_file_properties(fn: str) -> None: + run_local_tool("./tools/precommit/check_file_properties.py", fn) + + +# ====================================================================================== +def run_local_tool(*cmd: str, timeout: int = 30) -> None: + p = subprocess.run(cmd, timeout=timeout, stdout=PIPE, stderr=STDOUT) + if p.returncode != 0: + raise Exception(p.stdout.decode("utf8")) + + +# ====================================================================================== +def run_remote_tool(tool: str, fn: str) -> None: + if os.path.getsize(fn) > 2**20: + return # skip files larger than 1MiB, matching CP2K behavior + + url = f"{SERVER}/{tool}" + r = http_post(url, fn) + if r.status == 304: + pass + elif r.status == 200: + Path(fn).write_bytes(r.read()) + else: + raise Exception(r.read().decode("utf8")) + + +# ====================================================================================== +def http_post(url: str, fn: str) -> HTTPResponse: + boundary = uuid.uuid1().hex + name = Path(fn).name + data = b"".join( + [ + f"--{boundary}\r\nContent-Disposition: ".encode("utf8"), + f'form-data; name="{name}"; filename="{name}"\r\n\r\n'.encode("utf8"), + Path(fn).read_bytes(), + f"\r\n--{boundary}--\r\n".encode("utf8"), + ] + ) + headers = { + "Content-Length": f"{len(data)}", + "Content-Type": f"multipart/form-data; boundary={boundary}", + } + try: + response = urlopen(Request(url, data=data, headers=headers), timeout=60) + return cast(HTTPResponse, response) + except HTTPError as err: + return cast(HTTPResponse, err) + + +# ====================================================================================== +if __name__ == "__main__": + main() + +# EOF diff --git a/tools/precommit/precommit_server.py b/tools/precommit/precommit_server.py new file mode 100755 index 00000000000..ab14e649866 --- /dev/null +++ b/tools/precommit/precommit_server.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +# Based on CP2K's tools/precommit/precommit_server.py, adapted for ABACUS. + +import logging +import os +from os import path +import subprocess +from subprocess import PIPE, STDOUT +import tempfile +from time import time + +from flask import Flask, request + +app = Flask(__name__) +app.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 # 1MiB +app.logger.setLevel(logging.INFO) +app.logger.info("ABACUS Precommit Server is up and running :-)") + + +# ====================================================================================== +@app.route("/") +def hello(): + return "abacus precommit server revision: " + os.environ.get("REVISION", "unknown") + + +# ====================================================================================== +@app.route("/black", methods=["POST"]) +def black(): + return run_tool(["black"]) + + +# ====================================================================================== +@app.route("/shfmt", methods=["POST"]) +def shfmt(): + return run_tool(["shfmt", "-i=2", "-ci", "-sr", "-w"]) + + +# ====================================================================================== +@app.route("/shellcheck", methods=["POST"]) +def shellcheck(): + return run_tool(["shellcheck"], timeout=30) + + +# ====================================================================================== +@app.route("/mdformat", methods=["POST"]) +@app.route("/markdownlint", methods=["POST"]) +def mdformat(): + return run_tool(["mdformat", "--wrap=100"], timeout=30) + + +# ====================================================================================== +@app.route("/clangformat", methods=["POST"]) +def clangformat(): + return run_tool(["clang_format_wrapper.sh"]) + + +# ====================================================================================== +@app.route("/cmakeformat", methods=["POST"]) +def cmakeformat(): + return run_tool(["cmake-format", "-i"], timeout=30) + + +# ====================================================================================== +def run_tool(cmd, timeout=3): + assert len(request.files) == 1 + orig_fn = list(request.files.keys())[0] + data_before = request.files[orig_fn].read() + data_kb = len(data_before) / 1024.0 + fn = path.basename(orig_fn) + + with tempfile.TemporaryDirectory() as workdir: + abs_fn = path.join(workdir, fn) + with open(abs_fn, "wb") as f: + f.write(data_before) + + t1 = time() + try: + p = subprocess.run( + cmd + [fn], cwd=workdir, timeout=timeout, stdout=PIPE, stderr=STDOUT + ) + except subprocess.TimeoutExpired: + app.logger.info(f"Timeout of {cmd[0]} on {data_kb:.1f}KB after {timeout}s.") + return f"Timeout while running {cmd[0]} - please try again.", 408 + t2 = time() + app.logger.info(f"Ran {cmd[0]} on {data_kb:.1f}KB in {t2-t1:.1f}s.") + + if p.returncode != 0: + return p.stdout, 422 + with open(abs_fn, "rb") as f: + data_after = f.read() + if data_after == data_before: + return "Not Modified", 304 + return data_after, 200 + + +# ====================================================================================== +if __name__ == "__main__": + app.run() + +# EOF diff --git a/tools/precommit/requirements.txt b/tools/precommit/requirements.txt new file mode 100644 index 00000000000..a7853c39e68 --- /dev/null +++ b/tools/precommit/requirements.txt @@ -0,0 +1,30 @@ +black==26.3.1 +blinker==1.9.0 +click==8.3.1 +cmake-format==0.6.13 +cmakelang==0.6.13 +Flask==3.1.3 +gunicorn==25.1.0 +itsdangerous==2.2.0 +Jinja2==3.1.6 +markdown-it-py==3.0.0 +MarkupSafe==3.0.3 +mdformat==0.7.22 +mdformat-gfm==1.0.0 +mdformat_footnote==0.1.3 +mdformat_front_matters==2.0.0 +mdformat_frontmatter==2.0.10 +mdformat_myst==0.3.0 +mdformat_tables==1.0.0 +mdit-py-plugins==0.5.0 +mdurl==0.1.2 +mypy_extensions==1.1.0 +packaging==26.0 +pathspec==1.0.4 +platformdirs==4.9.2 +pytokens==0.4.1 +ruamel.yaml==0.19.1 +six==1.17.0 +toml==0.10.2 +wcwidth==0.6.0 +Werkzeug==3.1.6 diff --git a/tools/precommit/start_local_server.sh b/tools/precommit/start_local_server.sh new file mode 100755 index 00000000000..e4ce0b15edd --- /dev/null +++ b/tools/precommit/start_local_server.sh @@ -0,0 +1,11 @@ +#!/bin/bash -e + +# Based on CP2K's tools/precommit/start_local_server.sh, adapted for ABACUS. + +set -x + +SHORT_SHA=$(git rev-parse --short HEAD) +podman build --build-arg "REVISION=${SHORT_SHA}" -t abacus-precommit . +podman run --rm -p127.0.0.1:8080:8080 abacus-precommit + +# EOF From d149a3f3b80bca79728a9f6daae58d7d86af97c2 Mon Sep 17 00:00:00 2001 From: Growl Date: Wed, 13 May 2026 18:31:27 +0800 Subject: [PATCH 2/7] Temporarily skip precommit failure --- .github/workflows/precommit.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/precommit.yml b/.github/workflows/precommit.yml index 5a1a4270df0..a6024786fa2 100644 --- a/.github/workflows/precommit.yml +++ b/.github/workflows/precommit.yml @@ -45,6 +45,7 @@ jobs: - name: Run precommit env: ABACUS_PRECOMMIT_SERVER: "http://127.0.0.1:8080" + continue-on-error: true run: | ./tools/precommit/precommit.py --no-cache From f460cad95182f979cc8946412d40105e2573f553 Mon Sep 17 00:00:00 2001 From: Growl Date: Wed, 13 May 2026 18:57:53 +0800 Subject: [PATCH 3/7] Clean old precommit configuration --- .clang-format | 50 ----------------------------------------- .clang-tidy | 43 ----------------------------------- .pre-commit-config.yaml | 14 ------------ 3 files changed, 107 deletions(-) delete mode 100644 .clang-format delete mode 100644 .clang-tidy delete mode 100644 .pre-commit-config.yaml diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 8970df99c29..00000000000 --- a/.clang-format +++ /dev/null @@ -1,50 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: Microsoft - -AlwaysBreakTemplateDeclarations: Yes - -AllowAllArgumentsOnNextLine: false -AllowAllParametersOfDeclarationOnNextLine: false -BinPackArguments: false -BinPackParameters: false - -BreakBeforeBinaryOperators: All -BreakBeforeTernaryOperators: true - -Cpp11BracedListStyle: true -FixNamespaceComments: true - -# InsertBraces: true # only for clang-format version15.0.0 or later - -# About include -IncludeBlocks: Regroup -IncludeIsMainRegex: '([-_](test|unittest))?$' -IncludeIsMainSourceRegex: '' - -IndentWidth: 4 -IndentWrappedFunctionNames: true - -# About Point -DerivePointerAlignment: false -PointerAlignment: Left - -ReflowComments: true -SortIncludes: true -SortUsingDeclarations: true - -# About space -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceBeforeRangeBasedForLoopColon: false -SpaceInEmptyParentheses: false -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: false -SpacesInParentheses: false -SpacesInSquareBrackets: false - -Standard: c++11 -TabWidth: 4 -UseTab: Never -... diff --git a/.clang-tidy b/.clang-tidy deleted file mode 100644 index d5587c46012..00000000000 --- a/.clang-tidy +++ /dev/null @@ -1,43 +0,0 @@ ---- -Checks: ' - modernize-deprecated-headers, - modernize-redundant-void-arg, - modernize-use-bool-literals, - modernize-use-nullptr, - readability-avoid-return-with-void-value, - readability-braces-around-statements - - # llvm-header-guard, - # bugprone-*, - # clang-analyzer-*, - # clang-diagnostic-*, - # cppcoreguidelines-avoid-non-const-global-variables, - # cppcoreguidelines-macro-usage, - # cppcoreguidelines-pro-type-member-init, - # fuchsia-multiple-inheritance, - # google-*, - # -google-runtime-references, - # misc-*, - # modernize-shrink-to-fit, - # modernize-use-starts-ends-with, - # mpi-*, - # performance-*, - # -performance-avoid-endl, - # readability-*, - # -readability-else-after-return, - # -readability-magic-numbers, - # -readability-isolate-declaration, - # -readability-braces-around-statements, - # -readability-implicit-bool-conversion, - # -google-readability-braces-around-statements, - # -misc-unused-parameters, - # -modernize-pass-by-value, - # -modernize-use-auto, - # -google-readability-casting, - # -readability-make-member-function-const, - # -cppcoreguidelines-avoid-non-const-global-variables, - # -readability-function-cognitive-complexity, - # -google-build-using-namespace, - # -bugprone-narrowing-conversions, -' -... diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 4c03332257c..00000000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,14 +0,0 @@ -fail_fast: false -repos: - - repo: https://github.com/pocc/pre-commit-hooks - rev: v1.3.5 - hooks: - # - id: clang-format - # args: [-i] - - id: clang-tidy - args: [-p=build, --fix-errors] - # - id: oclint - # - id: uncrustify - # - id: cppcheck - # - id: cpplint - # - id: include-what-you-use From 75926139ed5c8c3d503077797bae0938da6fc2cb Mon Sep 17 00:00:00 2001 From: Growl Date: Wed, 13 May 2026 19:15:31 +0800 Subject: [PATCH 4/7] Add linebreak rules to .gitattributes --- .gitattributes | 6 ++ .../module_ao/1_Documents/sphinx/make.bat | 70 +++++++++---------- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/.gitattributes b/.gitattributes index 9b8c3bc74e9..bc979070968 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,11 @@ +# Export-ignore .gitattributes export-ignore .gitignore export-ignore .gitmodules export-ignore .pre-commit-config.yaml export-ignore .github/ export-ignore + +# Line break +* text=auto eol=lf +*.bat text eol=crlf +*.cmd text eol=crlf diff --git a/source/source_basis/module_ao/1_Documents/sphinx/make.bat b/source/source_basis/module_ao/1_Documents/sphinx/make.bat index 6247f7e2317..9534b018135 100644 --- a/source/source_basis/module_ao/1_Documents/sphinx/make.bat +++ b/source/source_basis/module_ao/1_Documents/sphinx/make.bat @@ -1,35 +1,35 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd From 45cb3d3db1628056a18604eca64a4ea4dad11a37 Mon Sep 17 00:00:00 2001 From: Growl Date: Wed, 13 May 2026 18:40:13 +0800 Subject: [PATCH 5/7] Make pretty (docs/, cmake/, toolchain/) --- CMakeLists.txt | 166 +- README.md | 18 +- cmake/BuildInfo.cmake | 25 +- cmake/CollectBuildInfoVars.cmake | 512 +-- cmake/FindBlas.cmake | 12 +- cmake/FindCereal.cmake | 34 +- cmake/FindDeePMD.cmake | 103 +- cmake/FindELPA.cmake | 79 +- cmake/FindFFTW3.cmake | 130 +- cmake/FindLapack.cmake | 8 +- cmake/FindLibComm.cmake | 37 +- cmake/FindLibRI.cmake | 35 +- cmake/FindLibxc.cmake | 37 +- cmake/FindMKL.cmake | 244 +- cmake/FindNEP.cmake | 64 +- cmake/FindPEXSI.cmake | 109 +- cmake/FindScaLAPACK.cmake | 51 +- cmake/FindTensorFlow.cmake | 36 +- cmake/SetupCuBlasMp.cmake | 54 +- cmake/SetupCuSolverMp.cmake | 137 +- cmake/SetupNccl.cmake | 36 +- cmake/Testing.cmake | 56 +- docs/CITATIONS.md | 47 +- docs/CONTRIBUTING.md | 594 ++-- docs/DevelopingTeam.md | 5 +- docs/Makefile | 4 +- docs/_static/css/custom.css | 2 +- docs/advanced/acceleration/cuda.md | 85 +- docs/advanced/elec_properties/Berry_phase.md | 45 +- docs/advanced/elec_properties/Mulliken.md | 28 +- docs/advanced/elec_properties/band.md | 34 +- docs/advanced/elec_properties/charge.md | 26 +- .../elec_properties/density_matrix.md | 58 +- docs/advanced/elec_properties/dos.md | 65 +- docs/advanced/elec_properties/hs_matrix.md | 79 +- .../elec_properties/position_matrix.md | 30 +- docs/advanced/elec_properties/potential.md | 10 +- docs/advanced/elec_properties/wfc.md | 30 +- docs/advanced/input_files/input-main.md | 2913 +++++++++++------ docs/advanced/input_files/kpt.md | 78 +- docs/advanced/input_files/stru.md | 521 +-- docs/advanced/install.md | 179 +- docs/advanced/interface/Hefei-NAMD.md | 27 +- docs/advanced/interface/ShengBTE.md | 125 +- docs/advanced/interface/TB2J.md | 80 +- docs/advanced/interface/Wannier90.md | 275 +- docs/advanced/interface/ase.md | 45 +- docs/advanced/interface/candela.md | 36 +- docs/advanced/interface/deeph.md | 42 +- docs/advanced/interface/deepks.md | 32 +- docs/advanced/interface/deeptb.md | 16 +- docs/advanced/interface/dpgen.md | 27 +- .../interface/migration-guide-csr-format.md | 36 +- docs/advanced/interface/phonopy.md | 8 +- docs/advanced/interface/pyabacus.md | 129 +- docs/advanced/interface/pyatb.md | 237 +- docs/advanced/json/json_add.md | 91 +- docs/advanced/json/json_para.md | 41 +- docs/advanced/md.md | 182 +- docs/advanced/opt.md | 123 +- .../output_files/output-specification.md | 212 +- docs/advanced/output_files/running_scf.log.md | 43 +- docs/advanced/pp_orb.md | 169 +- docs/advanced/scf/advanced.md | 122 +- docs/advanced/scf/construct_H.md | 149 +- docs/advanced/scf/converge.md | 63 +- docs/advanced/scf/hsolver.md | 36 +- docs/advanced/scf/initialization.md | 46 +- docs/advanced/scf/performance.md | 35 +- docs/advanced/scf/spin.md | 169 +- docs/advanced/windows_installer.md | 226 +- docs/community/cicd.md | 57 +- docs/community/contribution_guide.md | 26 +- docs/community/faq.md | 128 +- docs/conf.py | 44 +- docs/developers_guide/basic_types_class.md | 66 +- docs/generate_input_main.py | 102 +- docs/quick_start/easy_install.md | 275 +- docs/quick_start/hands_on.md | 81 +- docs/quick_start/input.md | 77 +- docs/quick_start/output.md | 35 +- toolchain/README.md | 252 +- toolchain/build_abacus_aocc-aocl.sh | 2 +- toolchain/build_abacus_gcc-aocl.sh | 2 +- toolchain/build_abacus_gcc-mkl.sh | 2 +- toolchain/build_abacus_gnu.sh | 2 +- toolchain/build_abacus_intel.sh | 6 +- toolchain/scripts/stage4/install_nep.sh | 14 +- 88 files changed, 6829 insertions(+), 3980 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d384199c5a..889111f165a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,8 +23,8 @@ option(USE_ABACUS_LIBM "Build libmath from source to speed up" OFF) option(ENABLE_LIBXC "Enable using the LibXC package" OFF) option(ENABLE_FLOAT_FFTW "Enable using single-precision FFTW library." OFF) -# option(ENABLE_DEEPKS "Enable the DeePKS algorithm" OFF) -# option(ENABLE_MLKEDF "Enable the Machine-Learning-based KEDF for OFDFT" OFF) +# option(ENABLE_DEEPKS "Enable the DeePKS algorithm" OFF) option(ENABLE_MLKEDF +# "Enable the Machine-Learning-based KEDF for OFDFT" OFF) option(ENABLE_MLALGO "Enable the machine learning algorithms" OFF) @@ -51,7 +51,8 @@ option(ENABLE_GOOGLEBENCH "Enable GOOGLE-benchmark usage" OFF) option(ENABLE_RAPIDJSON "Enable rapid-json usage" OFF) option(ENABLE_CNPY "Enable cnpy usage" OFF) option(ENABLE_CUSOLVERMP "Enable cusolvermp" OFF) -option(ENABLE_NCCL_PARALLEL_DEVICE "Enable NCCL-backed collectives in parallel_device" OFF) +option(ENABLE_NCCL_PARALLEL_DEVICE + "Enable NCCL-backed collectives in parallel_device" OFF) if(NOT DEFINED NVHPC_ROOT_DIR AND DEFINED ENV{NVHPC_ROOT}) set(NVHPC_ROOT_DIR @@ -70,8 +71,7 @@ if(ENABLE_RAPIDJSON) include(FetchContent) FetchContent_Declare( rapidjson - URL https://codeload.github.com/Tencent/rapidjson/tar.gz/24b5e7a - ) + URL https://codeload.github.com/Tencent/rapidjson/tar.gz/24b5e7a) set(RAPIDJSON_BUILD_TESTS OFF CACHE INTERNAL "") @@ -145,7 +145,7 @@ if(ENABLE_LCAO) set(ABACUS_BIN_NAME abacus_max_gpu) endif() endif() - # Case: CPU is enabled (suffix with 'p' for parallel) + # Case: CPU is enabled (suffix with 'p' for parallel) else() if(ENABLE_MPI) if(NOT ENABLE_LIBRI AND NOT ENABLE_MLALGO) @@ -169,7 +169,7 @@ if(ENABLE_LCAO) endif() endif() endif() -# Case : PW only + # Case : PW only else() if(USE_CUDA) if(ENABLE_MPI) @@ -184,18 +184,17 @@ else() endif() endif() - # Use DSP hardware -if (USE_DSP) +if(USE_DSP) set(USE_ELPA OFF) set(ABACUS_BIN_NAME abacus_dsp) endif() -if (USE_CUDA_ON_DCU) +if(USE_CUDA_ON_DCU) add_compile_definitions(__CUDA_ON_DCU) endif() -if (USE_CUDA_MPI) +if(USE_CUDA_MPI) add_compile_definitions(__CUDA_MPI) endif() @@ -210,11 +209,11 @@ if(ENABLE_COVERAGE) GIT_REPOSITORY https://github.com/RWTH-HPC/CMake-codecov.git GIT_TAG master GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - ) + GIT_PROGRESS TRUE) FetchContent_Populate(cmakecodecov) list(APPEND CMAKE_MODULE_PATH ${cmakecodecov_SOURCE_DIR}/cmake) - set(CMAKE_MODULE_PATH "${cmakecodecov_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) + set(CMAKE_MODULE_PATH "${cmakecodecov_SOURCE_DIR}/cmake" + ${CMAKE_MODULE_PATH}) find_package(codecov REQUIRED) endif() endif() @@ -235,7 +234,6 @@ if(ENABLE_COVERAGE) add_coverage(${ABACUS_BIN_NAME}) endif() - macro(set_if_higher VARIABLE VALUE) if(${VARIABLE} LESS ${VALUE}) set(${VARIABLE} ${VALUE}) @@ -275,9 +273,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES Intel) # stick to strict floating point model on Intel Compiler add_compile_options(-fp-model=strict) set(USE_ABACUS_LIBM OFF) # Force turn off USE_ABACUS_LIBM on Intel Compiler - set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -Wno-write-strings " - ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-write-strings ") endif() if(USE_ABACUS_LIBM) @@ -306,7 +302,9 @@ if(ENABLE_LCAO) if(ENABLE_PEXSI) find_package(PEXSI REQUIRED) - target_link_libraries(${ABACUS_BIN_NAME} ${PEXSI_LIBRARY} ${SuperLU_DIST_LIBRARY} ${ParMETIS_LIBRARY} ${METIS_LIBRARY} pexsi) + target_link_libraries( + ${ABACUS_BIN_NAME} ${PEXSI_LIBRARY} ${SuperLU_DIST_LIBRARY} + ${ParMETIS_LIBRARY} ${METIS_LIBRARY} pexsi) include_directories(${PEXSI_INCLUDE_DIR} ${ParMETIS_INCLUDE_DIR}) add_compile_definitions(__PEXSI) set(CMAKE_CXX_STANDARD 14) @@ -321,23 +319,27 @@ if(DEBUG_INFO) endif() if(ENABLE_MPI) - find_package(MPI COMPONENTS CXX REQUIRED) + find_package( + MPI + COMPONENTS CXX + REQUIRED) include_directories(${MPI_CXX_INCLUDE_PATH}) target_link_libraries(${ABACUS_BIN_NAME} MPI::MPI_CXX) add_compile_definitions(__MPI) list(APPEND math_libs MPI::MPI_CXX) endif() - -if (USE_DSP) +if(USE_DSP) add_compile_definitions(__DSP) target_link_libraries(${ABACUS_BIN_NAME} ${OMPI_LIBRARY1}) include_directories(${MTBLAS_FFT_DIR}/libmtblas/include) include_directories(${MT_HOST_DIR}/include) - target_link_libraries(${ABACUS_BIN_NAME} ${MT_HOST_DIR}/hthreads/lib/libhthread_device.a) - target_link_libraries(${ABACUS_BIN_NAME} ${MT_HOST_DIR}/hthreads/lib/libhthread_host.a) + target_link_libraries(${ABACUS_BIN_NAME} + ${MT_HOST_DIR}/hthreads/lib/libhthread_device.a) + target_link_libraries(${ABACUS_BIN_NAME} + ${MT_HOST_DIR}/hthreads/lib/libhthread_host.a) endif() -if (USE_SW) +if(USE_SW) add_compile_definitions(__SW) set(SW ON) include_directories(${SW_MATH}/include) @@ -374,21 +376,22 @@ if(CMAKE_CUDA_COMPILER) endif() else() # CUDA not found if(USE_CUDA) - message( - FATAL_ERROR - "USE_CUDA is set but no CUDA components found.") + message(FATAL_ERROR "USE_CUDA is set but no CUDA components found.") endif() endif() if(USE_CUDA) cmake_minimum_required(VERSION 3.18) # required by `CUDA_ARCHITECTURES` below - + # Always find CUDAToolkit to get CUDAToolkit_VERSION find_package(CUDAToolkit REQUIRED) - + set_if_higher(CMAKE_CXX_STANDARD 14) if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL "13.0") - message(STATUS "CUDA ${CUDAToolkit_VERSION} detected. Setting CMAKE_CUDA_STANDARD to 17.") + message( + STATUS + "CUDA ${CUDAToolkit_VERSION} detected. Setting CMAKE_CUDA_STANDARD to 17." + ) set_if_higher(CMAKE_CXX_STANDARD 17) endif() set(CMAKE_CXX_EXTENSIONS ON) @@ -399,21 +402,20 @@ if(USE_CUDA) # check # https://gitlab.kitware.com/cmake/cmake/-/blob/master/Modules/Internal/CMakeCUDAArchitecturesAll.cmake # for available architectures in different CUDA versions - + # CUDA 13.0+ dropped support for architectures below 75 if(CUDAToolkit_VERSION VERSION_LESS "13.0") - set(CMAKE_CUDA_ARCHITECTURES - 60 # P100 - 70 # V100 + set(CMAKE_CUDA_ARCHITECTURES 60 # P100 + 70 # V100 ) else() # Start with empty list; architectures 75+ will be added below set(CMAKE_CUDA_ARCHITECTURES) endif() - - # Add your CUDA arch here Check the Compute Capability version of your - # GPU at: https://en.wikipedia.org/wiki/CUDA#GPUs_supported - + + # Add your CUDA arch here Check the Compute Capability version of your GPU + # at: https://en.wikipedia.org/wiki/CUDA#GPUs_supported + if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.0) list(APPEND CMAKE_CUDA_ARCHITECTURES 75) # T4 endif() @@ -429,13 +431,13 @@ if(USE_CUDA) endif() enable_language(CUDA) # ${ABACUS_BIN_NAME} is added before CUDA is enabled - set_property(TARGET ${ABACUS_BIN_NAME} - PROPERTY CUDA_ARCHITECTURES ${CMAKE_CUDA_ARCHITECTURES}) - if (CUDAToolkit_VERSION VERSION_GREATER_EQUAL 12.9) + set_property(TARGET ${ABACUS_BIN_NAME} PROPERTY CUDA_ARCHITECTURES + ${CMAKE_CUDA_ARCHITECTURES}) + if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 12.9) target_link_libraries(${ABACUS_BIN_NAME} cudart) - else () + else() target_link_libraries(${ABACUS_BIN_NAME} cudart nvToolsExt) - endif () + endif() include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 13.0) if(EXISTS "${CUDAToolkit_ROOT}/include/cccl") @@ -446,40 +448,46 @@ if(USE_CUDA) add_compile_definitions(__CUDA) add_compile_definitions(__UT_USE_CUDA) target_compile_definitions(${ABACUS_BIN_NAME} PRIVATE __USE_NVTX) - if (CMAKE_BUILD_TYPE STREQUAL "Debug") - set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -g -G" CACHE STRING "CUDA flags for debug build" FORCE) + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CMAKE_CUDA_FLAGS_DEBUG + "${CMAKE_CUDA_FLAGS_DEBUG} -g -G" + CACHE STRING "CUDA flags for debug build" FORCE) endif() - if (USE_OPENMP AND OpenMP_CXX_FOUND) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=${OpenMP_CXX_FLAGS}" CACHE STRING "CUDA flags" FORCE) + if(USE_OPENMP AND OpenMP_CXX_FOUND) + set(CMAKE_CUDA_FLAGS + "${CMAKE_CUDA_FLAGS} -Xcompiler=${OpenMP_CXX_FLAGS}" + CACHE STRING "CUDA flags" FORCE) endif() - if (ENABLE_NCCL_PARALLEL_DEVICE) - if (NOT ENABLE_MPI) - message(FATAL_ERROR - "ENABLE_NCCL_PARALLEL_DEVICE requires ENABLE_MPI=ON.") + if(ENABLE_NCCL_PARALLEL_DEVICE) + if(NOT ENABLE_MPI) + message( + FATAL_ERROR "ENABLE_NCCL_PARALLEL_DEVICE requires ENABLE_MPI=ON.") endif() add_compile_definitions(__NCCL_PARALLEL_DEVICE) include(cmake/SetupNccl.cmake) abacus_setup_nccl(${ABACUS_BIN_NAME}) endif() - if (ENABLE_CUSOLVERMP) + if(ENABLE_CUSOLVERMP) # Keep cuSOLVERMp discovery/linking logic in a dedicated module. include(cmake/SetupCuSolverMp.cmake) abacus_setup_cusolvermp(${ABACUS_BIN_NAME}) endif() - if (ENABLE_CUBLASMP) + if(ENABLE_CUBLASMP) # Enforcement 1: cuBLASMp requires cuSOLVERMp to be enabled - if (NOT ENABLE_CUSOLVERMP) - message(FATAL_ERROR - "ENABLE_CUBLASMP is set to ON, but ENABLE_CUSOLVERMP is OFF." - "In ABACUS, cuBLASMp support requires cuSOLVERMp to be enabled simultaneously." - "Please set -DENABLE_CUSOLVERMP=ON.") + if(NOT ENABLE_CUSOLVERMP) + message( + FATAL_ERROR + "ENABLE_CUBLASMP is set to ON, but ENABLE_CUSOLVERMP is OFF." + "In ABACUS, cuBLASMp support requires cuSOLVERMp to be enabled simultaneously." + "Please set -DENABLE_CUSOLVERMP=ON.") endif() - # Enforcement 2: cuBLASMp 0.8.0+ is incompatible with CAL backend - # Note: _use_cal is defined inside abacus_setup_cusolvermp - if (_use_cal) - message(FATAL_ERROR - "cuBLASMp 0.8.0+ requires NCCL Symmetric Memory, but cuSOLVERMp is using CAL backend." - "Please upgrade cuSOLVERMp to >= 0.7.0 to use NCCL for both.") + # Enforcement 2: cuBLASMp 0.8.0+ is incompatible with CAL backend Note: + # _use_cal is defined inside abacus_setup_cusolvermp + if(_use_cal) + message( + FATAL_ERROR + "cuBLASMp 0.8.0+ requires NCCL Symmetric Memory, but cuSOLVERMp is using CAL backend." + "Please upgrade cuSOLVERMp to >= 0.7.0 to use NCCL for both.") endif() include(cmake/SetupCuBlasMp.cmake) abacus_setup_cublasmp(${ABACUS_BIN_NAME}) @@ -609,8 +617,8 @@ if(ENABLE_MLALGO) add_compile_definitions(__MLALGO) endif() -# Torch uses outdated components to detect CUDA arch, causing failure on -# latest CUDA kits. Set CMake variable TORCH_CUDA_ARCH_LIST in the form of +# Torch uses outdated components to detect CUDA arch, causing failure on latest +# CUDA kits. Set CMake variable TORCH_CUDA_ARCH_LIST in the form of # "major.minor" if required. if(ENABLE_MLALGO OR DEFINED Torch_DIR) find_package(Torch REQUIRED) @@ -628,18 +636,14 @@ if(ENABLE_MLALGO OR DEFINED Torch_DIR) add_compile_options(${TORCH_CXX_FLAGS}) endif() -if (ENABLE_CNPY) - find_path(cnpy_SOURCE_DIR - cnpy.h - HINTS ${libnpy_INCLUDE_DIR} - ) +if(ENABLE_CNPY) + find_path(cnpy_SOURCE_DIR cnpy.h HINTS ${libnpy_INCLUDE_DIR}) if(NOT cnpy_SOURCE_DIR) include(FetchContent) FetchContent_Declare( cnpy GIT_REPOSITORY https://github.com/rogersce/cnpy.git - GIT_PROGRESS TRUE - ) + GIT_PROGRESS TRUE) FetchContent_MakeAvailable(cnpy) else() include_directories(${cnpy_INCLUDE_DIR}) @@ -681,6 +685,7 @@ endif() if(ENABLE_LIBRI) set_if_higher(CMAKE_CXX_STANDARD 14) if(LIBRI_DIR) + else() find_package(LibRI REQUIRED) endif() @@ -695,13 +700,13 @@ if(ENABLE_LIBRI OR DEFINED LIBCOMM_DIR) endif() if(ENABLE_LIBCOMM) if(LIBCOMM_DIR) + else() find_package(LibComm REQUIRED) endif() include_directories(${LIBCOMM_DIR}/include) endif() - if(DEFINED Libxc_DIR) set(ENABLE_LIBXC ON) endif() @@ -816,7 +821,7 @@ if(ENABLE_RAPIDJSON) target_link_libraries(${ABACUS_BIN_NAME} json_output) endif() -if (USE_SW) +if(USE_SW) target_link_libraries(${ABACUS_BIN_NAME} ${SW_MATH}/libswfft.a) target_link_libraries(${ABACUS_BIN_NAME} ${SW_MATH}/libswscalapack.a) target_link_libraries(${ABACUS_BIN_NAME} ${SW_MATH}/libswlapack.a) @@ -827,13 +832,14 @@ endif() list(APPEND math_libs m) target_link_libraries(${ABACUS_BIN_NAME} ${math_libs}) -install(PROGRAMS ${ABACUS_BIN_PATH} - TYPE BIN - # DESTINATION ${CMAKE_INSTALL_BINDIR} +install(PROGRAMS ${ABACUS_BIN_PATH} TYPE BIN # DESTINATION + # ${CMAKE_INSTALL_BINDIR} ) # Create a symbolic link 'abacus' pointing to the actual executable -install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${ABACUS_BIN_NAME} ${CMAKE_INSTALL_PREFIX}/bin/abacus WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin)") +install( + CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${ABACUS_BIN_NAME} ${CMAKE_INSTALL_PREFIX}/bin/abacus WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin)" +) if(ENABLE_COVERAGE) coverage_evaluate() diff --git a/README.md b/README.md index e0c81ae6554..4ecfb9e2da3 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,21 @@ # About ABACUS -ABACUS (**A**tomic-orbital **B**ased **A**b-initio **C**omputation at **US**tc) is an open-source package based on density functional theory (DFT). The package utilizes both plane wave and numerical atomic basis sets with the usage of pseudopotentials to describe the interactions between nuclear ions and valence electrons. ABACUS supports LDA, GGA, meta-GGA, and hybrid functionals. Apart from single-point calculations, the package allows geometry optimizations and ab-initio molecular dynamics with various ensembles. The package also provides a variety of advanced functionalities for simulating materials, including the DFT+U, VdW corrections, and implicit solvation model, etc. In addition, ABACUS strives to provide a general infrastructure to facilitate the developments and applications of novel machine-learning-assisted DFT methods (DeePKS, DP-GEN, DeepH, DeePTB etc.) in molecular and material simulations. +ABACUS (**A**tomic-orbital **B**ased **A**b-initio **C**omputation at **US**tc) is an open-source +package based on density functional theory (DFT). The package utilizes both plane wave and numerical +atomic basis sets with the usage of pseudopotentials to describe the interactions between nuclear +ions and valence electrons. ABACUS supports LDA, GGA, meta-GGA, and hybrid functionals. Apart from +single-point calculations, the package allows geometry optimizations and ab-initio molecular +dynamics with various ensembles. The package also provides a variety of advanced functionalities for +simulating materials, including the DFT+U, VdW corrections, and implicit solvation model, etc. In +addition, ABACUS strives to provide a general infrastructure to facilitate the developments and +applications of novel machine-learning-assisted DFT methods (DeePKS, DP-GEN, DeepH, DeePTB etc.) in +molecular and material simulations. # Online Documentation -For detailed documentation, please refer to [our documentation website](https://abacus.deepmodeling.com/). -See our [Github Pages](https://mcresearch.github.io/abacus-user-guide/) for more tutorials and developer guides. \ No newline at end of file +For detailed documentation, please refer to +[our documentation website](https://abacus.deepmodeling.com/). + +See our [Github Pages](https://mcresearch.github.io/abacus-user-guide/) for more tutorials and +developer guides. diff --git a/cmake/BuildInfo.cmake b/cmake/BuildInfo.cmake index 94a267e9c6a..44c6be46cdc 100644 --- a/cmake/BuildInfo.cmake +++ b/cmake/BuildInfo.cmake @@ -5,24 +5,19 @@ # include_guard(GLOBAL) function(setup_build_info) - message(STATUS "Setting up build information...") + message(STATUS "Setting up build information...") - include(cmake/CollectBuildInfoVars.cmake) + include(cmake/CollectBuildInfoVars.cmake) -set(BUILD_INFO_TEMPLATE "${CMAKE_SOURCE_DIR}/source/source_io/build_info.h.in") -set(BUILD_INFO_OUTPUT "${CMAKE_BINARY_DIR}/source/source_io/build_info.h") + set(BUILD_INFO_TEMPLATE + "${CMAKE_SOURCE_DIR}/source/source_io/build_info.h.in") + set(BUILD_INFO_OUTPUT "${CMAKE_BINARY_DIR}/source/source_io/build_info.h") -configure_file( - ${BUILD_INFO_TEMPLATE} - ${BUILD_INFO_OUTPUT} - @ONLY -) + configure_file(${BUILD_INFO_TEMPLATE} ${BUILD_INFO_OUTPUT} @ONLY) - # add_library(BuildInfo::Headers INTERFACE IMPORTED GLOBAL) - # target_include_directories(BuildInfo::Headers - # INTERFACE - # ${CMAKE_BINARY_DIR}/source/source_io - # ) + # add_library(BuildInfo::Headers INTERFACE IMPORTED GLOBAL) + # target_include_directories(BuildInfo::Headers INTERFACE + # ${CMAKE_BINARY_DIR}/source/source_io ) - message(STATUS "Build info header configured: ${BUILD_INFO_OUTPUT}") + message(STATUS "Build info header configured: ${BUILD_INFO_OUTPUT}") endfunction() diff --git a/cmake/CollectBuildInfoVars.cmake b/cmake/CollectBuildInfoVars.cmake index 79e925af1dc..10d20cebf4b 100644 --- a/cmake/CollectBuildInfoVars.cmake +++ b/cmake/CollectBuildInfoVars.cmake @@ -1,63 +1,61 @@ # ============================================================================= -# This script is included to set all build information variables in the -# calling scope. It does not use a function to avoid variable scope issues. +# This script is included to set all build information variables in the calling +# scope. It does not use a function to avoid variable scope issues. # ============================================================================== # --- 1. Collect Basic Build Information --- if(NOT CMAKE_BUILD_TYPE) - set(ABACUS_BUILD_TYPE "Custom (no CMAKE_BUILD_TYPE)") + set(ABACUS_BUILD_TYPE "Custom (no CMAKE_BUILD_TYPE)") else() - set(ABACUS_BUILD_TYPE ${CMAKE_BUILD_TYPE}) + set(ABACUS_BUILD_TYPE ${CMAKE_BUILD_TYPE}) endif() if(DEFINED ENV{USER}) - set(ABACUS_BUILD_USER "$ENV{USER}") + set(ABACUS_BUILD_USER "$ENV{USER}") else() - set(ABACUS_BUILD_USER "Unknown") + set(ABACUS_BUILD_USER "Unknown") endif() site_name(ABACUS_BUILD_HOST) set(ABACUS_CXX_COMPILER_ID ${CMAKE_CXX_COMPILER_ID}) set(ABACUS_CXX_COMPILER_PATH ${CMAKE_CXX_COMPILER}) set(ABACUS_CXX_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION}) set(TEMP_CXX_FLAGS_LIST "${CMAKE_CXX_FLAGS}") -#if(DEFINED CMAKE_BUILD_TYPE) -# string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER) -# list(APPEND TEMP_CXX_FLAGS_LIST "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}") -#endif() +# if(DEFINED CMAKE_BUILD_TYPE) string(TOUPPER ${CMAKE_BUILD_TYPE} +# CMAKE_BUILD_TYPE_UPPER) list(APPEND TEMP_CXX_FLAGS_LIST +# "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}") endif() string(REPLACE ";" " " ABACUS_CXX_FLAGS "${TEMP_CXX_FLAGS_LIST}") set(TEMP_LINKER_FLAGS_LIST "${CMAKE_EXE_LINKER_FLAGS}") -#if(DEFINED CMAKE_BUILD_TYPE) -# string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER) -# list(APPEND TEMP_LINKER_FLAGS_LIST "${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}") -#endif() +# if(DEFINED CMAKE_BUILD_TYPE) string(TOUPPER ${CMAKE_BUILD_TYPE} +# CMAKE_BUILD_TYPE_UPPER) list(APPEND TEMP_LINKER_FLAGS_LIST +# "${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}") endif() string(REPLACE ";" " " ABACUS_LINKER_FLAGS "${TEMP_LINKER_FLAGS_LIST}") set(TEMP_CUDA_FLAGS_LIST "${CMAKE_EXE_CUDA_FLAGS}") string(REPLACE ";" " " ABACUS_CUDA_FLAGS "${TEMP_CUDA_FLAGS_LIST}") # --- 2. Determine Target Platform --- if(USE_DSP) - set(ABACUS_PLATFORM_NAME "DSP") + set(ABACUS_PLATFORM_NAME "DSP") elseif(USE_SW) - set(ABACUS_PLATFORM_NAME "CPU + SW-MATH") + set(ABACUS_PLATFORM_NAME "CPU + SW-MATH") elseif(USE_CUDA_ON_DCU) - set(ABACUS_PLATFORM_NAME "CPU + DCU (Hygon CUDA)") + set(ABACUS_PLATFORM_NAME "CPU + DCU (Hygon CUDA)") elseif(USE_CUDA) - set(ABACUS_PLATFORM_NAME "CPU + NVIDIA CUDA") + set(ABACUS_PLATFORM_NAME "CPU + NVIDIA CUDA") elseif(USE_ROCM) - set(ABACUS_PLATFORM_NAME "CPU + AMD ROCm") + set(ABACUS_PLATFORM_NAME "CPU + AMD ROCm") else() - set(ABACUS_PLATFORM_NAME "CPU") + set(ABACUS_PLATFORM_NAME "CPU") endif() # --- 3. Sanitizers & Debugging --- if(ENABLE_ASAN) - set(ABACUS_ASAN_STATUS "yes") + set(ABACUS_ASAN_STATUS "yes") else() - set(ABACUS_ASAN_STATUS "no") + set(ABACUS_ASAN_STATUS "no") endif() if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(ABACUS_DEBUG_SYMBOLS "yes") + set(ABACUS_DEBUG_SYMBOLS "yes") else() - set(ABACUS_DEBUG_SYMBOLS "no") + set(ABACUS_DEBUG_SYMBOLS "no") endif() # --- 4. Get Dependency Versions (Enhanced with path fallback) --- @@ -66,324 +64,384 @@ set(ABACUS_MPI_IMPLEMENTATION "no") set(ABACUS_MPI_VERSION "no") set(ABACUS_CUDA_AWARE_MPI "no") if(ENABLE_MPI) - execute_process(COMMAND ${MPI_CXX_COMPILER} --version OUTPUT_VARIABLE MPI_VERSION_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) - if(MPI_VERSION_OUTPUT MATCHES "Intel") - set(ABACUS_MPI_IMPLEMENTATION "Intel MPI") - string(REGEX MATCH "Intel\\(R\\) oneAPI DPC\\+\\+/C\\+\\+ Compiler ([0-9]+\\.[0-9]+\\.[0-9]+)" _ "${MPI_VERSION_OUTPUT}") - if(CMAKE_MATCH_1) - set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}") - else() - string(REGEX MATCH "icpc \\(ICC\\) ([0-9]+\\.[0-9]+\\.[0-9]+)" _ "${MPI_VERSION_OUTPUT}") - if(CMAKE_MATCH_1) - set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}") - endif() - endif() - elseif(MPI_VERSION_OUTPUT MATCHES "Open MPI") - set(ABACUS_MPI_IMPLEMENTATION "OpenMPI") - elseif(MPI_VERSION_OUTPUT MATCHES "MPICH") - set(ABACUS_MPI_IMPLEMENTATION "MPICH") + execute_process( + COMMAND ${MPI_CXX_COMPILER} --version + OUTPUT_VARIABLE MPI_VERSION_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + if(MPI_VERSION_OUTPUT MATCHES "Intel") + set(ABACUS_MPI_IMPLEMENTATION "Intel MPI") + string( + REGEX + MATCH + "Intel\\(R\\) oneAPI DPC\\+\\+/C\\+\\+ Compiler ([0-9]+\\.[0-9]+\\.[0-9]+)" + _ + "${MPI_VERSION_OUTPUT}") + if(CMAKE_MATCH_1) + set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}") else() - set(ABACUS_MPI_IMPLEMENTATION "Unknown") + string(REGEX MATCH "icpc \\(ICC\\) ([0-9]+\\.[0-9]+\\.[0-9]+)" _ + "${MPI_VERSION_OUTPUT}") + if(CMAKE_MATCH_1) + set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}") + endif() endif() - # Fallback: try mpirun/mpiexec - if(NOT MPI_DETECTED_VERSION) - find_program(MPIRUN_EXECUTABLE mpirun) - if(MPIRUN_EXECUTABLE) - execute_process(COMMAND ${MPIRUN_EXECUTABLE} --version OUTPUT_VARIABLE MPIRUN_VERSION_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) - if(MPIRUN_VERSION_OUTPUT MATCHES "Open MPI") - set(ABACUS_MPI_IMPLEMENTATION "OpenMPI") - string(REGEX MATCH "Open MPI ([0-9]+\\.[0-9]+\\.[0-9]+)" _ "${MPIRUN_VERSION_OUTPUT}") - if(CMAKE_MATCH_1) - set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}") - endif() - elseif(MPIRUN_VERSION_OUTPUT MATCHES "MPICH") - set(ABACUS_MPI_IMPLEMENTATION "MPICH") - string(REGEX MATCH "MPICH Version: ([0-9]+\\.[0-9]+\\.[0-9]+)" _ "${MPIRUN_VERSION_OUTPUT}") - if(CMAKE_MATCH_1) - set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}") - endif() - endif() + elseif(MPI_VERSION_OUTPUT MATCHES "Open MPI") + set(ABACUS_MPI_IMPLEMENTATION "OpenMPI") + elseif(MPI_VERSION_OUTPUT MATCHES "MPICH") + set(ABACUS_MPI_IMPLEMENTATION "MPICH") + else() + set(ABACUS_MPI_IMPLEMENTATION "Unknown") + endif() + # Fallback: try mpirun/mpiexec + if(NOT MPI_DETECTED_VERSION) + find_program(MPIRUN_EXECUTABLE mpirun) + if(MPIRUN_EXECUTABLE) + execute_process( + COMMAND ${MPIRUN_EXECUTABLE} --version + OUTPUT_VARIABLE MPIRUN_VERSION_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + if(MPIRUN_VERSION_OUTPUT MATCHES "Open MPI") + set(ABACUS_MPI_IMPLEMENTATION "OpenMPI") + string(REGEX MATCH "Open MPI ([0-9]+\\.[0-9]+\\.[0-9]+)" _ + "${MPIRUN_VERSION_OUTPUT}") + if(CMAKE_MATCH_1) + set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}") endif() - endif() - if(MPI_DETECTED_VERSION) - set(ABACUS_MPI_VERSION "yes (v${MPI_DETECTED_VERSION})") - elseif(MPI_VERSION) - set(ABACUS_MPI_VERSION "yes (v${MPI_VERSION})") - else() - set(ABACUS_MPI_VERSION "yes (version unknown)") - endif() - if(USE_CUDA) - # OpenMPI hint - find_program(OMPI_INFO_EXECUTABLE ompi_info) - if(OMPI_INFO_EXECUTABLE) - execute_process(COMMAND ${OMPI_INFO_EXECUTABLE} --parsable --all OUTPUT_VARIABLE OMPI_INFO_OUT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) - if(OMPI_INFO_OUT MATCHES "mpi_built_with_cuda_support:value:true") - set(ABACUS_CUDA_AWARE_MPI "yes") - else() - set(ABACUS_CUDA_AWARE_MPI "no (or undetectable)") - endif() - else() - execute_process(COMMAND ${MPI_CXX_COMPILER} -showme:compile OUTPUT_VARIABLE MPI_COMPILE_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) - if(MPI_COMPILE_FLAGS MATCHES "cuda" OR MPI_COMPILE_FLAGS MATCHES "CUDA") - set(ABACUS_CUDA_AWARE_MPI "yes (likely)") - else() - set(ABACUS_CUDA_AWARE_MPI "no (or undetectable)") - endif() + elseif(MPIRUN_VERSION_OUTPUT MATCHES "MPICH") + set(ABACUS_MPI_IMPLEMENTATION "MPICH") + string(REGEX MATCH "MPICH Version: ([0-9]+\\.[0-9]+\\.[0-9]+)" _ + "${MPIRUN_VERSION_OUTPUT}") + if(CMAKE_MATCH_1) + set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}") endif() + endif() + endif() + endif() + if(MPI_DETECTED_VERSION) + set(ABACUS_MPI_VERSION "yes (v${MPI_DETECTED_VERSION})") + elseif(MPI_VERSION) + set(ABACUS_MPI_VERSION "yes (v${MPI_VERSION})") + else() + set(ABACUS_MPI_VERSION "yes (version unknown)") + endif() + if(USE_CUDA) + # OpenMPI hint + find_program(OMPI_INFO_EXECUTABLE ompi_info) + if(OMPI_INFO_EXECUTABLE) + execute_process( + COMMAND ${OMPI_INFO_EXECUTABLE} --parsable --all + OUTPUT_VARIABLE OMPI_INFO_OUT + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + if(OMPI_INFO_OUT MATCHES "mpi_built_with_cuda_support:value:true") + set(ABACUS_CUDA_AWARE_MPI "yes") + else() + set(ABACUS_CUDA_AWARE_MPI "no (or undetectable)") + endif() else() - set(ABACUS_CUDA_AWARE_MPI "no (CUDA not enabled)") + execute_process( + COMMAND ${MPI_CXX_COMPILER} -showme:compile + OUTPUT_VARIABLE MPI_COMPILE_FLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + if(MPI_COMPILE_FLAGS MATCHES "cuda" OR MPI_COMPILE_FLAGS MATCHES "CUDA") + set(ABACUS_CUDA_AWARE_MPI "yes (likely)") + else() + set(ABACUS_CUDA_AWARE_MPI "no (or undetectable)") + endif() endif() + else() + set(ABACUS_CUDA_AWARE_MPI "no (CUDA not enabled)") + endif() endif() # OpenMP Version if(USE_OPENMP AND OpenMP_CXX_VERSION) - set(ABACUS_OPENMP_VERSION "yes (v${OpenMP_CXX_VERSION})") + set(ABACUS_OPENMP_VERSION "yes (v${OpenMP_CXX_VERSION})") elseif(USE_OPENMP) - set(ABACUS_OPENMP_VERSION "yes (version unknown)") + set(ABACUS_OPENMP_VERSION "yes (version unknown)") else() - set(ABACUS_OPENMP_VERSION "no") + set(ABACUS_OPENMP_VERSION "no") endif() # Core Math Libraries if(ENABLE_LCAO AND USE_ELPA) - set(ABACUS_ELPA_VERSION "yes (version unknown)") - if(ELPA_VERSION) + set(ABACUS_ELPA_VERSION "yes (version unknown)") + if(ELPA_VERSION) set(ABACUS_ELPA_VERSION "yes (v${ELPA_VERSION})") - else() - find_program(ELPA_VERSION_EXE elpa2_print_version PATHS ${ELPA_DIR}/bin NO_DEFAULT_PATH) - if(ELPA_VERSION_EXE) - execute_process(COMMAND ${ELPA_VERSION_EXE} OUTPUT_VARIABLE ELPA_VER_RAW OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) - if(ELPA_VER_RAW) - set(ABACUS_ELPA_VERSION "yes (${ELPA_VER_RAW})") -endif() - endif() - endif() - if(ABACUS_ELPA_VERSION STREQUAL "yes (version unknown)" AND ELPA_DIR) - set(ABACUS_ELPA_VERSION "yes (path: ${ELPA_DIR})") + else() + find_program( + ELPA_VERSION_EXE elpa2_print_version + PATHS ${ELPA_DIR}/bin + NO_DEFAULT_PATH) + if(ELPA_VERSION_EXE) + execute_process( + COMMAND ${ELPA_VERSION_EXE} + OUTPUT_VARIABLE ELPA_VER_RAW + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + if(ELPA_VER_RAW) + set(ABACUS_ELPA_VERSION "yes (${ELPA_VER_RAW})") + endif() endif() + endif() + if(ABACUS_ELPA_VERSION STREQUAL "yes (version unknown)" AND ELPA_DIR) + set(ABACUS_ELPA_VERSION "yes (path: ${ELPA_DIR})") + endif() else() - set(ABACUS_ELPA_VERSION "no") + set(ABACUS_ELPA_VERSION "no") endif() if(MKLROOT) - set(ABACUS_MKL_SUPPORT "yes (version unknown)") - find_path(MKL_VERSION_HEADER mkl_version.h PATHS ${MKL_INCLUDE} NO_DEFAULT_PATH) - if(MKL_VERSION_HEADER) - file(STRINGS "${MKL_VERSION_HEADER}" MKL_VERSION_LINE REGEX "^#define INTEL_MKL_VERSION [0-9]+") - string(REGEX REPLACE "^#define INTEL_MKL_VERSION ([0-9]+)" "\\1" MKL_VER_NUM "${MKL_VERSION_LINE}") - if(MKL_VER_NUM) - math(EXPR MKL_MAJOR "${MKL_VER_NUM} / 10000") - math(EXPR MKL_MINOR "(${MKL_VER_NUM} % 10000) / 100") - math(EXPR MKL_PATCH "${MKL_VER_NUM} % 100") - set(ABACUS_MKL_SUPPORT "yes (v${MKL_MAJOR}.${MKL_MINOR}.${MKL_PATCH})") - endif() + set(ABACUS_MKL_SUPPORT "yes (version unknown)") + find_path( + MKL_VERSION_HEADER mkl_version.h + PATHS ${MKL_INCLUDE} + NO_DEFAULT_PATH) + if(MKL_VERSION_HEADER) + file(STRINGS "${MKL_VERSION_HEADER}" MKL_VERSION_LINE + REGEX "^#define INTEL_MKL_VERSION [0-9]+") + string(REGEX REPLACE "^#define INTEL_MKL_VERSION ([0-9]+)" "\\1" + MKL_VER_NUM "${MKL_VERSION_LINE}") + if(MKL_VER_NUM) + math(EXPR MKL_MAJOR "${MKL_VER_NUM} / 10000") + math(EXPR MKL_MINOR "(${MKL_VER_NUM} % 10000) / 100") + math(EXPR MKL_PATCH "${MKL_VER_NUM} % 100") + set(ABACUS_MKL_SUPPORT "yes (v${MKL_MAJOR}.${MKL_MINOR}.${MKL_PATCH})") endif() + endif() else() - set(ABACUS_MKL_SUPPORT "no") + set(ABACUS_MKL_SUPPORT "no") endif() if(ENABLE_LIBXC AND Libxc_VERSION) - set(ABACUS_LIBXC_VERSION "yes (v${Libxc_VERSION})") + set(ABACUS_LIBXC_VERSION "yes (v${Libxc_VERSION})") elseif(ENABLE_LIBXC) - set(ABACUS_LIBXC_VERSION "yes (path: ${Libxc_DIR})") + set(ABACUS_LIBXC_VERSION "yes (path: ${Libxc_DIR})") else() - set(ABACUS_LIBXC_VERSION "no") + set(ABACUS_LIBXC_VERSION "no") endif() -if(NOT USE_SW AND NOT MKLROOT AND FFTW3_VERSION) - set(ABACUS_FFTW_VERSION "yes (v${FFTW3_VERSION})") +if(NOT USE_SW + AND NOT MKLROOT + AND FFTW3_VERSION) + set(ABACUS_FFTW_VERSION "yes (v${FFTW3_VERSION})") elseif(NOT USE_SW AND NOT MKLROOT) - if(FFTW3_INCLUDE_DIR AND EXISTS "${FFTW3_INCLUDE_DIR}/fftw3.h") - file(STRINGS "${FFTW3_INCLUDE_DIR}/fftw3.h" _fftw_ver_line REGEX "^#define[\t ]+FFTW_VERSION[\t ]+\"[^\"]+\"") - if(_fftw_ver_line) - string(REGEX REPLACE "^#define[\t ]+FFTW_VERSION[\t ]+\"([^\"]+)\"" "\\1" FFTW3_VERSION "${_fftw_ver_line}") - set(ABACUS_FFTW_VERSION "yes (v${FFTW3_VERSION})") - else() - set(ABACUS_FFTW_VERSION "yes (version unknown)") - endif() + if(FFTW3_INCLUDE_DIR AND EXISTS "${FFTW3_INCLUDE_DIR}/fftw3.h") + file(STRINGS "${FFTW3_INCLUDE_DIR}/fftw3.h" _fftw_ver_line + REGEX "^#define[\t ]+FFTW_VERSION[\t ]+\"[^\"]+\"") + if(_fftw_ver_line) + string(REGEX REPLACE "^#define[\t ]+FFTW_VERSION[\t ]+\"([^\"]+)\"" "\\1" + FFTW3_VERSION "${_fftw_ver_line}") + set(ABACUS_FFTW_VERSION "yes (v${FFTW3_VERSION})") else() - set(ABACUS_FFTW_VERSION "yes (version unknown)") + set(ABACUS_FFTW_VERSION "yes (version unknown)") endif() + else() + set(ABACUS_FFTW_VERSION "yes (version unknown)") + endif() else() - set(ABACUS_FFTW_VERSION "no (using MKL or SW)") + set(ABACUS_FFTW_VERSION "no (using MKL or SW)") endif() # Cereal Version (Enhanced) if(ENABLE_LCAO) - set(ABACUS_CEREAL_VERSION "yes (version unknown)") - if(NOT CEREAL_INCLUDE_DIR) - find_path(CEREAL_INCLUDE_DIR cereal/version.hpp) - endif() - if(CEREAL_INCLUDE_DIR AND EXISTS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp") - file(STRINGS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp" CEREAL_MAJOR_LINE REGEX "^#define CEREAL_VERSION_MAJOR") - file(STRINGS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp" CEREAL_MINOR_LINE REGEX "^#define CEREAL_VERSION_MINOR") - file(STRINGS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp" CEREAL_PATCH_LINE REGEX "^#define CEREAL_VERSION_PATCH") - string(REGEX REPLACE "^#define CEREAL_VERSION_MAJOR +([0-9]+).*" "\\1" CEREAL_MAJOR "${CEREAL_MAJOR_LINE}") - string(REGEX REPLACE "^#define CEREAL_VERSION_MINOR +([0-9]+).*" "\\1" CEREAL_MINOR "${CEREAL_MINOR_LINE}") - string(REGEX REPLACE "^#define CEREAL_VERSION_PATCH +([0-9]+).*" "\\1" CEREAL_PATCH "${CEREAL_PATCH_LINE}") - if(CEREAL_MAJOR AND CEREAL_MINOR AND CEREAL_PATCH) - set(ABACUS_CEREAL_VERSION "yes (v${CEREAL_MAJOR}.${CEREAL_MINOR}.${CEREAL_PATCH})") - endif() - endif() - if(ABACUS_CEREAL_VERSION STREQUAL "yes (version unknown)" AND CEREAL_INCLUDE_DIR) - set(ABACUS_CEREAL_VERSION "yes (path: ${CEREAL_INCLUDE_DIR})") + set(ABACUS_CEREAL_VERSION "yes (version unknown)") + if(NOT CEREAL_INCLUDE_DIR) + find_path(CEREAL_INCLUDE_DIR cereal/version.hpp) + endif() + if(CEREAL_INCLUDE_DIR AND EXISTS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp") + file(STRINGS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp" CEREAL_MAJOR_LINE + REGEX "^#define CEREAL_VERSION_MAJOR") + file(STRINGS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp" CEREAL_MINOR_LINE + REGEX "^#define CEREAL_VERSION_MINOR") + file(STRINGS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp" CEREAL_PATCH_LINE + REGEX "^#define CEREAL_VERSION_PATCH") + string(REGEX REPLACE "^#define CEREAL_VERSION_MAJOR +([0-9]+).*" "\\1" + CEREAL_MAJOR "${CEREAL_MAJOR_LINE}") + string(REGEX REPLACE "^#define CEREAL_VERSION_MINOR +([0-9]+).*" "\\1" + CEREAL_MINOR "${CEREAL_MINOR_LINE}") + string(REGEX REPLACE "^#define CEREAL_VERSION_PATCH +([0-9]+).*" "\\1" + CEREAL_PATCH "${CEREAL_PATCH_LINE}") + if(CEREAL_MAJOR + AND CEREAL_MINOR + AND CEREAL_PATCH) + set(ABACUS_CEREAL_VERSION + "yes (v${CEREAL_MAJOR}.${CEREAL_MINOR}.${CEREAL_PATCH})") endif() + endif() + if(ABACUS_CEREAL_VERSION STREQUAL "yes (version unknown)" + AND CEREAL_INCLUDE_DIR) + set(ABACUS_CEREAL_VERSION "yes (path: ${CEREAL_INCLUDE_DIR})") + endif() else() - set(ABACUS_CEREAL_VERSION "no") + set(ABACUS_CEREAL_VERSION "no") endif() # Accelerators if(USE_CUDA AND CUDAToolkit_VERSION) - set(ABACUS_CUDA_VERSION "yes (v${CUDAToolkit_VERSION})") + set(ABACUS_CUDA_VERSION "yes (v${CUDAToolkit_VERSION})") elseif(USE_CUDA) - set(ABACUS_CUDA_VERSION "yes (version unknown)") + set(ABACUS_CUDA_VERSION "yes (version unknown)") else() - set(ABACUS_CUDA_VERSION "no") + set(ABACUS_CUDA_VERSION "no") endif() if(USE_ROCM) - set(ABACUS_ROCM_VERSION "yes (version unknown)") - if(HIP_VERSION) + set(ABACUS_ROCM_VERSION "yes (version unknown)") + if(HIP_VERSION) set(ABACUS_ROCM_VERSION "yes (v${HIP_VERSION})") - else() - find_program(HIPCC_EXECUTABLE hipcc) - if(HIPCC_EXECUTABLE) - execute_process(COMMAND ${HIPCC_EXECUTABLE} --version OUTPUT_VARIABLE HIPCC_VERSION_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) - string(REGEX MATCH "HIP version: ([0-9]+\\.[0-9]+\\.[0-9]+)" _ "${HIPCC_VERSION_OUTPUT}") - if(CMAKE_MATCH_1) - set(ABACUS_ROCM_VERSION "yes (v${CMAKE_MATCH_1})") -endif() - endif() - endif() - if(ABACUS_ROCM_VERSION STREQUAL "yes (version unknown)" AND ROCM_PATH) - set(ABACUS_ROCM_VERSION "yes (path: ${ROCM_PATH})") + else() + find_program(HIPCC_EXECUTABLE hipcc) + if(HIPCC_EXECUTABLE) + execute_process( + COMMAND ${HIPCC_EXECUTABLE} --version + OUTPUT_VARIABLE HIPCC_VERSION_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + string(REGEX MATCH "HIP version: ([0-9]+\\.[0-9]+\\.[0-9]+)" _ + "${HIPCC_VERSION_OUTPUT}") + if(CMAKE_MATCH_1) + set(ABACUS_ROCM_VERSION "yes (v${CMAKE_MATCH_1})") + endif() endif() + endif() + if(ABACUS_ROCM_VERSION STREQUAL "yes (version unknown)" AND ROCM_PATH) + set(ABACUS_ROCM_VERSION "yes (path: ${ROCM_PATH})") + endif() else() - set(ABACUS_ROCM_VERSION "no") + set(ABACUS_ROCM_VERSION "no") endif() if(DEFINED CAL_CUSOLVERMP_PATH AND ENABLE_CUSOLVERMP) - set(ABACUS_CUSOLVERMP_VERSION "yes (path: ${CAL_CUSOLVERMP_PATH})") + set(ABACUS_CUSOLVERMP_VERSION "yes (path: ${CAL_CUSOLVERMP_PATH})") elseif(ENABLE_CUSOLVERMP) - set(ABACUS_CUSOLVERMP_VERSION "yes (version unknown)") + set(ABACUS_CUSOLVERMP_VERSION "yes (version unknown)") else() - set(ABACUS_CUSOLVERMP_VERSION "no") + set(ABACUS_CUSOLVERMP_VERSION "no") endif() # EXX Libraries if(ENABLE_LIBRI) - set(ABACUS_LIBRI_VERSION "yes (version unknown)") - set(LIBRI_VERSION_HEADER "${LIBRI_DIR}/include/RI/version.h") - if(EXISTS ${LIBRI_VERSION_HEADER}) - file(STRINGS "${LIBRI_VERSION_HEADER}" LIBRI_MAJOR_LINE REGEX "__LIBRI_VERSION_MAJOR") - file(STRINGS "${LIBRI_VERSION_HEADER}" LIBRI_MINOR_LINE REGEX "__LIBRI_VERSION_MINOR") - file(STRINGS "${LIBRI_VERSION_HEADER}" LIBRI_PATCH_LINE REGEX "__LIBRI_VERSION_PATCH") - string(REGEX MATCH "([0-9]+)" LIBRI_MAJOR "${LIBRI_MAJOR_LINE}") - string(REGEX MATCH "([0-9]+)" LIBRI_MINOR "${LIBRI_MINOR_LINE}") - string(REGEX MATCH "([0-9]+)" LIBRI_PATCH "${LIBRI_PATCH_LINE}") - if(LIBRI_MAJOR AND LIBRI_MINOR AND LIBRI_PATCH) - set(ABACUS_LIBRI_VERSION "yes (v${LIBRI_MAJOR}.${LIBRI_MINOR}.${LIBRI_PATCH})") - endif() - endif() - if(ABACUS_LIBRI_VERSION STREQUAL "yes (version unknown)" AND LIBRI_DIR) - set(ABACUS_LIBRI_VERSION "yes (path: ${LIBRI_DIR})") + set(ABACUS_LIBRI_VERSION "yes (version unknown)") + set(LIBRI_VERSION_HEADER "${LIBRI_DIR}/include/RI/version.h") + if(EXISTS ${LIBRI_VERSION_HEADER}) + file(STRINGS "${LIBRI_VERSION_HEADER}" LIBRI_MAJOR_LINE + REGEX "__LIBRI_VERSION_MAJOR") + file(STRINGS "${LIBRI_VERSION_HEADER}" LIBRI_MINOR_LINE + REGEX "__LIBRI_VERSION_MINOR") + file(STRINGS "${LIBRI_VERSION_HEADER}" LIBRI_PATCH_LINE + REGEX "__LIBRI_VERSION_PATCH") + string(REGEX MATCH "([0-9]+)" LIBRI_MAJOR "${LIBRI_MAJOR_LINE}") + string(REGEX MATCH "([0-9]+)" LIBRI_MINOR "${LIBRI_MINOR_LINE}") + string(REGEX MATCH "([0-9]+)" LIBRI_PATCH "${LIBRI_PATCH_LINE}") + if(LIBRI_MAJOR + AND LIBRI_MINOR + AND LIBRI_PATCH) + set(ABACUS_LIBRI_VERSION + "yes (v${LIBRI_MAJOR}.${LIBRI_MINOR}.${LIBRI_PATCH})") endif() + endif() + if(ABACUS_LIBRI_VERSION STREQUAL "yes (version unknown)" AND LIBRI_DIR) + set(ABACUS_LIBRI_VERSION "yes (path: ${LIBRI_DIR})") + endif() else() - set(ABACUS_LIBRI_VERSION "no") + set(ABACUS_LIBRI_VERSION "no") endif() if(ENABLE_LIBCOMM AND LIBCOMM_DIR) - set(ABACUS_LIBCOMM_VERSION "yes (path: ${LIBCOMM_DIR})") + set(ABACUS_LIBCOMM_VERSION "yes (path: ${LIBCOMM_DIR})") elseif(ENABLE_LIBCOMM) - set(ABACUS_LIBCOMM_VERSION "yes (version unknown)") + set(ABACUS_LIBCOMM_VERSION "yes (version unknown)") else() - set(ABACUS_LIBCOMM_VERSION "no") + set(ABACUS_LIBCOMM_VERSION "no") endif() # ML & AI Libraries if((DEFINED Torch_DIR OR ENABLE_MLALGO) AND Torch_VERSION) - set(ABACUS_LIBTORCH_VERSION "yes (v${Torch_VERSION})") + set(ABACUS_LIBTORCH_VERSION "yes (v${Torch_VERSION})") elseif(DEFINED Torch_DIR OR ENABLE_MLALGO) - set(ABACUS_LIBTORCH_VERSION "yes (path: ${Torch_DIR})") + set(ABACUS_LIBTORCH_VERSION "yes (path: ${Torch_DIR})") else() - set(ABACUS_LIBTORCH_VERSION "no") + set(ABACUS_LIBTORCH_VERSION "no") endif() if(DEFINED DeePMD_DIR) - set(ABACUS_DEEPMD_VERSION "yes (version unknown)") - set(DEEPMD_VERSION_HEADER "${DeePMD_DIR}/include/deepmd/version.h") - if(EXISTS ${DEEPMD_VERSION_HEADER}) - file(STRINGS "${DEEPMD_VERSION_HEADER}" DEEPMD_VERSION_LINE REGEX "global_install_prefix") - if(DEEPMD_VERSION_LINE) - string(REGEX MATCH "global_install_prefix=\".*deepmd-kit-([0-9]+\\.[0-9]+\\.[0-9]+)\"" _ "${DEEPMD_VERSION_LINE}") - if(CMAKE_MATCH_1) - set(ABACUS_DEEPMD_VERSION "yes (v${CMAKE_MATCH_1})") -endif() - endif() - endif() - if(ABACUS_DEEPMD_VERSION STREQUAL "yes (version unknown)") - set(ABACUS_DEEPMD_VERSION "yes (path: ${DeePMD_DIR})") + set(ABACUS_DEEPMD_VERSION "yes (version unknown)") + set(DEEPMD_VERSION_HEADER "${DeePMD_DIR}/include/deepmd/version.h") + if(EXISTS ${DEEPMD_VERSION_HEADER}) + file(STRINGS "${DEEPMD_VERSION_HEADER}" DEEPMD_VERSION_LINE + REGEX "global_install_prefix") + if(DEEPMD_VERSION_LINE) + string( + REGEX + MATCH + "global_install_prefix=\".*deepmd-kit-([0-9]+\\.[0-9]+\\.[0-9]+)\"" _ + "${DEEPMD_VERSION_LINE}") + if(CMAKE_MATCH_1) + set(ABACUS_DEEPMD_VERSION "yes (v${CMAKE_MATCH_1})") + endif() endif() + endif() + if(ABACUS_DEEPMD_VERSION STREQUAL "yes (version unknown)") + set(ABACUS_DEEPMD_VERSION "yes (path: ${DeePMD_DIR})") + endif() else() - set(ABACUS_DEEPMD_VERSION "no") + set(ABACUS_DEEPMD_VERSION "no") endif() if(DEFINED NEP_DIR AND NEP_VERSION) - set(ABACUS_NEP_VERSION "yes (v${NEP_VERSION})") + set(ABACUS_NEP_VERSION "yes (v${NEP_VERSION})") elseif(DEFINED NEP_DIR) - set(ABACUS_NEP_VERSION "yes (path: ${NEP_DIR})") + set(ABACUS_NEP_VERSION "yes (path: ${NEP_DIR})") else() - set(ABACUS_NEP_VERSION "no") + set(ABACUS_NEP_VERSION "no") endif() if(DEFINED TensorFlow_DIR) - set(ABACUS_TENSORFLOW_VERSION "yes (path: ${TensorFlow_DIR})") + set(ABACUS_TENSORFLOW_VERSION "yes (path: ${TensorFlow_DIR})") else() - set(ABACUS_TENSORFLOW_VERSION "no") + set(ABACUS_TENSORFLOW_VERSION "no") endif() # Testing & Other Libraries if(BUILD_TESTING) - set(ABACUS_GTEST_VERSION "yes (from git origin/main)") + set(ABACUS_GTEST_VERSION "yes (from git origin/main)") else() - set(ABACUS_GTEST_VERSION "no") + set(ABACUS_GTEST_VERSION "no") endif() if(ENABLE_GOOGLEBENCH) - set(ABACUS_GOOGLEBENCH_VERSION "yes (from git origin/main)") + set(ABACUS_GOOGLEBENCH_VERSION "yes (from git origin/main)") else() - set(ABACUS_GOOGLEBENCH_VERSION "no") + set(ABACUS_GOOGLEBENCH_VERSION "no") endif() if(DEFINED RapidJSON_DIR AND ENABLE_RAPIDJSON) - set(ABACUS_RAPIDJSON_VERSION "yes (path: ${RapidJSON_DIR})") + set(ABACUS_RAPIDJSON_VERSION "yes (path: ${RapidJSON_DIR})") elseif(ENABLE_RAPIDJSON) - set(ABACUS_RAPIDJSON_VERSION "yes (from git origin/master)") + set(ABACUS_RAPIDJSON_VERSION "yes (from git origin/master)") else() - set(ABACUS_RAPIDJSON_VERSION "no") + set(ABACUS_RAPIDJSON_VERSION "no") endif() if(ENABLE_MLALGO) - set(ABACUS_LIBNPY_VERSION "yes (path: ${libnpy_SOURCE_DIR})") + set(ABACUS_LIBNPY_VERSION "yes (path: ${libnpy_SOURCE_DIR})") else() - set(ABACUS_LIBNPY_VERSION "no") + set(ABACUS_LIBNPY_VERSION "no") endif() if(ENABLE_PEXSI) - set(ABACUS_PEXSI_VERSION "yes (version unknown)") - if(PEXSI_VERSION) + set(ABACUS_PEXSI_VERSION "yes (version unknown)") + if(PEXSI_VERSION) set(ABACUS_PEXSI_VERSION "yes (v${PEXSI_VERSION})") - elseif(PEXSI_DIR) + elseif(PEXSI_DIR) set(ABACUS_PEXSI_VERSION "yes (path: ${PEXSI_DIR})") - endif() + endif() else() - set(ABACUS_PEXSI_VERSION "no") + set(ABACUS_PEXSI_VERSION "no") endif() if(ENABLE_CNPY) - set(ABACUS_CNPY_VERSION "yes (path: ${cnpy_SOURCE_DIR})") + set(ABACUS_CNPY_VERSION "yes (path: ${cnpy_SOURCE_DIR})") else() - set(ABACUS_CNPY_VERSION "no") + set(ABACUS_CNPY_VERSION "no") endif() # --- 5. Collect CMake Configuration Summary --- @@ -399,7 +457,7 @@ list(APPEND CMAKE_OPTIONS_LIST " ENABLE_MLALGO=${ENABLE_MLALGO}") list(APPEND CMAKE_OPTIONS_LIST " ENABLE_ASAN=${ENABLE_ASAN}") list(APPEND CMAKE_OPTIONS_LIST " BUILD_TESTING=${BUILD_TESTING}") foreach(option_line ${CMAKE_OPTIONS_LIST}) - set(ABACUS_CMAKE_OPTIONS "${ABACUS_CMAKE_OPTIONS}${option_line}") + set(ABACUS_CMAKE_OPTIONS "${ABACUS_CMAKE_OPTIONS}${option_line}") endforeach() set(ABACUS_CMAKE_FIND_PACKAGES "FindPackage Results:") @@ -412,5 +470,5 @@ list(APPEND CMAKE_FIND_PACKAGES_LIST " Libxc Found=${Libxc_FOUND}") list(APPEND CMAKE_FIND_PACKAGES_LIST " PEXSI Found=${PEXSI_FOUND}") list(APPEND CMAKE_FIND_PACKAGES_LIST " LibRI Found=${LIBRI_FOUND}") foreach(package_line ${CMAKE_FIND_PACKAGES_LIST}) - set(ABACUS_CMAKE_FIND_PACKAGES "${ABACUS_CMAKE_FIND_PACKAGES}${package_line}") + set(ABACUS_CMAKE_FIND_PACKAGES "${ABACUS_CMAKE_FIND_PACKAGES}${package_line}") endforeach() diff --git a/cmake/FindBlas.cmake b/cmake/FindBlas.cmake index a3c7f75069d..044ac93afa1 100644 --- a/cmake/FindBlas.cmake +++ b/cmake/FindBlas.cmake @@ -1,15 +1,15 @@ if(DEFINED BLAS_DIR) - string(APPEND CMAKE_PREFIX_PATH ";${BLAS_DIR}") + string(APPEND CMAKE_PREFIX_PATH ";${BLAS_DIR}") endif() if(DEFINED BLAS_LIBRARY) - set(BLAS_LIBRARIES ${BLAS_LIBRARY}) + set(BLAS_LIBRARIES ${BLAS_LIBRARY}) endif() find_package(BLAS REQUIRED) if(NOT TARGET BLAS::BLAS) - add_library(BLAS::BLAS UNKNOWN IMPORTED) - set_target_properties(BLAS::BLAS PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${BLAS_LIBRARIES}") + add_library(BLAS::BLAS UNKNOWN IMPORTED) + set_target_properties( + BLAS::BLAS PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${BLAS_LIBRARIES}") endif() diff --git a/cmake/FindCereal.cmake b/cmake/FindCereal.cmake index 204a1233f24..fafaa6cd909 100644 --- a/cmake/FindCereal.cmake +++ b/cmake/FindCereal.cmake @@ -1,27 +1,23 @@ -############################################################################### -# - Find cereal -# Find the native cereal headers. +# ############################################################################## +# * Find cereal Find the native cereal headers. # -# CEREAL_FOUND - True if cereal is found. -# CEREAL_INCLUDE_DIR - Where to find cereal headers. +# CEREAL_FOUND - True if cereal is found. CEREAL_INCLUDE_DIR - Where to find +# cereal headers. -find_path(CEREAL_INCLUDE_DIR - cereal/cereal.hpp - HINTS ${CEREAL_INCLUDE_DIR} - HINTS ${Cereal_INCLUDE_DIR} -) +find_path( + CEREAL_INCLUDE_DIR cereal/cereal.hpp + HINTS ${CEREAL_INCLUDE_DIR} + HINTS ${Cereal_INCLUDE_DIR}) if(NOT CEREAL_INCLUDE_DIR) - include(FetchContent) - FetchContent_Declare( - cereal - URL https://codeload.github.com/USCiLab/cereal/tar.gz/22a1b36 - ) - FetchContent_Populate(cereal) - set(CEREAL_INCLUDE_DIR ${cereal_SOURCE_DIR}/include) + include(FetchContent) + FetchContent_Declare( + cereal URL https://codeload.github.com/USCiLab/cereal/tar.gz/22a1b36) + FetchContent_Populate(cereal) + set(CEREAL_INCLUDE_DIR ${cereal_SOURCE_DIR}/include) endif() -# Handle the QUIET and REQUIRED arguments and -# set Cereal_FOUND to TRUE if all variables are non-zero. +# Handle the QUIET and REQUIRED arguments and set Cereal_FOUND to TRUE if all +# variables are non-zero. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Cereal DEFAULT_MSG CEREAL_INCLUDE_DIR) diff --git a/cmake/FindDeePMD.cmake b/cmake/FindDeePMD.cmake index 50563799216..bb987f4ca4b 100644 --- a/cmake/FindDeePMD.cmake +++ b/cmake/FindDeePMD.cmake @@ -1,65 +1,64 @@ -############################################################################### -# - Find DeePMD -# Find the native DeePMD headers and libraries. +# ############################################################################## +# * Find DeePMD Find the native DeePMD headers and libraries. # -# DeePMD_FOUND - True if lib is found. -# DeePMDC_FOUND - True if C API is found. -# DeePMD_LIBRARIES - List of libraries -# DeePMD_INCLUDE_DIR - Where to find DeePMD headers. +# DeePMD_FOUND - True if lib is found. DeePMDC_FOUND - True if C +# API is found. DeePMD_LIBRARIES - List of libraries DeePMD_INCLUDE_DIR - +# Where to find DeePMD headers. # # C API -find_path(DeePMD_INCLUDE_C_DIR - deepmd/deepmd.hpp - deepmd/c_api.h - HINTS ${DeePMD_DIR} - PATH_SUFFIXES "include" - ) -find_library(deepmd_c - NAMES deepmd_c - HINTS ${DeePMD_DIR} - PATH_SUFFIXES "lib" - ) +find_path( + DeePMD_INCLUDE_C_DIR deepmd/deepmd.hpp deepmd/c_api.h + HINTS ${DeePMD_DIR} + PATH_SUFFIXES "include") +find_library( + deepmd_c + NAMES deepmd_c + HINTS ${DeePMD_DIR} + PATH_SUFFIXES "lib") # C++ API -find_path(DeePMD_INCLUDE_DIR - deepmd/DeepPot.h - HINTS ${DeePMD_DIR} - PATH_SUFFIXES "include" - ) -find_library(deepmd_cc - NAMES deepmd_cc - HINTS ${DeePMD_DIR} - PATH_SUFFIXES "lib" - ) +find_path( + DeePMD_INCLUDE_DIR deepmd/DeepPot.h + HINTS ${DeePMD_DIR} + PATH_SUFFIXES "include") +find_library( + deepmd_cc + NAMES deepmd_cc + HINTS ${DeePMD_DIR} + PATH_SUFFIXES "lib") -# Handle the QUIET and REQUIRED arguments and -# set DeePMD_FOUND to TRUE if all variables are non-zero. +# Handle the QUIET and REQUIRED arguments and set DeePMD_FOUND to TRUE if all +# variables are non-zero. include(FindPackageHandleStandardArgs) -if (DeePMD_INCLUDE_C_DIR) - find_package_handle_standard_args(DeePMD DEFAULT_MSG deepmd_c DeePMD_INCLUDE_C_DIR) - if (DeePMD_FOUND) - set(DeePMDC_FOUND TRUE) - set(DeePMD_INCLUDE_DIR ${DeePMD_INCLUDE_C_DIR}) - if(NOT TARGET DeePMD::deepmd_c) - add_library(DeePMD::deepmd_c UNKNOWN IMPORTED) - set_target_properties(DeePMD::deepmd_c PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${deepmd_c}" - INTERFACE_INCLUDE_DIRECTORIES "${DeePMD_INCLUDE_DIR}") - endif() +if(DeePMD_INCLUDE_C_DIR) + find_package_handle_standard_args(DeePMD DEFAULT_MSG deepmd_c + DeePMD_INCLUDE_C_DIR) + if(DeePMD_FOUND) + set(DeePMDC_FOUND TRUE) + set(DeePMD_INCLUDE_DIR ${DeePMD_INCLUDE_C_DIR}) + if(NOT TARGET DeePMD::deepmd_c) + add_library(DeePMD::deepmd_c UNKNOWN IMPORTED) + set_target_properties( + DeePMD::deepmd_c + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${deepmd_c}" + INTERFACE_INCLUDE_DIRECTORIES "${DeePMD_INCLUDE_DIR}") endif() + endif() else() - find_package_handle_standard_args(DeePMD DEFAULT_MSG deepmd_cc DeePMD_INCLUDE_DIR) - if(DeePMD_FOUND) - set(DeePMD_INCLUDE_DIR ${DeePMD_INCLUDE_DIR}) - if(NOT TARGET DeePMD::deepmd_cc) - add_library(DeePMD::deepmd_cc UNKNOWN IMPORTED) - set_target_properties(DeePMD::deepmd_cc PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${deepmd_cc}" - INTERFACE_INCLUDE_DIRECTORIES "${DeePMD_INCLUDE_DIR}") - endif() + find_package_handle_standard_args(DeePMD DEFAULT_MSG deepmd_cc + DeePMD_INCLUDE_DIR) + if(DeePMD_FOUND) + set(DeePMD_INCLUDE_DIR ${DeePMD_INCLUDE_DIR}) + if(NOT TARGET DeePMD::deepmd_cc) + add_library(DeePMD::deepmd_cc UNKNOWN IMPORTED) + set_target_properties( + DeePMD::deepmd_cc + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${deepmd_cc}" + INTERFACE_INCLUDE_DIRECTORIES "${DeePMD_INCLUDE_DIR}") endif() + endif() endif() set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${DeePMD_INCLUDE_DIR}) diff --git a/cmake/FindELPA.cmake b/cmake/FindELPA.cmake index 75689a73641..6414a966f86 100644 --- a/cmake/FindELPA.cmake +++ b/cmake/FindELPA.cmake @@ -1,10 +1,8 @@ -############################################################################### -# - Find ELPA -# Find the native ELPA headers and libraries. +# ############################################################################## +# * Find ELPA Find the native ELPA headers and libraries. # -# ELPA_FOUND - True if libelpa is found. -# ELPA_LIBRARIES - List of libraries when using libyaml -# ELPA_INCLUDE_DIR - Where to find ELPA headers. +# ELPA_FOUND - True if libelpa is found. ELPA_LIBRARIES - List of +# libraries when using libyaml ELPA_INCLUDE_DIR - Where to find ELPA headers. # find_package(PkgConfig) @@ -17,13 +15,11 @@ if(DEFINED ELPA_LIBRARIES) set(ELPA_LINK_LIBRARIES ${ELPA_LIBRARIES}) endif() -find_path(ELPA_INCLUDE_DIRS - elpa/elpa.h - HINTS ${ELPA_DIR} - PATH_SUFFIXES "include" "include/elpa" - ) -# Fix #3589 -# First if judges if ELPA dir specified +find_path( + ELPA_INCLUDE_DIRS elpa/elpa.h + HINTS ${ELPA_DIR} + PATH_SUFFIXES "include" "include/elpa") +# Fix #3589 First if judges if ELPA dir specified if(ELPA_INCLUDE_DIRS MATCHES "^/usr/include/elpa/.*") # Second if judges if global visible ELPA header found if(DEFINED ELPA_DIR OR CMAKE_PREFIX_PATH MATCHES ".*elpa.*") @@ -31,22 +27,21 @@ if(ELPA_INCLUDE_DIRS MATCHES "^/usr/include/elpa/.*") endif() endif() if(USE_OPENMP) - find_library(ELPA_LINK_LIBRARIES + find_library( + ELPA_LINK_LIBRARIES NAMES elpa_openmp elpa HINTS ${ELPA_DIR} - PATH_SUFFIXES "lib" - ) + PATH_SUFFIXES "lib") else() - find_library(ELPA_LINK_LIBRARIES + find_library( + ELPA_LINK_LIBRARIES NAMES elpa HINTS ${ELPA_DIR} - PATH_SUFFIXES "lib" - ) + PATH_SUFFIXES "lib") endif() -# Incompatible with ELPA earlier than 2021.11.001 -# Before ELPA 2021.11.001, its pkg-config file -# is named like "elpa-2021.05.002.pc". +# Incompatible with ELPA earlier than 2021.11.001 Before ELPA 2021.11.001, its +# pkg-config file is named like "elpa-2021.05.002.pc". if(NOT ELPA_INCLUDE_DIRS AND PKG_CONFIG_FOUND) if(DEFINED ELPA_DIR) string(APPEND CMAKE_PREFIX_PATH ";${ELPA_DIR}") @@ -57,43 +52,47 @@ if(NOT ELPA_INCLUDE_DIRS AND PKG_CONFIG_FOUND) pkg_search_module(ELPA REQUIRED IMPORTED_TARGET GLOBAL elpa) endif() elseif(NOT PKG_CONFIG_FOUND) - message(STATUS - "ELPA : We need pkg-config to get all information about the elpa library") + message( + STATUS + "ELPA : We need pkg-config to get all information about the elpa library") endif() -# Handle the QUIET and REQUIRED arguments and -# set ELPA_FOUND to TRUE if all variables are non-zero. +# Handle the QUIET and REQUIRED arguments and set ELPA_FOUND to TRUE if all +# variables are non-zero. include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(ELPA DEFAULT_MSG ELPA_LINK_LIBRARIES ELPA_INCLUDE_DIRS) +find_package_handle_standard_args(ELPA DEFAULT_MSG ELPA_LINK_LIBRARIES + ELPA_INCLUDE_DIRS) # Copy the results to the output variables and target. if(ELPA_FOUND) - list(GET ELPA_LINK_LIBRARIES 0 ELPA_LIBRARY) - set(ELPA_INCLUDE_DIR ${ELPA_INCLUDE_DIRS}) + list(GET ELPA_LINK_LIBRARIES 0 ELPA_LIBRARY) + set(ELPA_INCLUDE_DIR ${ELPA_INCLUDE_DIRS}) - if(NOT TARGET ELPA::ELPA) - add_library(ELPA::ELPA UNKNOWN IMPORTED) - set_target_properties(ELPA::ELPA PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${ELPA_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${ELPA_INCLUDE_DIR}") - endif() + if(NOT TARGET ELPA::ELPA) + add_library(ELPA::ELPA UNKNOWN IMPORTED) + set_target_properties( + ELPA::ELPA + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${ELPA_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${ELPA_INCLUDE_DIR}") + endif() endif() set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${ELPA_INCLUDE_DIR}) include(CheckCXXSourceCompiles) -check_cxx_source_compiles(" +check_cxx_source_compiles( + " #include #if ELPA_API_VERSION < 20210430 #error ELPA version is too old. #endif int main(){} " -ELPA_VERSION_SATISFIES -) + ELPA_VERSION_SATISFIES) if(NOT ELPA_VERSION_SATISFIES) - message(FATAL_ERROR "ELPA version is too old. We support version 2021 or higher.") + message( + FATAL_ERROR "ELPA version is too old. We support version 2021 or higher.") endif() mark_as_advanced(ELPA_INCLUDE_DIR ELPA_LIBRARY) diff --git a/cmake/FindFFTW3.cmake b/cmake/FindFFTW3.cmake index b79f97013ca..e6da3deceaa 100644 --- a/cmake/FindFFTW3.cmake +++ b/cmake/FindFFTW3.cmake @@ -1,85 +1,91 @@ -# - Find FFTW3 -# Find the native double precision FFTW3 headers and libraries. +# * Find FFTW3 Find the native double precision FFTW3 headers and libraries. # -# FFTW3_INCLUDE_DIRS - Where to find FFTW3 headers. -# FFTW3_LIBRARIES - List of libraries when using FFTW3. -# FFTW3_FOUND - True if FFTW3 is found. +# FFTW3_INCLUDE_DIRS - Where to find FFTW3 headers. FFTW3_LIBRARIES - List +# of libraries when using FFTW3. FFTW3_FOUND - True if FFTW3 is found. # -find_path(FFTW3_INCLUDE_DIR - NAMES fftw3.h - HINTS ${FFTW3_DIR} - PATH_SUFFIXES "include" - ) -find_library(FFTW3_LIBRARY - NAMES fftw3 - HINTS ${FFTW3_DIR} - PATH_SUFFIXES "lib" - ) -find_library(FFTW3_FLOAT_LIBRARY - NAMES fftw3f - HINTS ${FFTW3_DIR} - PATH_SUFFIXES "lib" - ) +find_path( + FFTW3_INCLUDE_DIR + NAMES fftw3.h + HINTS ${FFTW3_DIR} + PATH_SUFFIXES "include") +find_library( + FFTW3_LIBRARY + NAMES fftw3 + HINTS ${FFTW3_DIR} + PATH_SUFFIXES "lib") +find_library( + FFTW3_FLOAT_LIBRARY + NAMES fftw3f + HINTS ${FFTW3_DIR} + PATH_SUFFIXES "lib") # both libfftw3.so and libfftw3_omp.so should be link in multi-thread term -if (USE_OPENMP) -find_library(FFTW3_OMP_LIBRARY +if(USE_OPENMP) + find_library( + FFTW3_OMP_LIBRARY NAMES fftw3_omp HINTS ${FFTW3_DIR} - PATH_SUFFIXES "lib" - ) + PATH_SUFFIXES "lib") endif() -# Handle the QUIET and REQUIRED arguments and -# set FFTW3_FOUND to TRUE if all variables are non-zero. +# Handle the QUIET and REQUIRED arguments and set FFTW3_FOUND to TRUE if all +# variables are non-zero. include(FindPackageHandleStandardArgs) -if (USE_OPENMP) -find_package_handle_standard_args(FFTW3 DEFAULT_MSG FFTW3_OMP_LIBRARY FFTW3_LIBRARY FFTW3_FLOAT_LIBRARY FFTW3_INCLUDE_DIR) +if(USE_OPENMP) + find_package_handle_standard_args( + FFTW3 DEFAULT_MSG FFTW3_OMP_LIBRARY FFTW3_LIBRARY FFTW3_FLOAT_LIBRARY + FFTW3_INCLUDE_DIR) else() -find_package_handle_standard_args(FFTW3 DEFAULT_MSG FFTW3_LIBRARY FFTW3_FLOAT_LIBRARY FFTW3_INCLUDE_DIR) + find_package_handle_standard_args(FFTW3 DEFAULT_MSG FFTW3_LIBRARY + FFTW3_FLOAT_LIBRARY FFTW3_INCLUDE_DIR) endif() # Copy the results to the output variables and target. if(FFTW3_FOUND) - set(FFTW3_LIBRARIES ${FFTW3_LIBRARY}) - if (USE_OPENMP) - list(APPEND FFTW3_LIBRARIES ${FFTW3_OMP_LIBRARY}) - endif() + set(FFTW3_LIBRARIES ${FFTW3_LIBRARY}) + if(USE_OPENMP) + list(APPEND FFTW3_LIBRARIES ${FFTW3_OMP_LIBRARY}) + endif() - set(FFTW3_INCLUDE_DIRS ${FFTW3_INCLUDE_DIR}) + set(FFTW3_INCLUDE_DIRS ${FFTW3_INCLUDE_DIR}) - # Try to extract FFTW version from header - if(FFTW3_INCLUDE_DIR AND EXISTS "${FFTW3_INCLUDE_DIR}/fftw3.h") - file(STRINGS "${FFTW3_INCLUDE_DIR}/fftw3.h" _fftw_ver_line REGEX "^#define[\t ]+FFTW_VERSION[\t ]+\"[^\"]+\"") - if(_fftw_ver_line) - string(REGEX REPLACE "^#define[\t ]+FFTW_VERSION[\t ]+\"([^\"]+)\"" "\\1" FFTW3_VERSION "${_fftw_ver_line}") - endif() + # Try to extract FFTW version from header + if(FFTW3_INCLUDE_DIR AND EXISTS "${FFTW3_INCLUDE_DIR}/fftw3.h") + file(STRINGS "${FFTW3_INCLUDE_DIR}/fftw3.h" _fftw_ver_line + REGEX "^#define[\t ]+FFTW_VERSION[\t ]+\"[^\"]+\"") + if(_fftw_ver_line) + string(REGEX REPLACE "^#define[\t ]+FFTW_VERSION[\t ]+\"([^\"]+)\"" "\\1" + FFTW3_VERSION "${_fftw_ver_line}") endif() + endif() - if(NOT TARGET FFTW3::FFTW3) - add_library(FFTW3::FFTW3 UNKNOWN IMPORTED) - set_target_properties(FFTW3::FFTW3 PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${FFTW3_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIRS}") - endif() - if(NOT TARGET FFTW3::FFTW3_FLOAT) - add_library(FFTW3::FFTW3_FLOAT UNKNOWN IMPORTED) - set_target_properties(FFTW3::FFTW3_FLOAT PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${FFTW3_FLOAT_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIRS}") - endif() - if (USE_OPENMP) - if(NOT TARGET FFTW3::FFTW3_OMP) - add_library(FFTW3::FFTW3_OMP UNKNOWN IMPORTED) - set_target_properties(FFTW3::FFTW3_OMP PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${FFTW3_OMP_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIRS}") - endif() + if(NOT TARGET FFTW3::FFTW3) + add_library(FFTW3::FFTW3 UNKNOWN IMPORTED) + set_target_properties( + FFTW3::FFTW3 + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${FFTW3_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIRS}") + endif() + if(NOT TARGET FFTW3::FFTW3_FLOAT) + add_library(FFTW3::FFTW3_FLOAT UNKNOWN IMPORTED) + set_target_properties( + FFTW3::FFTW3_FLOAT + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${FFTW3_FLOAT_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIRS}") + endif() + if(USE_OPENMP) + if(NOT TARGET FFTW3::FFTW3_OMP) + add_library(FFTW3::FFTW3_OMP UNKNOWN IMPORTED) + set_target_properties( + FFTW3::FFTW3_OMP + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${FFTW3_OMP_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIRS}") endif() + endif() endif() mark_as_advanced(FFTW3_INCLUDE_DIR FFTW3_LIBRARY FFTW3_OMP_LIBRARY) diff --git a/cmake/FindLapack.cmake b/cmake/FindLapack.cmake index 15c3976d64c..60bfa080344 100644 --- a/cmake/FindLapack.cmake +++ b/cmake/FindLapack.cmake @@ -10,8 +10,8 @@ find_package(Blas REQUIRED) find_package(LAPACK REQUIRED) if(NOT TARGET LAPACK::LAPACK) - add_library(LAPACK::LAPACK UNKNOWN IMPORTED) - set_target_properties(LAPACK::LAPACK PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${LAPACK_LIBRARIES}") + add_library(LAPACK::LAPACK UNKNOWN IMPORTED) + set_target_properties( + LAPACK::LAPACK PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${LAPACK_LIBRARIES}") endif() diff --git a/cmake/FindLibComm.cmake b/cmake/FindLibComm.cmake index 64b34333998..98de2b48da3 100644 --- a/cmake/FindLibComm.cmake +++ b/cmake/FindLibComm.cmake @@ -1,28 +1,25 @@ -############################################################################### -# - Find LibComm -# Find the native LibComm files. +# ############################################################################## +# * Find LibComm Find the native LibComm files. # -# LIBCOMM_FOUND - True if LibComm is found. -# LIBCOMM_DIR - Where to find LibComm files. +# LIBCOMM_FOUND - True if LibComm is found. LIBCOMM_DIR - Where to find LibComm +# files. -find_path(LIBCOMM_DIR - include/Comm/Comm_Tools.h - HINTS ${LIBCOMM_DIR} - HINTS ${LibComm_DIR} - HINTS ${libcomm_DIR} -) +find_path( + LIBCOMM_DIR include/Comm/Comm_Tools.h + HINTS ${LIBCOMM_DIR} + HINTS ${LibComm_DIR} + HINTS ${libcomm_DIR}) if(NOT LIBCOMM_DIR) - include(FetchContent) - FetchContent_Declare( - LibComm - URL https://codeload.github.com/abacusmodeling/LibComm/tar.gz/965bf90 - ) - FetchContent_Populate(LibComm) - set(LIBCOMM_DIR ${libcomm_SOURCE_DIR}) + include(FetchContent) + FetchContent_Declare( + LibComm + URL https://codeload.github.com/abacusmodeling/LibComm/tar.gz/965bf90) + FetchContent_Populate(LibComm) + set(LIBCOMM_DIR ${libcomm_SOURCE_DIR}) endif() -# Handle the QUIET and REQUIRED arguments and -# set LIBCOMM_FOUND to TRUE if all variables are non-zero. +# Handle the QUIET and REQUIRED arguments and set LIBCOMM_FOUND to TRUE if all +# variables are non-zero. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LibComm DEFAULT_MSG LIBCOMM_DIR) diff --git a/cmake/FindLibRI.cmake b/cmake/FindLibRI.cmake index 23b5426fbdd..3722abef9cb 100644 --- a/cmake/FindLibRI.cmake +++ b/cmake/FindLibRI.cmake @@ -1,28 +1,23 @@ -############################################################################### -# - Find LibRI -# Find the native LibRI files. +# ############################################################################## +# * Find LibRI Find the native LibRI files. # -# LIBRI_FOUND - True if LibRI is found. -# LIBRI_DIR - Where to find LibRI files. +# LIBRI_FOUND - True if LibRI is found. LIBRI_DIR - Where to find LibRI files. -find_path(LIBRI_DIR - include/RI/version.h - HINTS ${LIBRI_DIR} - HINTS ${LibRI_DIR} - HINTS ${libri_DIR} -) +find_path( + LIBRI_DIR include/RI/version.h + HINTS ${LIBRI_DIR} + HINTS ${LibRI_DIR} + HINTS ${libri_DIR}) if(NOT LIBRI_DIR) - include(FetchContent) - FetchContent_Declare( - LibRI - URL https://codeload.github.com/abacusmodeling/LibRI/tar.gz/e6d78e0 - ) - FetchContent_Populate(LibRI) - set(LIBRI_DIR ${libri_SOURCE_DIR}) + include(FetchContent) + FetchContent_Declare( + LibRI URL https://codeload.github.com/abacusmodeling/LibRI/tar.gz/e6d78e0) + FetchContent_Populate(LibRI) + set(LIBRI_DIR ${libri_SOURCE_DIR}) endif() -# Handle the QUIET and REQUIRED arguments and -# set LIBRI_FOUND to TRUE if all variables are non-zero. +# Handle the QUIET and REQUIRED arguments and set LIBRI_FOUND to TRUE if all +# variables are non-zero. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LibRI DEFAULT_MSG LIBRI_DIR) diff --git a/cmake/FindLibxc.cmake b/cmake/FindLibxc.cmake index 18a0ace4a3d..11d69affcba 100644 --- a/cmake/FindLibxc.cmake +++ b/cmake/FindLibxc.cmake @@ -3,35 +3,30 @@ include(FindPackageHandleStandardArgs) if(DEFINED Libxc_DIR) string(APPEND CMAKE_PREFIX_PATH ";${Libxc_DIR}") endif() -# Using pkg-config interface as default, to -# avoid linking to wrong global visible Libxc instead of -# specified one. -# NO REQUIRED here, otherwhile it would throw error -# with no LibXC found. +# Using pkg-config interface as default, to avoid linking to wrong global +# visible Libxc instead of specified one. NO REQUIRED here, otherwhile it would +# throw error with no LibXC found. find_package(PkgConfig) if(PKG_CONFIG_FOUND) pkg_search_module(Libxc IMPORTED_TARGET GLOBAL libxc) - find_package_handle_standard_args(Libxc DEFAULT_MSG Libxc_LINK_LIBRARIES Libxc_FOUND) + find_package_handle_standard_args(Libxc DEFAULT_MSG Libxc_LINK_LIBRARIES + Libxc_FOUND) endif() if(NOT Libxc_FOUND) - find_package(Libxc REQUIRED HINTS - ${Libxc_DIR}/share/cmake/Libxc - ${Libxc_DIR}/lib/cmake/Libxc - ${Libxc_DIR}/lib64/cmake/Libxc - ) + find_package(Libxc REQUIRED HINTS ${Libxc_DIR}/share/cmake/Libxc + ${Libxc_DIR}/lib/cmake/Libxc ${Libxc_DIR}/lib64/cmake/Libxc) endif() -# Copy the results to the output variables and target. -# if find_package() above works, Libxc::xc would be present and -# below would be skipped. +# Copy the results to the output variables and target. if find_package() above +# works, Libxc::xc would be present and below would be skipped. if(Libxc_FOUND AND NOT TARGET Libxc::xc) - set(Libxc_LIBRARY ${Libxc_LINK_LIBRARIES}) - set(Libxc_LIBRARIES ${Libxc_LIBRARY}) - set(Libxc_INCLUDE_DIR ${Libxc_INCLUDE_DIRS}) - add_library(Libxc::xc UNKNOWN IMPORTED) - set_target_properties(Libxc::xc PROPERTIES - IMPORTED_LOCATION "${Libxc_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${Libxc_INCLUDE_DIR}") + set(Libxc_LIBRARY ${Libxc_LINK_LIBRARIES}) + set(Libxc_LIBRARIES ${Libxc_LIBRARY}) + set(Libxc_INCLUDE_DIR ${Libxc_INCLUDE_DIRS}) + add_library(Libxc::xc UNKNOWN IMPORTED) + set_target_properties( + Libxc::xc PROPERTIES IMPORTED_LOCATION "${Libxc_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${Libxc_INCLUDE_DIR}") endif() set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${Libxc_INCLUDE_DIR}) diff --git a/cmake/FindMKL.cmake b/cmake/FindMKL.cmake index 5d8ccdcc9b4..8da18a9433c 100644 --- a/cmake/FindMKL.cmake +++ b/cmake/FindMKL.cmake @@ -1,129 +1,167 @@ -# - Find mkl -# Find the native MKL headers and libraries. +# * Find mkl Find the native MKL headers and libraries. # -# MKL_INCLUDE - where to find mkl.h, etc. -# MKL_FOUND - True if mkl found. +# MKL_INCLUDE - where to find mkl.h, etc. MKL_FOUND - True if mkl found. # find_package(MKL NO_MODULE) # try using official module first if(NOT TARGET MKL::MKL) -find_path(MKL_INCLUDE mkl_service.h HINTS ${MKLROOT}/include) + find_path(MKL_INCLUDE mkl_service.h HINTS ${MKLROOT}/include) -find_library(MKL_CORE NAMES mkl_core HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) -if(CMAKE_CXX_COMPILER_ID MATCHES "Intel") - find_library(MKL_INTERFACE_LIB NAMES mkl_intel_lp64 HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) - find_library(MKL_THREAD NAMES mkl_intel_thread HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) - find_library(MKL_IOMP5 NAMES iomp5 - HINTS ENV CMPLR_ROOT - PATH_SUFFIXES lib lib/intel64 linux/compiler/lib/intel64_lin - ) -else() - find_library(MKL_INTERFACE_LIB NAMES mkl_gf_lp64 HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) - find_library(MKL_THREAD NAMES mkl_gnu_thread HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) - # With GCC we use system-installed GNU OpenMP -endif() - -if(ENABLE_MPI) - execute_process(COMMAND ${MPI_CXX_COMPILER} --showme:version - OUTPUT_VARIABLE MPI_VER_OUT - ERROR_VARIABLE MPI_VER_ERR) - if(MPI_VER_OUT MATCHES "Open MPI" OR MPI_VER_ERR MATCHES "Open MPI") - set(MKL_BLACS_LIB_NAME "mkl_blacs_openmpi_lp64") + find_library( + MKL_CORE + NAMES mkl_core + HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) + if(CMAKE_CXX_COMPILER_ID MATCHES "Intel") + find_library( + MKL_INTERFACE_LIB + NAMES mkl_intel_lp64 + HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) + find_library( + MKL_THREAD + NAMES mkl_intel_thread + HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) + find_library( + MKL_IOMP5 + NAMES iomp5 + HINTS ENV CMPLR_ROOT + PATH_SUFFIXES lib lib/intel64 linux/compiler/lib/intel64_lin) else() - set(MKL_BLACS_LIB_NAME "mkl_blacs_intelmpi_lp64") + find_library( + MKL_INTERFACE_LIB + NAMES mkl_gf_lp64 + HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) + find_library( + MKL_THREAD + NAMES mkl_gnu_thread + HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) + # With GCC we use system-installed GNU OpenMP endif() - find_library(MKL_SCALAPACK NAMES mkl_scalapack_lp64 HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) - find_library(MKL_BLACS NAMES ${MKL_BLACS_LIB_NAME} HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) -endif() -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set MKL_FOUND to TRUE -# if all listed variables are TRUE + if(ENABLE_MPI) + execute_process( + COMMAND ${MPI_CXX_COMPILER} --showme:version + OUTPUT_VARIABLE MPI_VER_OUT + ERROR_VARIABLE MPI_VER_ERR) + if(MPI_VER_OUT MATCHES "Open MPI" OR MPI_VER_ERR MATCHES "Open MPI") + set(MKL_BLACS_LIB_NAME "mkl_blacs_openmpi_lp64") + else() + set(MKL_BLACS_LIB_NAME "mkl_blacs_intelmpi_lp64") + endif() + find_library( + MKL_SCALAPACK + NAMES mkl_scalapack_lp64 + HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) + find_library( + MKL_BLACS + NAMES ${MKL_BLACS_LIB_NAME} + HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) + endif() -if(ENABLE_MPI) - find_package_handle_standard_args(MKL DEFAULT_MSG MKL_INTERFACE_LIB MKL_THREAD MKL_CORE MKL_SCALAPACK MKL_BLACS MKL_INCLUDE) -else() - find_package_handle_standard_args(MKL MKL_INTERFACE_LIB MKL_THREAD MKL_CORE MKL_INCLUDE) -endif() + include(FindPackageHandleStandardArgs) + # handle the QUIETLY and REQUIRED arguments and set MKL_FOUND to TRUE if all + # listed variables are TRUE -if(MKL_FOUND) - if(NOT TARGET MKL::INTERFACE_LIB) - add_library(MKL::INTERFACE_LIB UNKNOWN IMPORTED) - set_target_properties(MKL::INTERFACE_LIB PROPERTIES - IMPORTED_LOCATION "${MKL_INTERFACE_LIB}" - INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") - endif() - if(NOT TARGET MKL::THREAD) - add_library(MKL::THREAD UNKNOWN IMPORTED) - set_target_properties(MKL::THREAD PROPERTIES - IMPORTED_LOCATION "${MKL_THREAD}" - INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") - endif() - if(NOT TARGET MKL::CORE) - add_library(MKL::CORE UNKNOWN IMPORTED) - set_target_properties(MKL::CORE PROPERTIES - IMPORTED_LOCATION "${MKL_CORE}" - INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") - endif() - if(NOT TARGET MKL::MKL_SCALAPACK) - add_library(MKL::MKL_SCALAPACK UNKNOWN IMPORTED) - set_target_properties(MKL::MKL_SCALAPACK PROPERTIES - IMPORTED_LOCATION "${MKL_SCALAPACK}" - INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") - endif() - if(ENABLE_MPI AND NOT TARGET MKL::BLACS) - add_library(MKL::BLACS UNKNOWN IMPORTED) - set_target_properties(MKL::BLACS PROPERTIES - IMPORTED_LOCATION "${MKL_BLACS}" - INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") - endif() - if(MKL_IOMP5 AND NOT TARGET MKL::IOMP5) - add_library(MKL::IOMP5 UNKNOWN IMPORTED) - set_target_properties(MKL::IOMP5 PROPERTIES - IMPORTED_LOCATION "${MKL_IOMP5}") - endif() - add_library(MKL::MKL INTERFACE IMPORTED) - if (ENABLE_MPI) - set_property(TARGET MKL::MKL PROPERTY - INTERFACE_LINK_LIBRARIES - "-Wl,--start-group" - MKL::INTERFACE_LIB MKL::THREAD MKL::CORE MKL::MKL_SCALAPACK MKL::BLACS - "-Wl,--end-group" - ) + if(ENABLE_MPI) + find_package_handle_standard_args( + MKL + DEFAULT_MSG + MKL_INTERFACE_LIB + MKL_THREAD + MKL_CORE + MKL_SCALAPACK + MKL_BLACS + MKL_INCLUDE) else() - set_property(TARGET MKL::MKL PROPERTY - INTERFACE_LINK_LIBRARIES - "-Wl,--start-group" - MKL::INTERFACE_LIB MKL::THREAD MKL::CORE - "-Wl,--end-group" - ) + find_package_handle_standard_args(MKL MKL_INTERFACE_LIB MKL_THREAD MKL_CORE + MKL_INCLUDE) endif() - if(TARGET MKL::IOMP5) - set_property(TARGET MKL::MKL APPEND PROPERTY - INTERFACE_LINK_LIBRARIES MKL::IOMP5) + + if(MKL_FOUND) + if(NOT TARGET MKL::INTERFACE_LIB) + add_library(MKL::INTERFACE_LIB UNKNOWN IMPORTED) + set_target_properties( + MKL::INTERFACE_LIB + PROPERTIES IMPORTED_LOCATION "${MKL_INTERFACE_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") + endif() + if(NOT TARGET MKL::THREAD) + add_library(MKL::THREAD UNKNOWN IMPORTED) + set_target_properties( + MKL::THREAD PROPERTIES IMPORTED_LOCATION "${MKL_THREAD}" + INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") + endif() + if(NOT TARGET MKL::CORE) + add_library(MKL::CORE UNKNOWN IMPORTED) + set_target_properties( + MKL::CORE PROPERTIES IMPORTED_LOCATION "${MKL_CORE}" + INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") + endif() + if(NOT TARGET MKL::MKL_SCALAPACK) + add_library(MKL::MKL_SCALAPACK UNKNOWN IMPORTED) + set_target_properties( + MKL::MKL_SCALAPACK + PROPERTIES IMPORTED_LOCATION "${MKL_SCALAPACK}" + INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") + endif() + if(ENABLE_MPI AND NOT TARGET MKL::BLACS) + add_library(MKL::BLACS UNKNOWN IMPORTED) + set_target_properties( + MKL::BLACS PROPERTIES IMPORTED_LOCATION "${MKL_BLACS}" + INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") + endif() + if(MKL_IOMP5 AND NOT TARGET MKL::IOMP5) + add_library(MKL::IOMP5 UNKNOWN IMPORTED) + set_target_properties(MKL::IOMP5 PROPERTIES IMPORTED_LOCATION + "${MKL_IOMP5}") + endif() + add_library(MKL::MKL INTERFACE IMPORTED) + if(ENABLE_MPI) + set_property( + TARGET MKL::MKL + PROPERTY INTERFACE_LINK_LIBRARIES + "-Wl,--start-group" + MKL::INTERFACE_LIB + MKL::THREAD + MKL::CORE + MKL::MKL_SCALAPACK + MKL::BLACS + "-Wl,--end-group") + else() + set_property( + TARGET MKL::MKL + PROPERTY INTERFACE_LINK_LIBRARIES "-Wl,--start-group" + MKL::INTERFACE_LIB MKL::THREAD MKL::CORE "-Wl,--end-group") + endif() + if(TARGET MKL::IOMP5) + set_property( + TARGET MKL::MKL + APPEND + PROPERTY INTERFACE_LINK_LIBRARIES MKL::IOMP5) + endif() endif() -endif() -if(ENABLE_MPI) - mark_as_advanced(MKL_INCLUDE MKL_INTERFACE_LIB MKL_THREAD MKL_CORE MKL_SCALAPACK MKL_BLACS) -else() - mark_as_advanced(MKL_INCLUDE MKL_INTERFACE_LIB MKL_THREAD MKL_CORE) -endif() + if(ENABLE_MPI) + mark_as_advanced(MKL_INCLUDE MKL_INTERFACE_LIB MKL_THREAD MKL_CORE + MKL_SCALAPACK MKL_BLACS) + else() + mark_as_advanced(MKL_INCLUDE MKL_INTERFACE_LIB MKL_THREAD MKL_CORE) + endif() endif() # MKL::MKL - - # In oneAPI 2022, MKL_SCALAPACK might not be linked properly if(NOT TARGET MKL::MKL_SCALAPACK) - find_library(MKL_SCALAPACK NAMES mkl_scalapack_lp64 HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) + find_library( + MKL_SCALAPACK + NAMES mkl_scalapack_lp64 + HINTS ${MKLROOT}/lib ${MKLROOT}/lib/intel64) message(STATUS "Found MKL_SCALAPACK: ${MKL_SCALAPACK}") if(MKL_SCALAPACK) # create an IMPORTED target that points to the discovered library file add_library(MKL::MKL_SCALAPACK UNKNOWN IMPORTED) - set_target_properties(MKL::MKL_SCALAPACK PROPERTIES - IMPORTED_LOCATION "${MKL_SCALAPACK}" - INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}" - ) + set_target_properties( + MKL::MKL_SCALAPACK + PROPERTIES IMPORTED_LOCATION "${MKL_SCALAPACK}" + INTERFACE_INCLUDE_DIRECTORIES "${MKL_INCLUDE}") endif() endif() diff --git a/cmake/FindNEP.cmake b/cmake/FindNEP.cmake index e20734f5c03..99441915e42 100644 --- a/cmake/FindNEP.cmake +++ b/cmake/FindNEP.cmake @@ -1,49 +1,47 @@ -############################################################################### -# - Find NEP -# Finds the NEP header and library. +# ############################################################################## +# * Find NEP Finds the NEP header and library. # -# This module will search for the NEP library, looking for a hint -# from the NEP_DIR environment variable or CMake variable. +# This module will search for the NEP library, looking for a hint from the +# NEP_DIR environment variable or CMake variable. # # This module defines the following variables: # -# NEP_FOUND - True if the NEP library and headers were found. -# NEP_INCLUDE_DIR - The directory where nep.h is located. -# NEP_LIBRARY - The full path to the NEP library. +# NEP_FOUND - True if the NEP library and headers were found. +# NEP_INCLUDE_DIR - The directory where nep.h is located. NEP_LIBRARY - +# The full path to the NEP library. # # It also defines the following imported target: # -# NEP::nep - The NEP library target. +# NEP::nep - The NEP library target. # -############################################################################### -# Note: Currently only CPU version is supported, Since the NEP interface with GPU support is not available yet. -# In feature, if available, we can use USE_CUDA to switch between CPU and GPU version. +# ############################################################################## +# Note: Currently only CPU version is supported, Since the NEP interface with +# GPU support is not available yet. In feature, if available, we can use +# USE_CUDA to switch between CPU and GPU version. -find_path(NEP_INCLUDE_DIR nep.h - HINTS ${NEP_DIR} - PATH_SUFFIXES "include" - ) +find_path( + NEP_INCLUDE_DIR nep.h + HINTS ${NEP_DIR} + PATH_SUFFIXES "include") -find_library(NEP_LIBRARY - NAMES nep - HINTS ${NEP_DIR} - PATH_SUFFIXES "lib" - ) +find_library( + NEP_LIBRARY + NAMES nep + HINTS ${NEP_DIR} + PATH_SUFFIXES "lib") include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(NEP - DEFAULT_MSG - NEP_LIBRARY NEP_INCLUDE_DIR) +find_package_handle_standard_args(NEP DEFAULT_MSG NEP_LIBRARY NEP_INCLUDE_DIR) if(NEP_FOUND) - if(NOT TARGET NEP::nep) - add_library(NEP::nep UNKNOWN IMPORTED) - set_target_properties(NEP::nep PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${NEP_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${NEP_INCLUDE_DIR}" - ) - endif() + if(NOT TARGET NEP::nep) + add_library(NEP::nep UNKNOWN IMPORTED) + set_target_properties( + NEP::nep + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${NEP_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${NEP_INCLUDE_DIR}") + endif() endif() -mark_as_advanced(NEP_INCLUDE_DIR NEP_LIBRARY) \ No newline at end of file +mark_as_advanced(NEP_INCLUDE_DIR NEP_LIBRARY) diff --git a/cmake/FindPEXSI.cmake b/cmake/FindPEXSI.cmake index 5adc4c8a6d9..f6cbfa0e5d6 100644 --- a/cmake/FindPEXSI.cmake +++ b/cmake/FindPEXSI.cmake @@ -1,57 +1,60 @@ -############################################################################### -# - Find PEXSI -# Find PEXSI and its dependencies. +# ############################################################################## +# * Find PEXSI Find PEXSI and its dependencies. # -# PEXSI_FOUND - True if pexsi is found. -# PEXSI_INCLUDE_DIR - Where to find pexsi headers. -# PEXSI_LIBRARY - pexsi library. -# ParMETIS_INCLUDE_DIR - Where to find pexsi headers. -# ParMETIS_LIBRARY - parmetis library. -# METIS_LIBRARY - metis library. -# SuperLU_DIST_LIBRARY - superlu_dist library. - -find_path(PEXSI_INCLUDE_DIR - NAMES c_pexsi_interface.h - HINTS ${PEXSI_DIR} - PATH_SUFFIXES "include" -) - -find_library(PEXSI_LIBRARY - NAMES pexsi - HINTS ${PEXSI_DIR} - PATH_SUFFIXES "lib" -) - -find_path(ParMETIS_INCLUDE_DIR - NAMES metis.h parmetis.h - HINTS ${ParMETIS_DIR} - PATH_SUFFIXES "include" -) - -find_library(METIS_LIBRARY - NAMES metis - HINTS ${ParMETIS_DIR} - PATH_SUFFIXES "lib" -) - -find_library(ParMETIS_LIBRARY - NAMES parmetis - HINTS ${ParMETIS_DIR} - PATH_SUFFIXES "lib" -) - -find_library(SuperLU_DIST_LIBRARY - NAMES superlu_dist - HINTS ${SuperLU_DIST_DIR} - PATH_SUFFIXES "lib" -) - -# Handle the QUIET and REQUIRED arguments and -# set PEXSI_FOUND to TRUE if all variables are non-zero. +# PEXSI_FOUND - True if pexsi is found. PEXSI_INCLUDE_DIR - Where to +# find pexsi headers. PEXSI_LIBRARY - pexsi library. ParMETIS_INCLUDE_DIR +# - Where to find pexsi headers. ParMETIS_LIBRARY - parmetis library. +# METIS_LIBRARY - metis library. SuperLU_DIST_LIBRARY - superlu_dist +# library. + +find_path( + PEXSI_INCLUDE_DIR + NAMES c_pexsi_interface.h + HINTS ${PEXSI_DIR} + PATH_SUFFIXES "include") + +find_library( + PEXSI_LIBRARY + NAMES pexsi + HINTS ${PEXSI_DIR} + PATH_SUFFIXES "lib") + +find_path( + ParMETIS_INCLUDE_DIR + NAMES metis.h parmetis.h + HINTS ${ParMETIS_DIR} + PATH_SUFFIXES "include") + +find_library( + METIS_LIBRARY + NAMES metis + HINTS ${ParMETIS_DIR} + PATH_SUFFIXES "lib") + +find_library( + ParMETIS_LIBRARY + NAMES parmetis + HINTS ${ParMETIS_DIR} + PATH_SUFFIXES "lib") + +find_library( + SuperLU_DIST_LIBRARY + NAMES superlu_dist + HINTS ${SuperLU_DIST_DIR} + PATH_SUFFIXES "lib") + +# Handle the QUIET and REQUIRED arguments and set PEXSI_FOUND to TRUE if all +# variables are non-zero. include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(PEXSI DEFAULT_MSG PEXSI_LIBRARY PEXSI_INCLUDE_DIR ParMETIS_LIBRARY METIS_LIBRARY SuperLU_DIST_LIBRARY) - +find_package_handle_standard_args( + PEXSI + DEFAULT_MSG + PEXSI_LIBRARY + PEXSI_INCLUDE_DIR + ParMETIS_LIBRARY + METIS_LIBRARY + SuperLU_DIST_LIBRARY) # Copy the results to the output variables and target. -mark_as_advanced(PEXSI_LIBRARY PEXSI_INCLUDE_DIR ParMETIS_LIBRARY SuperLU_DIST_LIBRARY) - +mark_as_advanced(PEXSI_LIBRARY PEXSI_INCLUDE_DIR ParMETIS_LIBRARY + SuperLU_DIST_LIBRARY) diff --git a/cmake/FindScaLAPACK.cmake b/cmake/FindScaLAPACK.cmake index febecd2de41..8d5e154a538 100644 --- a/cmake/FindScaLAPACK.cmake +++ b/cmake/FindScaLAPACK.cmake @@ -1,47 +1,36 @@ -# - Find ScaLAPACK -# Find the native double precision ScaLAPACK headers and libraries. +# * Find ScaLAPACK Find the native double precision ScaLAPACK headers and +# libraries. # -# ScaLAPACK_LIBRARIES - List of libraries when using ScaLAPACK. -# ScaLAPACK_FOUND - True if ScaLAPACK is found. +# ScaLAPACK_LIBRARIES - List of libraries when using ScaLAPACK. +# ScaLAPACK_FOUND - True if ScaLAPACK is found. # # Accept common root hints from cache vars and environment. -set(_scalapack_hints - ${SCALAPACK_DIR} - ${SCALAPACK_ROOT} - $ENV{SCALAPACK_DIR} - $ENV{SCALAPACK_ROOT} -) +set(_scalapack_hints ${SCALAPACK_DIR} ${SCALAPACK_ROOT} $ENV{SCALAPACK_DIR} + $ENV{SCALAPACK_ROOT}) -find_library(ScaLAPACK_LIBRARY - NAMES - scalapack - scalapack-openmpi - scalapack-mpi - scalapack-mpich - HINTS ${_scalapack_hints} - PATH_SUFFIXES lib lib64 -) +find_library( + ScaLAPACK_LIBRARY + NAMES scalapack scalapack-openmpi scalapack-mpi scalapack-mpich + HINTS ${_scalapack_hints} + PATH_SUFFIXES lib lib64) unset(_scalapack_hints) -# Handle the QUIET and REQUIRED arguments and -# set ScaLAPACK_FOUND to TRUE if all variables are non-zero. +# Handle the QUIET and REQUIRED arguments and set ScaLAPACK_FOUND to TRUE if all +# variables are non-zero. include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - ScaLAPACK - REQUIRED_VARS ScaLAPACK_LIBRARY -) +find_package_handle_standard_args(ScaLAPACK REQUIRED_VARS ScaLAPACK_LIBRARY) # Copy the results to the output variables and target. if(ScaLAPACK_FOUND) - set(ScaLAPACK_LIBRARIES ${ScaLAPACK_LIBRARY}) + set(ScaLAPACK_LIBRARIES ${ScaLAPACK_LIBRARY}) - if(NOT TARGET ScaLAPACK::ScaLAPACK) - add_library(ScaLAPACK::ScaLAPACK UNKNOWN IMPORTED) - set_target_properties(ScaLAPACK::ScaLAPACK PROPERTIES - IMPORTED_LOCATION "${ScaLAPACK_LIBRARY}") - endif() + if(NOT TARGET ScaLAPACK::ScaLAPACK) + add_library(ScaLAPACK::ScaLAPACK UNKNOWN IMPORTED) + set_target_properties(ScaLAPACK::ScaLAPACK + PROPERTIES IMPORTED_LOCATION "${ScaLAPACK_LIBRARY}") + endif() endif() mark_as_advanced(ScaLAPACK_LIBRARY) diff --git a/cmake/FindTensorFlow.cmake b/cmake/FindTensorFlow.cmake index a391111bc4d..bf51c651122 100644 --- a/cmake/FindTensorFlow.cmake +++ b/cmake/FindTensorFlow.cmake @@ -1,29 +1,27 @@ -############################################################################### -# - Find TensorFlow -# Find the native TensorFlow libraries. +# ############################################################################## +# * Find TensorFlow Find the native TensorFlow libraries. # -# TensorFlow_FOUND - True if lib is found. -# TensorFlow_LIBRARIES - List of libraries +# TensorFlow_FOUND - True if lib is found. TensorFlow_LIBRARIES - List +# of libraries +find_library( + tensorflow_cc + NAMES tensorflow_cc libtensorflow_cc.so.2 + HINTS ${TensorFlow_DIR} + PATH_SUFFIXES "lib") -find_library(tensorflow_cc - NAMES tensorflow_cc libtensorflow_cc.so.2 - HINTS ${TensorFlow_DIR} - PATH_SUFFIXES "lib" - ) - -# Handle the QUIET and REQUIRED arguments and -# set TensorFlow_FOUND to TRUE if all variables are non-zero. +# Handle the QUIET and REQUIRED arguments and set TensorFlow_FOUND to TRUE if +# all variables are non-zero. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(TensorFlow DEFAULT_MSG tensorflow_cc) if(TensorFlow_FOUND) - if(NOT TARGET TensorFlow::tensorflow_cc) - add_library(TensorFlow::tensorflow_cc UNKNOWN IMPORTED) - set_target_properties(TensorFlow::tensorflow_cc PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${tensorflow_cc}") - endif() + if(NOT TARGET TensorFlow::tensorflow_cc) + add_library(TensorFlow::tensorflow_cc UNKNOWN IMPORTED) + set_target_properties( + TensorFlow::tensorflow_cc PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${tensorflow_cc}") + endif() endif() mark_as_advanced(tensorflow_cc) diff --git a/cmake/SetupCuBlasMp.cmake b/cmake/SetupCuBlasMp.cmake index 7937a02936a..2c4204ea4c6 100644 --- a/cmake/SetupCuBlasMp.cmake +++ b/cmake/SetupCuBlasMp.cmake @@ -7,29 +7,32 @@ include_guard(GLOBAL) function(abacus_setup_cublasmp target_name) add_compile_definitions(__CUBLASMP) - # 1. Search for cuBLASMp library and header files - # libcublasmp.so - find_library(CUBLASMP_LIBRARY NAMES cublasmp - HINTS ${CUBLASMP_PATH} ${NVHPC_ROOT_DIR} - PATH_SUFFIXES lib lib64 math_libs/lib math_libs/lib64) + # 1. Search for cuBLASMp library and header files libcublasmp.so + find_library( + CUBLASMP_LIBRARY + NAMES cublasmp + HINTS ${CUBLASMP_PATH} ${NVHPC_ROOT_DIR} + PATH_SUFFIXES lib lib64 math_libs/lib math_libs/lib64) # cublasmp.h - find_path(CUBLASMP_INCLUDE_DIR NAMES cublasmp.h - HINTS ${CUBLASMP_PATH} ${NVHPC_ROOT_DIR} - PATH_SUFFIXES include math_libs/include) + find_path( + CUBLASMP_INCLUDE_DIR + NAMES cublasmp.h + HINTS ${CUBLASMP_PATH} ${NVHPC_ROOT_DIR} + PATH_SUFFIXES include math_libs/include) if(NOT CUBLASMP_LIBRARY OR NOT CUBLASMP_INCLUDE_DIR) - message(FATAL_ERROR - "cuBLASMp not found. Please ensure CUBLASMP_PATH is set correctly." - ) + message( + FATAL_ERROR + "cuBLASMp not found. Please ensure CUBLASMP_PATH is set correctly.") endif() message(STATUS "Found cuBLASMp: ${CUBLASMP_LIBRARY}") - # 2. Version validation by parsing header macros + # 1. Version validation by parsing header macros set(CUBLASMP_VERSION_STR "") set(CUBLASMP_VERSION_HEADER "${CUBLASMP_INCLUDE_DIR}/cublasmp.h") - + if(EXISTS "${CUBLASMP_VERSION_HEADER}") # Extract version lines using regular expressions from cublasmp.h file(STRINGS "${CUBLASMP_VERSION_HEADER}" CUBLASMP_MAJOR_LINE @@ -38,12 +41,12 @@ function(abacus_setup_cublasmp target_name) REGEX "^#define[ \t]+CUBLASMP_VER_MINOR[ \t]+[0-9]+") file(STRINGS "${CUBLASMP_VERSION_HEADER}" CUBLASMP_PATCH_LINE REGEX "^#define[ \t]+CUBLASMP_VER_PATCH[ \t]+[0-9]+") - + # Extract numeric values from the matched strings string(REGEX MATCH "([0-9]+)" CUBLASMP_VER_MAJOR "${CUBLASMP_MAJOR_LINE}") string(REGEX MATCH "([0-9]+)" CUBLASMP_VER_MINOR "${CUBLASMP_MINOR_LINE}") string(REGEX MATCH "([0-9]+)" CUBLASMP_VER_PATCH "${CUBLASMP_PATCH_LINE}") - + if(NOT CUBLASMP_VER_MAJOR STREQUAL "" AND NOT CUBLASMP_VER_MINOR STREQUAL "" AND NOT CUBLASMP_VER_PATCH STREQUAL "") @@ -54,25 +57,26 @@ function(abacus_setup_cublasmp target_name) message(STATUS "Detected cuBLASMp version: ${CUBLASMP_VERSION_STR}") - # 3. Version constraint: ABACUS requires cuBLASMp >= 0.8.0 + # 1. Version constraint: ABACUS requires cuBLASMp >= 0.8.0 if(CUBLASMP_VERSION_STR AND CUBLASMP_VERSION_STR VERSION_LESS "0.8.0") - message(FATAL_ERROR - "cuBLASMp version ${CUBLASMP_VERSION_STR} is too old. " - "ABACUS requires cuBLASMp >= 0.8.0 for NCCL Symmetric Memory support." - ) + message( + FATAL_ERROR + "cuBLASMp version ${CUBLASMP_VERSION_STR} is too old. " + "ABACUS requires cuBLASMp >= 0.8.0 for NCCL Symmetric Memory support.") elseif(NOT CUBLASMP_VERSION_STR) message(WARNING "Could not detect cuBLASMp version. Proceeding cautiously.") endif() - # 4. Create cublasMp::cublasMp imported target + # 1. Create cublasMp::cublasMp imported target if(NOT TARGET cublasMp::cublasMp) add_library(cublasMp::cublasMp IMPORTED INTERFACE) - set_target_properties(cublasMp::cublasMp PROPERTIES - INTERFACE_LINK_LIBRARIES "${CUBLASMP_LIBRARY};NCCL::NCCL" - INTERFACE_INCLUDE_DIRECTORIES "${CUBLASMP_INCLUDE_DIR}") + set_target_properties( + cublasMp::cublasMp + PROPERTIES INTERFACE_LINK_LIBRARIES "${CUBLASMP_LIBRARY};NCCL::NCCL" + INTERFACE_INCLUDE_DIRECTORIES "${CUBLASMP_INCLUDE_DIR}") endif() - # 5. Link the library to the target + # 1. Link the library to the target target_link_libraries(${target_name} cublasMp::cublasMp) endfunction() diff --git a/cmake/SetupCuSolverMp.cmake b/cmake/SetupCuSolverMp.cmake index 004665686b6..aa4e7ba3778 100644 --- a/cmake/SetupCuSolverMp.cmake +++ b/cmake/SetupCuSolverMp.cmake @@ -8,17 +8,21 @@ function(abacus_setup_cusolvermp target_name) add_compile_definitions(__CUSOLVERMP) # Find cuSOLVERMp first, then decide communicator backend. - find_library(CUSOLVERMP_LIBRARY NAMES cusolverMp - HINTS ${CAL_CUSOLVERMP_PATH} ${NVHPC_ROOT_DIR} - PATH_SUFFIXES lib lib64 math_libs/lib math_libs/lib64) - - find_path(CUSOLVERMP_INCLUDE_DIR NAMES cusolverMp.h - HINTS ${CAL_CUSOLVERMP_PATH} ${NVHPC_ROOT_DIR} - PATH_SUFFIXES include math_libs/include) + find_library( + CUSOLVERMP_LIBRARY + NAMES cusolverMp + HINTS ${CAL_CUSOLVERMP_PATH} ${NVHPC_ROOT_DIR} + PATH_SUFFIXES lib lib64 math_libs/lib math_libs/lib64) + + find_path( + CUSOLVERMP_INCLUDE_DIR + NAMES cusolverMp.h + HINTS ${CAL_CUSOLVERMP_PATH} ${NVHPC_ROOT_DIR} + PATH_SUFFIXES include math_libs/include) if(NOT CUSOLVERMP_LIBRARY OR NOT CUSOLVERMP_INCLUDE_DIR) - message(FATAL_ERROR - "cuSOLVERMp not found. Set CUSOLVERMP_PATH or NVHPC_ROOT_DIR." + message( + FATAL_ERROR "cuSOLVERMp not found. Set CUSOLVERMP_PATH or NVHPC_ROOT_DIR." ) endif() @@ -33,56 +37,71 @@ function(abacus_setup_cusolvermp target_name) REGEX "^#define[ \t]+CUSOLVERMP_VER_MINOR[ \t]+[0-9]+") file(STRINGS "${CUSOLVERMP_VERSION_HEADER}" CUSOLVERMP_PATCH_LINE REGEX "^#define[ \t]+CUSOLVERMP_VER_PATCH[ \t]+[0-9]+") - string(REGEX MATCH "([0-9]+)" CUSOLVERMP_VER_MAJOR "${CUSOLVERMP_MAJOR_LINE}") - string(REGEX MATCH "([0-9]+)" CUSOLVERMP_VER_MINOR "${CUSOLVERMP_MINOR_LINE}") - string(REGEX MATCH "([0-9]+)" CUSOLVERMP_VER_PATCH "${CUSOLVERMP_PATCH_LINE}") + string(REGEX MATCH "([0-9]+)" CUSOLVERMP_VER_MAJOR + "${CUSOLVERMP_MAJOR_LINE}") + string(REGEX MATCH "([0-9]+)" CUSOLVERMP_VER_MINOR + "${CUSOLVERMP_MINOR_LINE}") + string(REGEX MATCH "([0-9]+)" CUSOLVERMP_VER_PATCH + "${CUSOLVERMP_PATCH_LINE}") if(NOT CUSOLVERMP_VER_MAJOR STREQUAL "" AND NOT CUSOLVERMP_VER_MINOR STREQUAL "" AND NOT CUSOLVERMP_VER_PATCH STREQUAL "") set(CUSOLVERMP_VERSION_STR - "${CUSOLVERMP_VER_MAJOR}.${CUSOLVERMP_VER_MINOR}.${CUSOLVERMP_VER_PATCH}") + "${CUSOLVERMP_VER_MAJOR}.${CUSOLVERMP_VER_MINOR}.${CUSOLVERMP_VER_PATCH}" + ) endif() endif() # Check minimum version requirement (>= 0.4.0) if(CUSOLVERMP_VERSION_STR AND CUSOLVERMP_VERSION_STR VERSION_LESS "0.4.0") - message(FATAL_ERROR - "cuSOLVERMp version ${CUSOLVERMP_VERSION_STR} is too old. " - "ABACUS requires cuSOLVERMp >= 0.4.0 (NVIDIA HPC SDK >= 23.5). " - "Please upgrade your NVIDIA HPC SDK installation." - ) + message( + FATAL_ERROR + "cuSOLVERMp version ${CUSOLVERMP_VERSION_STR} is too old. " + "ABACUS requires cuSOLVERMp >= 0.4.0 (NVIDIA HPC SDK >= 23.5). " + "Please upgrade your NVIDIA HPC SDK installation.") endif() - # Auto-select communicator backend by cuSOLVERMp version. - # cuSOLVERMp < 0.7.0 -> CAL, otherwise -> NCCL. + # Auto-select communicator backend by cuSOLVERMp version. cuSOLVERMp < 0.7.0 + # -> CAL, otherwise -> NCCL. set(_use_cal OFF) if(CUSOLVERMP_VERSION_STR AND CUSOLVERMP_VERSION_STR VERSION_LESS "0.7.0") set(_use_cal ON) - message(STATUS - "Detected cuSOLVERMp ${CUSOLVERMP_VERSION_STR} (< 0.7.0). Using CAL backend.") + message( + STATUS + "Detected cuSOLVERMp ${CUSOLVERMP_VERSION_STR} (< 0.7.0). Using CAL backend." + ) elseif(CUSOLVERMP_VERSION_STR) - message(STATUS - "Detected cuSOLVERMp ${CUSOLVERMP_VERSION_STR} (>= 0.7.0). Using NCCL backend.") + message( + STATUS + "Detected cuSOLVERMp ${CUSOLVERMP_VERSION_STR} (>= 0.7.0). Using NCCL backend." + ) elseif(NOT CUSOLVERMP_VERSION_STR) - message(WARNING - "Unable to detect cuSOLVERMp version from header. Using NCCL backend by default.") + message( + WARNING + "Unable to detect cuSOLVERMp version from header. Using NCCL backend by default." + ) endif() # Raise the variable to the caller's scope - set(_use_cal ${_use_cal} PARENT_SCOPE) + set(_use_cal + ${_use_cal} + PARENT_SCOPE) - # Backend selection: - # - _use_cal=ON -> cal communicator backend - # - _use_cal=OFF -> NCCL communicator backend + # Backend selection: - _use_cal=ON -> cal communicator backend - _use_cal=OFF + # -> NCCL communicator backend if(_use_cal) add_compile_definitions(__USE_CAL) - find_library(CAL_LIBRARY NAMES cal - HINTS ${CAL_CUSOLVERMP_PATH} ${NVHPC_ROOT_DIR} - PATH_SUFFIXES lib lib64 math_libs/lib64) - find_path(CAL_INCLUDE_DIR NAMES cal.h - HINTS ${CAL_CUSOLVERMP_PATH} ${NVHPC_ROOT_DIR} - PATH_SUFFIXES include math_libs/include) + find_library( + CAL_LIBRARY + NAMES cal + HINTS ${CAL_CUSOLVERMP_PATH} ${NVHPC_ROOT_DIR} + PATH_SUFFIXES lib lib64 math_libs/lib64) + find_path( + CAL_INCLUDE_DIR + NAMES cal.h + HINTS ${CAL_CUSOLVERMP_PATH} ${NVHPC_ROOT_DIR} + PATH_SUFFIXES include math_libs/include) if(NOT CAL_LIBRARY OR NOT CAL_INCLUDE_DIR) message(FATAL_ERROR "CAL not found. Set CAL_PATH or NVHPC_ROOT_DIR.") @@ -91,19 +110,23 @@ function(abacus_setup_cusolvermp target_name) message(STATUS "Found CAL: ${CAL_LIBRARY}") if(NOT TARGET CAL::CAL) add_library(CAL::CAL IMPORTED INTERFACE) - set_target_properties(CAL::CAL PROPERTIES - INTERFACE_LINK_LIBRARIES "${CAL_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${CAL_INCLUDE_DIR}") + set_target_properties( + CAL::CAL PROPERTIES INTERFACE_LINK_LIBRARIES "${CAL_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${CAL_INCLUDE_DIR}") endif() else() - find_library(NCCL_LIBRARY NAMES nccl - HINTS ${NCCL_PATH} ${NVHPC_ROOT_DIR} - PATH_SUFFIXES lib lib64 comm_libs/nccl/lib) - find_path(NCCL_INCLUDE_DIR NAMES nccl.h - HINTS ${NCCL_PATH} ${NVHPC_ROOT_DIR} - PATHS ${CUDA_TOOLKIT_ROOT_DIR} - PATH_SUFFIXES include comm_libs/nccl/include) + find_library( + NCCL_LIBRARY + NAMES nccl + HINTS ${NCCL_PATH} ${NVHPC_ROOT_DIR} + PATH_SUFFIXES lib lib64 comm_libs/nccl/lib) + find_path( + NCCL_INCLUDE_DIR + NAMES nccl.h + HINTS ${NCCL_PATH} ${NVHPC_ROOT_DIR} + PATHS ${CUDA_TOOLKIT_ROOT_DIR} + PATH_SUFFIXES include comm_libs/nccl/include) if(NOT NCCL_LIBRARY OR NOT NCCL_INCLUDE_DIR) message(FATAL_ERROR "NCCL not found. Set NCCL_PATH or NVHPC_ROOT_DIR.") @@ -112,28 +135,26 @@ function(abacus_setup_cusolvermp target_name) message(STATUS "Found NCCL: ${NCCL_LIBRARY}") if(NOT TARGET NCCL::NCCL) add_library(NCCL::NCCL IMPORTED INTERFACE) - set_target_properties(NCCL::NCCL PROPERTIES - INTERFACE_LINK_LIBRARIES "${NCCL_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${NCCL_INCLUDE_DIR}") + set_target_properties( + NCCL::NCCL + PROPERTIES INTERFACE_LINK_LIBRARIES "${NCCL_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${NCCL_INCLUDE_DIR}") endif() endif() # Create cusolverMp::cusolverMp imported target if(NOT TARGET cusolverMp::cusolverMp) add_library(cusolverMp::cusolverMp IMPORTED INTERFACE) - set_target_properties(cusolverMp::cusolverMp PROPERTIES - INTERFACE_LINK_LIBRARIES "${CUSOLVERMP_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${CUSOLVERMP_INCLUDE_DIR}") + set_target_properties( + cusolverMp::cusolverMp + PROPERTIES INTERFACE_LINK_LIBRARIES "${CUSOLVERMP_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${CUSOLVERMP_INCLUDE_DIR}") endif() # === Link libraries === if(_use_cal) - target_link_libraries(${target_name} - CAL::CAL - cusolverMp::cusolverMp) + target_link_libraries(${target_name} CAL::CAL cusolverMp::cusolverMp) else() - target_link_libraries(${target_name} - NCCL::NCCL - cusolverMp::cusolverMp) + target_link_libraries(${target_name} NCCL::NCCL cusolverMp::cusolverMp) endif() endfunction() diff --git a/cmake/SetupNccl.cmake b/cmake/SetupNccl.cmake index 56e8e10e7b0..f43a5c18a40 100644 --- a/cmake/SetupNccl.cmake +++ b/cmake/SetupNccl.cmake @@ -3,13 +3,17 @@ include_guard(GLOBAL) include(CheckIncludeFileCXX) function(abacus_setup_nccl target_name) - find_library(NCCL_LIBRARY NAMES nccl - HINTS ${NCCL_PATH} ${NVHPC_ROOT_DIR} - PATH_SUFFIXES lib lib64 comm_libs/nccl/lib) - find_path(NCCL_INCLUDE_DIR NAMES nccl.h - HINTS ${NCCL_PATH} ${NVHPC_ROOT_DIR} - PATHS ${CUDAToolkit_ROOT} - PATH_SUFFIXES include comm_libs/nccl/include) + find_library( + NCCL_LIBRARY + NAMES nccl + HINTS ${NCCL_PATH} ${NVHPC_ROOT_DIR} + PATH_SUFFIXES lib lib64 comm_libs/nccl/lib) + find_path( + NCCL_INCLUDE_DIR + NAMES nccl.h + HINTS ${NCCL_PATH} ${NVHPC_ROOT_DIR} + PATHS ${CUDAToolkit_ROOT} + PATH_SUFFIXES include comm_libs/nccl/include) check_include_file_cxx("nccl.h" HAVE_NCCL_HEADER) @@ -18,24 +22,26 @@ function(abacus_setup_nccl target_name) endif() if(NOT NCCL_INCLUDE_DIR AND NOT HAVE_NCCL_HEADER) - message(FATAL_ERROR - "NCCL not found. Set NCCL_PATH or NVHPC_ROOT_DIR.") + message(FATAL_ERROR "NCCL not found. Set NCCL_PATH or NVHPC_ROOT_DIR.") endif() if(NCCL_INCLUDE_DIR) message(STATUS "Found NCCL for parallel_device: ${NCCL_LIBRARY}") else() - message(STATUS "Using default compiler/linker search paths for NCCL: ${NCCL_LIBRARY}") + message( + STATUS + "Using default compiler/linker search paths for NCCL: ${NCCL_LIBRARY}") endif() if(NOT TARGET NCCL::NCCL) add_library(NCCL::NCCL IMPORTED INTERFACE) if(NCCL_INCLUDE_DIR) - set_target_properties(NCCL::NCCL PROPERTIES - INTERFACE_LINK_LIBRARIES "${NCCL_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${NCCL_INCLUDE_DIR}") + set_target_properties( + NCCL::NCCL + PROPERTIES INTERFACE_LINK_LIBRARIES "${NCCL_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${NCCL_INCLUDE_DIR}") else() - set_target_properties(NCCL::NCCL PROPERTIES - INTERFACE_LINK_LIBRARIES "${NCCL_LIBRARY}") + set_target_properties(NCCL::NCCL PROPERTIES INTERFACE_LINK_LIBRARIES + "${NCCL_LIBRARY}") endif() endif() diff --git a/cmake/Testing.cmake b/cmake/Testing.cmake index 551b1d7182d..26b8f248c3c 100644 --- a/cmake/Testing.cmake +++ b/cmake/Testing.cmake @@ -29,38 +29,38 @@ if(ENABLE_GOOGLEBENCH) endif() endif() - function(AddTest) # function for UT - cmake_parse_arguments(UT "DYN" "TARGET" - "LIBS;DYN_LIBS;STATIC_LIBS;SOURCES;DEPENDS" ${ARGN}) - add_executable(${UT_TARGET} ${UT_SOURCES}) +function(AddTest) # function for UT + cmake_parse_arguments(UT "DYN" "TARGET" + "LIBS;DYN_LIBS;STATIC_LIBS;SOURCES;DEPENDS" ${ARGN}) + add_executable(${UT_TARGET} ${UT_SOURCES}) - if(ENABLE_COVERAGE) - add_coverage(${UT_TARGET}) - endif() + if(ENABLE_COVERAGE) + add_coverage(${UT_TARGET}) + endif() - # dependencies & link library - target_link_libraries(${UT_TARGET} ${UT_LIBS} Threads::Threads - GTest::gtest_main GTest::gmock_main) - if(ENABLE_GOOGLEBENCH) - target_link_libraries( - ${UT_TARGET} benchmark::benchmark) - endif() + # dependencies & link library + target_link_libraries(${UT_TARGET} ${UT_LIBS} Threads::Threads + GTest::gtest_main GTest::gmock_main) + if(ENABLE_GOOGLEBENCH) + target_link_libraries(${UT_TARGET} benchmark::benchmark) + endif() - if(USE_OPENMP) - target_link_libraries(${UT_TARGET} OpenMP::OpenMP_CXX) - endif() + if(USE_OPENMP) + target_link_libraries(${UT_TARGET} OpenMP::OpenMP_CXX) + endif() + + # Link to build info if needed + if("${UT_SOURCES}" MATCHES "parse_args.cpp") + target_include_directories(${UT_TARGET} + PUBLIC ${CMAKE_BINARY_DIR}/source/source_io) + endif() - # Link to build info if needed - if("${UT_SOURCES}" MATCHES "parse_args.cpp") - target_include_directories(${UT_TARGET} PUBLIC ${CMAKE_BINARY_DIR}/source/source_io) - endif() - - install(TARGETS ${UT_TARGET} DESTINATION ${CMAKE_BINARY_DIR}/tests) - add_test( - NAME ${UT_TARGET} - COMMAND ${UT_TARGET} - WORKING_DIRECTORY $) - endfunction(AddTest) + install(TARGETS ${UT_TARGET} DESTINATION ${CMAKE_BINARY_DIR}/tests) + add_test( + NAME ${UT_TARGET} + COMMAND ${UT_TARGET} + WORKING_DIRECTORY $) +endfunction(AddTest) if(BUILD_TESTING) set_if_higher(CMAKE_CXX_STANDARD 14) # Required in orbital diff --git a/docs/CITATIONS.md b/docs/CITATIONS.md index a25cb3e596c..14a6dad3d02 100644 --- a/docs/CITATIONS.md +++ b/docs/CITATIONS.md @@ -4,46 +4,63 @@ The following references are required to be cited when using ABACUS. Specificall - **For general purpose:** - *For LCAO basis:* + *For LCAO basis:* - Mohan Chen, G. C. Guo, and Lixin He. "Systematically improvable optimized atomic basis sets for ab initio calculations." Journal of Physics: Condensed Matter 22.44 (2010): 445501. + Mohan Chen, G. C. Guo, and Lixin He. "Systematically improvable optimized atomic basis sets for ab + initio calculations." Journal of Physics: Condensed Matter 22.44 (2010): 445501. - Pengfei Li, et al. "Large-scale ab initio simulations based on systematically improvable atomic basis." Computational Materials Science 112 (2016): 503-517. + Pengfei Li, et al. "Large-scale ab initio simulations based on systematically improvable atomic + basis." Computational Materials Science 112 (2016): 503-517. - Peize Lin, Xinguo Ren, Xiaohui Liu, Lixin He. Ab initio electronic structure calculations based on numerical atomic orbitals: Basic fomalisms and recent progresses. Wiley Interdisciplinary Reviews: Computational Molecular Science, 2024, 14(1): e1687. + Peize Lin, Xinguo Ren, Xiaohui Liu, Lixin He. Ab initio electronic structure calculations based on + numerical atomic orbitals: Basic fomalisms and recent progresses. Wiley Interdisciplinary Reviews: + Computational Molecular Science, 2024, 14(1): e1687. - *For LCAO and PW basis:* + *For LCAO and PW basis:* - Weiqing Zhou, Daye Zheng, Qianrui Liu, et al. ABACUS: An Electronic Structure Analysis Package for the AI Era. arXiv preprint arXiv:2501.08697, 2025. + Weiqing Zhou, Daye Zheng, Qianrui Liu, et al. ABACUS: An Electronic Structure Analysis Package for + the AI Era. arXiv preprint arXiv:2501.08697, 2025. - **If Stochastic DFT is used:** - Qianrui Liu, and Mohan Chen. "Plane-Wave-Based Stochastic-Deterministic Density Functional Theory for Extended Systems." . + Qianrui Liu, and Mohan Chen. "Plane-Wave-Based Stochastic-Deterministic Density Functional Theory + for Extended Systems." . - **If DFT+U is used:** - Xin Qu, et al. "DFT+ U within the framework of linear combination of numerical atomic orbitals." The Journal of Chemical Physics (2022). + Xin Qu, et al. "DFT+ U within the framework of linear combination of numerical atomic orbitals." + The Journal of Chemical Physics (2022). - **If second generation numerical orbital basis is used:** - Peize Lin, Xinguo Ren, and Lixin He. "Strategy for constructing compact numerical atomic orbital basis sets by incorporating the gradients of reference wavefunctions." Physical Review B 103.23 (2021): 235131. + Peize Lin, Xinguo Ren, and Lixin He. "Strategy for constructing compact numerical atomic orbital + basis sets by incorporating the gradients of reference wavefunctions." Physical Review B 103.23 + (2021): 235131. - **If berry curvature calculation is used in LCAO base:** - Gan Jin, Daye Zheng, and Lixin He. "Calculation of Berry curvature using non-orthogonal atomic orbitals." Journal of Physics: Condensed Matter 33.32 (2021): 325503. + Gan Jin, Daye Zheng, and Lixin He. "Calculation of Berry curvature using non-orthogonal atomic + orbitals." Journal of Physics: Condensed Matter 33.32 (2021): 325503. - **If DeePKS is used:** - Wenfei Li, Qi Ou, et al. "DeePKS+ABACUS as a Bridge between Expensive Quantum Mechanical Models and Machine Learning Potentials." J. Phys. Chem. A 126.49 (2022): 9154-9164. + Wenfei Li, Qi Ou, et al. "DeePKS+ABACUS as a Bridge between Expensive Quantum Mechanical Models + and Machine Learning Potentials." J. Phys. Chem. A 126.49 (2022): 9154-9164. - **If hybrid functional is used:** - Peize Lin, Xinguo Ren, and Lixin He. "Efficient Hybrid Density Functional Calculations for Large Periodic Systems Using Numerical Atomic Orbitals." Journal of Chemical Theory and Computation 2021, 17(1), 222–239. + Peize Lin, Xinguo Ren, and Lixin He. "Efficient Hybrid Density Functional Calculations for Large + Periodic Systems Using Numerical Atomic Orbitals." Journal of Chemical Theory and Computation + 2021, 17(1), 222–239. - Peize Lin, Xinguo Ren, and Lixin He. "Accuracy of Localized Resolution of the Identity in Periodic Hybrid Functional Calculations with Numerical Atomic Orbitals." Journal of Physical Chemistry Letters 2020, 11, 3082-3088. + Peize Lin, Xinguo Ren, and Lixin He. "Accuracy of Localized Resolution of the Identity in Periodic + Hybrid Functional Calculations with Numerical Atomic Orbitals." Journal of Physical Chemistry + Letters 2020, 11, 3082-3088. - **If ML-KEDF is used:** - Sun, Liang, and Mohan Chen. "Machine learning based nonlocal kinetic energy density functional for simple metals and alloys." Physical Review B 109.11 (2024): 115135. + Sun, Liang, and Mohan Chen. "Machine learning based nonlocal kinetic energy density functional for + simple metals and alloys." Physical Review B 109.11 (2024): 115135. - Sun, Liang, and Mohan Chen. "Multi-channel machine learning based nonlocal kinetic energy density functional for semiconductors." Electronic Structure 6.4 (2024): 045006. + Sun, Liang, and Mohan Chen. "Multi-channel machine learning based nonlocal kinetic energy density + functional for semiconductors." Electronic Structure 6.4 (2024): 045006. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 9839f4c81e8..18edb630350 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,8 +1,8 @@ # Contributing to ABACUS -First of all, thank you for taking time to make contributions to ABACUS! -This file provides the more technical guidelines on how to realize it. -For more non-technical aspects, please refer to the [ABACUS Contribution Guide](./community/contribution_guide.md) +First of all, thank you for taking time to make contributions to ABACUS! This file provides the more +technical guidelines on how to realize it. For more non-technical aspects, please refer to the +[ABACUS Contribution Guide](./community/contribution_guide.md) ## Table of Contents @@ -21,14 +21,22 @@ For more non-technical aspects, please refer to the [ABACUS Contribution Guide]( ## Got a question? -Please referring to our GitHub [issue tracker](https://github.com/deepmodeling/abacus-develop/issues), and our developers are willing to help. -If you find a bug, you can help us by submitting an issue to our GitHub Repository. Even better, you can submit a Pull Request with a patch. You can request a new feature by submitting an issue to our GitHub Repository. -If you would like to implement a new feature, please submit an issue with a proposal for your work first, and that ensures your work collaborates with our development road map well. For a major feature, first open an issue and outline your proposal so that it can be discussed. This will also allow us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project. +Please referring to our GitHub +[issue tracker](https://github.com/deepmodeling/abacus-develop/issues), and our developers are +willing to help. If you find a bug, you can help us by submitting an issue to our GitHub Repository. +Even better, you can submit a Pull Request with a patch. You can request a new feature by submitting +an issue to our GitHub Repository. If you would like to implement a new feature, please submit an +issue with a proposal for your work first, and that ensures your work collaborates with our +development road map well. For a major feature, first open an issue and outline your proposal so +that it can be discussed. This will also allow us to better coordinate our efforts, prevent +duplication of work, and help you to craft the change so that it is successfully accepted into the +project. ## Structure of the package -Please refer to [our instructions](./quick_start/easy_install.md) on how to installing ABACUS. -The source code of ABACUS is based on several modules. Under the ABACUS root directory, there are the following folders: +Please refer to [our instructions](./quick_start/easy_install.md) on how to installing ABACUS. The +source code of ABACUS is based on several modules. Under the ABACUS root directory, there are the +following folders: - `cmake`: relevant files for finding required packages when compiling the code with cmake; - `docs`: documents and supplementary info about ABACUS; @@ -37,7 +45,8 @@ The source code of ABACUS is based on several modules. Under the ABACUS root dir - `tests`: End-to-end test cases; - `tools`: the script for generating the numerical atomic orbitals. -For those who are interested in the source code, the following figure shows the structure of the source code. +For those who are interested in the source code, the following figure shows the structure of the +source code. ```text |-- source_base A basic module including @@ -88,63 +97,77 @@ For those who are interested in the source code, the following figure shows the ## Submitting an Issue -Before you submit an issue, please search the issue tracker, and maybe your problem has been discussed and fixed. You can [submit new issues](https://github.com/deepmodeling/abacus-develop/issues/new/choose) by filling our issue forms. -To help us reproduce and confirm a bug, please provide a test case and building environment in your issue. +Before you submit an issue, please search the issue tracker, and maybe your problem has been +discussed and fixed. You can +[submit new issues](https://github.com/deepmodeling/abacus-develop/issues/new/choose) by filling our +issue forms. To help us reproduce and confirm a bug, please provide a test case and building +environment in your issue. ## Comment style for documentation ABACUS uses Doxygen to generate docs directly from `.h` and `.cpp` code files. -For comments that need to be shown in documents, these formats should be used -- **Javadoc style** (as follow) is recommended, though Qt style is also ok. See it in [official manual](https://www.doxygen.nl/manual/docblocks.html). +For comments that need to be shown in documents, these formats should be used -- **Javadoc style** +(as follow) is recommended, though Qt style is also ok. See it in +[official manual](https://www.doxygen.nl/manual/docblocks.html). -A helpful VS Code extension -- [Doxygen Documentation Generator](https://marketplace.visualstudio.com/items?itemName=cschlosser.doxdocgen), can help you formating comments. +A helpful VS Code extension -- +[Doxygen Documentation Generator](https://marketplace.visualstudio.com/items?itemName=cschlosser.doxdocgen), +can help you formating comments. -An practical example is class [LCAO_Deepks](https://github.com/deepmodeling/abacus-develop/blob/deepks/source/source_lcao/module_deepks/LCAO_deepks.h), the effects can be seen on [readthedocs page](https://abacus-deepks.readthedocs.io/en/latest/DeePKS_API/classLCAO__Descriptor.html#exhale-class-classLCAO-Descriptor) +An practical example is class +[LCAO_Deepks](https://github.com/deepmodeling/abacus-develop/blob/deepks/source/source_lcao/module_deepks/LCAO_deepks.h), +the effects can be seen on +[readthedocs page](https://abacus-deepks.readthedocs.io/en/latest/DeePKS_API/classLCAO__Descriptor.html#exhale-class-classLCAO-Descriptor) - Tips - - Only comments in .h file will be visible in generated by Doxygen + Sphinx; + + - Only comments in .h file will be visible in generated by Doxygen + Sphinx; - Private class members will not be documented; - - Use [Markdown features](https://www.doxygen.nl/manual/markdown.html), such as using a empty new line for a new paragraph. + - Use [Markdown features](https://www.doxygen.nl/manual/markdown.html), such as using a empty new + line for a new paragraph. - Detailed Comment Block - ```cpp - /** - * ... text ... - */ - ``` + ```cpp + /** + * ... text ... + */ + ``` - Brief + Detailed Comment Block - ```cpp - /// Brief description which ends at this dot. Details follow - /// here. + ```cpp + /// Brief description which ends at this dot. Details follow + /// here. - /// Brief description. - /** Detailed description. */ - ``` + /// Brief description. + /** Detailed description. */ + ``` -- Comments After the Item: Add a "<" +- Comments After the Item: Add a "\<" - ```cpp - int var; /** to format the code. -It is performed after pushing new commits to a PR. You might need to pull the changes before adding new commits. +We use to format the code. It is performed after pushing new commits to a +PR. You might need to pull the changes before adding new commits. -To use pre-commit locally (**generally not required**): -Please install the pre-commit tool by running the following command: +To use pre-commit locally (**generally not required**): Please install the pre-commit tool by +running the following command: ```bash pip install pre-commit @@ -247,190 +283,240 @@ pre-commit install ## Adding a unit test -We use [GoogleTest](https://github.com/google/googletest) as our test framework. Write your test under the corresponding module folder at `abacus-develop/tests`, then append the test to `tests/CMakeLists.txt`. If there are currently no unit tests provided for the module, do as follows. `source_base` provides a simple demonstration. +We use [GoogleTest](https://github.com/google/googletest) as our test framework. Write your test +under the corresponding module folder at `abacus-develop/tests`, then append the test to +`tests/CMakeLists.txt`. If there are currently no unit tests provided for the module, do as follows. +`source_base` provides a simple demonstration. - Add a folder named `test` under the module. + - Append the content below to `CMakeLists.txt` of the module: - ```cmake - IF (BUILD_TESTING) - add_subdirectory(test) - endif() - ``` + ```cmake + IF (BUILD_TESTING) + add_subdirectory(test) + endif() + ``` - Add a blank `CMakeLists.txt` under `module*/test`. To add a unit test: - Write your test under `GoogleTest` framework. + - Add your testing source code with suffix `*_test.cpp` in `test` directory. + - Append the content below to `CMakeLists.txt` of the module: - ```cmake - AddTest( - TARGET _ # this is the executable file name of the test - SOURCES .cpp + ```cmake + AddTest( + TARGET _ # this is the executable file name of the test + SOURCES .cpp - # OPTIONAL: if this test requires external libraries, add them with "LIBS" statement. - LIBS math_libs # `math_libs` includes all math libraries in ABACUS. - ) - ``` + # OPTIONAL: if this test requires external libraries, add them with "LIBS" statement. + LIBS math_libs # `math_libs` includes all math libraries in ABACUS. + ) + ``` + +- Build with `-D BUILD_TESTING=1` flag, `cmake` will look for `GoogleTest` in the default path + (usually `/usr/local`); if not found, you can specify the path with `-D GTEST_DIR`. You can find + built testing programs under `build/source//test`. -- Build with `-D BUILD_TESTING=1` flag, `cmake` will look for `GoogleTest` in the default path (usually `/usr/local`); if not found, you can specify the path with `-D GTEST_DIR`. You can find built testing programs under `build/source//test`. - Follow the installing procedure of CMake. The tests will move to `build/test`. -- Considering `-D BUILD_TESTING=1`, the compilation will be slower compared with the case `-D BUILD_TESTING=0`. + +- Considering `-D BUILD_TESTING=1`, the compilation will be slower compared with the case + `-D BUILD_TESTING=0`. ## Running unit tests 1. Compiling ABACUS with unit tests. - In order to run unit tests, ABACUS needs to be configured with `-D BUILD_TESTING=ON` flag. For example: + In order to run unit tests, ABACUS needs to be configured with `-D BUILD_TESTING=ON` flag. For + example: - ```bash - cmake -B build -DBUILD_TESTING=ON - ``` + ```bash + cmake -B build -DBUILD_TESTING=ON + ``` - then build ABACUS and unit testing with + then build ABACUS and unit testing with - ```bash - cmake --build build -j${number of processors} - ``` + ```bash + cmake --build build -j${number of processors} + ``` - It is import to run the folloing command before running unit tests: + It is import to run the folloing command before running unit tests: - ```bash - cmake --install build - ``` + ```bash + cmake --install build + ``` - to install mandatory supporting input files for unit tests. - If you modified the unit tests to add new tests or learn how to write unit tests, it is convenient to run + to install mandatory supporting input files for unit tests. If you modified the unit tests to add + new tests or learn how to write unit tests, it is convenient to run - ```bash - cmake --build build -j${number of processors} --target ${unit test name} - ``` + ```bash + cmake --build build -j${number of processors} --target ${unit test name} + ``` - to build a specific unit test. And please remember to run `cmake --install build` after building the unit test if the unit test requires supporting input files. + to build a specific unit test. And please remember to run `cmake --install build` after building + the unit test if the unit test requires supporting input files. -2. Running unit tests +1. Running unit tests - The test cases are located in `build/source/${module_name}/test` directory. Note that there are other directory names for unit tests, for example, `test_parallel` for running parallel unit tests, `test_pw` for running unit tests only used in plane wave basis calculation. + The test cases are located in `build/source/${module_name}/test` directory. Note that there are + other directory names for unit tests, for example, `test_parallel` for running parallel unit + tests, `test_pw` for running unit tests only used in plane wave basis calculation. - You can run a single test in the specific directory. For example, run + You can run a single test in the specific directory. For example, run - ```bash - ./cell_unitcell_test - ``` + ```bash + ./cell_unitcell_test + ``` - under the directory of `build/source/source_cell/test` to run the test `cell_unitcell_test`. - However, it is more convenient to run unit tests with `ctest` command under the `build` directory. You can check all unit tests by + under the directory of `build/source/source_cell/test` to run the test `cell_unitcell_test`. + However, it is more convenient to run unit tests with `ctest` command under the `build` + directory. You can check all unit tests by - ```bash - ctest -N - ``` + ```bash + ctest -N + ``` - The results will be shown as + The results will be shown as - ```text - Test project /root/abacus/build - Test #1: integrated_test - Test #2: Container_UTs - Test #3: base_blas_connector - Test #4: base_blacs_connector - Test #5: base_timer - ... - ``` + ```text + Test project /root/abacus/build + Test #1: integrated_test + Test #2: Container_UTs + Test #3: base_blas_connector + Test #4: base_blacs_connector + Test #5: base_timer + ... + ``` - Note that the first one is integrated test, which is not a unit test. It is the test - suite for testing the whole ABACUS package. The examples are located in the `tests/integrate` directory. + Note that the first one is integrated test, which is not a unit test. It is the test suite for + testing the whole ABACUS package. The examples are located in the `tests/integrate` directory. - To run a subset of tests, run the following command + To run a subset of tests, run the following command - ```bash - ctest -R -V - ``` + ```bash + ctest -R -V + ``` - For example, `ctest -R cell` will perform tests with name matched by `cell`. - You can also run a single test with + For example, `ctest -R cell` will perform tests with name matched by `cell`. You can also run a + single test with - ```bash - ctest -R - ``` + ```bash + ctest -R + ``` - For example, `ctest -R cell_unitcell_test_readpp` will perform test `cell_unitcell_test_readpp`. - To run all the unit tests, together with the integrated test, run + For example, `ctest -R cell_unitcell_test_readpp` will perform test `cell_unitcell_test_readpp`. + To run all the unit tests, together with the integrated test, run - ```bash - cmake --build build --target test ARGS="-V --timeout 21600" - ``` + ```bash + cmake --build build --target test ARGS="-V --timeout 21600" + ``` - in the `abacus-develop` directory. + 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: + +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 BANDS_1.dat 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 ` to check if the new test can be run successfully. +1. 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. +1. 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 BANDS_1.dat 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. + 1. Add the reference file (such as: `refBANDS_1.dat` in previous case) to the new test + directory. + 1. 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) +1. Add a `jd` file in the new test directory, which is one setence to describe the new test. +1. Add the new test to `tests/integrate/CASES_CPU.txt` file (or `tests/integrate/CASES_GPU.txt` file + if it is for GPU verion). +1. Enter directory tests/integrate and run `bash Autotest.sh -r ` 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. +For the unexpected results when developing ABACUS, [GDB](https://www.sourceware.org/gdb/) will come +in handy. 1. Compile ABACUS with debug mode. - ```bash - cmake -B build -DCMAKE_BUILD_TYPE=Debug - ``` + ```bash + cmake -B build -DCMAKE_BUILD_TYPE=Debug + ``` -2. After building and installing the executable, enter the input directory, and launch the debug session with `gdb abacus`. For [debugging in Visual Studio Code](https://code.visualstudio.com/docs/cpp/cpp-debug), please set [cwd](https://code.visualstudio.com/docs/cpp/launch-json-reference#_cwd) to the input directory, and [program](https://code.visualstudio.com/docs/cpp/launch-json-reference#_program-required) to the path of ABACUS executable. +1. After building and installing the executable, enter the input directory, and launch the debug + session with `gdb abacus`. For + [debugging in Visual Studio Code](https://code.visualstudio.com/docs/cpp/cpp-debug), please set + [cwd](https://code.visualstudio.com/docs/cpp/launch-json-reference#_cwd) to the input directory, + and [program](https://code.visualstudio.com/docs/cpp/launch-json-reference#_program-required) to + the path of ABACUS executable. -3. Set breakpoints, and run ABACUS by typing "run" in GDB command line interface. If the program hits the breakpoints or exception is throwed, GDB will stop at the erroneous code line. Type "where" to show the stack backtrace, and "print i" to get the value of variable i. +1. Set breakpoints, and run ABACUS by typing "run" in GDB command line interface. If the program + hits the breakpoints or exception is throwed, GDB will stop at the erroneous code line. Type + "where" to show the stack backtrace, and "print i" to get the value of variable i. -4. For debugging ABACUS in multiprocessing situation, `mpirun -n 1 gdb abacus : -n 3 abacus` will attach GDB to the master process, and launch 3 other MPI processes. +1. For debugging ABACUS in multiprocessing situation, `mpirun -n 1 gdb abacus : -n 3 abacus` will + attach GDB to the master process, and launch 3 other MPI processes. -For segmentation faults, ABACUS can be built with [Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) to locate the bugs. +For segmentation faults, ABACUS can be built with +[Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) to locate the bugs. ```bash cmake -B build -DENABLE_ASAN=1 ``` -Run ABACUS as usual, and it will automatically detect the buffer overflow problems and memory leaks. It is also possible to [use GDB with binaries built by Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizerAndDebugger). +Run ABACUS as usual, and it will automatically detect the buffer overflow problems and memory leaks. +It is also possible to +[use GDB with binaries built by Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizerAndDebugger). [Valgrind](https://valgrind.org/) is another option for performing dynamic analysis. @@ -438,27 +524,33 @@ Run ABACUS as usual, and it will automatically detect the buffer overflow proble ABACUS uses CMake as its default building system. To add a new building component: -1. Add an `OPTION` to toggle the component to the `CMakeLists.txt` file under root directory. For example: +1. Add an `OPTION` to toggle the component to the `CMakeLists.txt` file under root directory. For + example: - ```cmake - OPTION(ENABLE_NEW_COMPONENT "Enable new component" OFF) - ``` + ```cmake + OPTION(ENABLE_NEW_COMPONENT "Enable new component" OFF) + ``` -2. Add the new component. For example: +1. Add the new component. For example: - ```cmake - IF (ENABLE_NEW_COMPONENT) - add_subdirectory(module_my_new_feature) # if the feature is implemented in a subdirectory - find_package(NewComponent REQUIRED) # if third-party libs are required - target_link_libraries(${ABACUS_BIN_NAME} PRIVATE NewComponent) # if the component is linked - include_directories(${NewComponent_INCLUDE_DIRS}) # if the component is included - endif() - ``` + ```cmake + IF (ENABLE_NEW_COMPONENT) + add_subdirectory(module_my_new_feature) # if the feature is implemented in a subdirectory + find_package(NewComponent REQUIRED) # if third-party libs are required + target_link_libraries(${ABACUS_BIN_NAME} PRIVATE NewComponent) # if the component is linked + include_directories(${NewComponent_INCLUDE_DIRS}) # if the component is included + endif() + ``` -3. Add the required third-party libraries to Dockerfiles. -4. After the changes above are merged, submit another PR to build and test the new component in the CI pipeline. - - For integration test and unit test: add `-DENABLE_NEW_COMPONENT=ON` to the building step at `.github/workflows/test.yml`. - - For building test: add `-DENABLE_NEW_COMPONENT=ON` as a new configuration at `.github/workflows/build_test_cmake.yml`. +1. Add the required third-party libraries to Dockerfiles. + +1. After the changes above are merged, submit another PR to build and test the new component in the + CI pipeline. + + - For integration test and unit test: add `-DENABLE_NEW_COMPONENT=ON` to the building step at + `.github/workflows/test.yml`. + - For building test: add `-DENABLE_NEW_COMPONENT=ON` as a new configuration at + `.github/workflows/build_test_cmake.yml`. ## Generating code coverage report @@ -466,86 +558,107 @@ This feature requires using GCC compiler. We use `gcov` and `lcov` to generate c 1. Add `-DENABLE_COVERAGE=ON` for CMake configure command. - ```bash - cmake -B build -DBUILD_TESTING=ON -DENABLE_COVERAGE=ON - ``` + ```bash + cmake -B build -DBUILD_TESTING=ON -DENABLE_COVERAGE=ON + ``` -2. Build, install ABACUS, and run test cases. Please note that since all optimizations are disabled to gather running status line by line, the performance is drastically decreased. Set a longer time out to ensure all tests are executed. +1. Build, install ABACUS, and run test cases. Please note that since all optimizations are disabled + to gather running status line by line, the performance is drastically decreased. Set a longer + time out to ensure all tests are executed. - ```bash - cmake --build build --target test ARGS="-V --timeout 21600" - ``` + ```bash + cmake --build build --target test ARGS="-V --timeout 21600" + ``` - If configuration fails unfortunately, you can find [required files](https://github.com/baixiaokuang/CMake-codecov/tree/master/cmake) (including three *.cmake and llvm-cov-wrapper), and copy these four files into `/abacus-develop/cmake`. Alternatively, you can define the path with option `-D CMAKE_CURRENT_SOURCE_DIR`. + If configuration fails unfortunately, you can find + [required files](https://github.com/baixiaokuang/CMake-codecov/tree/master/cmake) (including + three \*.cmake and llvm-cov-wrapper), and copy these four files into `/abacus-develop/cmake`. + Alternatively, you can define the path with option `-D CMAKE_CURRENT_SOURCE_DIR`. -3. Generate HTML report. +1. Generate HTML report. - ```bash - cd build/ - make lcov - ``` + ```bash + cd build/ + make lcov + ``` -Now you can copy `build/lcov` to your local device, and view `build/lcov/html/all_targets/index.html`. +Now you can copy `build/lcov` to your local device, and view +`build/lcov/html/all_targets/index.html`. -We use [Codecov](https://codecov.io/) to host and visualize our [**code coverage report**](https://app.codecov.io/gh/deepmodeling/abacus-develop). Analysis is scheduled after a new version releases; this [action](https://github.com/deepmodeling/abacus-develop/actions/workflows/coverage.yml) can also be manually triggered. +We use [Codecov](https://codecov.io/) to host and visualize our +[**code coverage report**](https://app.codecov.io/gh/deepmodeling/abacus-develop). Analysis is +scheduled after a new version releases; this +[action](https://github.com/deepmodeling/abacus-develop/actions/workflows/coverage.yml) can also be +manually triggered. ## Submitting a Pull Request -1. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) the [ABACUS repository](https://github.com/deepmodeling/abacus-develop). If you already had an existing fork, [sync](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork) the fork to keep your modification up-to-date. +1. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) the + [ABACUS repository](https://github.com/deepmodeling/abacus-develop). If you already had an + existing fork, + [sync](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork) + the fork to keep your modification up-to-date. -2. Pull your forked repository, create a new git branch, and make your changes in it: +1. Pull your forked repository, create a new git branch, and make your changes in it: - ```shell - git checkout -b my-fix-branch - ``` + ```shell + git checkout -b my-fix-branch + ``` -3. Coding your patch, including appropriate test cases and docs. -To run a subset of unit test, use `ctest -R ` to perform tests with name matched by given pattern. +1. Coding your patch, including appropriate test cases and docs. To run a subset of unit test, use + `ctest -R ` to perform tests with name matched by given pattern. -4. After tests passed, commit your changes [with a proper message](#commit-message-guidelines). +1. After tests passed, commit your changes [with a proper message](#commit-message-guidelines). -5. Push your branch to GitHub: +1. Push your branch to GitHub: - ```shell - git push origin my-fix-branch - ``` + ```shell + git push origin my-fix-branch + ``` -6. In GitHub, send a pull request (PR) with `deepmodeling/abacus-develop:develop` as the base repository. It is **required** to document your PR following [our guidelines](#commit-message-guidelines). +1. In GitHub, send a pull request (PR) with `deepmodeling/abacus-develop:develop` as the base + repository. It is **required** to document your PR following + [our guidelines](#commit-message-guidelines). -7. If more changes are needed, you can add more commits to your branch and push them to GitHub. Your PR will be updated automatically. +1. If more changes are needed, you can add more commits to your branch and push them to GitHub. Your + PR will be updated automatically. -8. After your pull request is merged, you can safely delete your branch and sync the changes from the main (upstream) repository: +1. After your pull request is merged, you can safely delete your branch and sync the changes from + the main (upstream) repository: - - Delete the remote branch on GitHub either [through the GitHub web UI](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/deleting-and-restoring-branches-in-a-pull-request#deleting-a-branch-used-for-a-pull-request) or your local shell as follows: + - Delete the remote branch on GitHub either + [through the GitHub web UI](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/deleting-and-restoring-branches-in-a-pull-request#deleting-a-branch-used-for-a-pull-request) + or your local shell as follows: - ```shell - git push origin --delete my-fix-branch - ``` + ```shell + git push origin --delete my-fix-branch + ``` - - Check out the master branch: + - Check out the master branch: - ```shell - git checkout develop -f - ``` + ```shell + git checkout develop -f + ``` - - Delete the local branch: + - Delete the local branch: - ```shell - git branch -D my-fix-branch - ``` + ```shell + git branch -D my-fix-branch + ``` - - Update your master with the latest upstream version: + - Update your master with the latest upstream version: - ```shell - git pull --ff upstream develop - ``` + ```shell + git pull --ff upstream develop + ``` ## Commit message guidelines -A well-formatted commit message leads a more readable history when we look through some changes, and helps us generate change log. -We follow up [The Conventional Commits specification](https://www.conventionalcommits.org) for commit message format. -This format is also required for PR title and message. -The commit message should be structured as follows: +A well-formatted commit message leads a more readable history when we look through some changes, and +helps us generate change log. We follow up +[The Conventional Commits specification](https://www.conventionalcommits.org) for commit message +format. This format is also required for PR title and message. The commit message should be +structured as follows: ```text [optional scope]: @@ -569,8 +682,11 @@ The commit message should be structured as follows: - `Revert`: Reverting commits - scope: optional, could be the module which this commit changes; for example, `orbital` - description: A short summary of the code changes: tell others what you did in one sentence. -- Body: optional, providing detailed, additional, or contextual information about the code changes, e.g. the motivation of this commit, referenced materials, the coding implementation, and so on. -- Footer: optional, reference GitHub issues or PRs that this commit closes or is related to. [Use a keyword](https://docs.github.com/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) to close an issue, e.g. "Fix #753". +- Body: optional, providing detailed, additional, or contextual information about the code changes, + e.g. the motivation of this commit, referenced materials, the coding implementation, and so on. +- Footer: optional, reference GitHub issues or PRs that this commit closes or is related to. + [Use a keyword](https://docs.github.com/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) + to close an issue, e.g. "Fix #753". Here is an example: diff --git a/docs/DevelopingTeam.md b/docs/DevelopingTeam.md index 333e923c67c..fdee775d978 100644 --- a/docs/DevelopingTeam.md +++ b/docs/DevelopingTeam.md @@ -1,8 +1,9 @@ - # Development team + The current development team consists the following research groups/affiliations: + - University of Science and Technology of China (Dr. Lixin He) - Peking University (Dr. Mohan Chen) - Institute of Physics, Chinese Academy of Sciences (Dr. Xinguo Ren) - Beijing AI for Science Institute (Dr. Daye Zheng) -- Institute of Artificial Intelligence, Hefei Comprehensive National Science Center (Dr. Lixin He). +- Institute of Artificial Intelligence, Hefei Comprehensive National Science Center (Dr. Lixin He). diff --git a/docs/Makefile b/docs/Makefile index d7b9e870f7a..7ca81b3aa23 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -10,11 +10,11 @@ BUILDDIR = build # Put it first so that "make" without argument is like "make help". help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 120e099e0ed..ad3ff349a4e 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -1,3 +1,3 @@ pre{ - overflow: auto; + overflow: auto; } diff --git a/docs/advanced/acceleration/cuda.md b/docs/advanced/acceleration/cuda.md index 64d47532750..b8b073ffc9e 100644 --- a/docs/advanced/acceleration/cuda.md +++ b/docs/advanced/acceleration/cuda.md @@ -1,53 +1,96 @@ # CUDA GPU Implementations -In ABACUS, we provide the option to use GPU devices to accelerate performance. The implementation of GPU acceleration differs between PW basis and LCAO basis. Specifically, under PW basis, it has the following features: +In ABACUS, we provide the option to use GPU devices to accelerate performance. The implementation of +GPU acceleration differs between PW basis and LCAO basis. Specifically, under PW basis, it has the +following features: -- **Full gpu implementations**: During the SCF progress, `Psi`, `Hamilt`, `Hsolver`, `DiagCG`, and `DiagoDavid` classes are stored or calculated by the GPU devices. +- **Full gpu implementations**: During the SCF progress, `Psi`, `Hamilt`, `Hsolver`, `DiagCG`, and + `DiagoDavid` classes are stored or calculated by the GPU devices. -- **Electronic state data**: (e.g. electronic density) are moved from the GPU to the CPU(s) every scf step. +- **Electronic state data**: (e.g. electronic density) are moved from the GPU to the CPU(s) every + scf step. -- **Accelerated by the NVIDIA libraries**: `cuBLAS` for common linear algebra calculations, `cuSolver` for eigen values/vectors, and `cuFFT` for the conversions between the real and recip spaces. +- **Accelerated by the NVIDIA libraries**: `cuBLAS` for common linear algebra calculations, + `cuSolver` for eigen values/vectors, and `cuFFT` for the conversions between the real and recip + spaces. -- **Multi GPU supprted**: Using multiple MPI tasks will often give the best performance. Note each MPI task will be bind to a GPU device with automatically computing load balancing. +- **Multi GPU supprted**: Using multiple MPI tasks will often give the best performance. Note each + MPI task will be bind to a GPU device with automatically computing load balancing. - **Parallel strategy**: K point parallel. -Unlike PW basis, only the grid integration module (module_gint) and the diagonalization of the Hamiltonian matrix (source_hsolver) have been implemented with GPU acceleration under LCAO basis. +Unlike PW basis, only the grid integration module (module_gint) and the diagonalization of the +Hamiltonian matrix (source_hsolver) have been implemented with GPU acceleration under LCAO basis. ## Required hardware/software -To compile and use ABACUS in CUDA mode, you currently need to have an NVIDIA GPU and install the corresponding NVIDIA CUDA toolkit software on your system (this is only tested on Linux and unsupported on Windows): +To compile and use ABACUS in CUDA mode, you currently need to have an NVIDIA GPU and install the +corresponding NVIDIA CUDA toolkit software on your system (this is only tested on Linux and +unsupported on Windows): -- Check if you have an NVIDIA GPU: cat /proc/driver/nvidia/gpus/*/information +- Check if you have an NVIDIA GPU: cat /proc/driver/nvidia/gpus/\*/information - Go to https://developer.nvidia.com/cuda-downloads - Install a driver and toolkit appropriate for your system (SDK is not necessary) - ## Building ABACUS with the GPU support: -Check the [Advanced Installation Options](https://abacus-rtd.readthedocs.io/en/latest/advanced/install.html#build-with-cuda-support) for the installation of CUDA version support. +Check the +[Advanced Installation Options](https://abacus-rtd.readthedocs.io/en/latest/advanced/install.html#build-with-cuda-support) +for the installation of CUDA version support. -Setting both USE_ELPA and USE_CUDA to ON does not automatically enable ELPA to run on GPUs. ELPA support for GPUs needs to be enabled when ELPA is compiled. [enable GPU support](https://github.com/marekandreas/elpa/blob/master/documentation/INSTALL.md). +Setting both USE_ELPA and USE_CUDA to ON does not automatically enable ELPA to run on GPUs. ELPA +support for GPUs needs to be enabled when ELPA is compiled. +[enable GPU support](https://github.com/marekandreas/elpa/blob/master/documentation/INSTALL.md). -The ABACUS program will automatically determine whether the current ELPA supports GPU based on the elpa/elpa_configured_options.h header file. Users can also check this header file to determine the GPU support of ELPA in their environment. ELPA introduced a new API elpa_setup_gpu in version 2023.11.001. So if you want to enable ELPA GPU in ABACUS, the ELPA version must be greater than or equal to 2023.11.001. +The ABACUS program will automatically determine whether the current ELPA supports GPU based on the +elpa/elpa_configured_options.h header file. Users can also check this header file to determine the +GPU support of ELPA in their environment. ELPA introduced a new API elpa_setup_gpu in version +2023.11.001. So if you want to enable ELPA GPU in ABACUS, the ELPA version must be greater than or +equal to 2023.11.001. ## Run with the GPU support by editing the INPUT script: -In `INPUT` file we need to set the input parameter [device](../input_files/input-main.md#device) to `gpu`. If this parameter is not set, ABACUS will try to determine if there are available GPUs. -- Set `ks_solver`: For the PW basis, CG, BPCG and Davidson methods are supported on GPU; set the input parameter [ks_solver](../input_files/input-main.md#ks_solver) to `cg`, `bpcg` or `dav`. For the LCAO basis, `cusolver`, `cusolvermp` and `elpa` is supported on GPU. -- **single-card**: ABACUS allows for single-GPU acceleration. You can run ABACUS without any MPI process by command `abacus`, and `ks_solver cusolver` is recommended for the LCAO basis. *note: avoid using `mpirun -n 1 abacus`*. -- **multi-cards**: ABACUS allows for multi-GPU acceleration. If you have multiple GPU cards, you can run ABACUS with several MPI processes, and each process will utilize one GPU card. For example, the command `mpirun -n 2 abacus` will by default launch two GPUs for computation. If you only have one card, this command will only start one GPU. *note: the number of MPI processes SHOULD be equal to the number of GPU cards, unless you are using MPS in your computer.* +In `INPUT` file we need to set the input parameter [device](../input_files/input-main.md#device) to +`gpu`. If this parameter is not set, ABACUS will try to determine if there are available GPUs. + +- Set `ks_solver`: For the PW basis, CG, BPCG and Davidson methods are supported on GPU; set the + input parameter [ks_solver](../input_files/input-main.md#ks_solver) to `cg`, `bpcg` or `dav`. For + the LCAO basis, `cusolver`, `cusolvermp` and `elpa` is supported on GPU. +- **single-card**: ABACUS allows for single-GPU acceleration. You can run ABACUS without any MPI + process by command `abacus`, and `ks_solver cusolver` is recommended for the LCAO basis. *note: + avoid using `mpirun -n 1 abacus`*. +- **multi-cards**: ABACUS allows for multi-GPU acceleration. If you have multiple GPU cards, you can + run ABACUS with several MPI processes, and each process will utilize one GPU card. For example, + the command `mpirun -n 2 abacus` will by default launch two GPUs for computation. If you only have + one card, this command will only start one GPU. *note: the number of MPI processes SHOULD be equal + to the number of GPU cards, unless you are using MPS in your computer.* ## Examples -We provides [examples](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/gpu) of gpu calculations. + +We provides [examples](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/gpu) of +gpu calculations. ## Known limitations + PW basis: -- Only k point parallelization is supported, so the input keyword `kpar` will be set to match the number of MPI tasks automatically. -- By default, CUDA architectures are automatically selected based on the CUDA Toolkit version. For CUDA versions before 13.0, architectures 60, 70, 75, 80, 86, 89, and 90 are compiled (if supported by the CUDA version). For CUDA 13.0 and later, only architectures 75 and above are compiled, as CUDA 13 dropped support for older architectures. This can be overridden using the CMake variable [`CMAKE_CUDA_ARCHITECTURES`](https://cmake.org/cmake/help/latest/variable/CMAKE_CUDA_ARCHITECTURES.html) or the environmental variable [`CUDAARCHS`](https://cmake.org/cmake/help/latest/envvar/CUDAARCHS.html). + +- Only k point parallelization is supported, so the input keyword `kpar` will be set to match the + number of MPI tasks automatically. +- By default, CUDA architectures are automatically selected based on the CUDA Toolkit version. For + CUDA versions before 13.0, architectures 60, 70, 75, 80, 86, 89, and 90 are compiled (if supported + by the CUDA version). For CUDA 13.0 and later, only architectures 75 and above are compiled, as + CUDA 13 dropped support for older architectures. This can be overridden using the CMake variable + [`CMAKE_CUDA_ARCHITECTURES`](https://cmake.org/cmake/help/latest/variable/CMAKE_CUDA_ARCHITECTURES.html) + or the environmental variable + [`CUDAARCHS`](https://cmake.org/cmake/help/latest/envvar/CUDAARCHS.html). LCAO basis: -- Unless there is a specific reason, avoid using multiple GPUs, as it can be slower than using a single GPU. This is because the generalized eigenvalue solution of the LCAO basis set will incur additional communication overhead when calculated on multiple cards. When the memory limit of a GPU card makes it insufficient to complete the task, it is recommended to use multiple cards for calculation. -- When using elpa on GPUs, some ELPA internal logs will be output. \ No newline at end of file + +- Unless there is a specific reason, avoid using multiple GPUs, as it can be slower than using a + single GPU. This is because the generalized eigenvalue solution of the LCAO basis set will incur + additional communication overhead when calculated on multiple cards. When the memory limit of a + GPU card makes it insufficient to complete the task, it is recommended to use multiple cards for + calculation. +- When using elpa on GPUs, some ELPA internal logs will be output. diff --git a/docs/advanced/elec_properties/Berry_phase.md b/docs/advanced/elec_properties/Berry_phase.md index 7f85689a5ff..dfa72287097 100644 --- a/docs/advanced/elec_properties/Berry_phase.md +++ b/docs/advanced/elec_properties/Berry_phase.md @@ -1,21 +1,32 @@ # Berry Phase Calculation -From version 2.0.0, ABACUS is capable of calculating macroscopic polarization of insulators by using the Berry phase method, known as the ["modern theory of polarization"](https://www.sciencedirect.com/science/article/abs/pii/S0022459612003234). To calculate the polarization, you need first to do a self-consistent calculation to get the converged charge density. Then, do a non-self-consistent calculation with berry_phase setting to 1. You need also to specify the direction of the polarization you want to calculate. An example is given in the directory [examples/berryphase/lcao_PbTiO3](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/berryphase/lcao_PbTiO3). +From version 2.0.0, ABACUS is capable of calculating macroscopic polarization of insulators by using +the Berry phase method, known as the +["modern theory of polarization"](https://www.sciencedirect.com/science/article/abs/pii/S0022459612003234). +To calculate the polarization, you need first to do a self-consistent calculation to get the +converged charge density. Then, do a non-self-consistent calculation with berry_phase setting to 1. +You need also to specify the direction of the polarization you want to calculate. An example is +given in the directory +[examples/berryphase/lcao_PbTiO3](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/berryphase/lcao_PbTiO3). To run this example, first do a self-consistent calculation: + ``` cp INPUT-scf INPUT cp KPT-scf KPT mpirun -np 4 abacus ``` + Then run a non-self-consistent berry-phase calculation: + ``` cp INPUT-nscf-c INPUT cp KPT-nscf-c KPT mpirun -np 4 abacus ``` -In this example, we calculate the electric polarization along c axis for PbTiO~3~, and below are the INPUT file (nscf) and KPT file (nscf): +In this example, we calculate the electric polarization along c axis for PbTiO~3~, and below are the +INPUT file (nscf) and KPT file (nscf): ``` INPUT_PARAMETERS @@ -31,11 +42,19 @@ berry_phase 1 // calculate Berry phase gdir 3 // calculate polarization along c axis ``` -Note: You need to turn off the symmetry when do Berry phase calculations. Currently, ABACUS support Berry phase calculation with nspin=1 and nspin=2. The Berry phase can be calculated in both pw and lcao bases. -- [berry_phase](../input_files/input-main.md#berry_phase) : 1, calculate berry phase; 0, no calculate berry phase. -- [gdir](../input_files/input-main.md#gdir) : 1, 2, 3, the lattice vector direction of the polarization you want to calculate. +Note: You need to turn off the symmetry when do Berry phase calculations. Currently, ABACUS support +Berry phase calculation with nspin=1 and nspin=2. The Berry phase can be calculated in both pw and +lcao bases. -The KPT file need to be modified according to gdir in the INPUT file. Generally, you need denser k points along this direction. For example, in the following KPT file, 4 k-points are taken along the a and b axes, and 8 k-points are taken along the c-axis. You should check the convergence of the k points when calculating the polarization. +- [berry_phase](../input_files/input-main.md#berry_phase) : 1, calculate berry phase; 0, no + calculate berry phase. +- [gdir](../input_files/input-main.md#gdir) : 1, 2, 3, the lattice vector direction of the + polarization you want to calculate. + +The KPT file need to be modified according to gdir in the INPUT file. Generally, you need denser k +points along this direction. For example, in the following KPT file, 4 k-points are taken along the +a and b axes, and 8 k-points are taken along the c-axis. You should check the convergence of the k +points when calculating the polarization. ``` K_POINTS @@ -43,9 +62,12 @@ K_POINTS Gamma 4 4 8 0 0 0 ``` -The results of the berry phase calculation are written in the “running_nscf.log” in the OUT folder. You may search for these results by searching for keywords “POLARIZATION CALCULATION”. + +The results of the berry phase calculation are written in the “running_nscf.log” in the OUT folder. +You may search for these results by searching for keywords “POLARIZATION CALCULATION”. The results are shown as follows: + ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | | @@ -70,6 +92,11 @@ The results are shown as follows: P = 0.8906925 (mod 2.1748536) ( 0.0000000, 0.0000000, 0.8906925) C/m^2 ``` -The electric polarization **P** is multivalued, which modulo a quantum e**R**/V~cell~. +The electric polarization **P** is multivalued, which modulo a quantum e**R**/V~cell~. -Note: The vectors R1, R2, and R3 refer to the three lattice vectors of the unit cell. When gdir=3, the calculated polarization is along the R3 direction. The three values in parentheses represent the re-projection of the polarization along the R3 direction onto the Cartesian coordinate system (i.e., the xyz coordinate system). To obtain the full polarization components in the Cartesian system, you need to calculate the polarization for R1, R2, and R3 separately, and then sum their respective x, y, and z components. +Note: The vectors R1, R2, and R3 refer to the three lattice vectors of the unit cell. When gdir=3, +the calculated polarization is along the R3 direction. The three values in parentheses represent the +re-projection of the polarization along the R3 direction onto the Cartesian coordinate system (i.e., +the xyz coordinate system). To obtain the full polarization components in the Cartesian system, you +need to calculate the polarization for R1, R2, and R3 separately, and then sum their respective x, +y, and z components. diff --git a/docs/advanced/elec_properties/Mulliken.md b/docs/advanced/elec_properties/Mulliken.md index a34bca5d07a..f832dd2919a 100644 --- a/docs/advanced/elec_properties/Mulliken.md +++ b/docs/advanced/elec_properties/Mulliken.md @@ -1,13 +1,19 @@ # Mulliken Charge Analysis -From version 2.1.0, ABACUS has the function of Mulliken population analysis. The example can be found in [examples/mulliken](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/mulliken). \ -To use this function, set [out_mul](./input-main.md#out_mul) to `1` in the INPUT file. After calculation, there will be an output file named `mulliken.txt` in the output directory. In MD calculations, the output interval is controlled by the keyword [out_freq_ion](./input-main.md#out_freq_ion). In the file, there are contents like (`nspin 1`): +From version 2.1.0, ABACUS has the function of Mulliken population analysis. The example can be +found in +[examples/mulliken](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/mulliken). +\ +To use this function, set [out_mul](./input-main.md#out_mul) to `1` in the INPUT file. After +calculation, there will be an output file named `mulliken.txt` in the output directory. In MD +calculations, the output interval is controlled by the keyword +[out_freq_ion](./input-main.md#out_freq_ion). In the file, there are contents like (`nspin 1`): ``` STEP: 0 CALCULATE THE MULLIkEN ANALYSIS FOR EACH ATOM - Total charge of spin 1: 8 - Total charge: 8 + Total charge of spin 1: 8 + Total charge: 8 Decomposed Mulliken populations 0 Zeta of Si Spin 1 s 0 1.2553358 @@ -35,7 +41,8 @@ Total Charge on atom: Si 4 ... ``` -The file gives Mulliken charge in turn according to the order of atoms in the system. For example, the following block is for the first atom in system (`nspin 2`), +The file gives Mulliken charge in turn according to the order of atoms in the system. For example, +the following block is for the first atom in system (`nspin 2`), ``` 0 Zeta of Si Spin 1 Spin 2 Sum Diff @@ -53,10 +60,11 @@ And the next block is for the second atom in system, and so on. For each atom, the file gives detailed Mulliken population analysis at different levels, -- magnetic quantum number level: such as lines beigin with ‘s,px,py,pz,...’ -- azimuthal quantum number level: such as lines begin with ‘sum over m’. -- principal quantum number level: such as lines begin with ‘sum over m+zeta’. Here ‘zeta’ - equals ‘zeta’ in the file, which means how many radial atomic orbitals there are for a given orbital angular momentum. -- atomic level: such as lines begin with ‘Total Charge on atom’. +- magnetic quantum number level: such as lines beigin with ‘s,px,py,pz,...’ +- azimuthal quantum number level: such as lines begin with ‘sum over m’. +- principal quantum number level: such as lines begin with ‘sum over m+zeta’. Here ‘zeta’ equals + ‘zeta’ in the file, which means how many radial atomic orbitals there are for a given orbital + angular momentum. +- atomic level: such as lines begin with ‘Total Charge on atom’. More orbital information can be found in 'Orbital' file output with 'mulliken.txt' when `out_mul 1` diff --git a/docs/advanced/elec_properties/band.md b/docs/advanced/elec_properties/band.md index 44fb88e1c51..49e4b989405 100644 --- a/docs/advanced/elec_properties/band.md +++ b/docs/advanced/elec_properties/band.md @@ -1,14 +1,22 @@ # Extracting Band Structure -In ABACUS, in order to obtain the eigenvalues of Hamiltonian, or generally called band structure, examples can be found in [examples/band](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/band). -Similar to the [DOS case](https://abacus-rtd.readthedocs.io/en/latest/advanced/elec_properties/dos.html), one first needs to perform a ground-state energy calculation ***with one additional keyword "[out_chg](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-chg)" in the INPUT file***: +In ABACUS, in order to obtain the eigenvalues of Hamiltonian, or generally called band structure, +examples can be found in +[examples/band](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/band). Similar +to the [DOS case](https://abacus-rtd.readthedocs.io/en/latest/advanced/elec_properties/dos.html), +one first needs to perform a ground-state energy calculation ***with one additional keyword +"[out_chg](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-chg)" +in the INPUT file***: ``` out_chg 1 ``` -With this input parameter, the converged charge density will be output in the files such as `chgs1.cube`, `chgs2.cube`, etc. -Then, one can use the same `STRU` file, pseudopotential files and atomic orbital files (and the local density matrix file onsite.dm if DFT+U is used) to do a non-self-consistent (NSCF) calculation. In this example, the potential is constructed from the ground-state charge density from the proceeding calculation. Now the INPUT file is like: +With this input parameter, the converged charge density will be output in the files such as +`chgs1.cube`, `chgs2.cube`, etc. Then, one can use the same `STRU` file, pseudopotential files and +atomic orbital files (and the local density matrix file onsite.dm if DFT+U is used) to do a +non-self-consistent (NSCF) calculation. In this example, the potential is constructed from the +ground-state charge density from the proceeding calculation. Now the INPUT file is like: ``` INPUT_PARAMETERS @@ -50,18 +58,18 @@ Line # line-mode This means we are using the following k-points: -- 6 k points, here means 6 k points: - (0.5, 0.0, 0.5) (0.0, 0.0, 0.0) (0.5, 0.5, 0.5) (0.5, 0.25, 0.75) (0.375, 0.375, 0.75) (0.0, 0.0, - 0.0) -- 20/1 number of k points along the segment line, which is constructed by two adjacent k - points. +- 6 k points, here means 6 k points: (0.5, 0.0, 0.5) (0.0, 0.0, 0.0) (0.5, 0.5, 0.5) (0.5, 0.25, + 0.75) (0.375, 0.375, 0.75) (0.0, 0.0, 0.0) +- 20/1 number of k points along the segment line, which is constructed by two adjacent k points. -Next, run ABACUS and you will see a file named `eigs1.txt` in the output directory. -Plot it and you will obtain the energy band structure! +Next, run ABACUS and you will see a file named `eigs1.txt` in the output directory. Plot it and you +will obtain the energy band structure! -If "out_proj_band" set 1, it will also produce the projected band structure in a file called PBAND_1 in xml format. +If "out_proj_band" set 1, it will also produce the projected band structure in a file called PBAND_1 +in xml format. -The PBAND_1 file starts with number of atomic orbitals in the system, the text contents of element `` is the same as data in the BANDS_1.dat file, such as: +The PBAND_1 file starts with number of atomic orbitals in the system, the text contents of element +`` is the same as data in the BANDS_1.dat file, such as: ``` diff --git a/docs/advanced/elec_properties/charge.md b/docs/advanced/elec_properties/charge.md index f957f7bf3a7..e10010e92f4 100644 --- a/docs/advanced/elec_properties/charge.md +++ b/docs/advanced/elec_properties/charge.md @@ -1,13 +1,16 @@ # Extracting Charge Density -ABACUS can output the charge density by adding the keyword [out_chg](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-chg) in INPUT file: +ABACUS can output the charge density by adding the keyword +[out_chg](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-chg) +in INPUT file: ``` out_chg 1 ``` -After finishing the calculation, the information of the charge density is stroed in files `OUT.${suffix}/SPIN${spin}_CHG.cube`, which can be used to do visualization. -The SPIN${spin}_CHG.cube file looks like: +After finishing the calculation, the information of the charge density is stroed in files +`OUT.${suffix}/SPIN${spin}_CHG.cube`, which can be used to do visualization. The +SPIN\$\{spin}\_CHG.cube file looks like: ``` STEP: 0 Cubefile created from ABACUS. Inner loop is z, followed by y and x @@ -34,10 +37,13 @@ STEP: 0 Cubefile created from ABACUS. Inner loop is z, followed by y and x The first line contains the current ion step.\ The second line contains NSPIN and Fermi energy.\ The following 4 lines are the informations of lattice, in order:\ - total number of atoms, the coordinate of original point.\ - the number of lattice points along lattice vector a1 (nx), a1/nx, in Bohr.\ - the number of lattice points along lattice vector a2 (ny), a2/ny, in Bohr.\ - the number of lattice points along lattice vector a3 (nz), a3/nz, in Bohr.\ -The following lines are about the elements and coordinates, in order: the atom number of each atoms, the electron number in pseudopotential, the Cartesian coordinates, in Bohr.\ -The rest lines are the value of charge density at each grid. Note that the inner loop is z index, followed by y index, x index in turn.\ -The examples can be found in [examples/charge_density](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/charge_density) +total number of atoms, the coordinate of original point.\ +the number of lattice points along lattice vector a1 (nx), a1/nx, in Bohr.\ +the number of lattice points along lattice vector a2 (ny), a2/ny, in Bohr.\ +the number of lattice points along lattice vector a3 (nz), a3/nz, in Bohr.\ +The following lines are about the elements and coordinates, in order: the atom number of each atoms, +the electron number in pseudopotential, the Cartesian coordinates, in Bohr.\ +The rest lines are the value of charge density at each grid. Note that the inner loop is z index, +followed by y index, x index in turn.\ +The examples can be found in +[examples/charge_density](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/charge_density) diff --git a/docs/advanced/elec_properties/density_matrix.md b/docs/advanced/elec_properties/density_matrix.md index 5d6b8ab2e12..0be59f21867 100644 --- a/docs/advanced/elec_properties/density_matrix.md +++ b/docs/advanced/elec_properties/density_matrix.md @@ -1,20 +1,29 @@ # Extracting Density Matrices -ABACUS can output the density matrix by adding the keyword "[out_dmk](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out_dmk)" in INPUT file: +ABACUS can output the density matrix by adding the keyword +"[out_dmk](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out_dmk)" +in INPUT file: + ``` out_dmk 1 ``` + After finishing the calculation, the density matrix is written into `OUT.${suffix}/`. For current develop versions: -- gamma-only (`gamma_only = 1`): `dmg1_nao.txt` (`nspin=1/4`) or `dms1g1_nao.txt` and `dms2g1_nao.txt` (`nspin=2`) -- multi-k (`gamma_only = 0`): `dmk1g1_nao.txt`, `dmk2g1_nao.txt`, ... (`nspin=1/4`) or `dmk1s1g1_nao.txt`, `dmk1s2g1_nao.txt`, ... (`nspin=2`) + +- gamma-only (`gamma_only = 1`): `dmg1_nao.txt` (`nspin=1/4`) or `dms1g1_nao.txt` and + `dms2g1_nao.txt` (`nspin=2`) +- multi-k (`gamma_only = 0`): `dmk1g1_nao.txt`, `dmk2g1_nao.txt`, ... (`nspin=1/4`) or + `dmk1s1g1_nao.txt`, `dmk1s2g1_nao.txt`, ... (`nspin=2`) Here `g{istep}` denotes the geometry/step index in the output filename. -For 3.10-LTS, the corresponding keyword is `out_dm`, and file names follow the legacy style such as `SPIN1_DM` and `SPIN2_DM`. +For 3.10-LTS, the corresponding keyword is `out_dm`, and file names follow the legacy style such as +`SPIN1_DM` and `SPIN2_DM`. The file content looks like: + ``` test 5.39761 @@ -34,36 +43,49 @@ Direct 3.904e-01 1.114e-02 2.050e-14 1.655e-13 1.517e-13 -7.492e-15 -1.729e-14 5.915e-15 -9.099e-15 2.744e-14 3.146e-14 6.631e-15 2.594e-15 3.904e-01 1.114e-02 -7.395e-15 ... - ``` +``` + The first 5 lines are the informations of lattice, in order: \ - lattice name (if keyword [latname](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#latname) is not specified in INPUT, this will be "test"), \ - lattice constance with unit in angstrom, \ - lattice vector a, \ - lattice vector b, \ - lattice vector c. \ -The following lines are about the elements and coordinates, in order: all elements, the atom number of each elements, the type of coordinate, the coordinates.\ +lattice name (if keyword +[latname](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#latname) +is not specified in INPUT, this will be "test"), \ +lattice constance with unit in angstrom, \ +lattice vector a, \ +lattice vector b, \ +lattice vector c. \ +The following lines are about the elements and coordinates, in order: all elements, the atom number +of each elements, the type of coordinate, the coordinates.\ After a blank line, the output is the values of NSPIN and fermi energy.\ -The following line is dimension of the density matrix, and the rest lines are the value of each matrix element. +The following line is dimension of the density matrix, and the rest lines are the value of each +matrix element. -The examples can be found in [examples/density_matrix](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/density_matrix) +The examples can be found in +[examples/density_matrix](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/density_matrix) - Note: Version difference summary: - - develop: `out_dmk` supports both gamma-only and multi-k-point output. - - 3.10-LTS: use `out_dm`. + - develop: `out_dmk` supports both gamma-only and multi-k-point output. + - 3.10-LTS: use `out_dm`. ## Real-space Density Matrix (CSR format) -ABACUS can also output the real-space density matrix DM(R) in CSR (Compressed Sparse Row) format by setting: +ABACUS can also output the real-space density matrix DM(R) in CSR (Compressed Sparse Row) format by +setting: + ``` out_dmr 1 ``` + This feature is only valid for multi-k calculations (`gamma_only = 0`). After the calculation, the density matrix files are written to `OUT.${suffix}/`: + - develop naming pattern: `dmr{s}{spin index}{g}{geometry index}{_nao}.csr` - `nspin=1`: `dmrs1_nao.csr` - `nspin=2` (spin-polarized): `dmrs1_nao.csr` (spin-up) and `dmrs2_nao.csr` (spin-down) -For 3.10-LTS, the corresponding keyword is `out_dm1`, and the file names are `data-DMR-sparse_SPIN0.csr` and `data-DMR-sparse_SPIN1.csr`, etc. +For 3.10-LTS, the corresponding keyword is `out_dm1`, and the file names are +`data-DMR-sparse_SPIN0.csr` and `data-DMR-sparse_SPIN1.csr`, etc. -These files can be used to restart calculations by setting `init_chg dm` in the INPUT file together with `read_file_dir` pointing to the directory containing the CSR files. This is supported for both `nspin=1` and `nspin=2`. +These files can be used to restart calculations by setting `init_chg dm` in the INPUT file together +with `read_file_dir` pointing to the directory containing the CSR files. This is supported for both +`nspin=1` and `nspin=2`. diff --git a/docs/advanced/elec_properties/dos.md b/docs/advanced/elec_properties/dos.md index c89e9d47d8d..68fb7b61400 100644 --- a/docs/advanced/elec_properties/dos.md +++ b/docs/advanced/elec_properties/dos.md @@ -2,15 +2,21 @@ ## DOS -ABACUS can calculate the density of states (DOS) of the system, and the examples can be found in [examples/dos](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/dos). -We first, do a ground-state energy calculation ***with one additional keyword "[out_chg](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-chg)" in the INPUT file***: +ABACUS can calculate the density of states (DOS) of the system, and the examples can be found in +[examples/dos](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/dos). We first, +do a ground-state energy calculation ***with one additional keyword +"[out_chg](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-chg)" +in the INPUT file***: ``` out_chg 1 ``` -this will produce the converged charge density, which is contained in the file SPIN1_CHG.cube. -Then, use the same `STRU` file, pseudopotential file and atomic orbital file (and the local density matrix file onsite.dm if DFT+U is used) to do a non-self-consistent calculation. In this example, the potential is constructed from the ground-state charge density from the proceeding calculation. Now the INPUT file is like: +this will produce the converged charge density, which is contained in the file SPIN1_CHG.cube. Then, +use the same `STRU` file, pseudopotential file and atomic orbital file (and the local density matrix +file onsite.dm if DFT+U is used) to do a non-self-consistent calculation. In this example, the +potential is constructed from the ground-state charge density from the proceeding calculation. Now +the INPUT file is like: ``` INPUT_PARAMETERS @@ -39,27 +45,48 @@ Some parameters in the INPUT file are explained: - calculation - choose which kind of calculation: scf calculation, nscf calculation, structure relaxation or Molecular Dynamics. Now we need to do one step of nscf calculation. - Attention: This is a main variable of ABACUS, and for its more information please see the [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#calculation). + choose which kind of calculation: scf calculation, nscf calculation, structure relaxation or + Molecular Dynamics. Now we need to do one step of nscf calculation. Attention: This is a main + variable of ABACUS, and for its more information please see the + [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#calculation). + - pw_diag_thr - threshold for the CG method which diagonalizes the Hamiltonian to get eigenvalues and eigen wave functions. If one wants to do nscf calculation, pw_diag_thr needs to be changed to a smaller account, typically smaller than 1.0e-3. Note that this parameter only apply to plane-wave calculations that employ the CG or Davidson method to diagonalize the Hamiltonian. For its more information please see the [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#pw_diag_thr). + threshold for the CG method which diagonalizes the Hamiltonian to get eigenvalues and eigen wave + functions. If one wants to do nscf calculation, pw_diag_thr needs to be changed to a smaller + account, typically smaller than 1.0e-3. Note that this parameter only apply to plane-wave + calculations that employ the CG or Davidson method to diagonalize the Hamiltonian. For its more + information please see the + [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#pw_diag_thr). For LCAO calculations, this parameter will be neglected ! + - init_chg - the type of starting density. When doing scf calculation, this variable can be set ”atomic”. When doing nscf calculation, the charge density already exists(eg. in SPIN1_CHG.cube), and the variable should be set as ”file”. It means the density will be read from the existing file SPIN1_CHG.cube. For its more information please see the [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#init_chg). + the type of starting density. When doing scf calculation, this variable can be set ”atomic”. When + doing nscf calculation, the charge density already exists(eg. in SPIN1_CHG.cube), and the variable + should be set as ”file”. It means the density will be read from the existing file SPIN1_CHG.cube. + For its more information please see the + [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#init_chg). + - out_dos - output density of state(DOS). The unit of DOS is `(number of states)/(eV * unitcell)`. For its more information please see the [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#out_dos). + output density of state(DOS). The unit of DOS is `(number of states)/(eV * unitcell)`. For its + more information please see the + [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#out_dos). + - dos_sigma - the gaussian smearing parameter(DOS), in unit of eV. For its more information please see the [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#dos_sigma). + the gaussian smearing parameter(DOS), in unit of eV. For its more information please see the + [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#dos_sigma). + - read_file_dir - the location of electron density file. For its more information please see the [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#read_file_dir). + the location of electron density file. For its more information please see the + [here](https://abacus-rtd--1282.org.readthedocs.build/en/1282/advanced/input_files/input-main.html#read_file_dir). -To have an accurate DOS, one needs to have a denser k-point mesh. For example, the KPT file can be set as: +To have an accurate DOS, one needs to have a denser k-point mesh. For example, the KPT file can be +set as: ``` K_POINTS @@ -68,7 +95,9 @@ Gamma 8 8 8 0 0 0 ``` -Run the program, and you will see a file named DOS1_smearing.dat in the output directory. The first two columns in the file are the energy and DOS, respectively, and the third column is the sum of DOS. Plot file DOS1_smearing.dat with graphing software, and you’ll get the DOS. +Run the program, and you will see a file named DOS1_smearing.dat in the output directory. The first +two columns in the file are the energy and DOS, respectively, and the third column is the sum of +DOS. Plot file DOS1_smearing.dat with graphing software, and you’ll get the DOS. ``` -5.49311 0.0518133 0.0518133 @@ -82,9 +111,11 @@ Run the program, and you will see a file named DOS1_smearing.dat in the output d ## PDOS -Along with the DOS1_smearing.dat file, we also produce the projected density of states (PDOS) in a file called PDOS. +Along with the DOS1_smearing.dat file, we also produce the projected density of states (PDOS) in a +file called PDOS. -The PDOS file starts with number of atomic orbitals in the system, then a list of energy values, such as: +The PDOS file starts with number of atomic orbitals in the system, then a list of energy values, +such as: ``` @@ -116,4 +147,6 @@ The rest of the fileis arranged in sections, each section with a header such as ``` -which tells the atom and symmetry of the current atomic orbital, and followed by the PDOS values. The values can thus be plotted against the energies. The unit of PDOS is also `(number of states)/(eV * unitcell)`. +which tells the atom and symmetry of the current atomic orbital, and followed by the PDOS values. +The values can thus be plotted against the energies. The unit of PDOS is also +`(number of states)/(eV * unitcell)`. diff --git a/docs/advanced/elec_properties/hs_matrix.md b/docs/advanced/elec_properties/hs_matrix.md index 9436b0ad7b3..16975541322 100644 --- a/docs/advanced/elec_properties/hs_matrix.md +++ b/docs/advanced/elec_properties/hs_matrix.md @@ -1,8 +1,12 @@ # Extracting Hamiltonian and Overlap Matrices -In ABACUS, we provide the option to write the Hamiltonian and Overlap matrices to files after SCF calculations. +In ABACUS, we provide the option to write the Hamiltonian and Overlap matrices to files after SCF +calculations. -For periodic systems, there are two ways to construct the matrices, the first is to write the entire square matrices for each $k$ point in the Brillouin zone, namely $H(k)$ and $S(k)$; the second one is the real space representation, $H(R)$ and $S(R)$, where R is the Bravis lattice vector. The two representations are connected by Fourier transform: +For periodic systems, there are two ways to construct the matrices, the first is to write the entire +square matrices for each $k$ point in the Brillouin zone, namely $H(k)$ and $S(k)$; the second one +is the real space representation, $H(R)$ and $S(R)$, where R is the Bravis lattice vector. The two +representations are connected by Fourier transform: - $H(k)=\sum_R H(R)e^{-ikR}$ @@ -12,31 +16,48 @@ and ## out_mat_hs -Users can set the keyword [out_mat_hs](../input_files/input-main.md#out_mat_hs) to true to print the upper triangular part of the Hamiltonian matrices and overlap matrices for each k point into files in the directory `OUT.${suffix}`. It is available for both gamma_only and multi-k calculations. +Users can set the keyword [out_mat_hs](../input_files/input-main.md#out_mat_hs) to true to print the +upper triangular part of the Hamiltonian matrices and overlap matrices for each k point into files +in the directory `OUT.${suffix}`. It is available for both gamma_only and multi-k calculations. -The $H(k)$ and $S(k)$ matrices are stored with numerical atomic orbitals as basis, and the corresponding sequence of the numerical atomic orbitals can be seen in [Basis Set](../pp_orb.md#basis-set). +The $H(k)$ and $S(k)$ matrices are stored with numerical atomic orbitals as basis, and the +corresponding sequence of the numerical atomic orbitals can be seen in +[Basis Set](../pp_orb.md#basis-set). -As for information on the k points, one may look for the `SETUP K-POINTS` section in the running log. +As for information on the k points, one may look for the `SETUP K-POINTS` section in the running +log. -The first number of the first line in each file gives the size of the matrix, namely, the number of atomic basis functions in the system. +The first number of the first line in each file gives the size of the matrix, namely, the number of +atomic basis functions in the system. -The rest of the file contains the upper triangular part of the specified matrices. For multi-k calculations, the matrices are Hermitian and the matrix elements are complex; for gamma-only calculations, the matrices are symmetric and the matrix elements are real. +The rest of the file contains the upper triangular part of the specified matrices. For multi-k +calculations, the matrices are Hermitian and the matrix elements are complex; for gamma-only +calculations, the matrices are symmetric and the matrix elements are real. ## out_mat_hs2 -The output of $H(R)$ and $S(R)$ matrices is controlled by the keyword [out_mat_hs2](../input_files/input-main.md#out_mat_hs2). This functionality is not available for gamma_only calculations. To generate such matrices for gamma only calculations, users should turn off [gamma_only](../input_files/input-main.md#gamma_only), and explicitly specify that gamma point is the only k point in the KPT file. +The output of $H(R)$ and $S(R)$ matrices is controlled by the keyword +[out_mat_hs2](../input_files/input-main.md#out_mat_hs2). This functionality is not available for +gamma_only calculations. To generate such matrices for gamma only calculations, users should turn +off [gamma_only](../input_files/input-main.md#gamma_only), and explicitly specify that gamma point +is the only k point in the KPT file. ### Output Format -The H(R) and S(R) matrices are output in standard Compressed Sparse Row (CSR) format, matching the format used by `out_dmr`. +The H(R) and S(R) matrices are output in standard Compressed Sparse Row (CSR) format, matching the +format used by `out_dmr`. For single-point SCF calculations: -- **nspin = 1 or nspin = 4**: Two files `hrs1_nao.csr` and `srs1_nao.csr` are generated, containing the Hamiltonian matrix $H(R)$ and overlap matrix $S(R)$ respectively. -- **nspin = 2**: Three files `hrs1_nao.csr`, `hrs2_nao.csr`, and `srs1_nao.csr` are created, where the first two files correspond to $H(R)$ for spin up and spin down, respectively. + +- **nspin = 1 or nspin = 4**: Two files `hrs1_nao.csr` and `srs1_nao.csr` are generated, containing + the Hamiltonian matrix $H(R)$ and overlap matrix $S(R)$ respectively. +- **nspin = 2**: Three files `hrs1_nao.csr`, `hrs2_nao.csr`, and `srs1_nao.csr` are created, where + the first two files correspond to $H(R)$ for spin up and spin down, respectively. ### File Structure Each file starts with a header: + ``` --- Ionic Step 1 --- # print H matrix in real space H(R) @@ -59,29 +80,45 @@ Each file starts with a header: 0 3 7 ... ``` -The CSR format stores a sparse m × n matrix M in row form using three arrays (values, column indices, row pointers). According to Wikipedia: +The CSR format stores a sparse m × n matrix M in row form using three arrays (values, column +indices, row pointers). According to Wikipedia: -- The arrays **values** and **column indices** are of length NNZ (number of nonzero entries), and contain the non-zero values and the column indices of those values respectively. -- The array **row pointers** is of length m + 1 and encodes the index where each row starts. The last element is NNZ. +- The arrays **values** and **column indices** are of length NNZ (number of nonzero entries), and + contain the non-zero values and the column indices of those values respectively. +- The array **row pointers** is of length m + 1 and encodes the index where each row starts. The + last element is NNZ. ### Precision Control Use `out_mat_hs2 1 12` to output with 12-digit precision (default is 8). -For calculations involving ionic movements, the output frequency of the matrix is controlled by [out_freq_ion](../input_files/input-main.md#out_freq_ion) and [out_app_flag](../input_files/input-main.md#out_app_flag). +For calculations involving ionic movements, the output frequency of the matrix is controlled by +[out_freq_ion](../input_files/input-main.md#out_freq_ion) and +[out_app_flag](../input_files/input-main.md#out_app_flag). ## get_s -We also offer the option of only calculating the overlap matrix without running SCF. For that purpose, in `INPUT` file we need to set the value keyword [calculation](../input_files/input-main.md#calculation) to be `get_s`. -A file named `sr_nao.csr` will be generated in the working directory, which contains the overlap matrix. +We also offer the option of only calculating the overlap matrix without running SCF. For that +purpose, in `INPUT` file we need to set the value keyword +[calculation](../input_files/input-main.md#calculation) to be `get_s`. -> When `nspin` is set to 1 or 2, the dimension of the overlap matrix is nlocal $\times$ nlocal, where nlocal is the total number of numerical atomic orbitals. -These numerical atomic orbitals are ordered from outer to inner loop as atom, angular quantum number $l$, zeta (multiple radial orbitals corresponding to each $l$), and magnetic quantum number $m$. -When `nspin` is set to 4, the dimension of the overlap matrix is (2 $\times$ nlocal) $\times$ (2 $\times$ nlocal). In this case, the numerical atomic orbitals are ordered from outer to inner loop as atom, angular quantum number $l$, zeta (multiple radial orbitals corresponding to each $l$), magnetic quantum number $m$, and npol (index of spin, ranges from 0 to 1). +A file named `sr_nao.csr` will be generated in the working directory, which contains the overlap +matrix. +> When `nspin` is set to 1 or 2, the dimension of the overlap matrix is nlocal $\times$ nlocal, +> where nlocal is the total number of numerical atomic orbitals. These numerical atomic orbitals are +> ordered from outer to inner loop as atom, angular quantum number $l$, zeta (multiple radial +> orbitals corresponding to each $l$), and magnetic quantum number $m$. When `nspin` is set to 4, +> the dimension of the overlap matrix is (2 $\times$ nlocal) $\times$ (2 $\times$ nlocal). In this +> case, the numerical atomic orbitals are ordered from outer to inner loop as atom, angular quantum +> number $l$, zeta (multiple radial orbitals corresponding to each $l$), magnetic quantum number +> $m$, and npol (index of spin, ranges from 0 to 1). ## examples -We provide [examples](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/matrix_hs) of outputting the matrices. There are four examples: + +We provide +[examples](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/matrix_hs) of +outputting the matrices. There are four examples: - out_hs_gammaonly: writing H(k) and S(k) for gamma-only calculation - out_hs_multik: writing H(k) and S(k) for multi-k calculation diff --git a/docs/advanced/elec_properties/position_matrix.md b/docs/advanced/elec_properties/position_matrix.md index c504a866b64..80ddaf9c02f 100644 --- a/docs/advanced/elec_properties/position_matrix.md +++ b/docs/advanced/elec_properties/position_matrix.md @@ -1,12 +1,19 @@ # Extracting Position Matrices -In ABACUS, we provide the INPUT keyword [out_mat_r](../input_files/input-main.md#out_mat_r) to write the position matrices into a file named `data-rR-tr` in the directory `OUT.${suffix}`. The position matrices is defined as: +In ABACUS, we provide the INPUT keyword [out_mat_r](../input_files/input-main.md#out_mat_r) to write +the position matrices into a file named `data-rR-tr` in the directory `OUT.${suffix}`. The position +matrices is defined as: $$\langle \chi_\mu|\hat{r}|\chi_\nu\rangle$$ -This functionality is not available for gamma_only calculations. If you want to use it in gamma_only calculations, you should turn off [gamma_only](../input_files/input-main.md#gamma_only), and explicitly specifies that gamma point is the only k point in the KPT file. +This functionality is not available for gamma_only calculations. If you want to use it in gamma_only +calculations, you should turn off [gamma_only](../input_files/input-main.md#gamma_only), and +explicitly specifies that gamma point is the only k point in the KPT file. -Each file or each section of the appended file starts with "STEP: " followed by the current ion/md step, then the second line starts with "Matrix Dimension of $r(R)$: " followed by the dimension of the matrix, and the third line starts with "Matrix number of $r(R)$: " followed by the matrix number. The rest of the format is arranged into blocks, such as: +Each file or each section of the appended file starts with "STEP: " followed by the current ion/md +step, then the second line starts with "Matrix Dimension of $r(R)$: " followed by the dimension of +the matrix, and the third line starts with "Matrix number of $r(R)$: " followed by the matrix +number. The rest of the format is arranged into blocks, such as: ``` -5 -5 -5 //R (lattice vector) @@ -16,9 +23,20 @@ Each file or each section of the appended file starts with "STEP: " followed by -5 -5 -3 //R (lattice vector) ``` -Each block here contains the matrix for the corresponding cell. There are three columns in each block, giving the matrix elements in x, y, z directions, respectively. There are altogether nbasis * nbasis lines in each block, which emulates the matrix elements. +Each block here contains the matrix for the corresponding cell. There are three columns in each +block, giving the matrix elements in x, y, z directions, respectively. There are altogether nbasis +\* nbasis lines in each block, which emulates the matrix elements. -In molecular dynamics (MD) calculations, if [out_app_flag](../input_files/input-main.md#out_app_flag) is set to true, then `data-rR-tr` is written in an append manner. Otherwise, output files will be put in a separate directory, `matrix`, and named as `$x`_data-rR-tr, where `$x` is the number of MD step. In addition, the output frequency is controlled by [out_freq_ion](../input_files/input-main.md#out_freq_ion). For example, if we are running a 10-step MD with out_freq_ion = 3, then `$x` will be 0, 3, 6, and 9. +In molecular dynamics (MD) calculations, if +[out_app_flag](../input_files/input-main.md#out_app_flag) is set to true, then `data-rR-tr` is +written in an append manner. Otherwise, output files will be put in a separate directory, `matrix`, +and named as `$x`\_data-rR-tr, where `$x` is the number of MD step. In addition, the output +frequency is controlled by [out_freq_ion](../input_files/input-main.md#out_freq_ion). For example, +if we are running a 10-step MD with out_freq_ion = 3, then `$x` will be 0, 3, 6, and 9. ## get_s -We also offer the option of only calculating the position matrix without running SCF. For that purpose, in `INPUT` file we need to set the keyword [calculation](../input_files/input-main.md#calculation) to `get_s`, and [out_mat_r](../input_files/input-main.md#out_mat_r) to `true`. + +We also offer the option of only calculating the position matrix without running SCF. For that +purpose, in `INPUT` file we need to set the keyword +[calculation](../input_files/input-main.md#calculation) to `get_s`, and +[out_mat_r](../input_files/input-main.md#out_mat_r) to `true`. diff --git a/docs/advanced/elec_properties/potential.md b/docs/advanced/elec_properties/potential.md index 00732f407b5..3524afface8 100644 --- a/docs/advanced/elec_properties/potential.md +++ b/docs/advanced/elec_properties/potential.md @@ -1,6 +1,11 @@ # Extracting Electrostatic Potential -From version 2.1.0, ABACUS has the function of outputing electrostatic potential, which consists of Hartree potential and the local pseudopotential. To use this function, set ‘[out_pot](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-pot)’ to ‘2’ in the INPUT file. Here is an example for the [Si-111 surface](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/electrostatic_potential/lcao_Si), and the INPUT file is: +From version 2.1.0, ABACUS has the function of outputing electrostatic potential, which consists of +Hartree potential and the local pseudopotential. To use this function, set +‘[out_pot](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-pot)’ +to ‘2’ in the INPUT file. Here is an example for the +[Si-111 surface](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/electrostatic_potential/lcao_Si), +and the INPUT file is: ``` INPUT_PARAMETERS @@ -104,4 +109,5 @@ Gamma Run the program, and you will see the following two files in the output directory, -- ElecStaticPot.cube: contains electrostatic potential (unit: Rydberg) in realspace. This file can be visually viewed by the software of VESTA. +- ElecStaticPot.cube: contains electrostatic potential (unit: Rydberg) in realspace. This file can + be visually viewed by the software of VESTA. diff --git a/docs/advanced/elec_properties/wfc.md b/docs/advanced/elec_properties/wfc.md index dc96eb88844..27096b41bf0 100644 --- a/docs/advanced/elec_properties/wfc.md +++ b/docs/advanced/elec_properties/wfc.md @@ -1,18 +1,36 @@ # Extracting Wave Functions -ABACUS is able to output electron wave functions in both PW and LCAO basis calculations. One can find the examples in [examples/11_wfc](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/11_wfc). +ABACUS is able to output electron wave functions in both PW and LCAO basis calculations. One can +find the examples in +[examples/11_wfc](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/11_wfc). ## Wave Function in G-Space -To output wave functions in G-space, add one of the following keywords to the `INPUT` file while performing SCF calculation: -- **PW basis**: Set [`out_wfc_pw`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-pw) to `1`. Output file format: `wfs[spin]k[kpoint]_pw.txt`, where `[spin]` is the spin channel index, and `[kpoint]` the k-point index. +To output wave functions in G-space, add one of the following keywords to the `INPUT` file while +performing SCF calculation: + +- **PW basis**: Set + [`out_wfc_pw`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-pw) + to `1`. Output file format: `wfs[spin]k[kpoint]_pw.txt`, where `[spin]` is the spin channel index, + and `[kpoint]` the k-point index. + +- **LCAO basis**: Set + [`out_wfc_lcao`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-lcao) + to `1`. -- **LCAO basis**: Set [`out_wfc_lcao`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-lcao) to `1`. - **Multi-k calculations**: Generates multiple files `wfs[spin]k[kpoint]_nao.txt`. - **Gamma-only calculations**: `wfs[spin]_nao.txt` instead. ## Wave Function in Real Space -One can also choose to output real-space wave functions with the keyword [`out_wfc_norm`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-norm) or [`out_wfc_re_im`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-re-im). +One can also choose to output real-space wave functions with the keyword +[`out_wfc_norm`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-norm) +or +[`out_wfc_re_im`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-re-im). -Notice: When the [`basis_type`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#basis-type) is `lcao`, only `get_wf` [`calculation`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#calculation) is effective. An example is [examples/11_wfc/lcao_ienvelope_Si2](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/11_wfc/lcao_ienvelope_Si2). \ No newline at end of file +Notice: When the +[`basis_type`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#basis-type) +is `lcao`, only `get_wf` +[`calculation`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#calculation) +is effective. An example is +[examples/11_wfc/lcao_ienvelope_Si2](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/11_wfc/lcao_ienvelope_Si2). diff --git a/docs/advanced/input_files/input-main.md b/docs/advanced/input_files/input-main.md index b5f458c21ea..4125c3ced80 100644 --- a/docs/advanced/input_files/input-main.md +++ b/docs/advanced/input_files/input-main.md @@ -1,48 +1,50 @@ # Full List of INPUT Keywords + + - [Full List of INPUT Keywords](#full-list-of-input-keywords) - [System variables](#system-variables) - [suffix](#suffix) - [ntype](#ntype) - [calculation](#calculation) - - [esolver\_type](#esolver_type) + - [esolver_type](#esolver_type) - [symmetry](#symmetry) - - [symmetry\_prec](#symmetry_prec) - - [symmetry\_autoclose](#symmetry_autoclose) - - [cal\_force](#cal_force) + - [symmetry_prec](#symmetry_prec) + - [symmetry_autoclose](#symmetry_autoclose) + - [cal_force](#cal_force) - [kpar](#kpar) - [bndpar](#bndpar) - [latname](#latname) - - [init\_wfc](#init_wfc) - - [init\_chg](#init_chg) - - [init\_vel](#init_vel) - - [mem\_saver](#mem_saver) - - [cal\_stress](#cal_stress) - - [diago\_proc](#diago_proc) + - [init_wfc](#init_wfc) + - [init_chg](#init_chg) + - [init_vel](#init_vel) + - [mem_saver](#mem_saver) + - [cal_stress](#cal_stress) + - [diago_proc](#diago_proc) - [nbspline](#nbspline) - [kspacing](#kspacing) - - [min\_dist\_coef](#min_dist_coef) + - [min_dist_coef](#min_dist_coef) - [device](#device) - [precision](#precision) - - [gint\_precision](#gint_precision) - - [timer\_enable\_nvtx](#timer_enable_nvtx) - - [cell\_factor](#cell_factor) - - [dm\_to\_rho](#dm_to_rho) - - [chg\_extrap](#chg_extrap) + - [gint_precision](#gint_precision) + - [timer_enable_nvtx](#timer_enable_nvtx) + - [cell_factor](#cell_factor) + - [dm_to_rho](#dm_to_rho) + - [chg_extrap](#chg_extrap) - [nb2d](#nb2d) - - [cal\_symm\_repr](#cal_symm_repr) + - [cal_symm_repr](#cal_symm_repr) - [Input files](#input-files) - - [stru\_file](#stru_file) - - [kpoint\_file](#kpoint_file) - - [pseudo\_dir](#pseudo_dir) - - [orbital\_dir](#orbital_dir) - - [read\_file\_dir](#read_file_dir) - - [restart\_load](#restart_load) - - [spillage\_outdir](#spillage_outdir) + - [stru_file](#stru_file) + - [kpoint_file](#kpoint_file) + - [pseudo_dir](#pseudo_dir) + - [orbital_dir](#orbital_dir) + - [read_file_dir](#read_file_dir) + - [restart_load](#restart_load) + - [spillage_outdir](#spillage_outdir) - [Plane wave related variables](#plane-wave-related-variables) - [ecutwfc](#ecutwfc) - [ecutrho](#ecutrho) @@ -52,500 +54,502 @@ - [ndx](#ndx) - [ndy](#ndy) - [ndz](#ndz) - - [pw\_seed](#pw_seed) - - [diag\_subspace](#diag_subspace) - - [erf\_ecut](#erf_ecut) - - [fft\_mode](#fft_mode) - - [erf\_height](#erf_height) - - [erf\_sigma](#erf_sigma) - - [pw\_diag\_thr](#pw_diag_thr) - - [diago\_smooth\_ethr](#diago_smooth_ethr) - - [use\_k\_continuity](#use_k_continuity) - - [pw\_diag\_nmax](#pw_diag_nmax) - - [pw\_diag\_ndim](#pw_diag_ndim) - - [diago\_cg\_prec](#diago_cg_prec) + - [pw_seed](#pw_seed) + - [diag_subspace](#diag_subspace) + - [erf_ecut](#erf_ecut) + - [fft_mode](#fft_mode) + - [erf_height](#erf_height) + - [erf_sigma](#erf_sigma) + - [pw_diag_thr](#pw_diag_thr) + - [diago_smooth_ethr](#diago_smooth_ethr) + - [use_k_continuity](#use_k_continuity) + - [pw_diag_nmax](#pw_diag_nmax) + - [pw_diag_ndim](#pw_diag_ndim) + - [diago_cg_prec](#diago_cg_prec) - [Numerical atomic orbitals related variables](#numerical-atomic-orbitals-related-variables) - [lmaxmax](#lmaxmax) - - [lcao\_ecut](#lcao_ecut) - - [lcao\_dk](#lcao_dk) - - [lcao\_dr](#lcao_dr) - - [lcao\_rmax](#lcao_rmax) - - [search\_radius](#search_radius) + - [lcao_ecut](#lcao_ecut) + - [lcao_dk](#lcao_dk) + - [lcao_dr](#lcao_dr) + - [lcao_rmax](#lcao_rmax) + - [search_radius](#search_radius) - [bx](#bx) - [by](#by) - [bz](#bz) - - [elpa\_num\_thread](#elpa_num_thread) - - [num\_stream](#num_stream) + - [elpa_num_thread](#elpa_num_thread) + - [num_stream](#num_stream) - [Electronic structure](#electronic-structure) - - [basis\_type](#basis_type) - - [ks\_solver](#ks_solver) + - [basis_type](#basis_type) + - [ks_solver](#ks_solver) - [nbands](#nbands) - [nelec](#nelec) - - [nelec\_delta](#nelec_delta) + - [nelec_delta](#nelec_delta) - [nupdown](#nupdown) - - [dft\_functional](#dft_functional) - - [xc\_temperature](#xc_temperature) - - [xc\_exch\_ext](#xc_exch_ext) - - [xc\_corr\_ext](#xc_corr_ext) - - [pseudo\_rcut](#pseudo_rcut) - - [pseudo\_mesh](#pseudo_mesh) + - [dft_functional](#dft_functional) + - [xc_temperature](#xc_temperature) + - [xc_exch_ext](#xc_exch_ext) + - [xc_corr_ext](#xc_corr_ext) + - [pseudo_rcut](#pseudo_rcut) + - [pseudo_mesh](#pseudo_mesh) - [nspin](#nspin) - - [smearing\_method](#smearing_method) - - [smearing\_sigma](#smearing_sigma) - - [smearing\_sigma\_temp](#smearing_sigma_temp) - - [mixing\_type](#mixing_type) - - [mixing\_beta](#mixing_beta) - - [mixing\_beta\_mag](#mixing_beta_mag) - - [mixing\_ndim](#mixing_ndim) - - [mixing\_restart](#mixing_restart) - - [mixing\_dmr](#mixing_dmr) - - [mixing\_gg0](#mixing_gg0) - - [mixing\_gg0\_mag](#mixing_gg0_mag) - - [mixing\_gg0\_min](#mixing_gg0_min) - - [mixing\_angle](#mixing_angle) - - [mixing\_tau](#mixing_tau) - - [mixing\_dftu](#mixing_dftu) - - [gamma\_only](#gamma_only) - - [scf\_nmax](#scf_nmax) - - [scf\_thr](#scf_thr) - - [scf\_ene\_thr](#scf_ene_thr) - - [scf\_thr\_type](#scf_thr_type) - - [scf\_os\_stop](#scf_os_stop) - - [scf\_os\_thr](#scf_os_thr) - - [scf\_os\_ndim](#scf_os_ndim) - - [sc\_os\_ndim](#sc_os_ndim) + - [smearing_method](#smearing_method) + - [smearing_sigma](#smearing_sigma) + - [smearing_sigma_temp](#smearing_sigma_temp) + - [mixing_type](#mixing_type) + - [mixing_beta](#mixing_beta) + - [mixing_beta_mag](#mixing_beta_mag) + - [mixing_ndim](#mixing_ndim) + - [mixing_restart](#mixing_restart) + - [mixing_dmr](#mixing_dmr) + - [mixing_gg0](#mixing_gg0) + - [mixing_gg0_mag](#mixing_gg0_mag) + - [mixing_gg0_min](#mixing_gg0_min) + - [mixing_angle](#mixing_angle) + - [mixing_tau](#mixing_tau) + - [mixing_dftu](#mixing_dftu) + - [gamma_only](#gamma_only) + - [scf_nmax](#scf_nmax) + - [scf_thr](#scf_thr) + - [scf_ene_thr](#scf_ene_thr) + - [scf_thr_type](#scf_thr_type) + - [scf_os_stop](#scf_os_stop) + - [scf_os_thr](#scf_os_thr) + - [scf_os_ndim](#scf_os_ndim) + - [sc_os_ndim](#sc_os_ndim) - [lspinorb](#lspinorb) - [noncolin](#noncolin) - - [soc\_lambda](#soc_lambda) - - [dfthalf\_type](#dfthalf_type) + - [soc_lambda](#soc_lambda) + - [dfthalf_type](#dfthalf_type) - [Electronic structure (SDFT)](#electronic-structure-sdft) - - [method\_sto](#method_sto) - - [nbands\_sto](#nbands_sto) - - [nche\_sto](#nche_sto) - - [emin\_sto](#emin_sto) - - [emax\_sto](#emax_sto) - - [seed\_sto](#seed_sto) - - [initsto\_ecut](#initsto_ecut) - - [initsto\_freq](#initsto_freq) - - [npart\_sto](#npart_sto) + - [method_sto](#method_sto) + - [nbands_sto](#nbands_sto) + - [nche_sto](#nche_sto) + - [emin_sto](#emin_sto) + - [emax_sto](#emax_sto) + - [seed_sto](#seed_sto) + - [initsto_ecut](#initsto_ecut) + - [initsto_freq](#initsto_freq) + - [npart_sto](#npart_sto) - [Geometry relaxation](#geometry-relaxation) - - [relax\_method](#relax_method) - - [relax\_new](#relax_new) - - [relax\_scale\_force](#relax_scale_force) - - [relax\_nmax](#relax_nmax) - - [relax\_cg\_thr](#relax_cg_thr) - - [force\_thr](#force_thr) - - [force\_thr\_ev](#force_thr_ev) - - [force\_zero\_out](#force_zero_out) - - [relax\_bfgs\_w1](#relax_bfgs_w1) - - [relax\_bfgs\_w2](#relax_bfgs_w2) - - [relax\_bfgs\_rmax](#relax_bfgs_rmax) - - [relax\_bfgs\_rmin](#relax_bfgs_rmin) - - [relax\_bfgs\_init](#relax_bfgs_init) - - [stress\_thr](#stress_thr) + - [relax_method](#relax_method) + - [relax_new](#relax_new) + - [relax_scale_force](#relax_scale_force) + - [relax_nmax](#relax_nmax) + - [relax_cg_thr](#relax_cg_thr) + - [force_thr](#force_thr) + - [force_thr_ev](#force_thr_ev) + - [force_zero_out](#force_zero_out) + - [relax_bfgs_w1](#relax_bfgs_w1) + - [relax_bfgs_w2](#relax_bfgs_w2) + - [relax_bfgs_rmax](#relax_bfgs_rmax) + - [relax_bfgs_rmin](#relax_bfgs_rmin) + - [relax_bfgs_init](#relax_bfgs_init) + - [stress_thr](#stress_thr) - [press1](#press1) - [press2](#press2) - [press3](#press3) - - [fixed\_axes](#fixed_axes) - - [fixed\_ibrav](#fixed_ibrav) - - [fixed\_atoms](#fixed_atoms) + - [fixed_axes](#fixed_axes) + - [fixed_ibrav](#fixed_ibrav) + - [fixed_atoms](#fixed_atoms) - [Output information](#output-information) - - [out\_freq\_ion](#out_freq_ion) - - [out\_freq\_td](#out_freq_td) - - [out\_freq\_elec](#out_freq_elec) - - [out\_chg](#out_chg) - - [out\_pot](#out_pot) - - [out\_dmk](#out_dmk) - - [out\_dmr](#out_dmr) - - [out\_wfc\_pw](#out_wfc_pw) - - [out\_wfc\_lcao](#out_wfc_lcao) - - [out\_dos](#out_dos) - - [out\_ldos](#out_ldos) - - [out\_band](#out_band) - - [out\_proj\_band](#out_proj_band) - - [out\_stru](#out_stru) - - [out\_level](#out_level) - - [out\_mat\_hs](#out_mat_hs) - - [out\_mat\_hs2](#out_mat_hs2) - - [out\_mat\_tk](#out_mat_tk) - - [out\_mat\_r](#out_mat_r) - - [out\_mat\_t](#out_mat_t) - - [out\_mat\_dh](#out_mat_dh) - - [out\_mat\_ds](#out_mat_ds) - - [out\_mat\_xc](#out_mat_xc) - - [out\_mat\_xc2](#out_mat_xc2) - - [out\_mat\_l](#out_mat_l) - - [out\_xc\_r](#out_xc_r) - - [out\_eband\_terms](#out_eband_terms) - - [out\_mul](#out_mul) - - [out\_app\_flag](#out_app_flag) - - [out\_ndigits](#out_ndigits) - - [out\_element\_info](#out_element_info) - - [restart\_save](#restart_save) + - [out_freq_ion](#out_freq_ion) + - [out_freq_td](#out_freq_td) + - [out_freq_elec](#out_freq_elec) + - [out_chg](#out_chg) + - [out_pot](#out_pot) + - [out_dmk](#out_dmk) + - [out_dmr](#out_dmr) + - [out_wfc_pw](#out_wfc_pw) + - [out_wfc_lcao](#out_wfc_lcao) + - [out_dos](#out_dos) + - [out_ldos](#out_ldos) + - [out_band](#out_band) + - [out_proj_band](#out_proj_band) + - [out_stru](#out_stru) + - [out_level](#out_level) + - [out_mat_hs](#out_mat_hs) + - [out_mat_hs2](#out_mat_hs2) + - [out_mat_tk](#out_mat_tk) + - [out_mat_r](#out_mat_r) + - [out_mat_t](#out_mat_t) + - [out_mat_dh](#out_mat_dh) + - [out_mat_ds](#out_mat_ds) + - [out_mat_xc](#out_mat_xc) + - [out_mat_xc2](#out_mat_xc2) + - [out_mat_l](#out_mat_l) + - [out_xc_r](#out_xc_r) + - [out_eband_terms](#out_eband_terms) + - [out_mul](#out_mul) + - [out_app_flag](#out_app_flag) + - [out_ndigits](#out_ndigits) + - [out_element_info](#out_element_info) + - [restart_save](#restart_save) - [rpa](#rpa) - - [out\_pchg](#out_pchg) - - [out\_wfc\_norm](#out_wfc_norm) - - [out\_wfc\_re\_im](#out_wfc_re_im) - - [if\_separate\_k](#if_separate_k) - - [out\_elf](#out_elf) - - [out\_spillage](#out_spillage) - - [out\_alllog](#out_alllog) + - [out_pchg](#out_pchg) + - [out_wfc_norm](#out_wfc_norm) + - [out_wfc_re_im](#out_wfc_re_im) + - [if_separate_k](#if_separate_k) + - [out_elf](#out_elf) + - [out_spillage](#out_spillage) + - [out_alllog](#out_alllog) - [Density of states](#density-of-states) - - [dos\_edelta\_ev](#dos_edelta_ev) - - [dos\_sigma](#dos_sigma) - - [dos\_scale](#dos_scale) - - [dos\_emin\_ev](#dos_emin_ev) - - [dos\_emax\_ev](#dos_emax_ev) - - [dos\_nche](#dos_nche) - - [stm\_bias](#stm_bias) - - [ldos\_line](#ldos_line) + - [dos_edelta_ev](#dos_edelta_ev) + - [dos_sigma](#dos_sigma) + - [dos_scale](#dos_scale) + - [dos_emin_ev](#dos_emin_ev) + - [dos_emax_ev](#dos_emax_ev) + - [dos_nche](#dos_nche) + - [stm_bias](#stm_bias) + - [ldos_line](#ldos_line) - [NAOs](#naos) - - [bessel\_nao\_ecut](#bessel_nao_ecut) - - [bessel\_nao\_tolerence](#bessel_nao_tolerence) - - [bessel\_nao\_rcut](#bessel_nao_rcut) - - [bessel\_nao\_smooth](#bessel_nao_smooth) - - [bessel\_nao\_sigma](#bessel_nao_sigma) + - [bessel_nao_ecut](#bessel_nao_ecut) + - [bessel_nao_tolerence](#bessel_nao_tolerence) + - [bessel_nao_rcut](#bessel_nao_rcut) + - [bessel_nao_smooth](#bessel_nao_smooth) + - [bessel_nao_sigma](#bessel_nao_sigma) - [DeePKS](#deepks) - - [deepks\_out\_labels](#deepks_out_labels) - - [deepks\_out\_freq\_elec](#deepks_out_freq_elec) - - [deepks\_out\_base](#deepks_out_base) - - [deepks\_scf](#deepks_scf) - - [deepks\_equiv](#deepks_equiv) - - [deepks\_model](#deepks_model) - - [bessel\_descriptor\_lmax](#bessel_descriptor_lmax) - - [bessel\_descriptor\_ecut](#bessel_descriptor_ecut) - - [bessel\_descriptor\_tolerence](#bessel_descriptor_tolerence) - - [bessel\_descriptor\_rcut](#bessel_descriptor_rcut) - - [bessel\_descriptor\_smooth](#bessel_descriptor_smooth) - - [bessel\_descriptor\_sigma](#bessel_descriptor_sigma) - - [deepks\_bandgap](#deepks_bandgap) - - [deepks\_band\_range](#deepks_band_range) - - [deepks\_v\_delta](#deepks_v_delta) - - [deepks\_out\_unittest](#deepks_out_unittest) + - [deepks_out_labels](#deepks_out_labels) + - [deepks_out_freq_elec](#deepks_out_freq_elec) + - [deepks_out_base](#deepks_out_base) + - [deepks_scf](#deepks_scf) + - [deepks_equiv](#deepks_equiv) + - [deepks_model](#deepks_model) + - [bessel_descriptor_lmax](#bessel_descriptor_lmax) + - [bessel_descriptor_ecut](#bessel_descriptor_ecut) + - [bessel_descriptor_tolerence](#bessel_descriptor_tolerence) + - [bessel_descriptor_rcut](#bessel_descriptor_rcut) + - [bessel_descriptor_smooth](#bessel_descriptor_smooth) + - [bessel_descriptor_sigma](#bessel_descriptor_sigma) + - [deepks_bandgap](#deepks_bandgap) + - [deepks_band_range](#deepks_band_range) + - [deepks_v_delta](#deepks_v_delta) + - [deepks_out_unittest](#deepks_out_unittest) - [OFDFT: orbital free density functional theory](#ofdft-orbital-free-density-functional-theory) - - [of\_kinetic](#of_kinetic) - - [of\_method](#of_method) - - [of\_conv](#of_conv) - - [of\_tole](#of_tole) - - [of\_tolp](#of_tolp) - - [of\_tf\_weight](#of_tf_weight) - - [of\_vw\_weight](#of_vw_weight) - - [of\_wt\_alpha](#of_wt_alpha) - - [of\_wt\_beta](#of_wt_beta) - - [of\_extwt\_kappa](#of_extwt_kappa) - - [of\_wt\_rho0](#of_wt_rho0) - - [of\_hold\_rho0](#of_hold_rho0) - - [of\_lkt\_a](#of_lkt_a) - - [of\_xwm\_rho\_ref](#of_xwm_rho_ref) - - [of\_xwm\_kappa](#of_xwm_kappa) - - [of\_read\_kernel](#of_read_kernel) - - [of\_kernel\_file](#of_kernel_file) - - [of\_full\_pw](#of_full_pw) - - [of\_full\_pw\_dim](#of_full_pw_dim) + - [of_kinetic](#of_kinetic) + - [of_method](#of_method) + - [of_conv](#of_conv) + - [of_tole](#of_tole) + - [of_tolp](#of_tolp) + - [of_tf_weight](#of_tf_weight) + - [of_vw_weight](#of_vw_weight) + - [of_wt_alpha](#of_wt_alpha) + - [of_wt_beta](#of_wt_beta) + - [of_extwt_kappa](#of_extwt_kappa) + - [of_wt_rho0](#of_wt_rho0) + - [of_hold_rho0](#of_hold_rho0) + - [of_lkt_a](#of_lkt_a) + - [of_xwm_rho_ref](#of_xwm_rho_ref) + - [of_xwm_kappa](#of_xwm_kappa) + - [of_read_kernel](#of_read_kernel) + - [of_kernel_file](#of_kernel_file) + - [of_full_pw](#of_full_pw) + - [of_full_pw_dim](#of_full_pw_dim) - [ML-KEDF: machine learning based kinetic energy density functional for OFDFT](#ml-kedf-machine-learning-based-kinetic-energy-density-functional-for-ofdft) - - [of\_ml\_gene\_data](#of_ml_gene_data) - - [of\_ml\_device](#of_ml_device) - - [of\_ml\_feg](#of_ml_feg) - - [of\_ml\_nkernel](#of_ml_nkernel) - - [of\_ml\_kernel](#of_ml_kernel) - - [of\_ml\_kernel\_scaling](#of_ml_kernel_scaling) - - [of\_ml\_yukawa\_alpha](#of_ml_yukawa_alpha) - - [of\_ml\_kernel\_file](#of_ml_kernel_file) - - [of\_ml\_gamma](#of_ml_gamma) - - [of\_ml\_p](#of_ml_p) - - [of\_ml\_q](#of_ml_q) - - [of\_ml\_tanhp](#of_ml_tanhp) - - [of\_ml\_tanhq](#of_ml_tanhq) - - [of\_ml\_chi\_p](#of_ml_chi_p) - - [of\_ml\_chi\_q](#of_ml_chi_q) - - [of\_ml\_gammanl](#of_ml_gammanl) - - [of\_ml\_pnl](#of_ml_pnl) - - [of\_ml\_qnl](#of_ml_qnl) - - [of\_ml\_xi](#of_ml_xi) - - [of\_ml\_tanhxi](#of_ml_tanhxi) - - [of\_ml\_tanhxi\_nl](#of_ml_tanhxi_nl) - - [of\_ml\_tanh\_pnl](#of_ml_tanh_pnl) - - [of\_ml\_tanh\_qnl](#of_ml_tanh_qnl) - - [of\_ml\_tanhp\_nl](#of_ml_tanhp_nl) - - [of\_ml\_tanhq\_nl](#of_ml_tanhq_nl) - - [of\_ml\_chi\_xi](#of_ml_chi_xi) - - [of\_ml\_chi\_pnl](#of_ml_chi_pnl) - - [of\_ml\_chi\_qnl](#of_ml_chi_qnl) - - [of\_ml\_local\_test](#of_ml_local_test) - - [ml\_exx](#ml_exx) + - [of_ml_gene_data](#of_ml_gene_data) + - [of_ml_device](#of_ml_device) + - [of_ml_feg](#of_ml_feg) + - [of_ml_nkernel](#of_ml_nkernel) + - [of_ml_kernel](#of_ml_kernel) + - [of_ml_kernel_scaling](#of_ml_kernel_scaling) + - [of_ml_yukawa_alpha](#of_ml_yukawa_alpha) + - [of_ml_kernel_file](#of_ml_kernel_file) + - [of_ml_gamma](#of_ml_gamma) + - [of_ml_p](#of_ml_p) + - [of_ml_q](#of_ml_q) + - [of_ml_tanhp](#of_ml_tanhp) + - [of_ml_tanhq](#of_ml_tanhq) + - [of_ml_chi_p](#of_ml_chi_p) + - [of_ml_chi_q](#of_ml_chi_q) + - [of_ml_gammanl](#of_ml_gammanl) + - [of_ml_pnl](#of_ml_pnl) + - [of_ml_qnl](#of_ml_qnl) + - [of_ml_xi](#of_ml_xi) + - [of_ml_tanhxi](#of_ml_tanhxi) + - [of_ml_tanhxi_nl](#of_ml_tanhxi_nl) + - [of_ml_tanh_pnl](#of_ml_tanh_pnl) + - [of_ml_tanh_qnl](#of_ml_tanh_qnl) + - [of_ml_tanhp_nl](#of_ml_tanhp_nl) + - [of_ml_tanhq_nl](#of_ml_tanhq_nl) + - [of_ml_chi_xi](#of_ml_chi_xi) + - [of_ml_chi_pnl](#of_ml_chi_pnl) + - [of_ml_chi_qnl](#of_ml_chi_qnl) + - [of_ml_local_test](#of_ml_local_test) + - [ml_exx](#ml_exx) - [TDOFDFT: time dependent orbital free density functional theory](#tdofdft-time-dependent-orbital-free-density-functional-theory) - - [of\_cd](#of_cd) - - [of\_mcd\_alpha](#of_mcd_alpha) + - [of_cd](#of_cd) + - [of_mcd_alpha](#of_mcd_alpha) - [Electric field and dipole correction](#electric-field-and-dipole-correction) - - [efield\_flag](#efield_flag) - - [dip\_cor\_flag](#dip_cor_flag) - - [efield\_dir](#efield_dir) - - [efield\_pos\_max](#efield_pos_max) - - [efield\_pos\_dec](#efield_pos_dec) - - [efield\_amp](#efield_amp) + - [efield_flag](#efield_flag) + - [dip_cor_flag](#dip_cor_flag) + - [efield_dir](#efield_dir) + - [efield_pos_max](#efield_pos_max) + - [efield_pos_dec](#efield_pos_dec) + - [efield_amp](#efield_amp) - [Gate field (compensating charge)](#gate-field-compensating-charge) - - [gate\_flag](#gate_flag) + - [gate_flag](#gate_flag) - [zgate](#zgate) - [block](#block) - - [block\_down](#block_down) - - [block\_up](#block_up) - - [block\_height](#block_height) + - [block_down](#block_down) + - [block_up](#block_up) + - [block_height](#block_height) - [Exact Exchange (Common)](#exact-exchange-common) - - [exx\_fock\_alpha](#exx_fock_alpha) - - [exx\_erfc\_alpha](#exx_erfc_alpha) - - [exx\_erfc\_omega](#exx_erfc_omega) - - [exx\_separate\_loop](#exx_separate_loop) - - [exx\_hybrid\_step](#exx_hybrid_step) - - [exx\_mixing\_beta](#exx_mixing_beta) + - [exx_fock_alpha](#exx_fock_alpha) + - [exx_erfc_alpha](#exx_erfc_alpha) + - [exx_erfc_omega](#exx_erfc_omega) + - [exx_separate_loop](#exx_separate_loop) + - [exx_hybrid_step](#exx_hybrid_step) + - [exx_mixing_beta](#exx_mixing_beta) - [Exact Exchange (LCAO in PW)](#exact-exchange-lcao-in-pw) - - [exx\_fock\_lambda](#exx_fock_lambda) + - [exx_fock_lambda](#exx_fock_lambda) - [Exact Exchange (LCAO)](#exact-exchange-lcao) - - [exx\_pca\_threshold](#exx_pca_threshold) - - [exx\_c\_threshold](#exx_c_threshold) - - [exx\_cs\_inv\_thr](#exx_cs_inv_thr) - - [shrink\_abfs\_pca\_thr](#shrink_abfs_pca_thr) - - [shrink\_lu\_inv\_thr](#shrink_lu_inv_thr) - - [exx\_v\_threshold](#exx_v_threshold) - - [exx\_dm\_threshold](#exx_dm_threshold) - - [exx\_c\_grad\_threshold](#exx_c_grad_threshold) - - [exx\_v\_grad\_threshold](#exx_v_grad_threshold) - - [exx\_c\_grad\_r\_threshold](#exx_c_grad_r_threshold) - - [exx\_v\_grad\_r\_threshold](#exx_v_grad_r_threshold) - - [exx\_ccp\_rmesh\_times](#exx_ccp_rmesh_times) - - [exx\_opt\_orb\_lmax](#exx_opt_orb_lmax) - - [exx\_opt\_orb\_ecut](#exx_opt_orb_ecut) - - [exx\_opt\_orb\_tolerence](#exx_opt_orb_tolerence) - - [exx\_real\_number](#exx_real_number) - - [exx\_singularity\_correction](#exx_singularity_correction) - - [rpa\_ccp\_rmesh\_times](#rpa_ccp_rmesh_times) - - [exx\_symmetry\_realspace](#exx_symmetry_realspace) - - [out\_ri\_cv](#out_ri_cv) - - [out\_unshrinked\_v](#out_unshrinked_v) - - [exx\_coul\_moment](#exx_coul_moment) - - [exx\_rotate\_abfs](#exx_rotate_abfs) - - [exx\_multip\_moments\_threshold](#exx_multip_moments_threshold) + - [exx_pca_threshold](#exx_pca_threshold) + - [exx_c_threshold](#exx_c_threshold) + - [exx_cs_inv_thr](#exx_cs_inv_thr) + - [shrink_abfs_pca_thr](#shrink_abfs_pca_thr) + - [shrink_lu_inv_thr](#shrink_lu_inv_thr) + - [exx_v_threshold](#exx_v_threshold) + - [exx_dm_threshold](#exx_dm_threshold) + - [exx_c_grad_threshold](#exx_c_grad_threshold) + - [exx_v_grad_threshold](#exx_v_grad_threshold) + - [exx_c_grad_r_threshold](#exx_c_grad_r_threshold) + - [exx_v_grad_r_threshold](#exx_v_grad_r_threshold) + - [exx_ccp_rmesh_times](#exx_ccp_rmesh_times) + - [exx_opt_orb_lmax](#exx_opt_orb_lmax) + - [exx_opt_orb_ecut](#exx_opt_orb_ecut) + - [exx_opt_orb_tolerence](#exx_opt_orb_tolerence) + - [exx_real_number](#exx_real_number) + - [exx_singularity_correction](#exx_singularity_correction) + - [rpa_ccp_rmesh_times](#rpa_ccp_rmesh_times) + - [exx_symmetry_realspace](#exx_symmetry_realspace) + - [out_ri_cv](#out_ri_cv) + - [out_unshrinked_v](#out_unshrinked_v) + - [exx_coul_moment](#exx_coul_moment) + - [exx_rotate_abfs](#exx_rotate_abfs) + - [exx_multip_moments_threshold](#exx_multip_moments_threshold) - [Exact Exchange (PW)](#exact-exchange-pw) - [exxace](#exxace) - - [exx\_gamma\_extrapolation](#exx_gamma_extrapolation) + - [exx_gamma_extrapolation](#exx_gamma_extrapolation) - [ecutexx](#ecutexx) - - [exx\_thr\_type](#exx_thr_type) - - [exx\_ene\_thr](#exx_ene_thr) + - [exx_thr_type](#exx_thr_type) + - [exx_ene_thr](#exx_ene_thr) - [Molecular dynamics](#molecular-dynamics) - - [md\_type](#md_type) - - [md\_nstep](#md_nstep) - - [md\_dt](#md_dt) - - [md\_thermostat](#md_thermostat) - - [md\_tfirst](#md_tfirst) - - [md\_tlast](#md_tlast) - - [md\_prec\_level](#md_prec_level) - - [md\_restart](#md_restart) - - [md\_restartfreq](#md_restartfreq) - - [md\_dumpfreq](#md_dumpfreq) - - [dump\_force](#dump_force) - - [dump\_vel](#dump_vel) - - [dump\_virial](#dump_virial) - - [md\_seed](#md_seed) - - [md\_tfreq](#md_tfreq) - - [md\_tchain](#md_tchain) - - [md\_pmode](#md_pmode) - - [ref\_cell\_factor](#ref_cell_factor) - - [md\_pcouple](#md_pcouple) - - [md\_pfirst](#md_pfirst) - - [md\_plast](#md_plast) - - [md\_pfreq](#md_pfreq) - - [md\_pchain](#md_pchain) - - [lj\_rule](#lj_rule) - - [lj\_eshift](#lj_eshift) - - [lj\_rcut](#lj_rcut) - - [lj\_epsilon](#lj_epsilon) - - [lj\_sigma](#lj_sigma) - - [pot\_file](#pot_file) - - [dp\_rescaling](#dp_rescaling) - - [dp\_fparam](#dp_fparam) - - [dp\_aparam](#dp_aparam) - - [msst\_direction](#msst_direction) - - [msst\_vel](#msst_vel) - - [msst\_vis](#msst_vis) - - [msst\_tscale](#msst_tscale) - - [msst\_qmass](#msst_qmass) - - [md\_damp](#md_damp) - - [md\_tolerance](#md_tolerance) - - [md\_nraise](#md_nraise) - - [cal\_syns](#cal_syns) + - [md_type](#md_type) + - [md_nstep](#md_nstep) + - [md_dt](#md_dt) + - [md_thermostat](#md_thermostat) + - [md_tfirst](#md_tfirst) + - [md_tlast](#md_tlast) + - [md_prec_level](#md_prec_level) + - [md_restart](#md_restart) + - [md_restartfreq](#md_restartfreq) + - [md_dumpfreq](#md_dumpfreq) + - [dump_force](#dump_force) + - [dump_vel](#dump_vel) + - [dump_virial](#dump_virial) + - [md_seed](#md_seed) + - [md_tfreq](#md_tfreq) + - [md_tchain](#md_tchain) + - [md_pmode](#md_pmode) + - [ref_cell_factor](#ref_cell_factor) + - [md_pcouple](#md_pcouple) + - [md_pfirst](#md_pfirst) + - [md_plast](#md_plast) + - [md_pfreq](#md_pfreq) + - [md_pchain](#md_pchain) + - [lj_rule](#lj_rule) + - [lj_eshift](#lj_eshift) + - [lj_rcut](#lj_rcut) + - [lj_epsilon](#lj_epsilon) + - [lj_sigma](#lj_sigma) + - [pot_file](#pot_file) + - [dp_rescaling](#dp_rescaling) + - [dp_fparam](#dp_fparam) + - [dp_aparam](#dp_aparam) + - [msst_direction](#msst_direction) + - [msst_vel](#msst_vel) + - [msst_vis](#msst_vis) + - [msst_tscale](#msst_tscale) + - [msst_qmass](#msst_qmass) + - [md_damp](#md_damp) + - [md_tolerance](#md_tolerance) + - [md_nraise](#md_nraise) + - [cal_syns](#cal_syns) - [dmax](#dmax) - [DFT+U correction](#dftu-correction) - - [dft\_plus\_u](#dft_plus_u) - - [dft\_plus\_dmft](#dft_plus_dmft) - - [orbital\_corr](#orbital_corr) - - [hubbard\_u](#hubbard_u) - - [yukawa\_potential](#yukawa_potential) - - [yukawa\_lambda](#yukawa_lambda) + - [dft_plus_u](#dft_plus_u) + - [dft_plus_dmft](#dft_plus_dmft) + - [orbital_corr](#orbital_corr) + - [hubbard_u](#hubbard_u) + - [yukawa_potential](#yukawa_potential) + - [yukawa_lambda](#yukawa_lambda) - [uramping](#uramping) - [omc](#omc) - - [onsite\_radius](#onsite_radius) + - [onsite_radius](#onsite_radius) - [Spin-Constrained DFT](#spin-constrained-dft) - - [sc\_mag\_switch](#sc_mag_switch) - - [decay\_grad\_switch](#decay_grad_switch) - - [sc\_thr](#sc_thr) + - [sc_mag_switch](#sc_mag_switch) + - [decay_grad_switch](#decay_grad_switch) + - [sc_thr](#sc_thr) - [nsc](#nsc) - - [nsc\_min](#nsc_min) - - [sc\_scf\_nmin](#sc_scf_nmin) - - [alpha\_trial](#alpha_trial) + - [nsc_min](#nsc_min) + - [sc_scf_nmin](#sc_scf_nmin) + - [alpha_trial](#alpha_trial) - [sccut](#sccut) - - [sc\_drop\_thr](#sc_drop_thr) - - [sc\_scf\_thr](#sc_scf_thr) + - [sc_drop_thr](#sc_drop_thr) + - [sc_scf_thr](#sc_scf_thr) - [vdW correction](#vdw-correction) - - [vdw\_method](#vdw_method) - - [vdw\_s6](#vdw_s6) - - [vdw\_s8](#vdw_s8) - - [vdw\_a1](#vdw_a1) - - [vdw\_a2](#vdw_a2) - - [vdw\_d](#vdw_d) - - [vdw\_abc](#vdw_abc) - - [vdw\_c6\_file](#vdw_c6_file) - - [vdw\_c6\_unit](#vdw_c6_unit) - - [vdw\_r0\_file](#vdw_r0_file) - - [vdw\_r0\_unit](#vdw_r0_unit) - - [vdw\_cutoff\_type](#vdw_cutoff_type) - - [vdw\_cutoff\_radius](#vdw_cutoff_radius) - - [vdw\_radius\_unit](#vdw_radius_unit) - - [vdw\_cutoff\_period](#vdw_cutoff_period) - - [vdw\_cn\_thr](#vdw_cn_thr) - - [vdw\_cn\_thr\_unit](#vdw_cn_thr_unit) + - [vdw_method](#vdw_method) + - [vdw_s6](#vdw_s6) + - [vdw_s8](#vdw_s8) + - [vdw_a1](#vdw_a1) + - [vdw_a2](#vdw_a2) + - [vdw_d](#vdw_d) + - [vdw_abc](#vdw_abc) + - [vdw_c6_file](#vdw_c6_file) + - [vdw_c6_unit](#vdw_c6_unit) + - [vdw_r0_file](#vdw_r0_file) + - [vdw_r0_unit](#vdw_r0_unit) + - [vdw_cutoff_type](#vdw_cutoff_type) + - [vdw_cutoff_radius](#vdw_cutoff_radius) + - [vdw_radius_unit](#vdw_radius_unit) + - [vdw_cutoff_period](#vdw_cutoff_period) + - [vdw_cn_thr](#vdw_cn_thr) + - [vdw_cn_thr_unit](#vdw_cn_thr_unit) - [Berry phase and wannier90 interface](#berry-phase-and-wannier90-interface) - - [berry\_phase](#berry_phase) + - [berry_phase](#berry_phase) - [gdir](#gdir) - [towannier90](#towannier90) - [nnkpfile](#nnkpfile) - - [wannier\_method](#wannier_method) - - [wannier\_spin](#wannier_spin) - - [out\_wannier\_mmn](#out_wannier_mmn) - - [out\_wannier\_amn](#out_wannier_amn) - - [out\_wannier\_eig](#out_wannier_eig) - - [out\_wannier\_unk](#out_wannier_unk) - - [out\_wannier\_wvfn\_formatted](#out_wannier_wvfn_formatted) + - [wannier_method](#wannier_method) + - [wannier_spin](#wannier_spin) + - [out_wannier_mmn](#out_wannier_mmn) + - [out_wannier_amn](#out_wannier_amn) + - [out_wannier_eig](#out_wannier_eig) + - [out_wannier_unk](#out_wannier_unk) + - [out_wannier_wvfn_formatted](#out_wannier_wvfn_formatted) - [RT-TDDFT: Real-Time Time-Dependent Density Functional Theory](#rt-tddft-real-time-time-dependent-density-functional-theory) - - [estep\_per\_md](#estep_per_md) - - [td\_dt](#td_dt) - - [td\_edm](#td_edm) - - [td\_print\_eij](#td_print_eij) - - [td\_propagator](#td_propagator) - - [td\_vext](#td_vext) - - [td\_vext\_dire](#td_vext_dire) - - [td\_stype](#td_stype) - - [td\_ttype](#td_ttype) - - [td\_tstart](#td_tstart) - - [td\_tend](#td_tend) - - [td\_lcut1](#td_lcut1) - - [td\_lcut2](#td_lcut2) - - [td\_gauss\_freq](#td_gauss_freq) - - [td\_gauss\_phase](#td_gauss_phase) - - [td\_gauss\_sigma](#td_gauss_sigma) - - [td\_gauss\_t0](#td_gauss_t0) - - [td\_gauss\_amp](#td_gauss_amp) - - [td\_trape\_freq](#td_trape_freq) - - [td\_trape\_phase](#td_trape_phase) - - [td\_trape\_t1](#td_trape_t1) - - [td\_trape\_t2](#td_trape_t2) - - [td\_trape\_t3](#td_trape_t3) - - [td\_trape\_amp](#td_trape_amp) - - [td\_trigo\_freq1](#td_trigo_freq1) - - [td\_trigo\_freq2](#td_trigo_freq2) - - [td\_trigo\_phase1](#td_trigo_phase1) - - [td\_trigo\_phase2](#td_trigo_phase2) - - [td\_trigo\_amp](#td_trigo_amp) - - [td\_heavi\_t0](#td_heavi_t0) - - [td\_heavi\_amp](#td_heavi_amp) - - [init\_vecpot\_file](#init_vecpot_file) + - [estep_per_md](#estep_per_md) + - [td_dt](#td_dt) + - [td_edm](#td_edm) + - [td_print_eij](#td_print_eij) + - [td_propagator](#td_propagator) + - [td_vext](#td_vext) + - [td_vext_dire](#td_vext_dire) + - [td_stype](#td_stype) + - [td_ttype](#td_ttype) + - [td_tstart](#td_tstart) + - [td_tend](#td_tend) + - [td_lcut1](#td_lcut1) + - [td_lcut2](#td_lcut2) + - [td_gauss_freq](#td_gauss_freq) + - [td_gauss_phase](#td_gauss_phase) + - [td_gauss_sigma](#td_gauss_sigma) + - [td_gauss_t0](#td_gauss_t0) + - [td_gauss_amp](#td_gauss_amp) + - [td_trape_freq](#td_trape_freq) + - [td_trape_phase](#td_trape_phase) + - [td_trape_t1](#td_trape_t1) + - [td_trape_t2](#td_trape_t2) + - [td_trape_t3](#td_trape_t3) + - [td_trape_amp](#td_trape_amp) + - [td_trigo_freq1](#td_trigo_freq1) + - [td_trigo_freq2](#td_trigo_freq2) + - [td_trigo_phase1](#td_trigo_phase1) + - [td_trigo_phase2](#td_trigo_phase2) + - [td_trigo_amp](#td_trigo_amp) + - [td_heavi_t0](#td_heavi_t0) + - [td_heavi_amp](#td_heavi_amp) + - [init_vecpot_file](#init_vecpot_file) - [ocp](#ocp) - - [ocp\_set](#ocp_set) - - [out\_dipole](#out_dipole) - - [out\_current](#out_current) - - [out\_current\_k](#out_current_k) - - [out\_efield](#out_efield) - - [out\_vecpot](#out_vecpot) + - [ocp_set](#ocp_set) + - [out_dipole](#out_dipole) + - [out_current](#out_current) + - [out_current_k](#out_current_k) + - [out_efield](#out_efield) + - [out_vecpot](#out_vecpot) - [Variables useful for debugging](#variables-useful-for-debugging) - [nurse](#nurse) - - [t\_in\_h](#t_in_h) - - [vl\_in\_h](#vl_in_h) - - [vnl\_in\_h](#vnl_in_h) - - [vh\_in\_h](#vh_in_h) - - [vion\_in\_h](#vion_in_h) - - [test\_force](#test_force) - - [test\_stress](#test_stress) - - [test\_skip\_ewald](#test_skip_ewald) + - [t_in_h](#t_in_h) + - [vl_in_h](#vl_in_h) + - [vnl_in_h](#vnl_in_h) + - [vh_in_h](#vh_in_h) + - [vion_in_h](#vion_in_h) + - [test_force](#test_force) + - [test_stress](#test_stress) + - [test_skip_ewald](#test_skip_ewald) - [Electronic conductivities](#electronic-conductivities) - - [cal\_cond](#cal_cond) - - [cond\_che\_thr](#cond_che_thr) - - [cond\_dw](#cond_dw) - - [cond\_wcut](#cond_wcut) - - [cond\_dt](#cond_dt) - - [cond\_dtbatch](#cond_dtbatch) - - [cond\_smear](#cond_smear) - - [cond\_fwhm](#cond_fwhm) - - [cond\_nonlocal](#cond_nonlocal) + - [cal_cond](#cal_cond) + - [cond_che_thr](#cond_che_thr) + - [cond_dw](#cond_dw) + - [cond_wcut](#cond_wcut) + - [cond_dt](#cond_dt) + - [cond_dtbatch](#cond_dtbatch) + - [cond_smear](#cond_smear) + - [cond_fwhm](#cond_fwhm) + - [cond_nonlocal](#cond_nonlocal) - [Implicit solvation model](#implicit-solvation-model) - - [imp\_sol](#imp_sol) - - [eb\_k](#eb_k) + - [imp_sol](#imp_sol) + - [eb_k](#eb_k) - [tau](#tau) - - [sigma\_k](#sigma_k) - - [nc\_k](#nc_k) + - [sigma_k](#sigma_k) + - [nc_k](#nc_k) - [Quasiatomic Orbital (QO) analysis](#quasiatomic-orbital-qo-analysis) - - [qo\_switch](#qo_switch) - - [qo\_basis](#qo_basis) - - [qo\_strategy](#qo_strategy) - - [qo\_screening\_coeff](#qo_screening_coeff) - - [qo\_thr](#qo_thr) + - [qo_switch](#qo_switch) + - [qo_basis](#qo_basis) + - [qo_strategy](#qo_strategy) + - [qo_screening_coeff](#qo_screening_coeff) + - [qo_thr](#qo_thr) - [PEXSI](#pexsi) - - [pexsi\_npole](#pexsi_npole) - - [pexsi\_inertia](#pexsi_inertia) - - [pexsi\_nmax](#pexsi_nmax) - - [pexsi\_comm](#pexsi_comm) - - [pexsi\_storage](#pexsi_storage) - - [pexsi\_ordering](#pexsi_ordering) - - [pexsi\_row\_ordering](#pexsi_row_ordering) - - [pexsi\_nproc](#pexsi_nproc) - - [pexsi\_symm](#pexsi_symm) - - [pexsi\_trans](#pexsi_trans) - - [pexsi\_method](#pexsi_method) - - [pexsi\_nproc\_pole](#pexsi_nproc_pole) - - [pexsi\_temp](#pexsi_temp) - - [pexsi\_gap](#pexsi_gap) - - [pexsi\_delta\_e](#pexsi_delta_e) - - [pexsi\_mu\_lower](#pexsi_mu_lower) - - [pexsi\_mu\_upper](#pexsi_mu_upper) - - [pexsi\_mu](#pexsi_mu) - - [pexsi\_mu\_thr](#pexsi_mu_thr) - - [pexsi\_mu\_expand](#pexsi_mu_expand) - - [pexsi\_mu\_guard](#pexsi_mu_guard) - - [pexsi\_elec\_thr](#pexsi_elec_thr) - - [pexsi\_zero\_thr](#pexsi_zero_thr) + - [pexsi_npole](#pexsi_npole) + - [pexsi_inertia](#pexsi_inertia) + - [pexsi_nmax](#pexsi_nmax) + - [pexsi_comm](#pexsi_comm) + - [pexsi_storage](#pexsi_storage) + - [pexsi_ordering](#pexsi_ordering) + - [pexsi_row_ordering](#pexsi_row_ordering) + - [pexsi_nproc](#pexsi_nproc) + - [pexsi_symm](#pexsi_symm) + - [pexsi_trans](#pexsi_trans) + - [pexsi_method](#pexsi_method) + - [pexsi_nproc_pole](#pexsi_nproc_pole) + - [pexsi_temp](#pexsi_temp) + - [pexsi_gap](#pexsi_gap) + - [pexsi_delta_e](#pexsi_delta_e) + - [pexsi_mu_lower](#pexsi_mu_lower) + - [pexsi_mu_upper](#pexsi_mu_upper) + - [pexsi_mu](#pexsi_mu) + - [pexsi_mu_thr](#pexsi_mu_thr) + - [pexsi_mu_expand](#pexsi_mu_expand) + - [pexsi_mu_guard](#pexsi_mu_guard) + - [pexsi_elec_thr](#pexsi_elec_thr) + - [pexsi_zero_thr](#pexsi_zero_thr) - [Linear Response TDDFT](#linear-response-tddft) - - [ri\_hartree\_benchmark](#ri_hartree_benchmark) - - [aims\_nbasis](#aims_nbasis) + - [ri_hartree_benchmark](#ri_hartree_benchmark) + - [aims_nbasis](#aims_nbasis) - [Linear Response TDDFT (Under Development Feature)](#linear-response-tddft-under-development-feature) - - [xc\_kernel](#xc_kernel) - - [lr\_init\_xc\_kernel](#lr_init_xc_kernel) - - [lr\_solver](#lr_solver) - - [lr\_thr](#lr_thr) + - [xc_kernel](#xc_kernel) + - [lr_init_xc_kernel](#lr_init_xc_kernel) + - [lr_solver](#lr_solver) + - [lr_thr](#lr_thr) - [nocc](#nocc) - [nvirt](#nvirt) - - [lr\_nstates](#lr_nstates) - - [lr\_unrestricted](#lr_unrestricted) - - [abs\_wavelen\_range](#abs_wavelen_range) - - [out\_wfc\_lr](#out_wfc_lr) - - [abs\_gauge](#abs_gauge) - - [abs\_broadening](#abs_broadening) + - [lr_nstates](#lr_nstates) + - [lr_unrestricted](#lr_unrestricted) + - [abs_wavelen_range](#abs_wavelen_range) + - [out_wfc_lr](#out_wfc_lr) + - [abs_gauge](#abs_gauge) + - [abs_broadening](#abs_broadening) - [Reduced Density Matrix Functional Theory](#reduced-density-matrix-functional-theory) - [rdmft](#rdmft) - - [rdmft\_power\_alpha](#rdmft_power_alpha) + - [rdmft_power_alpha](#rdmft_power_alpha) ## System variables ### suffix - **Type**: String -- **Description**: In each run, ABACUS will generate a subdirectory in the working directory. This subdirectory contains all the information of the run. The subdirectory name has the format: OUT.suffix, where the suffix is the name you can pick up for your convenience. +- **Description**: In each run, ABACUS will generate a subdirectory in the working directory. This + subdirectory contains all the information of the run. The subdirectory name has the format: + OUT.suffix, where the suffix is the name you can pick up for your convenience. - **Default**: ABACUS ### ntype @@ -557,20 +561,30 @@ ### calculation - **Type**: String + - **Description**: Specify the type of calculation. - scf: perform self-consistent electronic structure calculations - - nscf: perform non-self-consistent electronic structure calculations. A charge density file is required - - relax: perform structure relaxation calculations, the relax_nmax parameter depicts the maximal number of ionic iterations + - nscf: perform non-self-consistent electronic structure calculations. A charge density file is + required + - relax: perform structure relaxation calculations, the relax_nmax parameter depicts the maximal + number of ionic iterations - cell-relax: perform cell relaxation calculations - md: perform molecular dynamics simulations - - get_pchg: obtain partial (band-decomposed) charge densities (for LCAO basis only). See out_pchg for more information - - get_wf: obtain real space wave functions (for LCAO basis only). See out_wfc_norm and out_wfc_re_im for more information - - get_s: obtain the overlap matrix formed by localized orbitals (for LCAO basis with multiple k points). the file name is SR.csr with file format being the same as that generated by out_mat_hs2 - - gen_bessel: generates projectors, i.e., a series of Bessel functions, for the DeePKS method (for LCAO basis only) + - get_pchg: obtain partial (band-decomposed) charge densities (for LCAO basis only). See out_pchg + for more information + - get_wf: obtain real space wave functions (for LCAO basis only). See out_wfc_norm and + out_wfc_re_im for more information + - get_s: obtain the overlap matrix formed by localized orbitals (for LCAO basis with multiple k + points). the file name is SR.csr with file format being the same as that generated by + out_mat_hs2 + - gen_bessel: generates projectors, i.e., a series of Bessel functions, for the DeePKS method (for + LCAO basis only) - gen_opt_abfs: generate opt-ABFs as discussed in this article - test_memory: obtain a rough estimation of memory consumption for the calculation - - test_neighbour: obtain information of neighboring atoms (for LCAO basis only), please specify a positive search_radius manually + - test_neighbour: obtain information of neighboring atoms (for LCAO basis only), please specify a + positive search_radius manually + - **Default**: scf ### esolver_type @@ -592,19 +606,30 @@ ### symmetry - **Type**: String + - **Description**: Takes value 1, 0 or -1. - - -1: No symmetry will be considered. It is recommended to set -1 for non-colinear + soc calculations, where time reversal symmetry is broken sometimes. - - 0: Only time reversal symmetry would be considered in symmetry operations, which implied k point and -k point would be treated as a single k point with twice the weight. - - 1: Symmetry analysis will be performed to determine the type of Bravais lattice and associated symmetry operations. (point groups, space groups, primitive cells, and irreducible k-points) - > Note: When symmetry is enabled (value 1), k-points are reduced to the irreducible Brillouin zone (IBZ). For explicit k-point lists with custom weights (see KPT file), the custom weights are preserved during symmetry reduction. For Monkhorst-Pack grids, uniform weights are used. + - -1: No symmetry will be considered. It is recommended to set -1 for non-colinear + soc + calculations, where time reversal symmetry is broken sometimes. + - 0: Only time reversal symmetry would be considered in symmetry operations, which implied k point + and -k point would be treated as a single k point with twice the weight. + - 1: Symmetry analysis will be performed to determine the type of Bravais lattice and associated + symmetry operations. (point groups, space groups, primitive cells, and irreducible k-points) + + > Note: When symmetry is enabled (value 1), k-points are reduced to the irreducible Brillouin zone + > (IBZ). For explicit k-point lists with custom weights (see KPT file), the custom weights are + > preserved during symmetry reduction. For Monkhorst-Pack grids, uniform weights are used. + - **Default**: default ### symmetry_prec - **Type**: Real -- **Description**: The accuracy for symmetry analysis. Typically, the default value is good enough, but if the lattice parameters or atom positions in STRU file are not accurate enough, this value should be enlarged. - > Note: if calculation==cell_relax, this value can be dynamically changed corresponding to the variation of accuracy of the lattice parameters and atom positions during the relaxation. +- **Description**: The accuracy for symmetry analysis. Typically, the default value is good enough, + but if the lattice parameters or atom positions in STRU file are not accurate enough, this value + should be enlarged. + > Note: if calculation==cell_relax, this value can be dynamically changed corresponding to the + > variation of accuracy of the lattice parameters and atom positions during the relaxation. - **Default**: 1.0e-6 - **Unit**: Bohr @@ -612,7 +637,8 @@ - **Type**: Boolean - **Availability**: *symmetry==1* -- **Description**: Control how to deal with error in symmetry analysis due to inaccurate lattice parameters or atom positions in STRU file, especially useful when calculation==cell-relax +- **Description**: Control how to deal with error in symmetry analysis due to inaccurate lattice + parameters or atom positions in STRU file, especially useful when calculation==cell-relax - False: quit with an error message - True: automatically set symmetry to 0 and continue running without symmetry analysis - **Default**: True @@ -626,19 +652,24 @@ ### kpar - **Type**: Integer -- **Description**: Divide all processors into kpar groups, and k points will be distributed among each group. The value taken should be less than or equal to the number of k points as well as the number of MPI processes. +- **Description**: Divide all processors into kpar groups, and k points will be distributed among + each group. The value taken should be less than or equal to the number of k points as well as the + number of MPI processes. - **Default**: 1 ### bndpar - **Type**: Integer -- **Description**: Divide all processors into bndpar groups, and bands (only stochastic orbitals now) will be distributed among each group. It should be larger than 0. +- **Description**: Divide all processors into bndpar groups, and bands (only stochastic orbitals + now) will be distributed among each group. It should be larger than 0. - **Default**: 1 ### latname - **Type**: String -- **Description**: Specifies the type of Bravias lattice. When set to none, the three lattice vectors are supplied explicitly in STRU file. + +- **Description**: Specifies the type of Bravias lattice. When set to none, the three lattice + vectors are supplied explicitly in STRU file. Available options are: @@ -657,42 +688,56 @@ - sm: simple monoclinic - bacm: base-centered monoclinic - triclinic: triclinic + - **Default**: none ### init_wfc - **Type**: String + - **Description**: The type of the starting wave functions. Available options are: - - atomic: from atomic pseudo wave functions. If they are not enough, other wave functions are initialized with random numbers. + - atomic: from atomic pseudo wave functions. If they are not enough, other wave functions are + initialized with random numbers. - atomic+random: add small random numbers on atomic pseudo-wavefunctions - - file: from binary files wf*.dat, which are output by setting out_wfc_pw to 2. + - file: from binary files wf\*.dat, which are output by setting out_wfc_pw to 2. - random: random numbers - - nao: from numerical atomic orbitals. If they are not enough, other wave functions are initialized with random numbers. + - nao: from numerical atomic orbitals. If they are not enough, other wave functions are + initialized with random numbers. - nao+random: add small random numbers on numerical atomic orbitals - > Note: Only the file option is useful for the lcao basis set, which is mostly used when calculation is set to get_wf and get_pchg. + > Note: Only the file option is useful for the lcao basis set, which is mostly used when + > calculation is set to get_wf and get_pchg. + - **Default**: atomic ### init_chg - **Type**: String -- **Description**: This variable is used for both plane wave set and localized orbitals set. It indicates the type of starting density. + +- **Description**: This variable is used for both plane wave set and localized orbitals set. It + indicates the type of starting density. - atomic: the density is starting from the summation of the atomic density of single atoms. - - file: the density will be read in from a binary file charge-density.dat first. If it does not exist, the charge density will be read in from cube files. + - file: the density will be read in from a binary file charge-density.dat first. If it does not + exist, the charge density will be read in from cube files. - wfc: the density will be calculated by wavefunctions and occupations. - dm: the density will be calculated by real space density matrix(DMR) of LCAO base. - - hr: the real space Hamiltonian matrix(HR) will be read in from file hrs1_nao.csr in directory read_file_dir. - - auto: Abacus first attempts to read the density from a file; if not found, it defaults to using atomic density. + - hr: the real space Hamiltonian matrix(HR) will be read in from file hrs1_nao.csr in directory + read_file_dir. + - auto: Abacus first attempts to read the density from a file; if not found, it defaults to using + atomic density. + - **Default**: atomic ### init_vel - **Type**: Boolean -- **Description**: - True: read the atom velocity (atomic unit : 1 a.u. = 21.877 Angstrom/fs) from the atom file (STRU) and determine the initial temperature md_tfirst. If md_tfirst is unset or less than zero, init_vel is autoset to be true. +- **Description**: - True: read the atom velocity (atomic unit : 1 a.u. = 21.877 Angstrom/fs) from + the atom file (STRU) and determine the initial temperature md_tfirst. If md_tfirst is unset or + less than zero, init_vel is autoset to be true. - False: assign value to atom velocity using Gaussian distributed random numbers. - **Default**: False @@ -716,32 +761,42 @@ - **Type**: Integer - **Availability**: *Used only for plane wave basis set.* - **Description**: - 0: it will be set to the number of MPI processes. - - >0: it specifies the number of processes used for carrying out diagonalization. Must be less than or equal to total number of MPI processes. + - \>0: it specifies the number of processes used for carrying out diagonalization. Must be less + than or equal to total number of MPI processes. - **Default**: 0 ### nbspline - **Type**: Integer -- **Description**: If set to a natural number, a Cardinal B-spline interpolation will be used to calculate Structure Factor. nbspline represents the order of B-spline basis and a larger one can get more accurate results but cost more. It is turned off by default. +- **Description**: If set to a natural number, a Cardinal B-spline interpolation will be used to + calculate Structure Factor. nbspline represents the order of B-spline basis and a larger one can + get more accurate results but cost more. It is turned off by default. - **Default**: -1 ### kspacing - **Type**: Vector of Real (1 or 3 values) -- **Description**: Set the smallest allowed spacing between k points, unit in 1/bohr. It should be larger than 0.0, and suggest smaller than 0.25. When you have set this value > 0.0, then the KPT file is unnecessary. The default value 0.0 means that ABACUS will read the applied KPT file. + +- **Description**: Set the smallest allowed spacing between k points, unit in 1/bohr. It should be + larger than 0.0, and suggest smaller than 0.25. When you have set this value > 0.0, then the KPT + file is unnecessary. The default value 0.0 means that ABACUS will read the applied KPT file. > Note: If gamma_only is set to be true, kspacing is invalid. + - **Default**: 0.0 ### min_dist_coef - **Type**: Real -- **Description**: A factor related to the allowed minimum distance between two atoms. At the beginning, ABACUS will check the structure, and if the distance of two atoms is shorter than min_dist_coef*(standard covalent bond length), we think this structure is unreasonable. +- **Description**: A factor related to the allowed minimum distance between two atoms. At the + beginning, ABACUS will check the structure, and if the distance of two atoms is shorter than + min_dist_coef\*(standard covalent bond length), we think this structure is unreasonable. - **Default**: 0.2 ### device - **Type**: String + - **Description**: Specifies the computing device for ABACUS. Available options are: @@ -749,7 +804,9 @@ - cpu: for CPUs via Intel, AMD, or Other supported CPU devices - gpu: for GPUs via CUDA or ROCm. - > Note: ks_solver must also be set to the algorithms supported. lcao_in_pw currently does not support gpu. + > Note: ks_solver must also be set to the algorithms supported. lcao_in_pw currently does not + > support gpu. + - **Default**: cpu ### precision @@ -768,22 +825,27 @@ - **Description**: Specifies the precision when performing grid integral in LCAO calculations. - single: single precision - double: double precision - - mix: mixed precision, starting from single precision and switching to double precision when the SCF residual becomes small enough + - mix: mixed precision, starting from single precision and switching to double precision when the + SCF residual becomes small enough - **Default**: double ### timer_enable_nvtx - **Type**: Boolean -- **Description**: Controls whether NVTX profiling labels are emitted by the timer. This feature is only effective on CUDA platforms. + +- **Description**: Controls whether NVTX profiling labels are emitted by the timer. This feature is + only effective on CUDA platforms. - True: Enable NVTX profiling labels in the timer. - False: Disable NVTX profiling labels in the timer. + - **Default**: False ### cell_factor - **Type**: Real -- **Description**: Used in the construction of the pseudopotential tables. For cell-relax calculations, this is automatically set to 2.0. +- **Description**: Used in the construction of the pseudopotential tables. For cell-relax + calculations, this is automatically set to 2.0. - **Default**: 1.2 ### dm_to_rho @@ -801,13 +863,17 @@ ### nb2d - **Type**: Integer -- **Description**: In LCAO calculations, the Hamiltonian and overlap matrices are distributed across 2D processor grid. This parameter controls the 2D block size for distribution. +- **Description**: In LCAO calculations, the Hamiltonian and overlap matrices are distributed across + 2D processor grid. This parameter controls the 2D block size for distribution. - **Default**: 0 ### cal_symm_repr - **Type**: Integer \[Integer\](optional) -- **Description**: Whether to print the matrix representation of symmetry operation to running log file. If the first value is given as 1, then all matrix representations will be printed. The second optional parameter controls the precision (number of digits) to print, default is 3, which is enough for a quick check. +- **Description**: Whether to print the matrix representation of symmetry operation to running log + file. If the first value is given as 1, then all matrix representations will be printed. The + second optional parameter controls the precision (number of digits) to print, default is 3, which + is enough for a quick check. - **Default**: 1 3 [back to top](#full-list-of-input-keywords) @@ -817,38 +883,46 @@ ### stru_file - **Type**: String -- **Description**: The name of the structure file containing various information about atom species, including pseudopotential files, local orbitals files, cell information, atom positions, and whether atoms should be allowed to move. +- **Description**: The name of the structure file containing various information about atom species, + including pseudopotential files, local orbitals files, cell information, atom positions, and + whether atoms should be allowed to move. - **Default**: STRU ### kpoint_file - **Type**: String -- **Description**: The name of the k-point file that includes the k-point information of Brillouin zone. +- **Description**: The name of the k-point file that includes the k-point information of Brillouin + zone. - **Default**: KPT ### pseudo_dir - **Type**: String -- **Description**: The directory of pseudopotential files. This parameter is combined with the pseudopotential filenames in the STRU file to form the complete pseudopotential file paths. +- **Description**: The directory of pseudopotential files. This parameter is combined with the + pseudopotential filenames in the STRU file to form the complete pseudopotential file paths. - **Default**: "" ### orbital_dir - **Type**: String -- **Description**: The directory to save numerical atomic orbitals. This parameter is combined with orbital filenames in the STRU file to form the complete orbital file paths. +- **Description**: The directory to save numerical atomic orbitals. This parameter is combined with + orbital filenames in the STRU file to form the complete orbital file paths. - **Default**: "" ### read_file_dir - **Type**: String -- **Description**: Location of files, such as the electron density (chgs1.cube), required as a starting point. -- **Default**: OUT.$suffix +- **Description**: Location of files, such as the electron density (chgs1.cube), required as a + starting point. +- **Default**: OUT.\$suffix ### restart_load - **Type**: Boolean - **Availability**: *Used only when numerical atomic orbitals are employed as basis set.* -- **Description**: If restart_save is set to true and an electronic iteration is finished, calculations can be restarted from the charge density file, which are saved in the former calculation. +- **Description**: If restart_save is set to true and an electronic iteration is finished, + calculations can be restarted from the charge density file, which are saved in the former + calculation. - **Default**: False ### spillage_outdir @@ -865,71 +939,104 @@ ### ecutwfc - **Type**: Real -- **Description**: Energy cutoff for plane wave functions. Note that even for localized orbitals basis, you still need to setup an energy cutoff for this system. Because our local pseudopotential parts and the related force are calculated from plane wave basis set. - > Note: ecutwfc and ecutrho can be set simultaneously. If only one parameter is set, abacus will automatically set another parameter based on the 4-time relationship. +- **Description**: Energy cutoff for plane wave functions. Note that even for localized orbitals + basis, you still need to setup an energy cutoff for this system. Because our local pseudopotential + parts and the related force are calculated from plane wave basis set. + > Note: ecutwfc and ecutrho can be set simultaneously. If only one parameter is set, abacus will + > automatically set another parameter based on the 4-time relationship. - **Default**: 50 for PW basis, 100 for LCAO basis - **Unit**: Ry ### ecutrho - **Type**: Real -- **Description**: Energy cutoff for charge density and potential. For norm-conserving pseudopotential you should stick to the default value, you can reduce it by a little but it will introduce noise especially on forces and stress. -- **Default**: 4*ecutwfc +- **Description**: Energy cutoff for charge density and potential. For norm-conserving + pseudopotential you should stick to the default value, you can reduce it by a little but it will + introduce noise especially on forces and stress. +- **Default**: 4\*ecutwfc - **Unit**: Ry ### nx - **Type**: Integer -- **Description**: If set to a positive number, specifies the number of FFT grid points in x direction. If set to 0, the number will be calculated from ecutrho. + +- **Description**: If set to a positive number, specifies the number of FFT grid points in x + direction. If set to 0, the number will be calculated from ecutrho. > Note: You must specify all three dimensions (nx, ny, nz) for this setting to be used. + - **Default**: 0 ### ny - **Type**: Integer -- **Description**: If set to a positive number, specifies the number of FFT grid points in y direction. If set to 0, the number will be calculated from ecutrho. + +- **Description**: If set to a positive number, specifies the number of FFT grid points in y + direction. If set to 0, the number will be calculated from ecutrho. > Note: You must specify all three dimensions (nx, ny, nz) for this setting to be used. + - **Default**: 0 ### nz - **Type**: Integer -- **Description**: If set to a positive number, specifies the number of FFT grid points in z direction. If set to 0, the number will be calculated from ecutrho. + +- **Description**: If set to a positive number, specifies the number of FFT grid points in z + direction. If set to 0, the number will be calculated from ecutrho. > Note: You must specify all three dimensions (nx, ny, nz) for this setting to be used. + - **Default**: 0 ### ndx - **Type**: Integer -- **Description**: If set to a positive number, specifies the number of FFT grid points for the dense part of charge density in x direction. If set to 0, the number will be calculated from ecutwfc. - > Note: You must specify all three dimensions (ndx, ndy, ndz) for this setting to be used. These parameters must be used combined with nx, ny, nz. If nx, ny, nz are unset, ndx, ndy, ndz are used as nx, ny, nz. +- **Description**: If set to a positive number, specifies the number of FFT grid points for the + dense part of charge density in x direction. If set to 0, the number will be calculated from + ecutwfc. + + > Note: You must specify all three dimensions (ndx, ndy, ndz) for this setting to be used. These + > parameters must be used combined with nx, ny, nz. If nx, ny, nz are unset, ndx, ndy, ndz are + > used as nx, ny, nz. + - **Default**: 0 ### ndy - **Type**: Integer -- **Description**: If set to a positive number, specifies the number of FFT grid points for the dense part of charge density in y direction. If set to 0, the number will be calculated from ecutwfc. - > Note: You must specify all three dimensions (ndx, ndy, ndz) for this setting to be used. These parameters must be used combined with nx, ny, nz. If nx, ny, nz are unset, ndx, ndy, ndz are used as nx, ny, nz. +- **Description**: If set to a positive number, specifies the number of FFT grid points for the + dense part of charge density in y direction. If set to 0, the number will be calculated from + ecutwfc. + + > Note: You must specify all three dimensions (ndx, ndy, ndz) for this setting to be used. These + > parameters must be used combined with nx, ny, nz. If nx, ny, nz are unset, ndx, ndy, ndz are + > used as nx, ny, nz. + - **Default**: 0 ### ndz - **Type**: Integer -- **Description**: If set to a positive number, specifies the number of FFT grid points for the dense part of charge density in z direction. If set to 0, the number will be calculated from ecutwfc. - > Note: You must specify all three dimensions (ndx, ndy, ndz) for this setting to be used. These parameters must be used combined with nx, ny, nz. If nx, ny, nz are unset, ndx, ndy, ndz are used as nx, ny, nz. +- **Description**: If set to a positive number, specifies the number of FFT grid points for the + dense part of charge density in z direction. If set to 0, the number will be calculated from + ecutwfc. + + > Note: You must specify all three dimensions (ndx, ndy, ndz) for this setting to be used. These + > parameters must be used combined with nx, ny, nz. If nx, ny, nz are unset, ndx, ndy, ndz are + > used as nx, ny, nz. + - **Default**: 0 ### pw_seed - **Type**: Integer - **Availability**: *Only used for plane wave basis.* -- **Description**: Specify the random seed to initialize wave functions. Only positive integers are available. +- **Description**: Specify the random seed to initialize wave functions. Only positive integers are + available. - **Default**: 0 ### diag_subspace @@ -944,7 +1051,8 @@ ### erf_ecut - **Type**: Real -- **Description**: Used in variable-cell molecular dynamics (or in stress calculation). See erf_sigma for details. +- **Description**: Used in variable-cell molecular dynamics (or in stress calculation). See + erf_sigma for details. - **Default**: 0.0 - **Unit**: Ry @@ -961,47 +1069,62 @@ ### erf_height - **Type**: Real -- **Description**: Used in variable-cell molecular dynamics (or in stress calculation). See erf_sigma for details. +- **Description**: Used in variable-cell molecular dynamics (or in stress calculation). See + erf_sigma for details. - **Default**: 0.0 - **Unit**: Ry ### erf_sigma - **Type**: Real -- **Description**: In order to recover the accuracy of a constant energy cutoff calculation, the kinetic functional is modified, which is used in variable-cell molecular dynamics (or in stress calculation). +- **Description**: In order to recover the accuracy of a constant energy cutoff calculation, the + kinetic functional is modified, which is used in variable-cell molecular dynamics (or in stress + calculation). - **Default**: 0.1 - **Unit**: Ry ### pw_diag_thr - **Type**: Real -- **Description**: Only used when you use ks_solver = cg/dav/dav_subspace/bpcg. It indicates the threshold for the first electronic iteration, from the second iteration the pw_diag_thr will be updated automatically. For nscf calculations with planewave basis set, pw_diag_thr should be <= 1e-3. +- **Description**: Only used when you use ks_solver = cg/dav/dav_subspace/bpcg. It indicates the + threshold for the first electronic iteration, from the second iteration the pw_diag_thr will be + updated automatically. For nscf calculations with planewave basis set, pw_diag_thr should be \<= + 1e-3. - **Default**: 0.01 ### diago_smooth_ethr - **Type**: Boolean -- **Description**: If TRUE, the smooth threshold strategy, which applies a larger threshold (10e-5) for the empty states, will be implemented in the diagonalization methods. (This strategy should not affect total energy, forces, and other ground-state properties, but computational efficiency will be improved.) If FALSE, the smooth threshold strategy will not be applied. +- **Description**: If TRUE, the smooth threshold strategy, which applies a larger threshold (10e-5) + for the empty states, will be implemented in the diagonalization methods. (This strategy should + not affect total energy, forces, and other ground-state properties, but computational efficiency + will be improved.) If FALSE, the smooth threshold strategy will not be applied. - **Default**: false ### use_k_continuity - **Type**: Boolean - **Availability**: *Used only for plane wave basis set.* -- **Description**: If TRUE, the wavefunctions at k-point will be initialized from the converged wavefunctions at the nearest k-point, which can speed up the SCF convergence. Only works for PW basis. +- **Description**: If TRUE, the wavefunctions at k-point will be initialized from the converged + wavefunctions at the nearest k-point, which can speed up the SCF convergence. Only works for PW + basis. - **Default**: false ### pw_diag_nmax - **Type**: Integer - **Availability**: *basis_type==pw, ks_solver==cg/dav/dav_subspace/bpcg* -- **Description**: Only useful when you use ks_solver = cg/dav/dav_subspace/bpcg. It indicates the maximal iteration number for cg/david/dav_subspace/bpcg method. +- **Description**: Only useful when you use ks_solver = cg/dav/dav_subspace/bpcg. It indicates the + maximal iteration number for cg/david/dav_subspace/bpcg method. - **Default**: 50 ### pw_diag_ndim - **Type**: Integer -- **Description**: Only useful when you use ks_solver = dav or ks_solver = dav_subspace. It indicates dimension of workspace(number of wavefunction packets, at least 2 needed) for the Davidson method. A larger value may yield a smaller number of iterations in the algorithm but uses more memory and more CPU time in subspace diagonalization. +- **Description**: Only useful when you use ks_solver = dav or ks_solver = dav_subspace. It + indicates dimension of workspace(number of wavefunction packets, at least 2 needed) for the + Davidson method. A larger value may yield a smaller number of iterations in the algorithm but uses + more memory and more CPU time in subspace diagonalization. - **Default**: 4 ### diago_cg_prec @@ -1017,19 +1140,23 @@ ### lmaxmax - **Type**: Integer -- **Description**: If not equals to 2, then the maximum l channels on LCAO is set to lmaxmax. If 2, then the number of l channels will be read from the LCAO data sets. Normally no input should be supplied for this variable so that it is kept as its default. +- **Description**: If not equals to 2, then the maximum l channels on LCAO is set to lmaxmax. If 2, + then the number of l channels will be read from the LCAO data sets. Normally no input should be + supplied for this variable so that it is kept as its default. - **Default**: 2. ### lcao_ecut - **Type**: Real -- **Description**: Energy cutoff (in Ry) for two-center integrals in LCAO. The two-center integration table are obtained via a k space integral whose upper limit is about sqrt(lcao_ecut). +- **Description**: Energy cutoff (in Ry) for two-center integrals in LCAO. The two-center + integration table are obtained via a k space integral whose upper limit is about sqrt(lcao_ecut). - **Default**: ecutwfc ### lcao_dk - **Type**: Real -- **Description**: the interval of k points for two-center integrals. The two-center integration table are obtained via a k space integral on a uniform grid with spacing lcao_dk. +- **Description**: the interval of k points for two-center integrals. The two-center integration + table are obtained via a k space integral on a uniform grid with spacing lcao_dk. - **Default**: 0.01 - **Unit**: Bohr @@ -1050,34 +1177,44 @@ ### search_radius - **Type**: Real -- **Description**: Searching radius in finding the neighbouring atoms. By default the radius will be automatically determined by the cutoffs of orbitals and nonlocal beta projectors. +- **Description**: Searching radius in finding the neighbouring atoms. By default the radius will be + automatically determined by the cutoffs of orbitals and nonlocal beta projectors. - **Default**: -1 - **Unit**: Bohr ### bx - **Type**: Integer -- **Description**: In the matrix operation of grid integral, bx/by/bz grids (in x, y, z directions) are treated as a whole as a matrix element. A different value will affect the calculation speed. The default is 0, which means abacus will automatically calculate these values. +- **Description**: In the matrix operation of grid integral, bx/by/bz grids (in x, y, z directions) + are treated as a whole as a matrix element. A different value will affect the calculation speed. + The default is 0, which means abacus will automatically calculate these values. - **Default**: 0 ### by - **Type**: Integer -- **Description**: In the matrix operation of grid integral, bx/by/bz grids (in x, y, z directions) are treated as a whole as a matrix element. A different value will affect the calculation speed. The default is 0, which means abacus will automatically calculate these values. +- **Description**: In the matrix operation of grid integral, bx/by/bz grids (in x, y, z directions) + are treated as a whole as a matrix element. A different value will affect the calculation speed. + The default is 0, which means abacus will automatically calculate these values. - **Default**: 0 ### bz - **Type**: Integer -- **Description**: In the matrix operation of grid integral, bx/by/bz grids (in x, y, z directions) are treated as a whole as a matrix element. A different value will affect the calculation speed. The default is 0, which means abacus will automatically calculate these values. +- **Description**: In the matrix operation of grid integral, bx/by/bz grids (in x, y, z directions) + are treated as a whole as a matrix element. A different value will affect the calculation speed. + The default is 0, which means abacus will automatically calculate these values. - **Default**: 0 ### elpa_num_thread - **Type**: Integer + - **Description**: Number of threads used in one elpa calculation. - If the number is below 0 or 0 or beyond the max number of threads, all elpa calculation will be using all mpi threads + If the number is below 0 or 0 or beyond the max number of threads, all elpa calculation will be + using all mpi threads + - **Default**: -1 ### num_stream @@ -1096,20 +1233,25 @@ - **Description**: Choose the basis set. - pw: Using plane-wave basis set only. - lcao: Using localized atomic orbital sets. - - lcao_in_pw: Expand the localized atomic set in plane-wave basis, non-self-consistent field calculation not tested. + - lcao_in_pw: Expand the localized atomic set in plane-wave basis, non-self-consistent field + calculation not tested. - **Default**: pw ### ks_solver - **Type**: String -- **Description**: Choose the diagonalization methods for the Hamiltonian matrix expanded in a certain basis set. + +- **Description**: Choose the diagonalization methods for the Hamiltonian matrix expanded in a + certain basis set. For plane-wave basis, - cg: The conjugate-gradient (CG) method. - - bpcg: The BPCG method, which is a block-parallel Conjugate Gradient (CG) method, typically exhibits higher acceleration in a GPU environment. + - bpcg: The BPCG method, which is a block-parallel Conjugate Gradient (CG) method, typically + exhibits higher acceleration in a GPU environment. - dav: The Davidson algorithm. - - dav_subspace: The Davidson algorithm without orthogonalization operation, this method is the most recommended for efficiency. pw_diag_ndim can be set to 2 for this method. + - dav_subspace: The Davidson algorithm without orthogonalization operation, this method is the + most recommended for efficiency. pw_diag_ndim can be set to 2 for this method. For numerical atomic orbitals basis, @@ -1117,25 +1259,32 @@ - genelpa: Use GEN-ELPA to diagonalize the Hamiltonian. - scalapack_gvx: Use Scalapack to diagonalize the Hamiltonian. - cusolver: Use CUSOLVER to diagonalize the Hamiltonian, at least one GPU is needed. - - cusolvermp: Use CUSOLVER to diagonalize the Hamiltonian, supporting multi-GPU devices. Note that you should set the number of MPI processes equal to the number of GPUs. - - elpa: The ELPA solver supports both CPU and GPU. By setting the device to GPU, you can launch the ELPA solver with GPU acceleration (provided that you have installed a GPU-supported version of ELPA, which requires you to manually compile and install ELPA, and the ABACUS should be compiled with -DUSE_ELPA=ON and -DUSE_CUDA=ON). The ELPA solver also supports multi-GPU acceleration. + - cusolvermp: Use CUSOLVER to diagonalize the Hamiltonian, supporting multi-GPU devices. Note that + you should set the number of MPI processes equal to the number of GPUs. + - elpa: The ELPA solver supports both CPU and GPU. By setting the device to GPU, you can launch + the ELPA solver with GPU acceleration (provided that you have installed a GPU-supported version + of ELPA, which requires you to manually compile and install ELPA, and the ABACUS should be + compiled with -DUSE_ELPA=ON and -DUSE_CUDA=ON). The ELPA solver also supports multi-GPU + acceleration. If you set ks_solver=genelpa for basis_type=pw, the program will stop with an error message: - ``text genelpa can not be used with plane wave basis. `` + `text genelpa can not be used with plane wave basis. ` Then the user has to correct the input file and restart the calculation. ### nbands - **Type**: Integer -- **Description**: The number of Kohn-Sham orbitals to calculate. It is recommended to setup this value, especially when smearing techniques are utilized, more bands should be included. +- **Description**: The number of Kohn-Sham orbitals to calculate. It is recommended to setup this + value, especially when smearing techniques are utilized, more bands should be included. ### nelec - **Type**: Real -- **Description**: - 0.0: The total number of electrons will be calculated by the sum of valence electrons (i.e. assuming neutral system). - - >0.0: this denotes the total number of electrons in the system. Must be less than 2*nbands. +- **Description**: - 0.0: The total number of electrons will be calculated by the sum of valence + electrons (i.e. assuming neutral system). + - \>0.0: this denotes the total number of electrons in the system. Must be less than 2\*nbands. - **Default**: 0.0 ### nelec_delta @@ -1148,49 +1297,84 @@ - **Type**: Real - **Description**: - 0.0: no constrain apply to system. - - >0.0: The different number of electrons between spin-up and spin-down channels. The range of value must be in [-nelec ~ nelec]. It is one type of constrainted DFT method, two Fermi energies will be calculated. + - \>0.0: The different number of electrons between spin-up and spin-down channels. The range of + value must be in [-nelec ~ nelec]. It is one type of constrainted DFT method, two Fermi energies + will be calculated. - **Default**: 0.0 ### dft_functional - **Type**: String -- **Description**: In our package, the XC functional can either be set explicitly using the dft_functional keyword in INPUT file. If dft_functional is not specified, ABACUS will use the xc functional indicated in the pseudopotential file. On the other hand, if dft_functional is specified, it will overwrite the functional from pseudopotentials and performs calculation with whichever functional the user prefers. We further offer two ways of supplying exchange-correlation functional. The first is using 'short-hand' names. A complete list of 'short-hand' expressions can be found in the source code. Supported density functionals are: + +- **Description**: In our package, the XC functional can either be set explicitly using the + dft_functional keyword in INPUT file. If dft_functional is not specified, ABACUS will use the xc + functional indicated in the pseudopotential file. On the other hand, if dft_functional is + specified, it will overwrite the functional from pseudopotentials and performs calculation with + whichever functional the user prefers. We further offer two ways of supplying exchange-correlation + functional. The first is using 'short-hand' names. A complete list of 'short-hand' expressions can + be found in the source code. Supported density functionals are: + - LDA functionals - LDA (equivalent with PZ and SLAPZNOGXNOGC), PWLDA - GGA functionals - - PBE (equivalent with SLAPWPBXPBC), PBESOL, REVPBE, WC, BLYP, BP(referred to BP86), PW91, HCTH, OLYP, BLYP_LR + - PBE (equivalent with SLAPWPBXPBC), PBESOL, REVPBE, WC, BLYP, BP(referred to BP86), PW91, HCTH, + OLYP, BLYP_LR - meta-GGA functionals - SCAN (require LIBXC) - Hybrid functionals - PBE0, HF - - If LIBXC is available, additional short-hand names of hybrid functionals are supported: HSE(referred to HSE06), B3LYP, LC_PBE, LC_WPBE, LRC_WPBE, LRC_WPBEH, CAM_PBEH, WP22, CWP22, MULLER (equivalent with POWER) + - If LIBXC is available, additional short-hand names of hybrid functionals are supported: + HSE(referred to HSE06), B3LYP, LC_PBE, LC_WPBE, LRC_WPBE, LRC_WPBEH, CAM_PBEH, WP22, CWP22, + MULLER (equivalent with POWER) - Hybrid meta-GGA functionals - SCAN0 (require LIBXC) - The other way is only available when compiling with LIBXC, and it allows for supplying exchange-correlation functionals as combinations of LIBXC keywords for functional components, joined by a plus sign, for example, dft_functional='LDA_X_1D_EXPONENTIAL+LDA_C_1D_CSC'. + The other way is only available when compiling with LIBXC, and it allows for supplying + exchange-correlation functionals as combinations of LIBXC keywords for functional components, + joined by a plus sign, for example, dft_functional='LDA_X_1D_EXPONENTIAL+LDA_C_1D_CSC'. + - **Default**: Used the same as DFT functional as specified in the pseudopotential files. ### xc_temperature - **Type**: Real -- **Description**: Specifies temperature when using temperature-dependent XC functionals (KSDT and so on). +- **Description**: Specifies temperature when using temperature-dependent XC functionals (KSDT and + so on). - **Default**: 0.0 - **Unit**: Ry ### xc_exch_ext - **Type**: Integer followed by Real values -- **Description**: Customized parameterization on the exchange part of XC functional. The first value should be the LibXC ID of the original functional, and latter values are external parameters. Default values are those of Perdew-Burke-Ernzerhof (PBE) functional. For more information on LibXC ID of functionals, please refer to LibXC. For parameters of functionals of interest, please refer to the source code of LibXC, such as PBE functional interface in LibXC: gga_x_pbe.c. - > Note: Solely setting this keyword will take no effect on XC functionals. One should also set dft_functional to the corresponding functional to apply the customized parameterization. Presently this feature can only support parameterization on one exchange functional. +- **Description**: Customized parameterization on the exchange part of XC functional. The first + value should be the LibXC ID of the original functional, and latter values are external + parameters. Default values are those of Perdew-Burke-Ernzerhof (PBE) functional. For more + information on LibXC ID of functionals, please refer to LibXC. For parameters of functionals of + interest, please refer to the source code of LibXC, such as PBE functional interface in LibXC: + gga_x_pbe.c. + + > Note: Solely setting this keyword will take no effect on XC functionals. One should also set + > dft_functional to the corresponding functional to apply the customized parameterization. + > Presently this feature can only support parameterization on one exchange functional. + - **Default**: 101 0.8040 0.2195149727645171 ### xc_corr_ext - **Type**: Integer followed by Real values -- **Description**: Customized parameterization on the correlation part of XC functional. The first value should be the LibXC ID of the original functional, and latter values are external parameters. Default values are those of Perdew-Burke-Ernzerhof (PBE) functional. For more information on LibXC ID of functionals, please refer to LibXC. For parameters of functionals of interest, please refer to the source code of LibXC, such as PBE functional interface in LibXC: gga_c_pbe.c. - > Note: Solely setting this keyword will take no effect on XC functionals. One should also set dft_functional to the corresponding functional to apply the customized parameterization. Presently this feature can only support parameterization on one correlation functional. +- **Description**: Customized parameterization on the correlation part of XC functional. The first + value should be the LibXC ID of the original functional, and latter values are external + parameters. Default values are those of Perdew-Burke-Ernzerhof (PBE) functional. For more + information on LibXC ID of functionals, please refer to LibXC. For parameters of functionals of + interest, please refer to the source code of LibXC, such as PBE functional interface in LibXC: + gga_c_pbe.c. + + > Note: Solely setting this keyword will take no effect on XC functionals. One should also set + > dft_functional to the corresponding functional to apply the customized parameterization. + > Presently this feature can only support parameterization on one correlation functional. + - **Default**: 130 0.06672455060314922 0.031090690869654895034 1.0 ### pseudo_rcut @@ -1213,7 +1397,8 @@ - **Description**: The number of spin components of wave functions. - 1: Spin degeneracy - 2: Collinear spin polarized. - - 4: For the case of noncollinear polarized, nspin will be automatically set to 4 without being specified by the user. + - 4: For the case of noncollinear polarized, nspin will be automatically set to 4 without being + specified by the user. - **Default**: 1 ### smearing_method @@ -1245,67 +1430,98 @@ ### mixing_type - **Type**: String + - **Description**: Charge mixing methods. + - plain: Just simple mixing. - pulay: Standard Pulay method. P. Pulay Chemical Physics Letters, (1980) - broyden: Simplified modified Broyden method. D.D. Johnson Physical Review B (1988) - In general, the convergence of the Broyden method is slightly faster than that of the Pulay method. + In general, the convergence of the Broyden method is slightly faster than that of the Pulay + method. + - **Default**: broyden ### mixing_beta - **Type**: Real -- **Description**: In general, the formula of charge mixing can be written as rho_new = rho_old + mixing_beta * drho, where rho_new represents the new charge density after charge mixing, rho_old represents the charge density in previous step, drho is obtained through various mixing methods, and mixing_beta is set by this parameter. A lower value of 'mixing_beta' results in less influence of drho on rho_new, making the self-consistent field (SCF) calculation more stable. However, it may require more steps to achieve convergence. We recommend the following options: + +- **Description**: In general, the formula of charge mixing can be written as rho_new = rho_old + + mixing_beta * drho, where rho_new represents the new charge density after charge mixing, rho_old + represents the charge density in previous step, drho is obtained through various mixing methods, + and mixing_beta is set by this parameter. A lower value of 'mixing_beta' results in less influence + of drho on rho_new, making the self-consistent field (SCF) calculation more stable. However, it + may require more steps to achieve convergence. We recommend the following options: + - 0.8: nspin=1 - 0.4: nspin=2 and nspin=4 - 0: keep charge density unchanged, usually used for restarting with init_chg=file or testing. - - 0.1 or less: if convergence of SCF calculation is difficult to reach, please try 0 < mixing_beta < 0.1. + - 0.1 or less: if convergence of SCF calculation is difficult to reach, please try 0 < mixing_beta + < 0.1. + + Note: For low-dimensional large systems, the setup of mixing_beta=0.1, mixing_ndim=20, and + mixing_gg0=1.0 usually works well. - Note: For low-dimensional large systems, the setup of mixing_beta=0.1, mixing_ndim=20, and mixing_gg0=1.0 usually works well. - **Default**: 0.8 for nspin=1, 0.4 for nspin=2 and nspin=4. ### mixing_beta_mag - **Type**: Real - **Description**: Mixing parameter of magnetic density. -- **Default**: 4*mixing_beta, but the maximum value is 1.6. +- **Default**: 4\*mixing_beta, but the maximum value is 1.6. ### mixing_ndim - **Type**: Integer -- **Description**: It indicates the mixing dimensions in Pulay or Broyden. Pulay and Broyden method use the density from previous mixing_ndim steps and do a charge mixing based on this density. - For systems that are difficult to converge, one could try increasing the value of 'mixing_ndim' to enhance the stability of the self-consistent field (SCF) calculation. +- **Description**: It indicates the mixing dimensions in Pulay or Broyden. Pulay and Broyden method + use the density from previous mixing_ndim steps and do a charge mixing based on this density. + + For systems that are difficult to converge, one could try increasing the value of 'mixing_ndim' to + enhance the stability of the self-consistent field (SCF) calculation. + - **Default**: 8 ### mixing_restart - **Type**: Real -- **Description**: If the density difference between input and output drho is smaller than mixing_restart, SCF will restart at next step which means SCF will restart by using output charge density from perivos iteration as input charge density directly, and start a new mixing. Notice that mixing_restart will only take effect once in one SCF. +- **Description**: If the density difference between input and output drho is smaller than + mixing_restart, SCF will restart at next step which means SCF will restart by using output charge + density from perivos iteration as input charge density directly, and start a new mixing. Notice + that mixing_restart will only take effect once in one SCF. - **Default**: 0 ### mixing_dmr - **Type**: Boolean -- **Availability**: *Only for mixing_restart >= 0.0* -- **Description**: At n-th iteration which is calculated by drho<mixing_restart, SCF will start a mixing for real-space density matrix by using the same coefficiences as the mixing of charge density. +- **Availability**: *Only for mixing_restart >= 0.0* +- **Description**: At n-th iteration which is calculated by drho\0: The high frequency wave vectors will be suppressed by multiplying a scaling factor. Setting + mixing_gg0 = 1.0 is normally a good starting point. Kerker preconditioner will be automatically + turned off if mixing_beta \<= 0.1. - 0: No Kerker scaling is performed. - For systems that are difficult to converge, particularly metallic systems, enabling Kerker scaling may aid in achieving convergence. + For systems that are difficult to converge, particularly metallic systems, enabling Kerker scaling + may aid in achieving convergence. + - **Default**: 1.0 ### mixing_gg0_mag - **Type**: Real -- **Description**: Whether to perfom Kerker preconditioner of magnetic density. Note: we do not recommand to open Kerker preconditioner of magnetic density unless the system is too hard to converge. +- **Description**: Whether to perfom Kerker preconditioner of magnetic density. Note: we do not + recommand to open Kerker preconditioner of magnetic density unless the system is too hard to + converge. - **Default**: 0.0 ### mixing_gg0_min @@ -1318,9 +1534,15 @@ - **Type**: Real - **Availability**: *Only relevant for non-colinear calculations nspin=4.* -- **Description**: Normal broyden mixing can give the converged result for a given magnetic configuration. If one is not interested in the energies of a given magnetic configuration but wants to determine the ground state by relaxing the magnetic moments' directions, one cannot rely on the standard Broyden mixing algorithm. To enhance the ability to find correct magnetic configuration for non-colinear calculations, ABACUS implements a promising mixing method proposed by J. Phys. Soc. Jpn. 82 (2013) 114706. Here, mixing_angle is the angle mixing parameter. In fact, only mixing_angle=1.0 is implemented currently. - - <=0: Normal broyden mixing - - >0: Angle mixing for the modulus with mixing_angle=1.0 +- **Description**: Normal broyden mixing can give the converged result for a given magnetic + configuration. If one is not interested in the energies of a given magnetic configuration but + wants to determine the ground state by relaxing the magnetic moments' directions, one cannot rely + on the standard Broyden mixing algorithm. To enhance the ability to find correct magnetic + configuration for non-colinear calculations, ABACUS implements a promising mixing method proposed + by J. Phys. Soc. Jpn. 82 (2013) 114706. Here, mixing_angle is the angle mixing parameter. In fact, + only mixing_angle=1.0 is implemented currently. + - \<=0: Normal broyden mixing + - \>0: Angle mixing for the modulus with mixing_angle=1.0 - **Default**: -10.0 ### mixing_tau @@ -1328,7 +1550,9 @@ - **Type**: Boolean - **Availability**: *Only relevant for meta-GGA calculations.* - **Description**: Whether to mix the kinetic energy density. - - True: The kinetic energy density will also be mixed. It seems for general cases, SCF converges fine even without this mixing. However, if there is difficulty in converging SCF for meta-GGA, it might be helpful to turn this on. + - True: The kinetic energy density will also be mixed. It seems for general cases, SCF converges + fine even without this mixing. However, if there is difficulty in converging SCF for meta-GGA, + it might be helpful to turn this on. - False: The kinetic energy density will not be mixed. - **Default**: False @@ -1337,19 +1561,26 @@ - **Type**: Boolean - **Availability**: *Only relevant for DFT+U calculations.* - **Description**: Whether to mix the occupation matrices. - - True: The occupation matrices will also be mixed by plain mixing. From experience this is not very helpful if the +U calculation does not converge. + - True: The occupation matrices will also be mixed by plain mixing. From experience this is not + very helpful if the +U calculation does not converge. - False: The occupation matrices will not be mixed. - **Default**: False ### gamma_only - **Type**: Boolean + - **Availability**: *Only used in localized orbitals set* + - **Description**: Whether to use gamma_only algorithm. + - 0: more than one k-point is used and the ABACUS is slower compared to the gamma only algorithm. - - 1: ABACUS uses gamma only, the algorithm is faster and you don't need to specify the k-points file. + - 1: ABACUS uses gamma only, the algorithm is faster and you don't need to specify the k-points + file. + + Note: If gamma_only is set to 1, the KPT file will be overwritten. So make sure to turn off + gamma_only for multi-k calculations. - Note: If gamma_only is set to 1, the KPT file will be overwritten. So make sure to turn off gamma_only for multi-k calculations. - **Default**: 0 ### scf_nmax @@ -1361,14 +1592,22 @@ ### scf_thr - **Type**: Real -- **Description**: It's the density threshold for electronic iteration. It represents the charge density error between two sequential densities from electronic iterations. This criterion is always enabled. If `scf_ene_thr` is set, its total-energy criterion is applied as an additional convergence check only after the charge-density criterion (`scf_thr`) has been satisfied, and only from the second SCF iteration onward (`iter > 1`). For local-orbital calculations, 1e-6 is usually accurate enough. +- **Description**: It's the density threshold for electronic iteration. It represents the charge + density error between two sequential densities from electronic iterations. This criterion is + always enabled. If `scf_ene_thr` is set, its total-energy criterion is applied as an additional + convergence check only after the charge-density criterion (`scf_thr`) has been satisfied, and only + from the second SCF iteration onward (`iter > 1`). For local-orbital calculations, 1e-6 is usually + accurate enough. - **Default**: 1.0e-9 (plane-wave basis), or 1.0e-7 (localized atomic orbital basis). - **Unit**: Ry if scf_thr_type=1, dimensionless if scf_thr_type=2 ### scf_ene_thr - **Type**: Real -- **Description**: It's the energy threshold for electronic iteration. The compared quantity is the total-energy difference evaluated from the charge densities before and after the `Hpsi` operation in one SCF step. It is not the same as the screen-output `EDIFF`, which is the energy difference before `Hpsi` and after charge mixing (i.e., across both `Hpsi` and charge-mixing operations). +- **Description**: It's the energy threshold for electronic iteration. The compared quantity is the + total-energy difference evaluated from the charge densities before and after the `Hpsi` operation + in one SCF step. It is not the same as the screen-output `EDIFF`, which is the energy difference + before `Hpsi` and after charge mixing (i.e., across both `Hpsi` and charge-mixing operations). - **Default**: -1.0. If the user does not set this parameter, it will not take effect. - **Unit**: eV @@ -1377,22 +1616,34 @@ - **Type**: Integer - **Description**: Choose the calculation method of convergence criterion. - 1: the criterion is defined in reciprocal space, which is used in SCF of PW basis with unit Ry. - - 2: the criterion is defined in real space, where is the number of electron, which is used in SCF of LCAO with unit dimensionless. + - 2: the criterion is defined in real space, where is the number of electron, which is used in SCF + of LCAO with unit dimensionless. - **Default**: 1 (plane-wave basis), or 2 (localized atomic orbital basis). ### scf_os_stop - **Type**: Boolean -- **Description**: For systems that are difficult to converge, the SCF process may exhibit oscillations in charge density, preventing further progress toward the specified convergence criteria and resulting in continuous oscillation until the maximum number of steps is reached; this greatly wastes computational resources. To address this issue, this function allows ABACUS to terminate the SCF process early upon detecting oscillations, thus reducing subsequent meaningless calculations. The detection of oscillations is based on the slope of the logarithm of historical drho values. To this end, Least Squares Method is used to calculate the slope of the logarithmically taken drho for the previous scf_os_ndim iterations. If the calculated slope is larger than scf_os_thr, stop the SCF. + +- **Description**: For systems that are difficult to converge, the SCF process may exhibit + oscillations in charge density, preventing further progress toward the specified convergence + criteria and resulting in continuous oscillation until the maximum number of steps is reached; + this greatly wastes computational resources. To address this issue, this function allows ABACUS to + terminate the SCF process early upon detecting oscillations, thus reducing subsequent meaningless + calculations. The detection of oscillations is based on the slope of the logarithm of historical + drho values. To this end, Least Squares Method is used to calculate the slope of the + logarithmically taken drho for the previous scf_os_ndim iterations. If the calculated slope is + larger than scf_os_thr, stop the SCF. - 0: The SCF will continue to run regardless of whether there is oscillation or not. - 1: If the calculated slope is larger than scf_os_thr, stop the SCF. + - **Default**: false ### scf_os_thr - **Type**: Real -- **Description**: The slope threshold to determine if the SCF is stuck in a charge density oscillation. If the calculated slope is larger than scf_os_thr, stop the SCF. +- **Description**: The slope threshold to determine if the SCF is stuck in a charge density + oscillation. If the calculated slope is larger than scf_os_thr, stop the SCF. - **Default**: -0.01 ### scf_os_ndim @@ -1404,7 +1655,8 @@ ### sc_os_ndim - **Type**: Integer -- **Description**: To determine the number of old iterations to judge oscillation, it occured, more accurate lambda with DeltaSpin method would be calculated, only for PW base. +- **Description**: To determine the number of old iterations to judge oscillation, it occured, more + accurate lambda with DeltaSpin method would be calculated, only for PW base. - **Default**: 5 ### lspinorb @@ -1416,13 +1668,15 @@ - Symmetry is automatically disabled (SOC breaks inversion symmetry) - Requires full-relativistic pseudopotentials with has_so=true in the UPF header - False: Do not consider spin-orbit coupling effect. - - Common Error: "no soc upf used for lspinorb calculation" - ensure you are using full-relativistic pseudopotentials + - Common Error: "no soc upf used for lspinorb calculation" - ensure you are using + full-relativistic pseudopotentials - **Default**: False ### noncolin - **Type**: Boolean -- **Description**: Whether to allow non-collinear magnetic moments, where magnetization can point in arbitrary directions (x, y, z components) rather than being constrained to the z-axis. +- **Description**: Whether to allow non-collinear magnetic moments, where magnetization can point in + arbitrary directions (x, y, z components) rather than being constrained to the z-axis. - True: Allow non-collinear polarization. When enabled: - nspin is automatically set to 4 - Wave function dimension is doubled (npol=2), and the number of occupied states is doubled @@ -1439,8 +1693,12 @@ ### soc_lambda - **Type**: Real + - **Availability**: *Only works when lspinorb=true* -- **Description**: Modulates the strength of spin-orbit coupling effect. Sometimes, for some real materials, both scalar-relativistic and full-relativistic pseudopotentials cannot describe the exact spin-orbit coupling. Artificial modulation may help in such cases. + +- **Description**: Modulates the strength of spin-orbit coupling effect. Sometimes, for some real + materials, both scalar-relativistic and full-relativistic pseudopotentials cannot describe the + exact spin-orbit coupling. Artificial modulation may help in such cases. soc_lambda, which has value range [0.0, 1.0], is used to modulate SOC effect: @@ -1448,7 +1706,10 @@ - soc_lambda 1.0: Full-relativistic case (full SOC) - Intermediate values: Partial-relativistic SOC (interpolation between scalar and full) - Use case: When experimental or high-level theoretical results suggest that the SOC effect is weaker or stronger than what full-relativistic pseudopotentials predict, you can adjust this parameter to match the target behavior. + Use case: When experimental or high-level theoretical results suggest that the SOC effect is + weaker or stronger than what full-relativistic pseudopotentials predict, you can adjust this + parameter to match the target behavior. + - **Default**: 1.0 ### dfthalf_type @@ -1469,7 +1730,8 @@ - **Availability**: *esolver_type = sdft* - **Description**: Different methods to do stochastic DFT - 1: Calculate twice, this method cost less memory but is slower. - - 2: Calculate once but needs much more memory. This method is much faster. Besides, it calculates with a smaller nche_sto. However, when the memory is not enough, only method 1 can be used. + - 2: Calculate once but needs much more memory. This method is much faster. Besides, it calculates + with a smaller nche_sto. However, when the memory is not enough, only method 1 can be used. - other: use 2 - **Default**: 2 @@ -1478,9 +1740,12 @@ - **Type**: Integer or string - **Availability**: *esolver_type = sdft* - **Description**: The number of stochastic orbitals - - > 0: Perform stochastic DFT. Increasing the number of bands improves accuracy and reduces stochastic errors; To perform mixed stochastic-deterministic DFT, you should set nbands, which represents the number of KS orbitals. + - \> 0: Perform stochastic DFT. Increasing the number of bands improves accuracy and reduces + stochastic errors; To perform mixed stochastic-deterministic DFT, you should set nbands, which + represents the number of KS orbitals. - 0: Perform Kohn-Sham DFT. - - all: All complete basis sets are used to replace stochastic orbitals with the Chebyshev method (CT), resulting in the same results as KSDFT without stochastic errors. + - all: All complete basis sets are used to replace stochastic orbitals with the Chebyshev method + (CT), resulting in the same results as KSDFT without stochastic errors. - **Default**: 256 ### nche_sto @@ -1494,7 +1759,8 @@ - **Type**: Real - **Availability**: *esolver_type = sdft* -- **Description**: Trial energy to guess the lower bound of eigen energies of the Hamiltonian Operator. +- **Description**: Trial energy to guess the lower bound of eigen energies of the Hamiltonian + Operator. - **Default**: 0.0 - **Unit**: Ry @@ -1502,7 +1768,8 @@ - **Type**: Real - **Availability**: *esolver_type = sdft* -- **Description**: Trial energy to guess the upper bound of eigen energies of the Hamiltonian Operator. +- **Description**: Trial energy to guess the upper bound of eigen energies of the Hamiltonian + Operator. - **Default**: 0.0 - **Unit**: Ry @@ -1511,9 +1778,10 @@ - **Type**: Integer - **Availability**: *esolver_type = sdft* - **Description**: The random seed to generate stochastic orbitals. - - >= 0: Stochastic orbitals have the form of exp(i*theta), where theta is a uniform distribution in [0, 2*pi). + - \>= 0: Stochastic orbitals have the form of exp(i*theta), where theta is a uniform distribution + in \[0, 2*pi). - 0: the seed is decided by time(NULL). - - <= -1: Stochastic orbitals have the form of +1 or -1 with equal probability. + - \<= -1: Stochastic orbitals have the form of +1 or -1 with equal probability. - -1: the seed is decided by time(NULL). - **Default**: 0 @@ -1521,7 +1789,10 @@ - **Type**: Real - **Availability**: *esolver_type = sdft* -- **Description**: Stochastic wave functions are initialized in a large box generated by "4*initsto_ecut". initsto_ecut should be larger than ecutwfc. In this method, SDFT results are the same when using different cores. Besides, coefficients of the same G are the same when ecutwfc is rising to initsto_ecut. If it is smaller than ecutwfc, it will be turned off. +- **Description**: Stochastic wave functions are initialized in a large box generated by + "4\*initsto_ecut". initsto_ecut should be larger than ecutwfc. In this method, SDFT results are + the same when using different cores. Besides, coefficients of the same G are the same when ecutwfc + is rising to initsto_ecut. If it is smaller than ecutwfc, it will be turned off. - **Default**: 0.0 - **Unit**: Ry @@ -1529,7 +1800,8 @@ - **Type**: Integer - **Availability**: *esolver_type = sdft* -- **Description**: Frequency (once each initsto_freq steps) to generate new stochastic orbitals when running md. +- **Description**: Frequency (once each initsto_freq steps) to generate new stochastic orbitals when + running md. - positive integer: Update stochastic orbitals - 0: Never change stochastic orbitals. - **Default**: 0 @@ -1538,7 +1810,8 @@ - **Type**: Integer - **Availability**: *method_sto = 2 and out_dos = 1 or cal_cond = True* -- **Description**: Make memory cost to 1/npart_sto times of the previous one when running the post process of SDFT like DOS or conductivities. +- **Description**: Make memory cost to 1/npart_sto times of the previous one when running the post + process of SDFT like DOS or conductivities. - **Default**: 1 [back to top](#full-list-of-input-keywords) @@ -1548,79 +1821,120 @@ ### relax_method - **Type**: Vector of string -- **Description**: The methods to do geometry optimization. The available algorithms depend on the relax_new setting. + +- **Description**: The methods to do geometry optimization. The available algorithms depend on the + relax_new setting. First element (algorithm selection): - - cg: Conjugate gradient (CG) algorithm. Available for both relax_new = True (default, simultaneous optimization) and relax_new = False (nested optimization). See relax_new for implementation details. - - bfgs: Broyden–Fletcher–Goldfarb–Shanno (BFGS) quasi-Newton algorithm. Only available when relax_new = False. - - lbfgs: Limited-memory BFGS algorithm, suitable for large systems. Only available when relax_new = False. - - cg_bfgs: Mixed method starting with CG and switching to BFGS when force convergence reaches relax_cg_thr. Only available when relax_new = False. - - sd: Steepest descent algorithm. Only available when relax_new = False. Not recommended for production use. - - fire: Fast Inertial Relaxation Engine method, a molecular-dynamics-based relaxation algorithm. Use by setting calculation to md and md_type to fire. Ionic velocities must be set in STRU file. See fire for details. + - cg: Conjugate gradient (CG) algorithm. Available for both relax_new = True (default, + simultaneous optimization) and relax_new = False (nested optimization). See relax_new for + implementation details. + - bfgs: Broyden–Fletcher–Goldfarb–Shanno (BFGS) quasi-Newton algorithm. Only available when + relax_new = False. + - lbfgs: Limited-memory BFGS algorithm, suitable for large systems. Only available when relax_new + = False. + - cg_bfgs: Mixed method starting with CG and switching to BFGS when force convergence reaches + relax_cg_thr. Only available when relax_new = False. + - sd: Steepest descent algorithm. Only available when relax_new = False. Not recommended for + production use. + - fire: Fast Inertial Relaxation Engine method, a molecular-dynamics-based relaxation algorithm. + Use by setting calculation to md and md_type to fire. Ionic velocities must be set in STRU file. + See fire for details. Second element (BFGS variant, only when first element is bfgs): - 1: Traditional BFGS that updates the Hessian matrix B and then inverts it. - 2 or omitted: Default BFGS that directly updates the inverse Hessian (recommended). - > Note: In the 3.10-LTS version, the type of this parameter is std::string. It can be set to "cg", "bfgs", "cg_bfgs", "bfgs_trad", "lbfgs", "sd", "fire". + > Note: In the 3.10-LTS version, the type of this parameter is std::string. It can be set to "cg", + > "bfgs", "cg_bfgs", "bfgs_trad", "lbfgs", "sd", "fire". + - **Default**: cg 1 ### relax_new - **Type**: Boolean -- **Description**: Controls which implementation of geometry relaxation to use. At the end of 2022, a new implementation of the Conjugate Gradient (CG) method was introduced for relax and cell-relax calculations, while the old implementation was kept for backward compatibility. +- **Description**: Controls which implementation of geometry relaxation to use. At the end of 2022, + a new implementation of the Conjugate Gradient (CG) method was introduced for relax and cell-relax + calculations, while the old implementation was kept for backward compatibility. - True (default): Use the new CG implementation with the following features: - - Simultaneous optimization of ionic positions and cell parameters (for cell-relax) - - Line search algorithm for step size determination - - Only CG algorithm is available (relax_method must be cg) - - Supports advanced cell constraints: fixed_axes = "shape", "volume", "a", "b", "c", etc. - - Supports fixed_ibrav to maintain lattice type - - More efficient for variable-cell relaxation - - Step size controlled by relax_scale_force + + - Simultaneous optimization of ionic positions and cell parameters (for cell-relax) + + - Line search algorithm for step size determination + + - Only CG algorithm is available (relax_method must be cg) + + - Supports advanced cell constraints: fixed_axes = "shape", "volume", "a", "b", "c", etc. + + - Supports fixed_ibrav to maintain lattice type + + - More efficient for variable-cell relaxation + + - Step size controlled by relax_scale_force - False: Use the old implementation with the following features: - - Nested optimization procedure: ionic positions optimized first, then cell parameters (for cell-relax) - - Multiple algorithms available: cg, bfgs, lbfgs, sd, cg_bfgs - - Limited cell constraints: only fixed_axes = "volume" is supported - - Traditional approach with separate ionic and cell optimization steps + + - Nested optimization procedure: ionic positions optimized first, then cell parameters (for + cell-relax) + + - Multiple algorithms available: cg, bfgs, lbfgs, sd, cg_bfgs + + - Limited cell constraints: only fixed_axes = "volume" is supported + + - Traditional approach with separate ionic and cell optimization steps + - **Default**: True ### relax_scale_force - **Type**: Real - **Availability**: *Only used when relax_new set to True* -- **Description**: The paramether controls the size of the first conjugate gradient step. A smaller value means the first step along a new CG direction is smaller. This might be helpful for large systems, where it is safer to take a smaller initial step to prevent the collapse of the whole configuration. +- **Description**: The paramether controls the size of the first conjugate gradient step. A smaller + value means the first step along a new CG direction is smaller. This might be helpful for large + systems, where it is safer to take a smaller initial step to prevent the collapse of the whole + configuration. - **Default**: 0.5 ### relax_nmax - **Type**: Integer -- **Description**: The maximal number of ionic iteration steps. If set to 0, the code performs a quick "dry run", stopping just after initialization. This is useful to check for input correctness and to have the summary printed. +- **Description**: The maximal number of ionic iteration steps. If set to 0, the code performs a + quick "dry run", stopping just after initialization. This is useful to check for input correctness + and to have the summary printed. - **Default**: 1 for SCF, 50 for relax and cell-relax calcualtions ### relax_cg_thr - **Type**: Real - **Availability**: *Only used when relax_new = False and relax_method = cg_bfgs* -- **Description**: When relax_method is set to cg_bfgs, a mixed algorithm of conjugate gradient (CG) and Broyden–Fletcher–Goldfarb–Shanno (BFGS) is used. The ions first move according to the CG method, then switch to the BFGS method when the maximum force on atoms is reduced below this threshold. +- **Description**: When relax_method is set to cg_bfgs, a mixed algorithm of conjugate gradient (CG) + and Broyden–Fletcher–Goldfarb–Shanno (BFGS) is used. The ions first move according to the CG + method, then switch to the BFGS method when the maximum force on atoms is reduced below this + threshold. - **Default**: 0.5 - **Unit**: eV/Angstrom ### force_thr - **Type**: Real -- **Description**: Threshold of the force convergence. The threshold is compared with the largest force among all of the atoms. The recommended value for using atomic orbitals is 0.04 eV/Angstrom (0.0016 Ry/Bohr). The parameter is equivalent to force_thr_ev except for the unit, you can choose either you like. +- **Description**: Threshold of the force convergence. The threshold is compared with the largest + force among all of the atoms. The recommended value for using atomic orbitals is 0.04 eV/Angstrom + (0.0016 Ry/Bohr). The parameter is equivalent to force_thr_ev except for the unit, you can choose + either you like. - **Default**: 0.001 - **Unit**: Ry/Bohr (25.7112 eV/Angstrom) ### force_thr_ev - **Type**: Real -- **Description**: Threshold of the force convergence. The threshold is compared with the largest force among all of the atoms. The recommended value for using atomic orbitals is 0.04 eV/Angstrom (0.0016 Ry/Bohr). The parameter is equivalent to force_thr except for the unit. You may choose either you like. +- **Description**: Threshold of the force convergence. The threshold is compared with the largest + force among all of the atoms. The recommended value for using atomic orbitals is 0.04 eV/Angstrom + (0.0016 Ry/Bohr). The parameter is equivalent to force_thr except for the unit. You may choose + either you like. - **Default**: 0.0257112 - **Unit**: eV/Angstrom (0.03889 Ry/Bohr) @@ -1635,21 +1949,26 @@ - **Type**: Real - **Availability**: *Only used when relax_new = False and relax_method is bfgs or cg_bfgs* -- **Description**: Controls the Wolfe condition for the Broyden–Fletcher–Goldfarb–Shanno (BFGS) algorithm used in geometry relaxation. This parameter sets the sufficient decrease condition (c1 in Wolfe conditions). For more information, see Phys. Chem. Chem. Phys., 2000, 2, 2177. +- **Description**: Controls the Wolfe condition for the Broyden–Fletcher–Goldfarb–Shanno (BFGS) + algorithm used in geometry relaxation. This parameter sets the sufficient decrease condition (c1 + in Wolfe conditions). For more information, see Phys. Chem. Chem. Phys., 2000, 2, 2177. - **Default**: 0.01 ### relax_bfgs_w2 - **Type**: Real - **Availability**: *Only used when relax_new = False and relax_method is bfgs or cg_bfgs* -- **Description**: Controls the Wolfe condition for the Broyden–Fletcher–Goldfarb–Shanno (BFGS) algorithm used in geometry relaxation. This parameter sets the curvature condition (c2 in Wolfe conditions). For more information, see Phys. Chem. Chem. Phys., 2000, 2, 2177. +- **Description**: Controls the Wolfe condition for the Broyden–Fletcher–Goldfarb–Shanno (BFGS) + algorithm used in geometry relaxation. This parameter sets the curvature condition (c2 in Wolfe + conditions). For more information, see Phys. Chem. Chem. Phys., 2000, 2, 2177. - **Default**: 0.5 ### relax_bfgs_rmax - **Type**: Real - **Availability**: *Only used when relax_new = False and relax_method is bfgs or cg_bfgs* -- **Description**: Maximum allowed total displacement of all atoms during geometry optimization. The sum of atomic displacements can increase during optimization steps but cannot exceed this value. +- **Description**: Maximum allowed total displacement of all atoms during geometry optimization. The + sum of atomic displacements can increase during optimization steps but cannot exceed this value. - **Default**: 0.8 - **Unit**: Bohr @@ -1657,7 +1976,10 @@ - **Type**: Real - **Availability**: *Only used when relax_new = False and relax_method = bfgs 1 (traditional BFGS)* -- **Description**: Minimum allowed total displacement of all atoms. When the total atomic displacement falls below this value and force convergence is not achieved, the calculation will terminate. Note: This parameter is not used in the default BFGS algorithm (relax_method = bfgs 2 or bfgs). +- **Description**: Minimum allowed total displacement of all atoms. When the total atomic + displacement falls below this value and force convergence is not achieved, the calculation will + terminate. Note: This parameter is not used in the default BFGS algorithm (relax_method = bfgs 2 + or bfgs). - **Default**: 1e-5 - **Unit**: Bohr @@ -1665,43 +1987,51 @@ - **Type**: Real - **Availability**: *Only used when relax_new = False and relax_method is bfgs or cg_bfgs* -- **Description**: Initial total displacement of all atoms in the first BFGS step. This sets the scale for the initial movement. +- **Description**: Initial total displacement of all atoms in the first BFGS step. This sets the + scale for the initial movement. - **Default**: 0.5 - **Unit**: Bohr ### stress_thr - **Type**: Real -- **Description**: The threshold of the stress convergence. The threshold is compared with the largest component of the stress tensor. +- **Description**: The threshold of the stress convergence. The threshold is compared with the + largest component of the stress tensor. - **Default**: 0.5 - **Unit**: kbar ### press1 - **Type**: Real -- **Description**: The external pressures along three axes. Positive input value is taken as compressive stress. +- **Description**: The external pressures along three axes. Positive input value is taken as + compressive stress. - **Default**: 0 - **Unit**: kbar ### press2 - **Type**: Real -- **Description**: The external pressures along three axes. Positive input value is taken as compressive stress. +- **Description**: The external pressures along three axes. Positive input value is taken as + compressive stress. - **Default**: 0 - **Unit**: kbar ### press3 - **Type**: Real -- **Description**: The external pressures along three axes. Positive input value is taken as compressive stress. +- **Description**: The external pressures along three axes. Positive input value is taken as + compressive stress. - **Default**: 0 - **Unit**: kbar ### fixed_axes - **Type**: String + - **Availability**: *Only used when calculation is set to cell-relax* -- **Description**: Specifies which cell degrees of freedom are fixed during variable-cell relaxation. The available options depend on the relax_new setting: + +- **Description**: Specifies which cell degrees of freedom are fixed during variable-cell + relaxation. The available options depend on the relax_new setting: When relax_new = True (default), all options are available: @@ -1718,28 +2048,45 @@ When relax_new = False, all options are now available: - None: Default; all cell parameters can relax freely - - volume: Relaxation with fixed volume (allows shape changes). Volume is preserved by rescaling the lattice after each update. - - shape: Fix shape but allow volume changes (hydrostatic pressure only). Stress tensor is replaced with isotropic pressure. + - volume: Relaxation with fixed volume (allows shape changes). Volume is preserved by rescaling + the lattice after each update. + - shape: Fix shape but allow volume changes (hydrostatic pressure only). Stress tensor is replaced + with isotropic pressure. - a, b, c, ab, ac, bc: Fix specific lattice vectors. Gradients for fixed vectors are set to zero. - > Note: For VASP users, see the ISIF correspondence table in the geometry optimization documentation. Both implementations now support all constraint types. + > Note: For VASP users, see the ISIF correspondence table in the geometry optimization + > documentation. Both implementations now support all constraint types. + - **Default**: None ### fixed_ibrav - **Type**: Boolean -- **Availability**: *Can be used with both relax_new = True and relax_new = False. A specific latname must be provided.* -- **Description**: - True: the lattice type will be preserved during relaxation. The lattice vectors are reconstructed to match the specified Bravais lattice type after each update. + +- **Availability**: *Can be used with both relax_new = True and relax_new = False. A specific + latname must be provided.* + +- **Description**: - True: the lattice type will be preserved during relaxation. The lattice vectors + are reconstructed to match the specified Bravais lattice type after each update. + - False: No restrictions are exerted during relaxation in terms of lattice type - > Note: it is possible to use fixed_ibrav with fixed_axes, but please make sure you know what you are doing. For example, if we are doing relaxation of a simple cubic lattice (latname = "sc"), and we use fixed_ibrav along with fixed_axes = "volume", then the cell is never allowed to move and as a result, the relaxation never converges. When both are used, fixed_ibrav is applied first, then fixed_axes = "volume" rescaling is applied. + > Note: it is possible to use fixed_ibrav with fixed_axes, but please make sure you know what you + > are doing. For example, if we are doing relaxation of a simple cubic lattice (latname = "sc"), + > and we use fixed_ibrav along with fixed_axes = "volume", then the cell is never allowed to move + > and as a result, the relaxation never converges. When both are used, fixed_ibrav is applied + > first, then fixed_axes = "volume" rescaling is applied. + - **Default**: False ### fixed_atoms - **Type**: Boolean -- **Description**: - True: The direct coordinates of atoms will be preserved during variable-cell relaxation. - - False: No restrictions are exerted on positions of all atoms. However, users can still fix certain components of certain atoms by using the m keyword in STRU file. For the latter option, check the end of this instruction. +- **Description**: - True: The direct coordinates of atoms will be preserved during variable-cell + relaxation. + - False: No restrictions are exerted on positions of all atoms. However, users can still fix + certain components of certain atoms by using the m keyword in STRU file. For the latter option, + check the end of this instruction. - **Default**: False [back to top](#full-list-of-input-keywords) @@ -1749,133 +2096,215 @@ ### out_freq_ion - **Type**: Integer -- **Description**: Controls the output interval in ionic steps. When set to a positive integer, information such as charge density, local potential, electrostatic potential, Hamiltonian matrix, overlap matrix, density matrix, and Mulliken population analysis is printed every n ionic steps. - > Note: In RT-TDDFT calculations, this parameter is inactive; output frequency is instead controlled by out_freq_td. +- **Description**: Controls the output interval in ionic steps. When set to a positive integer, + information such as charge density, local potential, electrostatic potential, Hamiltonian matrix, + overlap matrix, density matrix, and Mulliken population analysis is printed every n ionic steps. + + > Note: In RT-TDDFT calculations, this parameter is inactive; output frequency is instead + > controlled by out_freq_td. + - **Default**: 0 ### out_freq_td - **Type**: Integer -- **Description**: Controls the output interval in completed electronic evolution steps during RT-TDDFT calculations. When set to a positive integer n, detailed information (see out_freq_ion) is printed every n electron time-evolution steps (i.e., every STEP OF ELECTRON EVOLVE). For example, if you wish to output information once per ionic step, you should set out_freq_td equal to estep_per_md, since one ionic step corresponds to estep_per_md electronic evolution steps. - > Note: This parameter is only active in RT-TDDFT mode (esolver_type = tddft). It has no effect in ground-state calculations. +- **Description**: Controls the output interval in completed electronic evolution steps during + RT-TDDFT calculations. When set to a positive integer n, detailed information (see out_freq_ion) + is printed every n electron time-evolution steps (i.e., every STEP OF ELECTRON EVOLVE). For + example, if you wish to output information once per ionic step, you should set out_freq_td equal + to estep_per_md, since one ionic step corresponds to estep_per_md electronic evolution steps. + + > Note: This parameter is only active in RT-TDDFT mode (esolver_type = tddft). It has no effect in + > ground-state calculations. + - **Default**: 0 ### out_freq_elec - **Type**: Integer -- **Description**: Output the charge density (only binary format, controlled by out_chg), wavefunction (controlled by out_wfc_pw) per out_freq_elec electronic iterations. Note that they are always output when converged or reach the maximum iterations scf_nmax. +- **Description**: Output the charge density (only binary format, controlled by out_chg), + wavefunction (controlled by out_wfc_pw) per out_freq_elec electronic iterations. Note that they + are always output when converged or reach the maximum iterations scf_nmax. - **Default**: scf_nmax ### out_chg - **Type**: Integer \[Integer\](optional) -- **Description**: The first integer controls whether to output the charge density on real space grids: - - 1: Output the charge density (in Bohr^-3) on real space grids into the density files in the folder OUT.{suffix} too, which can be read in NSCF calculation. + +- **Description**: The first integer controls whether to output the charge density on real space + grids: + + - 1: Output the charge density (in Bohr^-3) on real space grids into the density files in the + folder OUT.\{suffix} too, which can be read in NSCF calculation. In molecular dynamics simulations, the output frequency is controlled by out_freq_ion. > Note: In the 3.10-LTS version, the file names are SPIN1_CHG.cube and SPIN1_CHG_INI.cube, etc. + - **Default**: 0 3 ### out_pot - **Type**: Integer \[Integer\](optional) -- **Description**: - 1: Output the total local potential (i.e., local pseudopotential + Hartree potential + XC potential + external electric field (if exists) + dipole correction potential (if exists) + ...) on real space grids (in Ry) into files in the folder OUT.{suffix}. The files are named as: - - nspin = 1: pots1.cube; - - nspin = 2: pots1.cube and pots2.cube; - - nspin = 4: pots1.cube, pots2.cube, pots3.cube, and pots4.cube - - 2: Output the electrostatic potential on real space grids into OUT.{suffix}/pot_es.cube. The Python script named tools/average_pot/aveElecStatPot.py can be used to calculate the average electrostatic potential along the z-axis and outputs it into ElecStaticPot_AVE. Please note that the total local potential refers to the local component of the self-consistent potential, excluding the non-local pseudopotential. The distinction between the local potential and the electrostatic potential is as follows: local potential = electrostatic potential + XC potential. - - 3: Apart from 1, also output the total local potential of the initial charge density. The files are named as: - - nspin = 1: pots1_ini.cube; - - nspin = 2: pots1_ini.cube and pots2_ini.cube; - - nspin = 4: pots1_ini.cube, pots2_ini.cube, pots3_ini.cube, and pots4_ini.cube - - The optional second integer controls the output precision. If not provided, the default precision is 8. + +- **Description**: - 1: Output the total local potential (i.e., local pseudopotential + Hartree + potential + XC potential + external electric field (if exists) + dipole correction potential (if + exists) + ...) on real space grids (in Ry) into files in the folder OUT.\{suffix}. The files are + named as: + + - nspin = 1: pots1.cube; + - nspin = 2: pots1.cube and pots2.cube; + - nspin = 4: pots1.cube, pots2.cube, pots3.cube, and pots4.cube + - 2: Output the electrostatic potential on real space grids into OUT.\{suffix}/pot_es.cube. The + Python script named tools/average_pot/aveElecStatPot.py can be used to calculate the average + electrostatic potential along the z-axis and outputs it into ElecStaticPot_AVE. Please note that + the total local potential refers to the local component of the self-consistent potential, + excluding the non-local pseudopotential. The distinction between the local potential and the + electrostatic potential is as follows: local potential = electrostatic potential + XC potential. + - 3: Apart from 1, also output the total local potential of the initial charge density. The files + are named as: + - nspin = 1: pots1_ini.cube; + - nspin = 2: pots1_ini.cube and pots2_ini.cube; + - nspin = 4: pots1_ini.cube, pots2_ini.cube, pots3_ini.cube, and pots4_ini.cube + + The optional second integer controls the output precision. If not provided, the default precision + is 8. In molecular dynamics calculations, the output frequency is controlled by out_freq_ion. > Note: In the 3.10-LTS version, the file names are SPIN1_POT.cube and SPIN1_POT_INI.cube, etc. + - **Default**: 0 ### out_dmk - **Type**: Boolean \[Integer\](optional) + - **Availability**: *Numerical atomic orbital basis* -- **Description**: Whether to output the density matrix for each k-point into files in the folder OUT.${suffix}. For current develop versions, out_dmk writes *_nao.txt files and includes a g{istep} index in the file name: + +- **Description**: Whether to output the density matrix for each k-point into files in the folder + OUT.\$\{suffix}. For current develop versions, out_dmk writes \*\_nao.txt files and includes a + g\{istep} index in the file name: + - For gamma only case: - - nspin = 1 and 4: dmg1_nao.txt; - - nspin = 2: dms1g1_nao.txt and dms2g1_nao.txt for the two spin channels. + - nspin = 1 and 4: dmg1_nao.txt; + - nspin = 2: dms1g1_nao.txt and dms2g1_nao.txt for the two spin channels. - For multi-k points case: - - nspin = 1 and 4: dmk1g1_nao.txt, dmk2g1_nao.txt, ...; - - nspin = 2: dmk1s1g1_nao.txt... and dmk1s2g1_nao.txt... for the two spin channels. + - nspin = 1 and 4: dmk1g1_nao.txt, dmk2g1_nao.txt, ...; + - nspin = 2: dmk1s1g1_nao.txt... and dmk1s2g1_nao.txt... for the two spin channels. - Here, g{istep} denotes the geometry/step index in the output file name. + Here, g\{istep} denotes the geometry/step index in the output file name. > Note: Version difference (develop vs 3.10-LTS): > > - In develop, out_dmk supports both gamma-only and multi-k-point density-matrix output. - > - In 3.10-LTS, the corresponding keyword is out_dm, and the output files are SPIN1_DM and SPIN2_DM, etc. + > - In 3.10-LTS, the corresponding keyword is out_dm, and the output files are SPIN1_DM and + > SPIN2_DM, etc. + - **Default**: False ### out_dmr - **Type**: Boolean \[Integer\](optional) + - **Availability**: *Numerical atomic orbital basis (multi-k points)* -- **Description**: Whether to output the density matrix with Bravias lattice vector R index into files in the folder OUT.${suffix}. The files are named as dmr{s}{spin index}{g}{geometry index}{_nao} + {".csr"}. Here, 's' refers to spin, where s1 means spin up channel while s2 means spin down channel, and the sparse matrix format 'csr' is mentioned in out_mat_hs2. Finally, if out_app_flag is set to false, the file name contains the optional 'g' index for each ionic step that may have different geometries, and if out_app_flag is set to true, the density matrix with respect to Bravias lattice vector R accumulates during ionic steps: + +- **Description**: Whether to output the density matrix with Bravias lattice vector R index into + files in the folder OUT.\$\{suffix}. The files are named as dmr\{s}{spin index}\{g}{geometry + index}{\_nao} + {".csr"}. Here, 's' refers to spin, where s1 means spin up channel while s2 means + spin down channel, and the sparse matrix format 'csr' is mentioned in out_mat_hs2. Finally, if + out_app_flag is set to false, the file name contains the optional 'g' index for each ionic step + that may have different geometries, and if out_app_flag is set to true, the density matrix with + respect to Bravias lattice vector R accumulates during ionic steps: + - nspin = 1: dmrs1_nao.csr; - nspin = 2: dmrs1_nao.csr and dmrs2_nao.csr for the two spin channels. - > Note: In the 3.10-LTS version, the parameter is named out_dm1, and the file names are data-DMR-sparse_SPIN0.csr and data-DMR-sparse_SPIN1.csr, etc. + > Note: In the 3.10-LTS version, the parameter is named out_dm1, and the file names are + > data-DMR-sparse_SPIN0.csr and data-DMR-sparse_SPIN1.csr, etc. + - **Default**: False ### out_wfc_pw - **Type**: Integer -- **Availability**: *Output electronic wave functions in plane wave basis, or transform the real-space electronic wave function into plane wave basis (see get_wf option in calculation with NAO basis)* -- **Description**: Whether to output the electronic wavefunction coefficients into files and store them in the folder OUT.${suffix}. The files are named as wf{k}{k-point index}{s}{spin index}{g}{geometry index}{e}{electronic iteration index}{_pw} + {".txt"/".dat"}. Here, the s index refers to spin but the label will not show up for non-spin-polarized calculations, where s1 means spin up channel while s2 means spin down channel, and s4 refers to spinor wave functions that contains both spin channels with spin-orbital coupling or noncollinear calculations enabled. For scf or nscf calculations, g index will not appear, but the g index appears for geometry relaxation and molecular dynamics, where one can use the out_freq_ion command to control. To print out the electroinc wave functions every few SCF iterations, use the out_freq_elec command and the e index will appear in the file name. + +- **Availability**: *Output electronic wave functions in plane wave basis, or transform the + real-space electronic wave function into plane wave basis (see get_wf option in calculation with + NAO basis)* + +- **Description**: Whether to output the electronic wavefunction coefficients into files and store + them in the folder OUT.\$\{suffix}. The files are named as wf\{k}{k-point index}\{s}{spin + index}\{g}{geometry index}\{e}{electronic iteration index}{\_pw} + {".txt"/".dat"}. Here, the s + index refers to spin but the label will not show up for non-spin-polarized calculations, where s1 + means spin up channel while s2 means spin down channel, and s4 refers to spinor wave functions + that contains both spin channels with spin-orbital coupling or noncollinear calculations enabled. + For scf or nscf calculations, g index will not appear, but the g index appears for geometry + relaxation and molecular dynamics, where one can use the out_freq_ion command to control. To print + out the electroinc wave functions every few SCF iterations, use the out_freq_elec command and the + e index will appear in the file name. + - 0: no output - 1: (txt format) - - non-gamma-only with nspin=1: wfk1_pw.txt, wfk2_pw.txt, ...; - - non-gamma-only with nspin=2: wfk1s1_pw.txt, wfk1s2_pw.txt, wfk2s1_pw.txt, wfk2s2_pw.txt, ...; - - non-gamma-only with nspin=4: wfk1s4_pw.txt, wfk2s4_pw.txt, ...; + - non-gamma-only with nspin=1: wfk1_pw.txt, wfk2_pw.txt, ...; + - non-gamma-only with nspin=2: wfk1s1_pw.txt, wfk1s2_pw.txt, wfk2s1_pw.txt, wfk2s2_pw.txt, ...; + - non-gamma-only with nspin=4: wfk1s4_pw.txt, wfk2s4_pw.txt, ...; - 2: (binary format) - - non-gamma-only with nspin=1: wfk1_pw.dat, wfk2_pw.dat, ...; - - non-gamma-only with nspin=2: wfk1s1_pw.dat, wfk1s2_pw.dat, wfk2s1_pw.dat, wfk2s2_pw.dat, ...; - - non-gamma-only with nspin=4: wfk1s4_pw.dat, wfk2s4_pw.dat, ...; + - non-gamma-only with nspin=1: wfk1_pw.dat, wfk2_pw.dat, ...; + - non-gamma-only with nspin=2: wfk1s1_pw.dat, wfk1s2_pw.dat, wfk2s1_pw.dat, wfk2s2_pw.dat, ...; + - non-gamma-only with nspin=4: wfk1s4_pw.dat, wfk2s4_pw.dat, ...; > Note: In the 3.10-LTS version, the file names are WAVEFUNC1.dat, WAVEFUNC2.dat, etc. + - **Default**: 0 ### out_wfc_lcao - **Type**: Integer + - **Availability**: *Numerical atomic orbital basis* -- **Description**: Whether to output the electronic wavefunction coefficients into files and store them in the folder OUT.${suffix}. The files are named as wf{s}{spin index}{k(optional)}{k-point index}{g(optional)}{geometry index1}{_nao} + {".txt"/".dat"}. Here, 's' refers to spin, where s1 means spin up channel while s2 means spin down channel, and 's12' refer to spinor wave functions that contains both spin channels with spin-orbital coupling or noncollinear calculations enabled. In addition, if 'gamma_only' is set to 0, then the optinoal k-point sampling index appears with the k-point index attached to the electronic wave function file names. Finally, if out_app_flag is set to false, the file name contains the optional 'g' index for each ionic step that may have different geometries, and if out_app_flag is set to true, the wave functions accumulate during ionic steps. If the out_app_flag is set to false, a new folder named WFC will be created, and the wave function files will be saved into it. + +- **Description**: Whether to output the electronic wavefunction coefficients into files and store + them in the folder OUT.\$\{suffix}. The files are named as wf\{s}{spin index}{k(optional)}{k-point + index}{g(optional)}{geometry index1}{\_nao} + {".txt"/".dat"}. Here, 's' refers to spin, where s1 + means spin up channel while s2 means spin down channel, and 's12' refer to spinor wave functions + that contains both spin channels with spin-orbital coupling or noncollinear calculations enabled. + In addition, if 'gamma_only' is set to 0, then the optinoal k-point sampling index appears with + the k-point index attached to the electronic wave function file names. Finally, if out_app_flag is + set to false, the file name contains the optional 'g' index for each ionic step that may have + different geometries, and if out_app_flag is set to true, the wave functions accumulate during + ionic steps. If the out_app_flag is set to false, a new folder named WFC will be created, and the + wave function files will be saved into it. + - 0: no output - 1: (txt format) - - gamma-only: wfs1_nao.txt or wfs2_nao.txt, ...; - - non-gamma-only: wfs1k1_nao.txt or wfs1k2_nao.txt, ...; + - gamma-only: wfs1_nao.txt or wfs2_nao.txt, ...; + - non-gamma-only: wfs1k1_nao.txt or wfs1k2_nao.txt, ...; - 2: (binary format) - - gamma-only: wfs1_nao.dat or wfs2_nao.dat, ...; - - non-gamma-only: wfs1k1_nao.dat or wfs1k2_nao.dat, .... + - gamma-only: wfs1_nao.dat or wfs2_nao.dat, ...; + - non-gamma-only: wfs1k1_nao.dat or wfs1k2_nao.dat, .... The corresponding sequence of the orbitals can be seen in Basis Set. Also controled by out_freq_ion and out_app_flag. - > Note: In the 3.10-LTS version, the file names are WFC_NAO_GAMMA1_ION1.txt and WFC_NAO_K1_ION1.txt, etc. + > Note: In the 3.10-LTS version, the file names are WFC_NAO_GAMMA1_ION1.txt and + > WFC_NAO_K1_ION1.txt, etc. + - **Default**: 0 ### out_dos - **Type**: Integer -- **Description**: Whether to output the density of states (DOS). For more information, refer to the dos.md. +- **Description**: Whether to output the density of states (DOS). For more information, refer to the + dos.md. - 0: no output - 1: output the density of states (DOS) - - nspin=1 or 4: doss1g{geom}_{basis}.txt, where geom is the geometry index when cell changes or ions move while basis is either pw or nao. - - nspin=2: doss1g{geom}_{basis}.txt and doss2g{geom}_{basis}.txt for two spin channles. + - nspin=1 or 4: doss1g\{geom}\_\{basis}.txt, where geom is the geometry index when cell changes or + ions move while basis is either pw or nao. + - nspin=2: doss1g\{geom}_\{basis}.txt and doss2g\{geom}_\{basis}.txt for two spin channles. - 2: (LCAO) output the density of states (DOS) and the projected density of states (PDOS) - 3: output the Fermi surface file (fermi.bxsf) in BXSF format that can be visualized by XCrySDen - **Default**: 0 @@ -1883,273 +2312,421 @@ ### out_ldos - **Type**: Integer \[Integer\](optional) -- **Description**: Whether to output the local density of states (LDOS), optionally output precision can be set by a second parameter, default is 3. +- **Description**: Whether to output the local density of states (LDOS), optionally output precision + can be set by a second parameter, default is 3. - 0: no output - - 1: output the partial charge density for given bias (controlled by stm_bias) in cube file format, which can be used to plot scanning tunneling spectroscopys to mimick STM images using the Python script plot.py. - - 2: output LDOS along a line in real space (controlled by ldos_line). Parameters used to control DOS output are also valid for LDOS. + - 1: output the partial charge density for given bias (controlled by stm_bias) in cube file + format, which can be used to plot scanning tunneling spectroscopys to mimick STM images using + the Python script plot.py. + - 2: output LDOS along a line in real space (controlled by ldos_line). Parameters used to control + DOS output are also valid for LDOS. - 3: output both two LDOS modes above. - **Default**: 0 ### out_band - **Type**: Boolean \[Integer\](optional) -- **Description**: Whether to output the eigenvalues of the Hamiltonian matrix (in eV) into the running log during electronic iterations and into a file at the end of calculations. The former can be used with the 'out_freq_elec' parameter while the latter option allows the output precision to be set via a second parameter, with a default value of 8. The output file names are: - - nspin = 1 or 4: eig.txt; - - nspin = 2: eigs1.txt and eigs2.txt; - - For more information, refer to the band.md +- **Description**: Whether to output the eigenvalues of the Hamiltonian matrix (in eV) into the + running log during electronic iterations and into a file at the end of calculations. The former + can be used with the 'out_freq_elec' parameter while the latter option allows the output precision + to be set via a second parameter, with a default value of 8. The output file names are: + - nspin = 1 or 4: eig.txt; + - nspin = 2: eigs1.txt and eigs2.txt; + - For more information, refer to the band.md - **Default**: False ### out_proj_band - **Type**: Boolean -- **Description**: Whether to output the projected band structure. For more information, refer to the band.md +- **Description**: Whether to output the projected band structure. For more information, refer to + the band.md - **Default**: False ### out_stru - **Type**: Boolean -- **Description**: Whether to output structure files per ionic step in geometry relaxation calculations into OUT.{istep}_D, where ${istep} is the ionic step. +- **Description**: Whether to output structure files per ionic step in geometry relaxation + calculations into OUT.\{istep}\_D, where \$\{istep} is the ionic step. - **Default**: False ### out_level - **Type**: String -- **Description**: Control the output level of information in OUT.{calculation}.log. +- **Description**: Control the output level of information in OUT.\{calculation}.log. - ie: electronic iteration level, which prints useful information for electronic iterations; - - i: geometry relaxation level, which prints some information for geometry relaxations additionally; + - i: geometry relaxation level, which prints some information for geometry relaxations + additionally; - m: molecular dynamics level, which does not print some information for simplicity. - **Default**: ie ### out_mat_hs - **Type**: Boolean \[Integer\](optional) + - **Availability**: *Numerical atomic orbital basis* -- **Description**: Whether to print the upper triangular part of the Hamiltonian matrices and overlap matrices for each k-point into files in the directory OUT.${suffix}. The second number controls precision. For more information, please refer to hs_matrix.md. Also controled by out_freq_ion and out_app_flag. + +- **Description**: Whether to print the upper triangular part of the Hamiltonian matrices and + overlap matrices for each k-point into files in the directory OUT.\$\{suffix}. The second number + controls precision. For more information, please refer to hs_matrix.md. Also controled by + out_freq_ion and out_app_flag. + - For gamma only case: - - nspin = 1: hks1_nao.txt for the Hamiltonian matrix and sks1_nao.txt for the overlap matrix; - - nspin = 2: hks1_nao.txt and hks2_nao.txt for the Hamiltonian matrix and sks1_nao.txt for the overlap matrix. Note that the code will not output sks2_nao.txt because it is the same as sks1_nao.txt; - - nspin = 4: hks12_nao.txt for the Hamiltonian matrix and sks12_nao.txt for the overlap matrix. + - nspin = 1: hks1_nao.txt for the Hamiltonian matrix and sks1_nao.txt for the overlap matrix; + - nspin = 2: hks1_nao.txt and hks2_nao.txt for the Hamiltonian matrix and sks1_nao.txt for the + overlap matrix. Note that the code will not output sks2_nao.txt because it is the same as + sks1_nao.txt; + - nspin = 4: hks12_nao.txt for the Hamiltonian matrix and sks12_nao.txt for the overlap matrix. - For multi-k points case: - - nspin = 1: hks1k1_nao.txt for the Hamiltonian matrix at the 1st k-point, and sks1k1_nao.txt for the overlap matrix for the 1st k-point, ...; - - nspin = 2: hks1k1_nao.txt and hks2k1_nao.txt for the two spin channels of the Hamiltonian matrix at the 1st k-point, and sks1k1_nao.txt for the overlap matrix for the 1st k-point. Note that the code will not output sks2k1_nao.txt because it is the same as sks1k1_nao.txt, ...; - - nspin = 4: hks12k1_nao.txt for the Hamiltonian matrix at the 1st k-point, and sks12k1_nao.txt for the overlap matrix for the 1st k-point, ...; + - nspin = 1: hks1k1_nao.txt for the Hamiltonian matrix at the 1st k-point, and sks1k1_nao.txt for + the overlap matrix for the 1st k-point, ...; + - nspin = 2: hks1k1_nao.txt and hks2k1_nao.txt for the two spin channels of the Hamiltonian matrix + at the 1st k-point, and sks1k1_nao.txt for the overlap matrix for the 1st k-point. Note that the + code will not output sks2k1_nao.txt because it is the same as sks1k1_nao.txt, ...; + - nspin = 4: hks12k1_nao.txt for the Hamiltonian matrix at the 1st k-point, and sks12k1_nao.txt + for the overlap matrix for the 1st k-point, ...; > Note: In the 3.10-LTS version, the file names are data-0-H and data-0-S, etc. + - **Default**: False 8 + - **Unit**: Ry ### out_mat_hs2 - **Type**: Boolean \[Integer\](optional) + - **Availability**: *Numerical atomic orbital basis (not gamma-only algorithm)* -- **Description**: Whether to print files containing the Hamiltonian matrix and overlap matrix into files in the directory OUT.${suffix}. For more information, please refer to hs_matrix.md. - > Note: In the 3.10-LTS version, the file names are data-HR-sparse_SPIN0.csr and data-SR-sparse_SPIN0.csr, etc. +- **Description**: Whether to print files containing the Hamiltonian matrix and overlap matrix into + files in the directory OUT.\$\{suffix}. For more information, please refer to hs_matrix.md. + + > Note: In the 3.10-LTS version, the file names are data-HR-sparse_SPIN0.csr and + > data-SR-sparse_SPIN0.csr, etc. + - **Default**: False [8] + - **Unit**: Ry ### out_mat_tk - **Type**: Boolean \[Integer\](optional) + - **Availability**: *Numerical atomic orbital basis* -- **Description**: Whether to print the upper triangular part of the kinetic matrices for each k-point into OUT.${suffix}/tks1ki_nao.txt, where i is the index of k points. One may optionally provide a second parameter to specify the precision. + +- **Description**: Whether to print the upper triangular part of the kinetic matrices for each + k-point into OUT.\$\{suffix}/tks1ki_nao.txt, where i is the index of k points. One may optionally + provide a second parameter to specify the precision. > Note: In the 3.10-LTS version, the file names are data-TR-sparse_SPIN0.csr, etc. + - **Default**: False [8] + - **Unit**: Ry ### out_mat_r - **Type**: Boolean \[Integer\](optional) + - **Availability**: *Numerical atomic orbital basis (not gamma-only algorithm)* -- **Description**: Whether to print the matrix representation of the position matrix into files named rxrs1_nao.csr, ryrs1_nao.csr, rzrs1_nao.csr in the directory OUT.${suffix}. If calculation is set to get_s, the position matrix can be obtained without scf iterations. For more information, please refer to position_matrix.md. + +- **Description**: Whether to print the matrix representation of the position matrix into files + named rxrs1_nao.csr, ryrs1_nao.csr, rzrs1_nao.csr in the directory OUT.\$\{suffix}. If calculation + is set to get_s, the position matrix can be obtained without scf iterations. For more information, + please refer to position_matrix.md. > Note: In the 3.10-LTS version, the file name is data-rR-sparse.csr. + - **Default**: False 8 + - **Unit**: Bohr ### out_mat_t - **Type**: Boolean \[Integer\](optional) + - **Availability**: *Numerical atomic orbital basis (not gamma-only algorithm)* -- **Description**: Generate files containing the kinetic energy matrix. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be trs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. + +- **Description**: Generate files containing the kinetic energy matrix. The format will be the same + as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files + will be trs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. > Note: In the 3.10-LTS version, the file name is data-TR-sparse_SPIN0.csr. + - **Default**: False 8 + - **Unit**: Ry ### out_mat_dh - **Type**: Integer + - **Availability**: *Numerical atomic orbital basis (not gamma-only algorithm)* -- **Description**: Whether to print files containing the derivatives of the Hamiltonian matrix. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be dhrxs1_nao.csr, dhrys1_nao.csr, dhrzs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. + +- **Description**: Whether to print files containing the derivatives of the Hamiltonian matrix. The + format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. + The name of the files will be dhrxs1_nao.csr, dhrys1_nao.csr, dhrzs1_nao.csr and so on. Also + controled by out_freq_ion and out_app_flag. > Note: In the 3.10-LTS version, the file name is data-dHRx-sparse_SPIN0.csr and so on. + - **Default**: 0 8 + - **Unit**: Ry/Bohr ### out_mat_ds - **Type**: Boolean \[Integer\](optional) + - **Availability**: *Numerical atomic orbital basis (not gamma-only algorithm)* -- **Description**: Whether to print files containing the derivatives of the overlap matrix. The format will be the same as the overlap matrix as mentioned in out_mat_dh. The name of the files will be dsxrs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. This feature can be used with calculation get_s. + +- **Description**: Whether to print files containing the derivatives of the overlap matrix. The + format will be the same as the overlap matrix as mentioned in out_mat_dh. The name of the files + will be dsxrs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. This feature + can be used with calculation get_s. > Note: In the 3.10-LTS version, the file name is data-dSRx-sparse_SPIN0.csr and so on. + - **Default**: False 8 + - **Unit**: Ry/Bohr ### out_mat_xc - **Type**: Boolean + - **Availability**: *Numerical atomic orbital (NAO) and NAO-in-PW basis* -- **Description**: Whether to print the upper triangular part of the exchange-correlation matrices in Kohn-Sham orbital representation: for each k point into files in the directory OUT.i_nao.txt, where {suffix}/vxc_out.dat. If EXX is calculated, the local and EXX part of band energy will also be printed in OUT.{suffix}/vxc_exx_out.dat, respectively. All the vxc_out.dat files contains 3 integers (nk, nspin, nband) followed by nk*nspin*nband lines of energy Hartree and eV. - > Note: In the 3.10-LTS version, the file name is k-$k-Vxc and so on. +- **Description**: Whether to print the upper triangular part of the exchange-correlation matrices + in Kohn-Sham orbital representation: for each k point into files in the directory OUT.i_nao.txt, + where \{suffix}/vxc_out.dat. If EXX is calculated, the local and EXX part of band energy will also + be printed in OUT.\{suffix}/vxc_exx_out.dat, respectively. All the vxc_out.dat files contains 3 + integers (nk, nspin, nband) followed by nk*nspin*nband lines of energy Hartree and eV. + + > Note: In the 3.10-LTS version, the file name is k-\$k-Vxc and so on. + - **Default**: False + - **Unit**: Ry ### out_mat_xc2 - **Type**: Boolean \[Integer\](optional) + - **Availability**: *Numerical atomic orbital (NAO) basis* -- **Description**: Whether to print the exchange-correlation matrices in numerical orbital representation: in CSR format in the directory OUT.${suffix}. The name of the files will be vxcrs1_nao.csr and so on. - > Note: In the 3.10-LTS version, the file name is Vxc_R_spin$s and so on. +- **Description**: Whether to print the exchange-correlation matrices in numerical orbital + representation: in CSR format in the directory OUT.\$\{suffix}. The name of the files will be + vxcrs1_nao.csr and so on. + + > Note: In the 3.10-LTS version, the file name is Vxc_R_spin\$s and so on. + - **Default**: False 8 + - **Unit**: Ry ### out_mat_l - **Type**: Boolean \[Integer\](optional) - **Availability**: *Numerical atomic orbital (NAO) basis* -- **Description**: Whether to print the expectation value of the angular momentum operator , , and in the basis of the localized atomic orbitals. The files are named OUT.{suffix}_Lx.dat, OUT.{suffix}_Ly.dat, and OUT.{suffix}_Lz.dat. The second integer controls the precision of the output. +- **Description**: Whether to print the expectation value of the angular momentum operator , , and + in the basis of the localized atomic orbitals. The files are named OUT.\{suffix}\_Lx.dat, + OUT.\{suffix}\_Ly.dat, and OUT.\{suffix}\_Lz.dat. The second integer controls the precision of the + output. - **Default**: False 8 ### out_xc_r - **Type**: Integer \[Integer\](optional) -- **Description**: The first integer controls whether to output the exchange-correlation (in Bohr^-3) on real space grids using Libxc to folder OUT.${suffix}: + +- **Description**: The first integer controls whether to output the exchange-correlation (in + Bohr^-3) on real space grids using Libxc to folder OUT.\$\{suffix}: + - 0: rho, amag, sigma, exc - 1: vrho, vsigma - 2: v2rho2, v2rhosigma, v2sigma2 - 3: v3rho3, v3rho2sigma, v3rhosigma2, v3sigma3 - - 4: v4rho4, v4rho3sigma, v4rho2sigma2, v4rhosigma3, v4sigma4 The meaning of the files is presented in Libxc + - 4: v4rho4, v4rho3sigma, v4rho2sigma2, v4rhosigma3, v4sigma4 The meaning of the files is + presented in Libxc + + The second integer controls the precision of the charge density output, if not given, will use 3 + as default. - The second integer controls the precision of the charge density output, if not given, will use 3 as default. + The circle order of the charge density on real space grids is: x is the outer loop, then y and + finally z (z is moving fastest). - The circle order of the charge density on real space grids is: x is the outer loop, then y and finally z (z is moving fastest). - **Default**: -1 3 ### out_eband_terms - **Type**: Boolean - **Availability**: *Numerical atomic orbital basis* -- **Description**: Whether to print the band energy terms separately in the file OUT.{term}_out.dat. The terms include the kinetic, pseudopotential (local + nonlocal), Hartree and exchange-correlation (including exact exchange if calculated). +- **Description**: Whether to print the band energy terms separately in the file + OUT.\{term}\_out.dat. The terms include the kinetic, pseudopotential (local + nonlocal), Hartree + and exchange-correlation (including exact exchange if calculated). - **Default**: False ### out_mul - **Type**: Boolean - **Availability**: *Numerical atomic orbital basis* -- **Description**: Whether to print the Mulliken population analysis result into OUT.${suffix}/mulliken.txt. In molecular dynamics calculations, the output frequency is controlled by out_freq_ion. +- **Description**: Whether to print the Mulliken population analysis result into + OUT.\$\{suffix}/mulliken.txt. In molecular dynamics calculations, the output frequency is + controlled by out_freq_ion. - **Default**: False ### out_app_flag - **Type**: Boolean - **Availability**: *Numerical atomic orbital basis (not gamma-only algorithm)* -- **Description**: Whether to output r(R), H(R), S(R), T(R), dH(R), dS(R), and wfc matrices in an append manner during molecular dynamics calculations. Check input parameters out_mat_r, out_mat_hs2, out_mat_t, out_mat_dh, out_mat_hs and out_wfc_lcao for more information. +- **Description**: Whether to output r(R), H(R), S(R), T(R), dH(R), dS(R), and wfc matrices in an + append manner during molecular dynamics calculations. Check input parameters out_mat_r, + out_mat_hs2, out_mat_t, out_mat_dh, out_mat_hs and out_wfc_lcao for more information. - **Default**: true ### out_ndigits - **Type**: Integer - **Availability**: *out_mat_hs 1 case presently.* -- **Description**: Controls the length of decimal part of output data, such as charge density, Hamiltonian matrix, Overlap matrix and so on. +- **Description**: Controls the length of decimal part of output data, such as charge density, + Hamiltonian matrix, Overlap matrix and so on. - **Default**: 8 ### out_element_info - **Type**: Boolean -- **Description**: Whether to print element information into files in the directory OUT.{element_label}, including pseudopotential and orbital information of the element (in atomic Ryberg units). +- **Description**: Whether to print element information into files in the directory + OUT.\{element_label}, including pseudopotential and orbital information of the element (in atomic + Ryberg units). - **Default**: False ### restart_save - **Type**: Boolean + - **Availability**: *Numerical atomic orbital basis* -- **Description**: Whether to save charge density files per ionic step, which are used to restart calculations. According to the value of read_file_dir: - - auto: These files are saved in folder OUT.{read_file_dir}/restart/. - If EXX(exact exchange) is calculated (i.e. dft_fuctional==hse/hf/pbe0/scan0 or rpa==True), the Hexx(R) files for each processor will also be saved in the above folder, which can be read in EXX calculation with restart_load==True. +- **Description**: Whether to save charge density files per ionic step, which are used to restart + calculations. According to the value of read_file_dir: + + - auto: These files are saved in folder OUT.\{read_file_dir}/restart/. + + If EXX(exact exchange) is calculated (i.e. dft_fuctional==hse/hf/pbe0/scan0 or rpa==True), the + Hexx(R) files for each processor will also be saved in the above folder, which can be read in EXX + calculation with restart_load==True. + - **Default**: False ### rpa - **Type**: Boolean + - **Description**: Generate output files used in rpa calculations. - > Note: If symmetry is set to 1, additional files containing the necessary information for exploiting symmetry in the subsequent rpa calculation will be output: irreducible_sector.txt, symrot_k.txt and symrot_R.txt. + > Note: If symmetry is set to 1, additional files containing the necessary information for + > exploiting symmetry in the subsequent rpa calculation will be output: irreducible_sector.txt, + > symrot_k.txt and symrot_R.txt. + - **Default**: False ### out_pchg - **Type**: String -- **Availability**: *For both PW and LCAO. When basis_type = lcao, used when calculation = get_pchg.* -- **Description**: Specifies the electronic states to calculate the charge densities with state index for, using a space-separated string of 0s and 1s. Each digit in the string corresponds to a state, starting from the first state. A 1 indicates that the charge density should be calculated for that state, while a 0 means the state will be ignored. The parameter allows a compact and flexible notation (similar to ocp_set), for example the syntax 1 4*0 5*1 0 is used to denote the selection of states: 1 means calculate for the first state, 4*0 skips the next four states, 5*1 means calculate for the following five states, and the final 0 skips the next state. It's essential that the total count of states does not exceed the total number of states (nbands); otherwise, it results in an error, and the process exits. The input string must contain only numbers and the asterisk (*) for repetition, ensuring correct format and intention of state selection. The outputs comprise multiple .cube files following the naming convention pchgi[state]s[spin]k[kpoint].cube. +- **Availability**: *For both PW and LCAO. When basis_type = lcao, used when calculation = + get_pchg.* +- **Description**: Specifies the electronic states to calculate the charge densities with state + index for, using a space-separated string of 0s and 1s. Each digit in the string corresponds to a + state, starting from the first state. A 1 indicates that the charge density should be calculated + for that state, while a 0 means the state will be ignored. The parameter allows a compact and + flexible notation (similar to ocp_set), for example the syntax 1 4*0 5*1 0 is used to denote the + selection of states: 1 means calculate for the first state, 4*0 skips the next four states, 5*1 + means calculate for the following five states, and the final 0 skips the next state. It's + essential that the total count of states does not exceed the total number of states (nbands); + otherwise, it results in an error, and the process exits. The input string must contain only + numbers and the asterisk (\*) for repetition, ensuring correct format and intention of state + selection. The outputs comprise multiple .cube files following the naming convention + pchgi[state]s[spin]k[kpoint].cube. - **Default**: none ### out_wfc_norm - **Type**: String - **Availability**: *For both PW and LCAO. When basis_type = lcao, used when calculation = get_wf.* -- **Description**: Specifies the electronic states to calculate the real-space wave function modulus (norm, or known as the envelope function) with state index. The syntax and state selection rules are identical to out_pchg, but the output is the norm of the wave function. The outputs comprise multiple .cube files following the naming convention wfi[state]s[spin]k[kpoint].cube. +- **Description**: Specifies the electronic states to calculate the real-space wave function modulus + (norm, or known as the envelope function) with state index. The syntax and state selection rules + are identical to out_pchg, but the output is the norm of the wave function. The outputs comprise + multiple .cube files following the naming convention wfi[state]s[spin]k[kpoint].cube. - **Default**: none ### out_wfc_re_im - **Type**: String - **Availability**: *For both PW and LCAO. When basis_type = lcao, used when calculation = get_wf.* -- **Description**: Specifies the electronic states to calculate the real and imaginary parts of the wave function with state index. The syntax and state selection rules are identical to out_pchg, but the output contains both the real and imaginary components of the wave function. The outputs comprise multiple .cube files following the naming convention wfi[state]s[spin]k[kpoint][re/im].cube. +- **Description**: Specifies the electronic states to calculate the real and imaginary parts of the + wave function with state index. The syntax and state selection rules are identical to out_pchg, + but the output contains both the real and imaginary components of the wave function. The outputs + comprise multiple .cube files following the naming convention + wfi[state]s[spin]k[kpoint][re/im].cube. - **Default**: none ### if_separate_k - **Type**: Boolean -- **Availability**: *For both PW and LCAO. When basis_type = pw, used if out_pchg is set. When basis_type = lcao, used only when calculation = get_pchg and gamma_only = 0.* -- **Description**: Specifies whether to write the partial charge densities for all k-points to individual files or merge them. Warning: Enabling symmetry may produce unwanted results due to reduced k-point weights and symmetry operations in real space. Therefore when calculating partial charge densities, if you are not sure what you want exactly, it is strongly recommended to set symmetry = -1. It is noteworthy that your symmetry setting should remain the same as that in the SCF procedure. +- **Availability**: *For both PW and LCAO. When basis_type = pw, used if out_pchg is set. When + basis_type = lcao, used only when calculation = get_pchg and gamma_only = 0.* +- **Description**: Specifies whether to write the partial charge densities for all k-points to + individual files or merge them. Warning: Enabling symmetry may produce unwanted results due to + reduced k-point weights and symmetry operations in real space. Therefore when calculating partial + charge densities, if you are not sure what you want exactly, it is strongly recommended to set + symmetry = -1. It is noteworthy that your symmetry setting should remain the same as that in the + SCF procedure. - **Default**: false ### out_elf - **Type**: Integer \[Integer\](optional) + - **Availability**: *Only for Kohn-Sham DFT and Orbital Free DFT.* -- **Description**: Whether to output the electron localization function (ELF) in the folder `OUT.${suffix}`. The files are named as + +- **Description**: Whether to output the electron localization function (ELF) in the folder + `OUT.${suffix}`. The files are named as + - nspin = 1: - - elf.cube: ${\rm{ELF}} = \frac{1}{1+\chi^2}$, $\chi = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i}|^2} - \frac{|\nabla\rho|^2}{8\rho}}{\frac{3}{10}(3\pi^2)^{2/3}\rho^{5/3}}$; + - elf.cube: ${\rm{ELF}} = \frac{1}{1+\chi^2}$, + $\chi = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i}|^2} - \frac{|\nabla\rho|^2}{8\rho}}{\frac{3}{10}(3\pi^2)^{2/3}\rho^{5/3}}$; - nspin = 2: - - elf1.cube, elf2.cube: ${\rm{ELF}}_\sigma = \frac{1}{1+\chi_\sigma^2}$, $\chi_\sigma = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i,\sigma}|^2} - \frac{|\nabla\rho_\sigma|^2}{8\rho_\sigma}}{\frac{3}{10}(6\pi^2)^{2/3}\rho_\sigma^{5/3}}$; - - elf.cube: ${\rm{ELF}} = \frac{1}{1+\chi^2}$, $\chi = \frac{\frac{1}{2}\sum_{i,\sigma}{f_i |\nabla\psi_{i,\sigma}|^2} - \sum_{\sigma}{\frac{|\nabla\rho_\sigma|^2}{8\rho_\sigma}}}{\sum_{\sigma}{\frac{3}{10}(6\pi^2)^{2/3}\rho_\sigma^{5/3}}}$; + - elf1.cube, elf2.cube: ${\rm{ELF}}_\sigma = \frac{1}{1+\chi_\sigma^2}$, + $\chi_\sigma = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i,\sigma}|^2} - \frac{|\nabla\rho_\sigma|^2}{8\rho_\sigma}}{\frac{3}{10}(6\pi^2)^{2/3}\rho_\sigma^{5/3}}$; + - elf.cube: ${\rm{ELF}} = \frac{1}{1+\chi^2}$, + $\chi = \frac{\frac{1}{2}\sum_{i,\sigma}{f_i |\nabla\psi_{i,\sigma}|^2} - \sum_{\sigma}{\frac{|\nabla\rho_\sigma|^2}{8\rho_\sigma}}}{\sum_{\sigma}{\frac{3}{10}(6\pi^2)^{2/3}\rho_\sigma^{5/3}}}$; - nspin = 4 (noncollinear): - - elf.cube: ELF for total charge density, ${\rm{ELF}} = \frac{1}{1+\chi^2}$, $\chi = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i}|^2} - \frac{|\nabla\rho|^2}{8\rho}}{\frac{3}{10}(3\pi^2)^{2/3}\rho^{5/3}}$ + - elf.cube: ELF for total charge density, ${\rm{ELF}} = \frac{1}{1+\chi^2}$, + $\chi = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i}|^2} - \frac{|\nabla\rho|^2}{8\rho}}{\frac{3}{10}(3\pi^2)^{2/3}\rho^{5/3}}$ - The second integer controls the precision of the kinetic energy density output, if not given, will use 3 as default. For purpose restarting from this file and other high-precision involved calculation, recommend to use 10. + The second integer controls the precision of the kinetic energy density output, if not given, will + use 3 as default. For purpose restarting from this file and other high-precision involved + calculation, recommend to use 10. In molecular dynamics calculations, the output frequency is controlled by out_freq_ion. + - **Default**: 0 3 ### out_spillage - **Type**: Integer - **Availability**: *Only for Kohn-Sham DFT with plane-wave basis.* -- **Description**: This output is only intentively needed by the ABACUS numerical atomic orbital generation workflow. This parameter is used to control whether to output the overlap integrals between truncated spherical Bessel functions (TSBFs) and plane-wave basis expanded wavefunctions (named as OVERLAP_Q), and between TSBFs (named as OVERLAP_Sq), also their first order derivatives. The output files are named starting with orb_matrix. A value of 2 would enable the output. +- **Description**: This output is only intentively needed by the ABACUS numerical atomic orbital + generation workflow. This parameter is used to control whether to output the overlap integrals + between truncated spherical Bessel functions (TSBFs) and plane-wave basis expanded wavefunctions + (named as OVERLAP_Q), and between TSBFs (named as OVERLAP_Sq), also their first order derivatives. + The output files are named starting with orb_matrix. A value of 2 would enable the output. - **Default**: 0 ### out_alllog - **Type**: Boolean - **Description**: Whether to print information into individual logs from all ranks in an MPI run. - - True: Information from each rank will be written into individual files named OUT.{calculation}_{suffix}/running_${calculation}.log. + - True: Information from each rank will be written into individual files named + OUT.\{calculation}_\{suffix}/running_\$\{calculation}.log. - **Default**: False [back to top](#full-list-of-input-keywords) @@ -2173,7 +2750,8 @@ ### dos_scale - **Type**: Real -- **Description**: Defines the energy range of DOS output as (emax-emin)*(1+dos_scale), centered at (emax+emin)/2. This parameter will be used when dos_emin and dos_emax are not set. +- **Description**: Defines the energy range of DOS output as (emax-emin)\*(1+dos_scale), centered at + (emax+emin)/2. This parameter will be used when dos_emin and dos_emax are not set. - **Default**: 0.01 - **Unit**: eV @@ -2196,24 +2774,32 @@ ### dos_nche - **Type**: Integer -- **Description**: The order of Chebyshev expansions when using Stochastic Density Functional Theory (SDFT) to calculate DOS. +- **Description**: The order of Chebyshev expansions when using Stochastic Density Functional Theory + (SDFT) to calculate DOS. - **Default**: 100 ### stm_bias - **Type**: Real Real(optional) Integer(optional) -- **Description**: The bias voltage used to calculate local density of states to simulate scanning tunneling microscope, see details in out_ldos. When using three parameters: + +- **Description**: The bias voltage used to calculate local density of states to simulate scanning + tunneling microscope, see details in out_ldos. When using three parameters: - The first parameter specifies the initial bias voltage value. - The second parameter defines the voltage increment (step size between consecutive bias values). - The third parameter determines the total number of voltage points + - **Default**: 1.0 + - **Unit**: V ### ldos_line -- **Type**: Real*6 Integer(optional) -- **Description**: Specify the path of the three-dimensional space and display LDOS in the form of a two-dimensional color chart, see details in out_ldos. The first three paramenters are the direct coordinates of the start point, the next three paramenters are the direct coordinates of the end point, and the final one is the number of points along the path, whose default is 100. +- **Type**: Real\*6 Integer(optional) +- **Description**: Specify the path of the three-dimensional space and display LDOS in the form of a + two-dimensional color chart, see details in out_ldos. The first three paramenters are the direct + coordinates of the start point, the next three paramenters are the direct coordinates of the end + point, and the final one is the number of points along the path, whose default is 100. - **Default**: 0.0 0.0 0.0 0.0 0.0 1.0 100 [back to top](#full-list-of-input-keywords) @@ -2223,7 +2809,9 @@ ### bessel_nao_ecut - **Type**: String -- **Description**: "Energy cutoff" (in Ry) of spherical Bessel functions. The number of spherical Bessel functions that constitute the radial parts of NAOs is determined by sqrt(bessel_nao_ecut)*bessel_nao_rcut/. +- **Description**: "Energy cutoff" (in Ry) of spherical Bessel functions. The number of spherical + Bessel functions that constitute the radial parts of NAOs is determined by + sqrt(bessel_nao_ecut)\*bessel_nao_rcut/. - **Default**: ecutwfc ### bessel_nao_tolerence @@ -2235,13 +2823,15 @@ ### bessel_nao_rcut - **Type**: Vector of Real (N values) -- **Description**: Cutoff radius (in Bohr) and the common node of spherical Bessel functions used to construct the NAOs. +- **Description**: Cutoff radius (in Bohr) and the common node of spherical Bessel functions used to + construct the NAOs. - **Default**: 6.0 ### bessel_nao_smooth - **Type**: Boolean -- **Description**: If True, NAOs will be smoothed near the cutoff radius. See bessel_nao_rcut and bessel_nao_sigma for parameters. +- **Description**: If True, NAOs will be smoothed near the cutoff radius. See bessel_nao_rcut and + bessel_nao_sigma for parameters. - **Default**: True ### bessel_nao_sigma @@ -2257,45 +2847,71 @@ ### deepks_out_labels - **Type**: Integer + - **Availability**: *Numerical atomic orbital basis* -- **Description**: Print labels and descriptors for DeePKS in OUT.${suffix}. The names of these files start with "deepks". + +- **Description**: Print labels and descriptors for DeePKS in OUT.\$\{suffix}. The names of these + files start with "deepks". + - 0 : No output. - 1 : Output intermediate files needed during DeePKS training. - - 2 : Output target labels for label preperation. The label files are named as deepks_<property>.npy or deepks_<property>.csr, where the units and formats are the same as label files <property>.npy or <property>.csr required for training, except that the first dimension (nframes) is excluded. System structrue files are also given in deepks_atom.npy and deepks_box.npy in the unit of Bohr, which means lattice_constant should be set to 1 when training. + - 2 : Output target labels for label preperation. The label files are named as + deepks\_\.npy or deepks\_\.csr, where the units and formats are the same as + label files \.npy or \.csr required for training, except that the first + dimension (nframes) is excluded. System structrue files are also given in deepks_atom.npy and + deepks_box.npy in the unit of Bohr, which means lattice_constant should be set to 1 when + training. + + > Note: When deepks_out_labels equals 1, the path of a numerical descriptor (an orb file) is + > needed to be specified under the NUMERICAL_DESCRIPTOR tag in the STRU file. This is not needed + > when deepks_out_labels equals 2. - > Note: When deepks_out_labels equals 1, the path of a numerical descriptor (an orb file) is needed to be specified under the NUMERICAL_DESCRIPTOR tag in the STRU file. This is not needed when deepks_out_labels equals 2. - **Default**: 0 ### deepks_out_freq_elec - **Type**: Integer - **Availability**: *Numerical atomic orbital basis* -- **Description**: When deepks_out_freq_elec is greater than 0, print labels and descriptors for DeePKS in OUT.${suffix}/DeePKS_Labels_Elec per deepks_out_freq_elec electronic iterations, with suffix _e* to distinguish different steps. Often used with deepks_out_labels equals 1. +- **Description**: When deepks_out_freq_elec is greater than 0, print labels and descriptors for + DeePKS in OUT.\$\{suffix}/DeePKS_Labels_Elec per deepks_out_freq_elec electronic iterations, with + suffix \_e\* to distinguish different steps. Often used with deepks_out_labels equals 1. - **Default**: 0 ### deepks_out_base - **Type**: String - **Availability**: *Numerical atomic orbital basis and deepks_out_freq_elec is greater than 0* -- **Description**: Print labels and descriptors calculated by base functional ( determined by deepks_out_base ) and target functional ( determined by dft_functional ) for DeePKS in per deepks_out_freq_elec electronic iterations. The SCF process, labels and descriptors output of the target functional are all consistent with those when the target functional is used alone. The only additional output under this configuration is the labels of the base functional. Often used with deepks_out_labels equals 1. +- **Description**: Print labels and descriptors calculated by base functional ( determined by + deepks_out_base ) and target functional ( determined by dft_functional ) for DeePKS in per + deepks_out_freq_elec electronic iterations. The SCF process, labels and descriptors output of the + target functional are all consistent with those when the target functional is used alone. The only + additional output under this configuration is the labels of the base functional. Often used with + deepks_out_labels equals 1. - **Default**: None ### deepks_scf - **Type**: Boolean + - **Availability**: *Numerical atomic orbital basis* + - **Description**: perform self-consistent field iteration in DeePKS method > Note: A trained, traced model file is needed. + - **Default**: False ### deepks_equiv - **Type**: Boolean + - **Availability**: *Numerical atomic orbital basis* + - **Description**: whether to use equivariant version of DeePKS - > Note: The equivariant version of DeePKS-kit is still under development, so this feature is currently only intended for internal usage. + > Note: The equivariant version of DeePKS-kit is still under development, so this feature is + > currently only intended for internal usage. + - **Default**: False ### deepks_model @@ -2309,7 +2925,9 @@ - **Type**: Integer - **Availability**: *gen_bessel calculation* -- **Description**: the maximum angular momentum of the Bessel functions generated as the projectors in DeePKS - NOte: To generate such projectors, set calculation type to gen_bessel in ABACUS. See also calculation. +- **Description**: the maximum angular momentum of the Bessel functions generated as the projectors + in DeePKS - NOte: To generate such projectors, set calculation type to gen_bessel in ABACUS. See + also calculation. - **Default**: 2 ### bessel_descriptor_ecut @@ -2358,35 +2976,58 @@ - 0: Don't include bandgap label - 1: Include target bandgap label (see deepks_band_range for more details) - 2: Include multiple bandgap label (see deepks_band_range for more details) - - 3: Used for systems containing H atoms. Here HOMO is defined as the max occupation except H atoms and the bandgap label is the energy between HOMO and (HOMO + 1) + - 3: Used for systems containing H atoms. Here HOMO is defined as the max occupation except H + atoms and the bandgap label is the energy between HOMO and (HOMO + 1) - **Default**: 0 ### deepks_band_range -- **Type**: Integer*2 -- **Availability**: *Numerical atomic orbital basis, deepks_scf is true, and deepks_bandgap is 1 or 2* -- **Description**: The first value should not be larger than the second one and the meaning differs in different cases below - - deepks_bandgap is 1: Bandgap label is the energy between LUMO + deepks_band_range[0] and LUMO + deepks_band_range[1]. If not set, it will calculate energy between HOMO and LUMO states. - - deepks_bandgap is 2: Bandgap labels are energies between HOMO and all states in range [LUMO + deepks_band_range[0], LUMO + deepks_band_range[1]] (Thus there are deepks_band_range[1] - deepks_band_range[0] + 1 bandgaps in total). If HOMO is included in the setting range, it will be ignored since it will always be zero and has no valuable messages (deepks_band_range[1] - deepks_band_range[0] bandgaps in this case). NOTICE: The set range can be greater than, less than, or include the value of HOMO. In the bandgap label, we always calculate the energy of the state in the set range minus the energy of HOMO state, so the bandgap can be negative if the state is lower than HOMO. +- **Type**: Integer\*2 +- **Availability**: *Numerical atomic orbital basis, deepks_scf is true, and deepks_bandgap is 1 or + 2* +- **Description**: The first value should not be larger than the second one and the meaning differs + in different cases below + - deepks_bandgap is 1: Bandgap label is the energy between LUMO + deepks_band_range[0] and LUMO + + deepks_band_range[1]. If not set, it will calculate energy between HOMO and LUMO states. + - deepks_bandgap is 2: Bandgap labels are energies between HOMO and all states in range \[LUMO + + deepks_band_range[0], LUMO + deepks_band_range[1]\] (Thus there are deepks_band_range[1] - + deepks_band_range[0] + 1 bandgaps in total). If HOMO is included in the setting range, it will + be ignored since it will always be zero and has no valuable messages (deepks_band_range[1] - + deepks_band_range[0] bandgaps in this case). NOTICE: The set range can be greater than, less + than, or include the value of HOMO. In the bandgap label, we always calculate the energy of the + state in the set range minus the energy of HOMO state, so the bandgap can be negative if the + state is lower than HOMO. - **Default**: -1 0 ### deepks_v_delta - **Type**: Integer - **Availability**: *Numerical atomic orbital basis* -- **Description**: Include V_delta/V_delta_R (Hamiltonian in k/real space) label for DeePKS training. When deepks_out_labels is true and deepks_v_delta > 0 (k space), ABACUS will output deepks_hbase.npy, deepks_vdelta.npy and deepks_htot.npy(htot=hbase+vdelta). When deepks_out_labels is true and deepks_v_delta < 0 (real space), ABACUS will output deepks_hrtot.csr, deepks_hrdelta.csr. Some more files output for different settings. NOTICE: To match the unit Normally used in DeePKS, the unit of Hamiltonian in k space is Hartree. However, currently in R space the unit is still Ry. +- **Description**: Include V_delta/V_delta_R (Hamiltonian in k/real space) label for DeePKS + training. When deepks_out_labels is true and deepks_v_delta > 0 (k space), ABACUS will output + deepks_hbase.npy, deepks_vdelta.npy and deepks_htot.npy(htot=hbase+vdelta). When deepks_out_labels + is true and deepks_v_delta < 0 (real space), ABACUS will output deepks_hrtot.csr, + deepks_hrdelta.csr. Some more files output for different settings. NOTICE: To match the unit + Normally used in DeePKS, the unit of Hamiltonian in k space is Hartree. However, currently in R + space the unit is still Ry. - deepks_v_delta = 1: deepks_vdpre.npy, which is used to calculate V_delta during DeePKS training. - - deepks_v_delta = 2: deepks_phialpha.npy and deepks_gevdm.npy, which can be used to calculate deepks_vdpre.npy. A recommanded method for memory saving. - - deepks_v_delta = -1: deepks_vdrpre.npy, which is used to calculate V_delta_R during DeePKS training. - - deepks_v_delta = -2: deepks_phialpha_r.npy and deepks_gevdm.npy, which can be used to calculate deepks_vdrpre.npy. A recommanded method for memory saving. + - deepks_v_delta = 2: deepks_phialpha.npy and deepks_gevdm.npy, which can be used to calculate + deepks_vdpre.npy. A recommanded method for memory saving. + - deepks_v_delta = -1: deepks_vdrpre.npy, which is used to calculate V_delta_R during DeePKS + training. + - deepks_v_delta = -2: deepks_phialpha_r.npy and deepks_gevdm.npy, which can be used to calculate + deepks_vdrpre.npy. A recommanded method for memory saving. - **Default**: 0 ### deepks_out_unittest - **Type**: Boolean + - **Description**: generate files for constructing DeePKS unit test - > Note: Not relevant when running actual calculations. When set to 1, ABACUS needs to be run with only 1 process. + > Note: Not relevant when running actual calculations. When set to 1, ABACUS needs to be run with + > only 1 process. + - **Default**: False [back to top](#full-list-of-input-keywords) @@ -2492,7 +3133,8 @@ - **Type**: Boolean - **Availability**: *OFDFT with of_kinetic=wt* - **Description**: Whether to fix the average density rho0. - - True: rho0 will be fixed even if the volume of system has changed, it will be set to True automatically if of_wt_rho0 is not zero. + - True: rho0 will be fixed even if the volume of system has changed, it will be set to True + automatically if of_wt_rho0 is not zero. - False: rho0 will change if volume of system has changed. - **Default**: False @@ -2507,14 +3149,16 @@ - **Type**: Real - **Availability**: *OFDFT with of_kinetic=xwm* -- **Description**: Reference charge density for XWM kinetic energy functional. If set to 0, the program will use average charge density. +- **Description**: Reference charge density for XWM kinetic energy functional. If set to 0, the + program will use average charge density. - **Default**: 0.0 ### of_xwm_kappa - **Type**: Real - **Availability**: *OFDFT with of_kinetic=xwm* -- **Description**: Parameter for XWM kinetic energy functional. See PHYSICAL REVIEW B 100, 205132 (2019) for optimal values. +- **Description**: Parameter for XWM kinetic energy functional. See PHYSICAL REVIEW B 100, 205132 + (2019) for optimal values. - **Default**: 0.0 ### of_read_kernel @@ -2522,7 +3166,8 @@ - **Type**: Boolean - **Availability**: *OFDFT with of_kinetic=wt* - **Description**: Whether to read in the kernel file. - - True: The kernel of WT KEDF (kinetic energy density functional) will be filled from the file specified by of_kernel_file. + - True: The kernel of WT KEDF (kinetic energy density functional) will be filled from the file + specified by of_kernel_file. - False: The kernel of WT KEDF (kinetic energy density functional) will be filled from formula. - **Default**: False @@ -2538,20 +3183,27 @@ - **Type**: Boolean - **Availability**: *OFDFT* - **Description**: Whether to use full planewaves. - - True: Ecut will be ignored while collecting planewaves, so that all planewaves will be used in FFT. + - True: Ecut will be ignored while collecting planewaves, so that all planewaves will be used in + FFT. - False: Only use the planewaves inside ecut, the same as KSDFT. - **Default**: True ### of_full_pw_dim - **Type**: Integer + - **Availability**: *OFDFT with of_full_pw = True* + - **Description**: Specify the parity of FFT dimensions. + - 0: either odd or even. - 1: odd only. - 2: even only. - Note: Even dimensions may cause slight errors in FFT. It should be ignorable in ofdft calculation, but it may make Cardinal B-spline interpolation unstable, so please set of_full_pw_dim = 1 if nbspline != -1. + Note: Even dimensions may cause slight errors in FFT. It should be ignorable in ofdft calculation, + but it may make Cardinal B-spline interpolation unstable, so please set of_full_pw_dim = 1 if + nbspline != -1. + - **Default**: 0 [back to top](#full-list-of-input-keywords) @@ -2562,7 +3214,8 @@ - **Type**: Boolean - **Availability**: *Used only for KSDFT with plane wave basis* -- **Description**: Controls the generation of machine learning training data. When enabled, training data in .npy format will be saved in the directory OUT.${suffix}/. +- **Description**: Controls the generation of machine learning training data. When enabled, training + data in .npy format will be saved in the directory OUT.\$\{suffix}/. - **Default**: False ### of_ml_device @@ -2595,7 +3248,8 @@ - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the type of the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the + type of the i-th kernel function. - 1: Wang-Teter kernel function. - 2: Modified Yukawa function, and alpha is specified by of_ml_yukawa_alpha. - 3: Truncated kinetic kernel (TKK), the file containing TKK is specified by of_ml_kernel_file. @@ -2605,21 +3259,24 @@ - **Type**: Vector of Real - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the RECIPROCAL of scaling parameter of the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the + RECIPROCAL of scaling parameter of the i-th kernel function. - **Default**: 1.0 ### of_ml_yukawa_alpha - **Type**: Vector of Real - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the parameter alpha of i-th kernel function. ONLY used for Yukawa kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the + parameter alpha of i-th kernel function. ONLY used for Yukawa kernel function. - **Default**: 1.0 ### of_ml_kernel_file - **Type**: Vector of String - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the file containing the i-th kernel function. ONLY used for TKK. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the + file containing the i-th kernel function. ONLY used for TKK. - **Default**: none ### of_ml_gamma @@ -2675,91 +3332,104 @@ - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the non-local descriptor gammanl defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the + non-local descriptor gammanl defined by the i-th kernel function. - **Default**: 0 ### of_ml_pnl - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the non-local descriptor pnl defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the + non-local descriptor pnl defined by the i-th kernel function. - **Default**: 0 ### of_ml_qnl - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the non-local descriptor qnl defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the + non-local descriptor qnl defined by the i-th kernel function. - **Default**: 0 ### of_ml_xi - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the non-local descriptor xi defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the + non-local descriptor xi defined by the i-th kernel function. - **Default**: 0 ### of_ml_tanhxi - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the non-local descriptor tanhxi defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the + non-local descriptor tanhxi defined by the i-th kernel function. - **Default**: 0 ### of_ml_tanhxi_nl - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the non-local descriptor tanhxi_nl defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the + non-local descriptor tanhxi_nl defined by the i-th kernel function. - **Default**: 0 ### of_ml_tanh_pnl - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the non-local descriptor tanh_pnl defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the + non-local descriptor tanh_pnl defined by the i-th kernel function. - **Default**: 0 ### of_ml_tanh_qnl - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the non-local descriptor tanh_qnl defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the + non-local descriptor tanh_qnl defined by the i-th kernel function. - **Default**: 0 ### of_ml_tanhp_nl - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the non-local descriptor tanhp_nl defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the + non-local descriptor tanhp_nl defined by the i-th kernel function. - **Default**: 0 ### of_ml_tanhq_nl - **Type**: Vector of Integer - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the non-local descriptor tanhq_nl defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element controls the + non-local descriptor tanhq_nl defined by the i-th kernel function. - **Default**: 0 ### of_ml_chi_xi - **Type**: Vector of Real - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the hyperparameter chi_xi of non-local descriptor tanhxi defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the + hyperparameter chi_xi of non-local descriptor tanhxi defined by the i-th kernel function. - **Default**: 1.0 ### of_ml_chi_pnl - **Type**: Vector of Real - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the hyperparameter chi_pnl of non-local descriptor tanh_pnl defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the + hyperparameter chi_pnl of non-local descriptor tanh_pnl defined by the i-th kernel function. - **Default**: 1.0 ### of_ml_chi_qnl - **Type**: Vector of Real - **Availability**: *OFDFT* -- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the hyperparameter chi_qnl of non-local descriptor tanh_qnl defined by the i-th kernel function. +- **Description**: Containing nkernel (see of_ml_nkernel) elements. The i-th element specifies the + hyperparameter chi_qnl of non-local descriptor tanh_qnl defined by the i-th kernel function. - **Default**: 1.0 ### of_ml_local_test @@ -2783,7 +3453,8 @@ - **Type**: Boolean - **Availability**: *TDOFDFT* -- **Description**: Added the current dependent(CD) potential. (https://doi.org/10.1103/PhysRevB.98.144302) +- **Description**: Added the current dependent(CD) potential. + (https://doi.org/10.1103/PhysRevB.98.144302) - True: Added the CD potential. - False: Not added the CD potential. - **Default**: False @@ -2792,7 +3463,8 @@ - **Type**: Real - **Availability**: *TDOFDFT* -- **Description**: The value of the parameter alpha in modified CD potential method. mCDPotential=alpha*CDPotential (proposed in paper PhysRevB.98.144302) +- **Description**: The value of the parameter alpha in modified CD potential method. + mCDPotential=alpha\*CDPotential (proposed in paper PhysRevB.98.144302) - **Default**: 1.0 [back to top](#full-list-of-input-keywords) @@ -2810,19 +3482,27 @@ ### dip_cor_flag - **Type**: Boolean + - **Availability**: *With dip_cor_flag = True and efield_flag = True.* + - **Description**: Added a dipole correction to the bare ionic potential. + - True: A dipole correction is also added to the bare ionic potential. - False: A dipole correction is not added to the bare ionic potential. - > Note: If you do not want any electric field, the parameter efield_amp should be set to zero. This should ONLY be used in a slab geometry for surface calculations, with the discontinuity FALLING IN THE EMPTY SPACE. + > Note: If you do not want any electric field, the parameter efield_amp should be set to zero. + > This should ONLY be used in a slab geometry for surface calculations, with the discontinuity + > FALLING IN THE EMPTY SPACE. + - **Default**: False ### efield_dir - **Type**: Integer - **Availability**: *with efield_flag = True.* -- **Description**: The direction of the electric field or dipole correction is parallel to the reciprocal lattice vector, so the potential is constant in planes defined by FFT grid points, efield_dir can set to 0, 1 or 2. +- **Description**: The direction of the electric field or dipole correction is parallel to the + reciprocal lattice vector, so the potential is constant in planes defined by FFT grid points, + efield_dir can set to 0, 1 or 2. - 0: parallel to the first reciprocal lattice vector - 1: parallel to the second reciprocal lattice vector - 2: parallel to the third reciprocal lattice vector @@ -2832,25 +3512,34 @@ - **Type**: Real - **Availability**: *with efield_flag = True.* -- **Description**: Position of the maximum of the saw-like potential along crystal axis efield_dir, within the unit cell, 0 <= efield_pos_max < 1. +- **Description**: Position of the maximum of the saw-like potential along crystal axis efield_dir, + within the unit cell, 0 \<= efield_pos_max < 1. - **Default**: Autoset to center of vacuum - width of vacuum / 20 ### efield_pos_dec - **Type**: Real - **Availability**: *with efield_flag = True.* -- **Description**: Zone in the unit cell where the saw-like potential decreases, 0 < efield_pos_dec < 1. +- **Description**: Zone in the unit cell where the saw-like potential decreases, 0 < efield_pos_dec + < 1. - **Default**: Autoset to width of vacuum / 10 ### efield_amp - **Type**: Real + - **Availability**: *with efield_flag = True.* -- **Description**: Amplitude of the electric field. The saw-like potential increases with slope efield_amp in the region from efield_pos_max+efield_pos_dec-1) to (efield_pos_max), then decreases until (efield_pos_max+efield_pos_dec), in units of the crystal vector efield_dir. - > Note: The change of slope of this potential must be located in the empty region, or else unphysical forces will result. +- **Description**: Amplitude of the electric field. The saw-like potential increases with slope + efield_amp in the region from efield_pos_max+efield_pos_dec-1) to (efield_pos_max), then decreases + until (efield_pos_max+efield_pos_dec), in units of the crystal vector efield_dir. + + > Note: The change of slope of this potential must be located in the empty region, or else + > unphysical forces will result. + - **Default**: 0.0 -- **Unit**: a.u., 1 a.u. = 51.4220632*10^10 V/m. + +- **Unit**: a.u., 1 a.u. = 51.4220632\*10^10 V/m. [back to top](#full-list-of-input-keywords) @@ -2859,8 +3548,10 @@ ### gate_flag - **Type**: Boolean -- **Description**: Controls the addition of compensating charge by a charged plate for charged cells. - - true: A charged plate is placed at the zgate position to add compensating charge. The direction is determined by efield_dir. +- **Description**: Controls the addition of compensating charge by a charged plate for charged + cells. + - true: A charged plate is placed at the zgate position to add compensating charge. The direction + is determined by efield_dir. - false: No compensating charge is added. - **Default**: false @@ -2875,7 +3566,9 @@ - **Type**: Boolean - **Description**: Controls the addition of a potential barrier to prevent electron spillover. - - true: A potential barrier is added from block_down to block_up with a height of block_height. If dip_cor_flag is set to true, efield_pos_dec is used to smoothly increase and decrease the potential barrier. + - true: A potential barrier is added from block_down to block_up with a height of block_height. If + dip_cor_flag is set to true, efield_pos_dec is used to smoothly increase and decrease the + potential barrier. - false: No potential barrier is added. - **Default**: false @@ -2907,34 +3600,42 @@ ### exx_fock_alpha - **Type**: Real -- **Description**: Fraction of full-ranged Fock exchange $1/r$ in range-separated hybrid functionals. +- **Description**: Fraction of full-ranged Fock exchange $1/r$ in range-separated hybrid + functionals. - **Default**: see hybrid_func_params ### exx_erfc_alpha - **Type**: Real -- **Description**: Fraction of short-ranged Fock exchange $\mathrm{erfc}(\omega r)/r$ in range-separated hybrid functionals. +- **Description**: Fraction of short-ranged Fock exchange $\mathrm{erfc}(\omega r)/r$ in + range-separated hybrid functionals. - **Default**: see hybrid_func_params ### exx_erfc_omega - **Type**: Real -- **Description**: Range-separation parameter $\omega$ in the short-ranged Fock term $\mathrm{erfc}(\omega r)/r$. +- **Description**: Range-separation parameter $\omega$ in the short-ranged Fock term + $\mathrm{erfc}(\omega r)/r$. - **Default**: see hybrid_func_params ### exx_separate_loop - **Type**: Boolean -- **Description**: There are two types of iterative approaches provided by ABACUS to evaluate Fock exchange. - - False: Start with a GGA-Loop, and then Hybrid-Loop, in which EXX Hamiltonian is updated with electronic iterations. - - True: A two-step method is employed, i.e. in the inner iterations, density matrix is updated, while in the outer iterations, is calculated based on density matrix that converges in the inner iteration. +- **Description**: There are two types of iterative approaches provided by ABACUS to evaluate Fock + exchange. + - False: Start with a GGA-Loop, and then Hybrid-Loop, in which EXX Hamiltonian is updated with + electronic iterations. + - True: A two-step method is employed, i.e. in the inner iterations, density matrix is updated, + while in the outer iterations, is calculated based on density matrix that converges in the inner + iteration. - **Default**: True ### exx_hybrid_step - **Type**: Integer - **Availability**: *exx_separate_loop==1* -- **Description**: The maximal iteration number of the outer-loop, where the Fock exchange is calculated +- **Description**: The maximal iteration number of the outer-loop, where the Fock exchange is + calculated - **Default**: 100 ### exx_mixing_beta @@ -2952,7 +3653,8 @@ - **Type**: Real - **Availability**: *basis_type==lcao_in_pw* -- **Description**: It is used to compensate for divergence points at G=0 in the evaluation of Fock exchange using lcao_in_pw method. +- **Description**: It is used to compensate for divergence points at G=0 in the evaluation of Fock + exchange using lcao_in_pw method. - **Default**: 0.3 [back to top](#full-list-of-input-keywords) @@ -2962,19 +3664,31 @@ ### exx_pca_threshold - **Type**: Real -- **Description**: To accelerate the evaluation of four-center integrals (), the product of atomic orbitals are expanded in the basis of auxiliary basis functions (ABF): . The size of the ABF (i.e. number of ) is reduced using principal component analysis. When a large PCA threshold is used, the number of ABF will be reduced, hence the calculation becomes faster. However, this comes at the cost of computational accuracy. A relatively safe choice of the value is 1e-4. +- **Description**: To accelerate the evaluation of four-center integrals (), the product of atomic + orbitals are expanded in the basis of auxiliary basis functions (ABF): . The size of the ABF (i.e. + number of ) is reduced using principal component analysis. When a large PCA threshold is used, the + number of ABF will be reduced, hence the calculation becomes faster. However, this comes at the + cost of computational accuracy. A relatively safe choice of the value is 1e-4. - **Default**: 1E-4 ### exx_c_threshold - **Type**: Real -- **Description**: See also the entry exx_pca_threshold. Smaller components (less than exx_c_threshold) of the matrix are neglected to accelerate calculation. The larger the threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice of the value is 1e-4. +- **Description**: See also the entry exx_pca_threshold. Smaller components (less than + exx_c_threshold) of the matrix are neglected to accelerate calculation. The larger the threshold + is, the faster the calculation and the lower the accuracy. A relatively safe choice of the value + is 1e-4. - **Default**: 1E-4 ### exx_cs_inv_thr - **Type**: Real -- **Description**: By default, the Coulomb matrix inversion required for obtaining LRI coefficients is performed using LU decomposition. However, this approach may suffer from numerical instabilities when a large set of auxiliary basis functions (ABFs) is employed. When exx_cs_inv_thr > 0, the inversion is instead carried out via matrix diagonalization. Eigenvalues smaller than exx_cs_inv_thr are discarded to improve numerical stability. A relatively safe and commonly recommended value is 1e-5. +- **Description**: By default, the Coulomb matrix inversion required for obtaining LRI coefficients + is performed using LU decomposition. However, this approach may suffer from numerical + instabilities when a large set of auxiliary basis functions (ABFs) is employed. When + exx_cs_inv_thr > 0, the inversion is instead carried out via matrix diagonalization. Eigenvalues + smaller than exx_cs_inv_thr are discarded to improve numerical stability. A relatively safe and + commonly recommended value is 1e-5. - **Default**: -1 ### shrink_abfs_pca_thr @@ -2986,62 +3700,89 @@ ### shrink_lu_inv_thr - **Type**: Real -- **Description**: Threshold for obtaining the inverse of the overlap matrix by LU decomposition in the auxiliary-basis representation. +- **Description**: Threshold for obtaining the inverse of the overlap matrix by LU decomposition in + the auxiliary-basis representation. - **Default**: 1e-6 ### exx_v_threshold - **Type**: Real -- **Description**: See also the entry exx_pca_threshold. With the approximation , the four-center integral in Fock exchange is expressed as , where is a double-center integral. Smaller values of the V matrix can be truncated to accelerate calculation. The larger the threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice of the value is 0, i.e. no truncation. +- **Description**: See also the entry exx_pca_threshold. With the approximation , the four-center + integral in Fock exchange is expressed as , where is a double-center integral. Smaller values of + the V matrix can be truncated to accelerate calculation. The larger the threshold is, the faster + the calculation and the lower the accuracy. A relatively safe choice of the value is 0, i.e. no + truncation. - **Default**: 1E-1 ### exx_dm_threshold - **Type**: Real -- **Description**: The Fock exchange can be expressed as where D is the density matrix. Smaller values of the density matrix can be truncated to accelerate calculation. The larger the threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice of the value is 1e-4. +- **Description**: The Fock exchange can be expressed as where D is the density matrix. Smaller + values of the density matrix can be truncated to accelerate calculation. The larger the threshold + is, the faster the calculation and the lower the accuracy. A relatively safe choice of the value + is 1e-4. - **Default**: 1E-4 ### exx_c_grad_threshold - **Type**: Real -- **Description**: See also the entry exx_pca_threshold. is used in force. Smaller components (less than exx_c_grad_threshold) of the matrix are neglected to accelerate calculation. The larger the threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice of the value is 1e-4. +- **Description**: See also the entry exx_pca_threshold. is used in force. Smaller components (less + than exx_c_grad_threshold) of the matrix are neglected to accelerate calculation. The larger the + threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice of + the value is 1e-4. - **Default**: 1E-4 ### exx_v_grad_threshold - **Type**: Real -- **Description**: See also the entry exx_pca_threshold. With the approximation , the four-center integral in Fock exchange is expressed as , where is a double-center integral. is used in force. Smaller values of the V matrix can be truncated to accelerate calculation. The larger the threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice of the value is 0, i.e. no truncation. +- **Description**: See also the entry exx_pca_threshold. With the approximation , the four-center + integral in Fock exchange is expressed as , where is a double-center integral. is used in force. + Smaller values of the V matrix can be truncated to accelerate calculation. The larger the + threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice of + the value is 0, i.e. no truncation. - **Default**: 1E-1 ### exx_c_grad_r_threshold - **Type**: Real -- **Description**: See also the entry exx_pca_threshold. is used in stress. Smaller components (less than exx_c_grad_r_threshold) of the matrix are neglected to accelerate calculation. The larger the threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice of the value is 1e-4. +- **Description**: See also the entry exx_pca_threshold. is used in stress. Smaller components (less + than exx_c_grad_r_threshold) of the matrix are neglected to accelerate calculation. The larger the + threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice of + the value is 1e-4. - **Default**: 1E-4 ### exx_v_grad_r_threshold - **Type**: Real -- **Description**: See also the entry exx_pca_threshold. With the approximation , the four-center integral in Fock exchange is expressed as , where is a double-center integral. is used in force and stress. Smaller values of the V matrix can be truncated to accelerate calculation. The larger the threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice of the value is 0, i.e. no truncation. +- **Description**: See also the entry exx_pca_threshold. With the approximation , the four-center + integral in Fock exchange is expressed as , where is a double-center integral. is used in force + and stress. Smaller values of the V matrix can be truncated to accelerate calculation. The larger + the threshold is, the faster the calculation and the lower the accuracy. A relatively safe choice + of the value is 0, i.e. no truncation. - **Default**: 1E-1 ### exx_ccp_rmesh_times - **Type**: String -- **Description**: This parameter determines how many times larger the radial mesh required for calculating Columb potential is to that of atomic orbitals. The value should be larger than 0. Reducing this value can effectively increase the speed of self-consistent calculations using hybrid functionals. +- **Description**: This parameter determines how many times larger the radial mesh required for + calculating Columb potential is to that of atomic orbitals. The value should be larger than 0. + Reducing this value can effectively increase the speed of self-consistent calculations using + hybrid functionals. ### exx_opt_orb_lmax - **Type**: Integer - **Availability**: *calculation==gen_opt_abfs* -- **Description**: The maximum l of the spherical Bessel functions, when the radial part of opt-ABFs are generated as linear combinations of spherical Bessel functions. A reasonable choice is 2. +- **Description**: The maximum l of the spherical Bessel functions, when the radial part of opt-ABFs + are generated as linear combinations of spherical Bessel functions. A reasonable choice is 2. - **Default**: 0 ### exx_opt_orb_ecut - **Type**: Real - **Availability**: *calculation==gen_opt_abfs* -- **Description**: The cut-off of plane wave expansion, when the plane wave basis is used to optimize the radial ABFs. A reasonable choice is 60. +- **Description**: The cut-off of plane wave expansion, when the plane wave basis is used to + optimize the radial ABFs. A reasonable choice is 60. - **Default**: 0 - **Unit**: Ry @@ -3049,41 +3790,48 @@ - **Type**: Real - **Availability**: *calculation==gen_opt_abfs* -- **Description**: The threshold when solving for the zeros of spherical Bessel functions. A reasonable choice is 1e-12. +- **Description**: The threshold when solving for the zeros of spherical Bessel functions. A + reasonable choice is 1e-12. - **Default**: 1E-12 ### exx_real_number - **Type**: String - **Description**: - True: Enforce LibRI to use double data type. - - False: Enforce LibRI to use complex data type. Setting it to True can effectively improve the speed of self-consistent calculations with hybrid functionals. + - False: Enforce LibRI to use complex data type. Setting it to True can effectively improve the + speed of self-consistent calculations with hybrid functionals. - **Default**: depends on the gamma_only option ### exx_singularity_correction - **Type**: String - **Description**: - spencer: see Phys. Rev. B 77, 193110 (2008). - - revised_spencer: see Phys. Rev. Mater. 5, 013807 (2021). Set the scheme of Coulomb singularity correction. + - revised_spencer: see Phys. Rev. Mater. 5, 013807 (2021). Set the scheme of Coulomb singularity + correction. - **Default**: default ### rpa_ccp_rmesh_times - **Type**: Real -- **Description**: How many times larger the radial mesh required is to that of atomic orbitals in the postprocess calculation of the bare Coulomb matrix for RPA, GW, etc. +- **Description**: How many times larger the radial mesh required is to that of atomic orbitals in + the postprocess calculation of the bare Coulomb matrix for RPA, GW, etc. - **Default**: 10 ### exx_symmetry_realspace - **Type**: Boolean -- **Availability**: *symmetry==1 and exx calculation (dft_fuctional==hse/hf/pbe0/scan0 or rpa==True)* -- **Description**: - False: only rotate k-space density matrix D(k) from irreducible k-points to accelerate diagonalization +- **Availability**: *symmetry==1 and exx calculation (dft_fuctional==hse/hf/pbe0/scan0 or + rpa==True)* +- **Description**: - False: only rotate k-space density matrix D(k) from irreducible k-points to + accelerate diagonalization - True: rotate both D(k) and Hexx(R) to accelerate both diagonalization and EXX calculation - **Default**: True ### out_ri_cv - **Type**: Boolean -- **Description**: Whether to output the coefficient tensor C(R) and ABFs-representation Coulomb matrix V(R) for each atom pair and cell in real space. +- **Description**: Whether to output the coefficient tensor C(R) and ABFs-representation Coulomb + matrix V(R) for each atom pair and cell in real space. - **Default**: false ### out_unshrinked_v @@ -3118,7 +3866,8 @@ - **Type**: Boolean - **Availability**: *exx_separate_loop==True.* -- **Description**: Whether to use the ACE method (https://doi.org/10.1021/acs.jctc.6b00092) to accelerate the calculation the Fock exchange matrix. Should be set to true most of the time. +- **Description**: Whether to use the ACE method (https://doi.org/10.1021/acs.jctc.6b00092) to + accelerate the calculation the Fock exchange matrix. Should be set to true most of the time. - True: Use the ACE method to calculate the Fock exchange operator. - False: Use the traditional method to calculate the Fock exchange operator. - **Default**: True @@ -3126,29 +3875,36 @@ ### exx_gamma_extrapolation - **Type**: Boolean -- **Description**: Whether to use the gamma point extrapolation method to calculate the Fock exchange operator. See https://doi.org/10.1103/PhysRevB.79.205114 for details. Should be set to true most of the time. +- **Description**: Whether to use the gamma point extrapolation method to calculate the Fock + exchange operator. See https://doi.org/10.1103/PhysRevB.79.205114 for details. Should be set to + true most of the time. - **Default**: True ### ecutexx - **Type**: Real -- **Description**: The energy cutoff for EXX (Fock) exchange operator in plane wave basis calculations. Reducing ecutexx below ecutrho may significantly accelerate EXX computations. This speed improvement comes with a reduced numerical accuracy in the exchange energy calculation. +- **Description**: The energy cutoff for EXX (Fock) exchange operator in plane wave basis + calculations. Reducing ecutexx below ecutrho may significantly accelerate EXX computations. This + speed improvement comes with a reduced numerical accuracy in the exchange energy calculation. - **Default**: same as ecutrho - **Unit**: Ry ### exx_thr_type - **Type**: String -- **Description**: The type of threshold used to judge whether the outer loop has converged in the separate loop EXX calculation. +- **Description**: The type of threshold used to judge whether the outer loop has converged in the + separate loop EXX calculation. - energy: use the change of exact exchange energy to judge convergence. - - density: if the change of charge density difference between two successive outer loop iterations is seen as converged according to scf_thr, then the outer loop is seen as converged. + - density: if the change of charge density difference between two successive outer loop iterations + is seen as converged according to scf_thr, then the outer loop is seen as converged. - **Default**: density ### exx_ene_thr - **Type**: Real - **Availability**: *exx_thr_type==energy* -- **Description**: The threshold for the change of exact exchange energy to judge convergence of the outer loop in the separate loop EXX calculation. +- **Description**: The threshold for the change of exact exchange energy to judge convergence of the + outer loop in the separate loop EXX calculation. - **Default**: 1e-5 - **Unit**: Ry @@ -3159,7 +3915,9 @@ ### md_type - **Type**: String -- **Description**: Control the algorithm to integrate the equation of motion for molecular dynamics (MD), see md.md in detail. + +- **Description**: Control the algorithm to integrate the equation of motion for molecular dynamics + (MD), see md.md in detail. - fire: a MD-based relaxation algorithm, named fast inertial relaxation engine. - nve: NVE ensemble with velocity Verlet algorithm. @@ -3167,6 +3925,7 @@ - npt: Nose-Hoover style NPT ensemble, see md_pmode in detail. - langevin: NVT ensemble with Langevin thermostat, see md_damp in detail. - msst: MSST method, see msst_direction, msst_vel, msst_qmass, msst_vis, msst_tscale in detail. + - **Default**: nvt ### md_nstep @@ -3185,6 +3944,7 @@ ### md_thermostat - **Type**: String + - **Description**: Specify the temperature control method used in NVT ensemble. - nhc: Nose-Hoover chain, see md_tfreq and md_tchain in detail. @@ -3192,120 +3952,160 @@ - berendsen: Berendsen thermostat, see md_nraise in detail. - rescaling: velocity Rescaling method 1, see md_tolerance in detail. - rescale_v: velocity Rescaling method 2, see md_nraise in detail. + - **Default**: nhc ### md_tfirst - **Type**: Real + - **Description**: The temperature used in molecular dynamics calculations. - If md_tfirst is unset or less than zero, init_vel is autoset to be true. If init_vel is true, the initial temperature will be determined by the velocities read from STRU. In this case, if velocities are unspecified in STRU, the initial temperature is set to zero. + If md_tfirst is unset or less than zero, init_vel is autoset to be true. If init_vel is true, the + initial temperature will be determined by the velocities read from STRU. In this case, if + velocities are unspecified in STRU, the initial temperature is set to zero. + + If md_tfirst is set to a positive value and init_vel is true simultaneously, please make sure they + are consistent, otherwise abacus will exit immediately. - If md_tfirst is set to a positive value and init_vel is true simultaneously, please make sure they are consistent, otherwise abacus will exit immediately. + Note that md_tlast is only used in NVT/NPT simulations. If md_tlast is unset or less than zero, + md_tlast is set to md_tfirst. If md_tlast is set to be different from md_tfirst, ABACUS will + automatically change the temperature from md_tfirst to md_tlast. - Note that md_tlast is only used in NVT/NPT simulations. If md_tlast is unset or less than zero, md_tlast is set to md_tfirst. If md_tlast is set to be different from md_tfirst, ABACUS will automatically change the temperature from md_tfirst to md_tlast. - **Default**: No default + - **Unit**: K ### md_tlast - **Type**: Real + - **Description**: The temperature used in molecular dynamics calculations. - If md_tfirst is unset or less than zero, init_vel is autoset to be true. If init_vel is true, the initial temperature will be determined by the velocities read from STRU. In this case, if velocities are unspecified in STRU, the initial temperature is set to zero. + If md_tfirst is unset or less than zero, init_vel is autoset to be true. If init_vel is true, the + initial temperature will be determined by the velocities read from STRU. In this case, if + velocities are unspecified in STRU, the initial temperature is set to zero. - If md_tfirst is set to a positive value and init_vel is true simultaneously, please make sure they are consistent, otherwise abacus will exit immediately. + If md_tfirst is set to a positive value and init_vel is true simultaneously, please make sure they + are consistent, otherwise abacus will exit immediately. + + Note that md_tlast is only used in NVT/NPT simulations. If md_tlast is unset or less than zero, + md_tlast is set to md_tfirst. If md_tlast is set to be different from md_tfirst, ABACUS will + automatically change the temperature from md_tfirst to md_tlast. - Note that md_tlast is only used in NVT/NPT simulations. If md_tlast is unset or less than zero, md_tlast is set to md_tfirst. If md_tlast is set to be different from md_tfirst, ABACUS will automatically change the temperature from md_tfirst to md_tlast. - **Default**: No default + - **Unit**: K ### md_prec_level - **Type**: Integer - **Description**: Determine the precision level of variable-cell molecular dynamics calculations. - - 0: FFT grids do not change, only G vectors and K vectors are changed due to the change of lattice vector. This level is suitable for cases where the variation of the volume and shape is not large, and the efficiency is relatively higher. - - 2: FFT grids change per step. This level is suitable for cases where the variation of the volume and shape is large, such as the MSST method. However, accuracy comes at the cost of efficiency. + - 0: FFT grids do not change, only G vectors and K vectors are changed due to the change of + lattice vector. This level is suitable for cases where the variation of the volume and shape is + not large, and the efficiency is relatively higher. + - 2: FFT grids change per step. This level is suitable for cases where the variation of the volume + and shape is large, such as the MSST method. However, accuracy comes at the cost of efficiency. - **Default**: 0 ### md_restart - **Type**: Boolean -- **Description**: Control whether to restart molecular dynamics calculations and time-dependent density functional theory calculations. - - True: ABACUS will read in {md_step}, then read in the corresponding STRU_MD_suffix/STRU/ automatically. For tddft, ABACUS will also read in WFC_NAO_K${kpoint} of the last step (You need to set out_wfc_lcao=1 and out_app_flag=0 to obtain this file). +- **Description**: Control whether to restart molecular dynamics calculations and time-dependent + density functional theory calculations. + - True: ABACUS will read in \{md_step}, then read in the corresponding STRU_MD_suffix/STRU/ + automatically. For tddft, ABACUS will also read in WFC_NAO_K\$\{kpoint} of the last step (You + need to set out_wfc_lcao=1 and out_app_flag=0 to obtain this file). - False: ABACUS will start molecular dynamics calculations normally from the first step. - **Default**: False ### md_restartfreq - **Type**: Integer -- **Description**: The output frequency of OUT.{suffix}/STRIU/, which are used to restart molecular dynamics calculations, see md_restart in detail. +- **Description**: The output frequency of OUT.\{suffix}/STRIU/, which are used to restart molecular + dynamics calculations, see md_restart in detail. - **Default**: 5 ### md_dumpfreq - **Type**: Integer -- **Description**: The output frequency of OUT.${suffix}/MD_dump in molecular dynamics calculations, which including the information of lattices and atoms. +- **Description**: The output frequency of OUT.\$\{suffix}/MD_dump in molecular dynamics + calculations, which including the information of lattices and atoms. - **Default**: 1 ### dump_force - **Type**: Boolean -- **Description**: Whether to output atomic forces into the file OUT.${suffix}/MD_dump. +- **Description**: Whether to output atomic forces into the file OUT.\$\{suffix}/MD_dump. - **Default**: True ### dump_vel - **Type**: Boolean -- **Description**: Whether to output atomic velocities into the file OUT.${suffix}/MD_dump. +- **Description**: Whether to output atomic velocities into the file OUT.\$\{suffix}/MD_dump. - **Default**: True ### dump_virial - **Type**: Boolean -- **Description**: Whether to output lattice virials into the file OUT.${suffix}/MD_dump. +- **Description**: Whether to output lattice virials into the file OUT.\$\{suffix}/MD_dump. - **Default**: True ### md_seed - **Type**: Integer -- **Description**: The random seed to initialize random numbers used in molecular dynamics calculations. - - < 0: No srand() function is called. - - >= 0: The function srand(md_seed) is called. +- **Description**: The random seed to initialize random numbers used in molecular dynamics + calculations. + - < 0: No srand() function is called. + - \>= 0: The function srand(md_seed) is called. - **Default**: -1 ### md_tfreq - **Type**: Real -- **Description**: Control the frequency of temperature oscillations during the simulation. If it is too large, the temperature will fluctuate violently; if it is too small, the temperature will take a very long time to equilibrate with the atomic system. - Note: It is a system-dependent empirical parameter, ranging from 1/(40*md_dt) to 1/(100*md_dt). An improper choice might lead to the failure of jobs. +- **Description**: Control the frequency of temperature oscillations during the simulation. If it is + too large, the temperature will fluctuate violently; if it is too small, the temperature will take + a very long time to equilibrate with the atomic system. + + Note: It is a system-dependent empirical parameter, ranging from 1/(40*md_dt) to 1/(100*md_dt). An + improper choice might lead to the failure of jobs. + - **Default**: 1/40/md_dt ### md_tchain - **Type**: Integer -- **Description**: Number of thermostats coupled with the particles in the NVT/NPT ensemble based on the Nose-Hoover style non-Hamiltonian equations of motion. +- **Description**: Number of thermostats coupled with the particles in the NVT/NPT ensemble based on + the Nose-Hoover style non-Hamiltonian equations of motion. - **Default**: 1 ### md_pmode - **Type**: String - **Description**: Determine the precision level of variable-cell molecular dynamics calculations. - - 0: FFT grids do not change, only G vectors and K vectors are changed due to the change of lattice vector. This level is suitable for cases where the variation of the volume and shape is not large, and the efficiency is relatively higher. - - 2: FFT grids change per step. This level is suitable for cases where the variation of the volume and shape is large, such as the MSST method. However, accuracy comes at the cost of efficiency. + - 0: FFT grids do not change, only G vectors and K vectors are changed due to the change of + lattice vector. This level is suitable for cases where the variation of the volume and shape is + not large, and the efficiency is relatively higher. + - 2: FFT grids change per step. This level is suitable for cases where the variation of the volume + and shape is large, such as the MSST method. However, accuracy comes at the cost of efficiency. - **Default**: iso ### ref_cell_factor - **Type**: Real -- **Description**: Construct a reference cell bigger than the initial cell. The reference cell has to be large enough so that the lattice vectors of the fluctuating cell do not exceed the reference lattice vectors during MD. Typically, 1.02 ~ 1.10 is sufficient. However, the cell fluctuations depend on the specific system and thermodynamic conditions. So users must test for a proper choice. This parameters should be used in conjunction with erf_ecut, erf_height, and erf_sigma. +- **Description**: Construct a reference cell bigger than the initial cell. The reference cell has + to be large enough so that the lattice vectors of the fluctuating cell do not exceed the reference + lattice vectors during MD. Typically, 1.02 ~ 1.10 is sufficient. However, the cell fluctuations + depend on the specific system and thermodynamic conditions. So users must test for a proper + choice. This parameters should be used in conjunction with erf_ecut, erf_height, and erf_sigma. - **Default**: 1.0 ### md_pcouple - **Type**: String -- **Description**: The coupled lattice vectors will scale proportionally in NPT ensemble based on the Nose-Hoover style non-Hamiltonian equations of motion. +- **Description**: The coupled lattice vectors will scale proportionally in NPT ensemble based on + the Nose-Hoover style non-Hamiltonian equations of motion. - none: Three lattice vectors scale independently. - xyz: Lattice vectors x, y, and z scale proportionally. - xy: Lattice vectors x and y scale proportionally. @@ -3316,29 +4116,39 @@ ### md_pfirst - **Type**: Real -- **Description**: The target pressure used in NPT ensemble simulations, the default value of md_plast is md_pfirst. If md_plast is set to be different from md_pfirst, ABACUS will automatically change the target pressure from md_pfirst to md_plast. +- **Description**: The target pressure used in NPT ensemble simulations, the default value of + md_plast is md_pfirst. If md_plast is set to be different from md_pfirst, ABACUS will + automatically change the target pressure from md_pfirst to md_plast. - **Default**: -1.0 - **Unit**: kbar ### md_plast - **Type**: Real -- **Description**: The target pressure used in NPT ensemble simulations, the default value of md_plast is md_pfirst. If md_plast is set to be different from md_pfirst, ABACUS will automatically change the target pressure from md_pfirst to md_plast. +- **Description**: The target pressure used in NPT ensemble simulations, the default value of + md_plast is md_pfirst. If md_plast is set to be different from md_pfirst, ABACUS will + automatically change the target pressure from md_pfirst to md_plast. - **Default**: -1.0 - **Unit**: kbar ### md_pfreq - **Type**: Real -- **Description**: The frequency of pressure oscillations during the NPT ensemble simulation. If it is too large, the pressure will fluctuate violently; if it is too small, the pressure will take a very long time to equilibrate with the atomic system. - Note: It is a system-dependent empirical parameter. An improper choice might lead to the failure of jobs. +- **Description**: The frequency of pressure oscillations during the NPT ensemble simulation. If it + is too large, the pressure will fluctuate violently; if it is too small, the pressure will take a + very long time to equilibrate with the atomic system. + + Note: It is a system-dependent empirical parameter. An improper choice might lead to the failure + of jobs. + - **Default**: 1/400/md_dt ### md_pchain - **Type**: Integer -- **Description**: The number of thermostats coupled with the barostat in the NPT ensemble based on the Nose-Hoover style non-Hamiltonian equations of motion. +- **Description**: The number of thermostats coupled with the barostat in the NPT ensemble based on + the Nose-Hoover style non-Hamiltonian equations of motion. - **Default**: 1 ### lj_rule @@ -3350,27 +4160,33 @@ ### lj_eshift - **Type**: Boolean -- **Description**: It True, the LJ potential is shifted by a constant such that it is zero at the cut-off distance. +- **Description**: It True, the LJ potential is shifted by a constant such that it is zero at the + cut-off distance. - **Default**: False ### lj_rcut - **Type**: Real -- **Description**: Cut-off radius for Leonard Jones potential, beyond which the interaction will be neglected. It can be a single value, which means that all pairs of atoms types share the same cut-off radius. Otherwise, it should be a multiple-component vector, containing values, see details in lj_rule. +- **Description**: Cut-off radius for Leonard Jones potential, beyond which the interaction will be + neglected. It can be a single value, which means that all pairs of atoms types share the same + cut-off radius. Otherwise, it should be a multiple-component vector, containing values, see + details in lj_rule. - **Default**: No default - **Unit**: Angstrom ### lj_epsilon - **Type**: Real -- **Description**: The vector representing the matrix for Leonard Jones potential. See details in lj_rule. +- **Description**: The vector representing the matrix for Leonard Jones potential. See details in + lj_rule. - **Default**: No default - **Unit**: eV ### lj_sigma - **Type**: Real -- **Description**: The vector representing the matrix for Leonard Jones potential. See details in lj_rule. +- **Description**: The vector representing the matrix for Leonard Jones potential. See details in + lj_rule. - **Default**: No default - **Unit**: Angstrom @@ -3384,21 +4200,25 @@ - **Type**: Real - **Availability**: *esolver_type = dp.* -- **Description**: Rescaling factor to use a temperature-dependent DP. Energy, stress and force calculated by DP will be multiplied by this factor. +- **Description**: Rescaling factor to use a temperature-dependent DP. Energy, stress and force + calculated by DP will be multiplied by this factor. - **Default**: 1.0 ### dp_fparam - **Type**: Real - **Availability**: *esolver_type = dp.* -- **Description**: The frame parameter for dp potential. The array size is dim_fparam, then all frames are assumed to be provided with the same fparam. +- **Description**: The frame parameter for dp potential. The array size is dim_fparam, then all + frames are assumed to be provided with the same fparam. - **Default**: {} ### dp_aparam - **Type**: Real - **Availability**: *esolver_type = dp.* -- **Description**: The atomic parameter for dp potential. The array size can be (1) natoms x dim_aparam, then all frames are assumed to be provided with the same aparam; (2) dim_aparam, then all frames and atoms are assumed to be provided with the same aparam. +- **Description**: The atomic parameter for dp potential. The array size can be (1) natoms x + dim_aparam, then all frames are assumed to be provided with the same aparam; (2) dim_aparam, then + all frames and atoms are assumed to be provided with the same aparam. - **Default**: {} ### msst_direction @@ -3427,7 +4247,8 @@ ### msst_tscale - **Type**: Real -- **Description**: The reduction percentage of the initial temperature used to compress volume in the MSST method. +- **Description**: The reduction percentage of the initial temperature used to compress volume in + the MSST method. - **Default**: 0.01 ### msst_qmass @@ -3446,7 +4267,8 @@ ### md_tolerance - **Type**: Real -- **Description**: The temperature tolerance for velocity rescaling. Velocities are rescaled if the current and target temperature differ more than md_tolerance. +- **Description**: The temperature tolerance for velocity rescaling. Velocities are rescaled if the + current and target temperature differ more than md_tolerance. - **Default**: 100.0 - **Unit**: K @@ -3454,22 +4276,31 @@ - **Type**: Integer - **Description**: - Anderson: The "collision frequency" parameter is given as 1/md_nraise. - - Berendsen: The "rise time" parameter is given in units of the time step: tau = md_nraise*md_dt, so md_dt/tau = 1/md_nraise. + - Berendsen: The "rise time" parameter is given in units of the time step: tau = md_nraise\*md_dt, + so md_dt/tau = 1/md_nraise. - Rescale_v: Every md_nraise steps the current temperature is rescaled to the target temperature. - **Default**: 1 ### cal_syns - **Type**: Boolean -- **Description**: Whether to calculate and output asynchronous overlap matrix for Hefei-NAMD interface. When enabled, calculates <phi(t-1)|phi(t)> by computing overlap between basis functions at atomic positions from previous time step and current time step. The overlap is calculated by shifting atom positions backward by velocity x md_dt. Output file: OUT.*/syns_nao.csr in CSR format. - > Note: Only works with LCAO basis and molecular dynamics calculations. Requires atomic velocities. Output starts from the second MD step (istep > 0). +- **Description**: Whether to calculate and output asynchronous overlap matrix for Hefei-NAMD + interface. When enabled, calculates \ by computing overlap between basis + functions at atomic positions from previous time step and current time step. The overlap is + calculated by shifting atom positions backward by velocity x md_dt. Output file: + OUT.\*/syns_nao.csr in CSR format. + + > Note: Only works with LCAO basis and molecular dynamics calculations. Requires atomic + > velocities. Output starts from the second MD step (istep > 0). + - **Default**: False ### dmax - **Type**: Real -- **Description**: The maximum displacement of all atoms in one step. This parameter is useful when cal_syns = True. +- **Description**: The maximum displacement of all atoms in one step. This parameter is useful when + cal_syns = True. - **Default**: 0.01 - **Unit**: bohr @@ -3480,9 +4311,12 @@ ### dft_plus_u - **Type**: Integer -- **Description**: Determines whether to calculate the plus U correction, which is especially important for correlated electrons. - - 1: Calculate plus U correction with radius-adjustable localized projections (with parameter onsite_radius). - - 2: Calculate plus U correction using first zeta of NAOs as projections (this is old method for testing). +- **Description**: Determines whether to calculate the plus U correction, which is especially + important for correlated electrons. + - 1: Calculate plus U correction with radius-adjustable localized projections (with parameter + onsite_radius). + - 2: Calculate plus U correction using first zeta of NAOs as projections (this is old method for + testing). - 0: Do not calculate plus U correction. - **Default**: 0 @@ -3490,13 +4324,15 @@ - **Type**: Boolean - **Availability**: *basis_type==lcao* -- **Description**: Whether to enable DFT+DMFT calculation. True: DFT+DMFT; False: standard DFT calculation. +- **Description**: Whether to enable DFT+DMFT calculation. True: DFT+DMFT; False: standard DFT + calculation. - **Default**: False ### orbital_corr - **Type**: Vector of Integer (n values where n is the number of atomic types) -- **Description**: Specifies which orbits need plus U correction for each atom type ( for atom type 1, 2, 3, respectively). +- **Description**: Specifies which orbits need plus U correction for each atom type ( for atom type + 1, 2, 3, respectively). - -1: The plus U correction will not be calculated for this atom. - 1: For p-electron orbits, the plus U correction is needed. - 2: For d-electron orbits, the plus U correction is needed. @@ -3506,15 +4342,20 @@ ### hubbard_u - **Type**: Vector of Real (n values where n is the number of atomic types) -- **Description**: Specifies the Hubbard Coulomb interaction parameter U (eV) in plus U correction, which should be specified for each atom unless the Yukawa potential is used. - > Note: Since only the simplified scheme by Duradev is implemented, the 'U' here is actually U-effective, which is given by Hubbard U minus Hund J. +- **Description**: Specifies the Hubbard Coulomb interaction parameter U (eV) in plus U correction, + which should be specified for each atom unless the Yukawa potential is used. + + > Note: Since only the simplified scheme by Duradev is implemented, the 'U' here is actually + > U-effective, which is given by Hubbard U minus Hund J. + - **Default**: 0.0 ### yukawa_potential - **Type**: Boolean -- **Description**: Determines whether to use the local screen Coulomb potential method to calculate the values of U and J. +- **Description**: Determines whether to use the local screen Coulomb potential method to calculate + the values of U and J. - True: hubbard_u does not need to be specified. - False: hubbard_u does need to be specified. - **Default**: False @@ -3523,34 +4364,51 @@ - **Type**: Real - **Availability**: *DFT+U with yukawa_potential = True.* -- **Description**: The screen length of Yukawa potential. If left to default, the screen length will be calculated as an average of the entire system. It's better to stick to the default setting unless there is a very good reason. +- **Description**: The screen length of Yukawa potential. If left to default, the screen length will + be calculated as an average of the entire system. It's better to stick to the default setting + unless there is a very good reason. - **Default**: Calculated on the fly. ### uramping - **Type**: Real -- **Availability**: *DFT+U calculations with mixing_restart > 0.* -- **Description**: Once uramping > 0.15 eV. DFT+U calculations will start SCF with U = 0 eV, namely normal LDA/PBE calculations. Once SCF restarts when drho<mixing_restart, U value will increase by uramping eV. SCF will repeat above calcuations until U values reach target defined in hubbard_u. As for uramping=1.0 eV, the recommendations of mixing_restart is around 5e-4. +- **Availability**: *DFT+U calculations with mixing_restart > 0.* +- **Description**: Once uramping > 0.15 eV. DFT+U calculations will start SCF with U = 0 eV, namely + normal LDA/PBE calculations. Once SCF restarts when drho\ Note: The easiest way to create initial_onsite.dm is to run a DFT+U calculation, look for a file named onsite.dm in the OUT.prefix directory, and make replacements there. The format of the file is rather straight-forward. + - 0: No occupation matrix control is performed, and the onsite density matrix will be calculated + from wavefunctions in each SCF step. + - 1: The first SCF step will use an initial density matrix read from a file named + initial_onsite.dm, but for later steps, the onsite density matrix will be updated. + - 2: The same onsite density matrix from initial_onsite.dm will be used throughout the entire + calculation. + + > Note: The easiest way to create initial_onsite.dm is to run a DFT+U calculation, look for a file + > named onsite.dm in the OUT.prefix directory, and make replacements there. The format of the file + > is rather straight-forward. + - **Default**: 0 ### onsite_radius - **Type**: Real - **Availability**: *dft_plus_u is set to 1* -- **Description**: - The onsite_radius parameter facilitates modulation of the single-zeta portion of numerical atomic orbitals used for DFT+U projections. - - The modulation algorithm applies a smooth truncation to the orbital tail followed by normalization. A representative profile is $f(r)=\frac{1}{2}\left[1+\operatorname{erf}\!\left(\frac{r_c-r}{\sigma}\right)\right]$, where $r_c$ is the cutoff radius and $\sigma=\gamma r_c$ controls smoothness. +- **Description**: - The onsite_radius parameter facilitates modulation of the single-zeta portion + of numerical atomic orbitals used for DFT+U projections. + - The modulation algorithm applies a smooth truncation to the orbital tail followed by + normalization. A representative profile is + $f(r)=\frac{1}{2}\left[1+\operatorname{erf}\!\left(\frac{r_c-r}{\sigma}\right)\right]$, where + $r_c$ is the cutoff radius and $\sigma=\gamma r_c$ controls smoothness. - **Default**: 3.0 - **Unit**: Bohr @@ -3636,38 +4494,60 @@ ### vdw_method - **Type**: String -- **Description**: Specifies the method used for Van der Waals (VdW) correction. Available options are: + +- **Description**: Specifies the method used for Van der Waals (VdW) correction. Available options + are: + - d2: Grimme's D2 dispersion correction method - d3_0: Grimme's DFT-D3(0) dispersion correction method (zero-damping) - d3_bj: Grimme's DFTD3(BJ) dispersion correction method (BJ-damping) - none: no vdW correction - > Note: ABACUS supports automatic setting of DFT-D3 parameters for common functionals. To benefit from this feature, please specify the parameter dft_functional explicitly, otherwise the autoset procedure will crash. If not satisfied with the built-in parameters, any manual setting on vdw_s6, vdw_s8, vdw_a1 and vdw_a2 will overwrite the automatic values. + > Note: ABACUS supports automatic setting of DFT-D3 parameters for common functionals. To benefit + > from this feature, please specify the parameter dft_functional explicitly, otherwise the autoset + > procedure will crash. If not satisfied with the built-in parameters, any manual setting on + > vdw_s6, vdw_s8, vdw_a1 and vdw_a2 will overwrite the automatic values. + - **Default**: none ### vdw_s6 - **Type**: String - **Availability**: *vdw_method is set to d2, d3_0, or d3_bj* -- **Description**: This scale factor is used to optimize the interaction energy deviations in van der Waals (vdW) corrected calculations. The recommended values of this parameter are dependent on the chosen vdW correction method and the DFT functional being used. For DFT-D2, the recommended values are 0.75 (PBE), 1.2 (BLYP), 1.05 (B-P86), 1.0 (TPSS), and 1.05 (B3LYP). If not set, will use values of PBE functional. For DFT-D3, recommended values with different DFT functionals can be found on the here. If not set, will search in ABACUS built-in dataset based on the dft_functional keywords. User set value will overwrite the searched value. +- **Description**: This scale factor is used to optimize the interaction energy deviations in van + der Waals (vdW) corrected calculations. The recommended values of this parameter are dependent on + the chosen vdW correction method and the DFT functional being used. For DFT-D2, the recommended + values are 0.75 (PBE), 1.2 (BLYP), 1.05 (B-P86), 1.0 (TPSS), and 1.05 (B3LYP). If not set, will + use values of PBE functional. For DFT-D3, recommended values with different DFT functionals can be + found on the here. If not set, will search in ABACUS built-in dataset based on the dft_functional + keywords. User set value will overwrite the searched value. ### vdw_s8 - **Type**: String - **Availability**: *vdw_method is set to d3_0 or d3_bj* -- **Description**: This scale factor is relevant for D3(0) and D3(BJ) van der Waals (vdW) correction methods. The recommended values of this parameter with different DFT functionals can be found on the webpage. If not set, will search in ABACUS built-in dataset based on the dft_functional keywords. User set value will overwrite the searched value. +- **Description**: This scale factor is relevant for D3(0) and D3(BJ) van der Waals (vdW) correction + methods. The recommended values of this parameter with different DFT functionals can be found on + the webpage. If not set, will search in ABACUS built-in dataset based on the dft_functional + keywords. User set value will overwrite the searched value. ### vdw_a1 - **Type**: String - **Availability**: *vdw_method is set to d3_0 or d3_bj* -- **Description**: This damping function parameter is relevant for D3(0) and D3(BJ) van der Waals (vdW) correction methods. The recommended values of this parameter with different DFT functionals can be found on the webpage. If not set, will search in ABACUS built-in dataset based on the dft_functional keywords. User set value will overwrite the searched value. +- **Description**: This damping function parameter is relevant for D3(0) and D3(BJ) van der Waals + (vdW) correction methods. The recommended values of this parameter with different DFT functionals + can be found on the webpage. If not set, will search in ABACUS built-in dataset based on the + dft_functional keywords. User set value will overwrite the searched value. ### vdw_a2 - **Type**: String - **Availability**: *vdw_method is set to d3_0 or d3_bj* -- **Description**: This damping function parameter is only relevant for D3(0) and D3(BJ) van der Waals (vdW) correction methods. The recommended values of this parameter with different DFT functionals can be found on the webpage. If not set, will search in ABACUS built-in dataset based on the dft_functional keywords. User set value will overwrite the searched value. +- **Description**: This damping function parameter is only relevant for D3(0) and D3(BJ) van der + Waals (vdW) correction methods. The recommended values of this parameter with different DFT + functionals can be found on the webpage. If not set, will search in ABACUS built-in dataset based + on the dft_functional keywords. User set value will overwrite the searched value. ### vdw_d @@ -3688,19 +4568,25 @@ ### vdw_c6_file - **Type**: String + - **Availability**: *vdw_method is set to d2* -- **Description**: Specifies the name of the file containing parameters for each element when using the D2 method. If not set, ABACUS uses the default parameters (Jnm6/mol) stored in the program. To manually set the parameters, provide a file containing the parameters. An example is given by: + +- **Description**: Specifies the name of the file containing parameters for each element when using + the D2 method. If not set, ABACUS uses the default parameters (Jnm6/mol) stored in the program. To + manually set the parameters, provide a file containing the parameters. An example is given by: H 0.1 Si 9.0 Namely, each line contains the element name and the corresponding parameter. + - **Default**: default ### vdw_c6_unit - **Type**: String - **Availability**: *vdw_C6_file is not default* -- **Description**: Specifies the unit of the provided parameters in the D2 method. Available options are: +- **Description**: Specifies the unit of the provided parameters in the D2 method. Available options + are: - Jnm6/mol (J nm^6/mol) - eVA (eV Angstrom) - **Default**: Jnm6/mol @@ -3708,19 +4594,25 @@ ### vdw_r0_file - **Type**: String + - **Availability**: *vdw_method is set to d2* -- **Description**: Specifies the name of the file containing parameters for each element when using the D2 method. If not set, ABACUS uses the default parameters (Angstrom) stored in the program. To manually set the parameters, provide a file containing the parameters. An example is given by: + +- **Description**: Specifies the name of the file containing parameters for each element when using + the D2 method. If not set, ABACUS uses the default parameters (Angstrom) stored in the program. To + manually set the parameters, provide a file containing the parameters. An example is given by: Li 1.0 Cl 2.0 Namely, each line contains the element name and the corresponding parameter. + - **Default**: default ### vdw_r0_unit - **Type**: String - **Availability**: *vdw_R0_file is not default* -- **Description**: Specifies the unit for the parameters in the D2 method when manually set by the user. Available options are: +- **Description**: Specifies the unit for the parameters in the D2 method when manually set by the + user. Available options are: - A (Angstrom) - Bohr - **Default**: A @@ -3728,8 +4620,10 @@ ### vdw_cutoff_type - **Type**: String -- **Description**: Determines the method used for specifying the cutoff radius in periodic systems when applying Van der Waals correction. Available options are: - - radius: The supercell is selected within a sphere centered at the origin with a radius defined by vdw_cutoff_radius. +- **Description**: Determines the method used for specifying the cutoff radius in periodic systems + when applying Van der Waals correction. Available options are: + - radius: The supercell is selected within a sphere centered at the origin with a radius defined + by vdw_cutoff_radius. - period: The extent of the supercell is explicitly specified using the vdw_cutoff_period keyword. - **Default**: radius @@ -3737,7 +4631,8 @@ - **Type**: String - **Availability**: *vdw_cutoff_type is set to radius* -- **Description**: Defines the radius of the cutoff sphere when vdw_cutoff_type is set to radius. The default values depend on the chosen vdw_method. +- **Description**: Defines the radius of the cutoff sphere when vdw_cutoff_type is set to radius. + The default values depend on the chosen vdw_method. - **Unit**: defined by vdw_radius_unit (default Bohr) ### vdw_radius_unit @@ -3753,7 +4648,8 @@ - **Type**: Integer Integer Integer - **Availability**: *vdw_cutoff_type is set to period* -- **Description**: The three integers supplied here explicitly specify the extent of the supercell in the directions of the three basis lattice vectors. +- **Description**: The three integers supplied here explicitly specify the extent of the supercell + in the directions of the three basis lattice vectors. - **Default**: 3 3 3 ### vdw_cn_thr @@ -3787,10 +4683,14 @@ ### gdir - **Type**: Integer -- **Description**: The direction of the polarization in the lattice vector for Berry phase calculation - - 1: Calculate the polarization in the direction of the lattice vector a_1 defined in the STRU file. - - 2: Calculate the polarization in the direction of the lattice vector a_2 defined in the STRU file. - - 3: Calculate the polarization in the direction of the lattice vector a_3 defined in the STRU file. +- **Description**: The direction of the polarization in the lattice vector for Berry phase + calculation + - 1: Calculate the polarization in the direction of the lattice vector a_1 defined in the STRU + file. + - 2: Calculate the polarization in the direction of the lattice vector a_2 defined in the STRU + file. + - 3: Calculate the polarization in the direction of the lattice vector a_3 defined in the STRU + file. - **Default**: 3 ### towannier90 @@ -3810,9 +4710,13 @@ ### wannier_method - **Type**: Integer -- **Description**: Only available on LCAO basis, using different methods to generate "\.mmn" file and "\.amn" file. - - 1: Calculated using the lcao_in_pw method, the calculation accuracy can be improved by increasing ecutwfc to maintain consistency with the pw basis set results. - - 2: The overlap between atomic orbitals is calculated using grid integration. The radial grid points are generated using the Gauss-Legendre method, while the spherical grid points are generated using the Lebedev-Laikov method. +- **Description**: Only available on LCAO basis, using different methods to generate ".mmn" file and + ".amn" file. + - 1: Calculated using the lcao_in_pw method, the calculation accuracy can be improved by + increasing ecutwfc to maintain consistency with the pw basis set results. + - 2: The overlap between atomic orbitals is calculated using grid integration. The radial grid + points are generated using the Gauss-Legendre method, while the spherical grid points are + generated using the Lebedev-Laikov method. - **Default**: 1 ### wannier_spin @@ -3826,41 +4730,41 @@ ### out_wannier_mmn - **Type**: Boolean -- **Description**: Write the "*.mmn" file or not. - - 0: don't write the "*.mmn" file. - - 1: write the "*.mmn" file. +- **Description**: Write the "\*.mmn" file or not. + - 0: don't write the "\*.mmn" file. + - 1: write the "\*.mmn" file. - **Default**: 1 ### out_wannier_amn - **Type**: Boolean -- **Description**: Write the "*.amn" file or not. - - 0: don't write the "*.amn" file. - - 1: write the "*.amn" file. +- **Description**: Write the "\*.amn" file or not. + - 0: don't write the "\*.amn" file. + - 1: write the "\*.amn" file. - **Default**: 1 ### out_wannier_eig - **Type**: Boolean -- **Description**: Write the "*.eig" file or not. - - 0: don't write the "*.eig" file. - - 1: write the "*.eig" file. +- **Description**: Write the "\*.eig" file or not. + - 0: don't write the "\*.eig" file. + - 1: write the "\*.eig" file. - **Default**: 1 ### out_wannier_unk - **Type**: Boolean -- **Description**: Write the "UNK.*" file or not. - - 0: don't write the "UNK.*" file. - - 1: write the "UNK.*" file. +- **Description**: Write the "UNK.\*" file or not. + - 0: don't write the "UNK.\*" file. + - 1: write the "UNK.\*" file. - **Default**: 0 ### out_wannier_wvfn_formatted - **Type**: Boolean -- **Description**: Write the "UNK.*" file in ASCII format or binary format. - - 0: write the "UNK.*" file in binary format. - - 1: write the "UNK.*" file in ASCII format (text file format). +- **Description**: Write the "UNK.\*" file in ASCII format or binary format. + - 0: write the "UNK.\*" file in binary format. + - 1: write the "UNK.\*" file in ASCII format (text file format). - **Default**: 1 [back to top](#full-list-of-input-keywords) @@ -3876,24 +4780,27 @@ ### td_dt - **Type**: Real -- **Description**: The time step used in electronic propagation. Setting td_dt will reset the value of md_dt to td_dt * estep_per_md. +- **Description**: The time step used in electronic propagation. Setting td_dt will reset the value + of md_dt to td_dt * estep_per_md. - **Default**: md_dt / estep_per_md - **Unit**: fs ### td_edm - **Type**: Integer -- **Description**: Method to calculate the energy-density matrix, mainly affects the calculation of force and stress. +- **Description**: Method to calculate the energy-density matrix, mainly affects the calculation of + force and stress. - 0: Using the original formula. - - 1: Using the formula for ground state (deprecated). Note that this usually does not hold if wave function is not the eigenstate of the Hamiltonian. + - 1: Using the formula for ground state (deprecated). Note that this usually does not hold if wave + function is not the eigenstate of the Hamiltonian. - **Default**: 0 ### td_print_eij - **Type**: Real - **Description**: Controls the printing of Hamiltonian matrix elements. - - < 0: Suppress all output. - - >= 0: Print only elements with either i or j exceeding td_print_eij. + - < 0: Suppress all output. + - \>= 0: Print only elements with either i or j exceeding td_print_eij. - **Default**: -1 - **Unit**: Ry @@ -3917,7 +4824,11 @@ ### td_vext_dire - **Type**: String -- **Description**: Specifies the direction(s) of the external electric field when td_vext is enabled. For example, td_vext_dire 1 2 indicates that external electric fields are applied to both the x and y directions simultaneously. Electric field parameters can also be written as strings. For example, td_gauss_phase 0 1.5707963 indicates that the Gaussian type electric fields in the x and y directions have a phase delay of pi/2. +- **Description**: Specifies the direction(s) of the external electric field when td_vext is + enabled. For example, td_vext_dire 1 2 indicates that external electric fields are applied to both + the x and y directions simultaneously. Electric field parameters can also be written as strings. + For example, td_gauss_phase 0 1.5707963 indicates that the Gaussian type electric fields in the x + and y directions have a phase delay of pi/2. - 1: The external field direction is along the x-axis. - 2: The external field direction is along the y-axis. - 3: The external field direction is along the z-axis. @@ -3951,19 +4862,22 @@ ### td_tend - **Type**: Integer -- **Description**: The final time step when the time-dependent electric field is deactivated. The field remains active between td_tstart and td_tend. +- **Description**: The final time step when the time-dependent electric field is deactivated. The + field remains active between td_tstart and td_tend. - **Default**: 1000 ### td_lcut1 - **Type**: Real -- **Description**: The lower bound of the interval in the length gauge RT-TDDFT, where the coordinate is the fractional coordinate. +- **Description**: The lower bound of the interval in the length gauge RT-TDDFT, where the + coordinate is the fractional coordinate. - **Default**: 0.05 ### td_lcut2 - **Type**: Real -- **Description**: The upper bound of the interval in the length gauge RT-TDDFT, where the coordinate is the fractional coordinate. +- **Description**: The upper bound of the interval in the length gauge RT-TDDFT, where the + coordinate is the fractional coordinate. - **Default**: 0.95 ### td_gauss_freq @@ -4087,7 +5001,8 @@ - **Type**: Boolean - **Description**: Initialize vector potential through file or not. - - True: Initialize vector potential from file At.dat (unit: a.u.). It consists of four columns, representing the step number and vector potential on each direction. + - True: Initialize vector potential from file At.dat (unit: a.u.). It consists of four columns, + representing the step number and vector potential on each direction. - False: Calculate vector potential by integrating the electric field. - **Default**: False @@ -4101,11 +5016,16 @@ ### ocp_set - **Type**: String -- **Description**: If ocp is set to 1, ocp_set must be provided as a string specifying the occupation numbers for each band across all k-points. The format follows a space-separated pattern, where occupations are assigned sequentially to bands for each k-point. A shorthand notation Nx can be used to repeat a value x for N bands. - - Example: - 1 10*1 0 1 represents occupations for 13 bands, where the 12th band is fully unoccupied (0), and all others are occupied (1). - - For a system with multiple k-points, the occupations must be specified for all k-points, following their order in the output file kpoints (may lead to fractional occupations). - - Incorrect specification of ocp_set could lead to inconsistencies in electron counting, causing the calculation to terminate with an error. +- **Description**: If ocp is set to 1, ocp_set must be provided as a string specifying the + occupation numbers for each band across all k-points. The format follows a space-separated + pattern, where occupations are assigned sequentially to bands for each k-point. A shorthand + notation Nx can be used to repeat a value x for N bands. + - Example: 1 10\*1 0 1 represents occupations for 13 bands, where the 12th band is fully + unoccupied (0), and all others are occupied (1). + - For a system with multiple k-points, the occupations must be specified for all k-points, + following their order in the output file kpoints (may lead to fractional occupations). + - Incorrect specification of ocp_set could lead to inconsistencies in electron counting, causing + the calculation to terminate with an error. - **Default**: None ### out_dipole @@ -4133,7 +5053,11 @@ ### out_efield - **Type**: Boolean -- **Description**: Whether to output the electric field data to files. When enabled, writes real-time electric field values (unit: V/A) into files named efield_[num].txt, where [num] is the sequential index of the electric field ranges from 0 to N-1 for N configured fields. It is noteworthy that the field type sequence follows td_ttype, while the direction sequence follows td_vext_dire. +- **Description**: Whether to output the electric field data to files. When enabled, writes + real-time electric field values (unit: V/A) into files named efield\_[num].txt, where [num] is the + sequential index of the electric field ranges from 0 to N-1 for N configured fields. It is + noteworthy that the field type sequence follows td_ttype, while the direction sequence follows + td_vext_dire. - True: Output electric field. - False: Do not output electric field. - **Default**: False @@ -4167,7 +5091,8 @@ ### vl_in_h - **Type**: Boolean -- **Description**: Specify whether to include local pseudopotential term in obtaining the Hamiltonian matrix. +- **Description**: Specify whether to include local pseudopotential term in obtaining the + Hamiltonian matrix. - 0: No. - 1: Yes. - **Default**: 1 @@ -4175,7 +5100,8 @@ ### vnl_in_h - **Type**: Boolean -- **Description**: Specify whether to include non-local pseudopotential term in obtaining the Hamiltonian matrix. +- **Description**: Specify whether to include non-local pseudopotential term in obtaining the + Hamiltonian matrix. - 0: No. - 1: Yes. - **Default**: 1 @@ -4183,7 +5109,8 @@ ### vh_in_h - **Type**: Boolean -- **Description**: Specify whether to include Hartree potential term in obtaining the Hamiltonian matrix. +- **Description**: Specify whether to include Hartree potential term in obtaining the Hamiltonian + matrix. - 0: No. - 1: Yes. - **Default**: 1 @@ -4191,7 +5118,8 @@ ### vion_in_h - **Type**: Boolean -- **Description**: Specify whether to include local ionic potential term in obtaining the Hamiltonian matrix. +- **Description**: Specify whether to include local ionic potential term in obtaining the + Hamiltonian matrix. - 0: No. - 1: Yes. - **Default**: 1 @@ -4266,7 +5194,8 @@ - **Type**: Integer - **Availability**: *esolver_type = sdft* -- **Description**: exp(iH\dt\cond_dtbatch) is expanded with Chebyshev expansion to calculate conductivities. It is faster but costs more memory. +- **Description**: exp(iH\\dt\\cond_dtbatch) is expanded with Chebyshev expansion to calculate + conductivities. It is faster but costs more memory. - If cond_dtbatch = 0: Autoset this parameter to make expansion orders larger than 100. - **Default**: 0 @@ -4290,7 +5219,8 @@ - **Type**: Boolean - **Availability**: *basis_type = pw* -- **Description**: Whether to consider nonlocal potential correction when calculating velocity matrix . +- **Description**: Whether to consider nonlocal potential correction when calculating velocity + matrix . - True: . - False: . - **Default**: True @@ -4315,13 +5245,16 @@ ### tau - **Type**: Real -- **Description**: The effective surface tension parameter that describes the cavitation, the dispersion, and the repulsion interaction between the solute and the solvent which are not captured by the electrostatic terms +- **Description**: The effective surface tension parameter that describes the cavitation, the + dispersion, and the repulsion interaction between the solute and the solvent which are not + captured by the electrostatic terms - **Default**: 1.0798e-05 ### sigma_k - **Type**: Real -- **Description**: The width of the diffuse cavity that is implicitly determined by the electronic structure of the solute +- **Description**: The width of the diffuse cavity that is implicitly determined by the electronic + structure of the solute - **Default**: 0.6 ### nc_k @@ -4352,20 +5285,24 @@ ### qo_strategy - **Type**: Vector of String (1 or n values where n is the number of atomic types) -- **Description**: Strategy to generate radial orbitals for QO analysis. For hydrogen: energy-valence, for pswfc and szv: all +- **Description**: Strategy to generate radial orbitals for QO analysis. For hydrogen: + energy-valence, for pswfc and szv: all - **Default**: for hydrogen: energy-valence, for pswfc and szv: all ### qo_screening_coeff -- **Type**: Vector of Real (n values where n is the number of atomic types; 1 value allowed for qo_basis=pswfc) -- **Description**: The screening coefficient for each atom type to rescale the shape of radial orbitals +- **Type**: Vector of Real (n values where n is the number of atomic types; 1 value allowed for + qo_basis=pswfc) +- **Description**: The screening coefficient for each atom type to rescale the shape of radial + orbitals - **Default**: 0.1 - **Unit**: Bohr^-1 ### qo_thr - **Type**: Real -- **Description**: The convergence threshold determining the cutoff of generated orbital. Lower threshold will yield orbital with larger cutoff radius. +- **Description**: The convergence threshold determining the cutoff of generated orbital. Lower + threshold will yield orbital with larger cutoff radius. - **Default**: 1.0e-6 [back to top](#full-list-of-input-keywords) @@ -4399,19 +5336,22 @@ ### pexsi_storage - **Type**: Boolean -- **Description**: Whether to use symmetric storage space used by the Selected Inversion algorithm for symmetric matrices. +- **Description**: Whether to use symmetric storage space used by the Selected Inversion algorithm + for symmetric matrices. - **Default**: True ### pexsi_ordering - **Type**: Integer -- **Description**: Ordering strategy for factorization and selected inversion. 0: Parallel ordering using ParMETIS, 1: Sequential ordering using METIS, 2: Multiple minimum degree ordering +- **Description**: Ordering strategy for factorization and selected inversion. 0: Parallel ordering + using ParMETIS, 1: Sequential ordering using METIS, 2: Multiple minimum degree ordering - **Default**: 0 ### pexsi_row_ordering - **Type**: Integer -- **Description**: Row permutation strategy for factorization and selected inversion, 0: No row permutation, 1: Make the diagonal entry of the matrix larger than the off-diagonal entries. +- **Description**: Row permutation strategy for factorization and selected inversion, 0: No row + permutation, 1: Make the diagonal entry of the matrix larger than the off-diagonal entries. - **Default**: 1 ### pexsi_nproc @@ -4435,7 +5375,8 @@ ### pexsi_method - **Type**: Integer -- **Description**: The pole expansion method to be used. 1 for Cauchy Contour Integral method, 2 for Moussa optimized method. +- **Description**: The pole expansion method to be used. 1 for Cauchy Contour Integral method, 2 for + Moussa optimized method. - **Default**: 1 ### pexsi_nproc_pole @@ -4447,7 +5388,8 @@ ### pexsi_temp - **Type**: Real -- **Description**: Temperature in Fermi-Dirac distribution, in Ry, should have the same effect as the smearing sigma when smearing method is set to Fermi-Dirac. +- **Description**: Temperature in Fermi-Dirac distribution, in Ry, should have the same effect as + the smearing sigma when smearing method is set to Fermi-Dirac. - **Default**: 0.015 ### pexsi_gap @@ -4459,7 +5401,7 @@ ### pexsi_delta_e - **Type**: Real -- **Description**: Upper bound for the spectral radius of S^{-1}H. +- **Description**: Upper bound for the spectral radius of S^\{-1}H. - **Default**: 20 ### pexsi_mu_lower @@ -4483,31 +5425,36 @@ ### pexsi_mu_thr - **Type**: Real -- **Description**: Stopping criterion in terms of the chemical potential for the inertia counting procedure. +- **Description**: Stopping criterion in terms of the chemical potential for the inertia counting + procedure. - **Default**: 0.05 ### pexsi_mu_expand - **Type**: Real -- **Description**: If the chemical potential is not in the initial interval, the interval is expanded by this value. +- **Description**: If the chemical potential is not in the initial interval, the interval is + expanded by this value. - **Default**: 0.3 ### pexsi_mu_guard - **Type**: Real -- **Description**: Safe guard criterion in terms of the chemical potential to reinvoke the inertia counting procedure. +- **Description**: Safe guard criterion in terms of the chemical potential to reinvoke the inertia + counting procedure. - **Default**: 0.2 ### pexsi_elec_thr - **Type**: Real -- **Description**: Stopping criterion of the PEXSI iteration in terms of the number of electrons compared to numElectronExact. +- **Description**: Stopping criterion of the PEXSI iteration in terms of the number of electrons + compared to numElectronExact. - **Default**: 0.001 ### pexsi_zero_thr - **Type**: Real -- **Description**: if the absolute value of CCS matrix element is less than this value, it will be considered as zero. +- **Description**: if the absolute value of CCS matrix element is less than this value, it will be + considered as zero. - **Default**: 1e-10 [back to top](#full-list-of-input-keywords) @@ -4517,14 +5464,16 @@ ### ri_hartree_benchmark - **Type**: String -- **Description**: Whether to use the RI approximation for the Hartree term in LR-TDDFT for benchmark (with FHI-aims/ABACUS read-in style) +- **Description**: Whether to use the RI approximation for the Hartree term in LR-TDDFT for + benchmark (with FHI-aims/ABACUS read-in style) - **Default**: none ### aims_nbasis - **Type**: A number(ntype) of Integers - **Availability**: *ri_hartree_benchmark = aims* -- **Description**: Atomic basis set size for each atom type (with the same order as in STRU) in FHI-aims. +- **Description**: Atomic basis set size for each atom type (with the same order as in STRU) in + FHI-aims. - **Default**: {} (empty list, where ABACUS use its own basis set size) [back to top](#full-list-of-input-keywords) @@ -4534,23 +5483,31 @@ ### xc_kernel - **Type**: String -- **Description**: The exchange-correlation kernel used in the calculation. Currently supported: RPA, LDA, PBE, HSE, HF. +- **Description**: The exchange-correlation kernel used in the calculation. Currently supported: + RPA, LDA, PBE, HSE, HF. - **Default**: LDA ### lr_init_xc_kernel -- **Type**: Vector of String (>=1 values) +- **Type**: Vector of String (>=1 values) - **Description**: The method to initalize the xc kernel. - "default": Calculate xc kernel from the ground-state charge density. - - "file": Read the xc kernel on grid from the provided files. The following words should be the paths of ".cube" files, where the first 1 (nspin==1) or 3 (nspin==2, namely spin-aa, spin-ab and spin-bb) will be read in. The parameter xc_kernel will be invalid. Now only LDA-type kernel is supported as the potential will be calculated by directly multiplying the transition density. - - "from_charge_file": Calculate fxc from the charge density read from the provided files. The following words should be the paths of ".cube" files, where the first nspin files will be read in. + - "file": Read the xc kernel on grid from the provided files. The following words should be the + paths of ".cube" files, where the first 1 (nspin==1) or 3 (nspin==2, namely spin-aa, spin-ab and + spin-bb) will be read in. The parameter xc_kernel will be invalid. Now only LDA-type kernel is + supported as the potential will be calculated by directly multiplying the transition density. + - "from_charge_file": Calculate fxc from the charge density read from the provided files. The + following words should be the paths of ".cube" files, where the first nspin files will be read + in. - **Default**: "default" ### lr_solver - **Type**: String -- **Description**: The method to solve the Casida equation in LR-TDDFT under Tamm-Dancoff approximation (TDA). - - dav/dav_subspace/cg: Construct and diagonalize the Hamiltonian matrix iteratively with Davidson/Non-ortho-Davidson/CG algorithm. +- **Description**: The method to solve the Casida equation in LR-TDDFT under Tamm-Dancoff + approximation (TDA). + - dav/dav_subspace/cg: Construct and diagonalize the Hamiltonian matrix iteratively with + Davidson/Non-ortho-Davidson/CG algorithm. - lapack: Construct the full matrix and directly diagonalize with LAPACK. - spectrum: Calculate absorption spectrum only without solving Casida equation. - **Default**: dav @@ -4558,20 +5515,23 @@ ### lr_thr - **Type**: Real -- **Description**: The convergence threshold of iterative diagonalization solver for LR-TDDFT. It is a pure-math number with the same meaning as pw_diag_thr, but since the Casida equation is a one-shot eigenvalue problem, it is also the convergence threshold of LR-TDDFT. +- **Description**: The convergence threshold of iterative diagonalization solver for LR-TDDFT. It is + a pure-math number with the same meaning as pw_diag_thr, but since the Casida equation is a + one-shot eigenvalue problem, it is also the convergence threshold of LR-TDDFT. - **Default**: 1e-2 ### nocc - **Type**: Integer - **Description**: The number of occupied orbitals (up to HOMO) used in the LR-TDDFT calculation. - - Note: If the value is illegal ( > nelec/2 or <= 0), it will be autoset to nelec/2. + - Note: If the value is illegal ( > nelec/2 or \<= 0), it will be autoset to nelec/2. - **Default**: nband ### nvirt - **Type**: Integer -- **Description**: The number of virtual orbitals (starting from LUMO) used in the LR-TDDFT calculation. +- **Description**: The number of virtual orbitals (starting from LUMO) used in the LR-TDDFT + calculation. - **Default**: 1 ### lr_nstates @@ -4583,7 +5543,8 @@ ### lr_unrestricted - **Type**: Boolean -- **Description**: Whether to use unrestricted construction for LR-TDDFT (the matrix size will be doubled). +- **Description**: Whether to use unrestricted construction for LR-TDDFT (the matrix size will be + doubled). - True: Always use unrestricted LR-TDDFT. - False: Use unrestricted LR-TDDFT only when the system is open-shell. - **Default**: False @@ -4598,13 +5559,16 @@ ### out_wfc_lr - **Type**: Boolean -- **Description**: Whether to output the eigenstates (excitation energy) and eigenvectors (excitation amplitude) of the LR-TDDFT calculation. The output files are OUT.{suffix}/Excitation_Amplitude_${processor_rank}.dat. +- **Description**: Whether to output the eigenstates (excitation energy) and eigenvectors + (excitation amplitude) of the LR-TDDFT calculation. The output files are + OUT.\{suffix}/Excitation_Amplitude\_\$\{processor_rank}.dat. - **Default**: False ### abs_gauge - **Type**: String -- **Description**: Whether to use length or velocity gauge to calculate the absorption spectrum in LR-TDDFT. +- **Description**: Whether to use length or velocity gauge to calculate the absorption spectrum in + LR-TDDFT. - **Default**: length ### abs_broadening @@ -4626,7 +5590,8 @@ ### rdmft_power_alpha - **Type**: Real -- **Description**: The alpha parameter of power-functional(or other exx-type/hybrid functionals) which used in RDMFT, g(occ_number) = occ_number^alpha +- **Description**: The alpha parameter of power-functional(or other exx-type/hybrid functionals) + which used in RDMFT, g(occ_number) = occ_number^alpha - **Default**: 0.656 [back to top](#full-list-of-input-keywords) diff --git a/docs/advanced/input_files/kpt.md b/docs/advanced/input_files/kpt.md index 1aac138fd00..e3551812417 100644 --- a/docs/advanced/input_files/kpt.md +++ b/docs/advanced/input_files/kpt.md @@ -4,20 +4,27 @@ - [Set k-points explicitly](#set-k-points-explicitly) - [Band structure calculations](#band-structure-calculations) -ABACUS uses periodic boundary conditions for both crystals and finite systems. For isolated systems, such as atoms, molecules, clusters, etc., one uses the so-called supercell model. Lattice vectors of the supercell are set in the `STRU` file. For the input k-point (`KPT`) file, the file should either contain the k-point coordinates and weights or the mesh size for creating the k-point gird. Both options are allowed in `ABACUS`. +ABACUS uses periodic boundary conditions for both crystals and finite systems. For isolated systems, +such as atoms, molecules, clusters, etc., one uses the so-called supercell model. Lattice vectors of +the supercell are set in the `STRU` file. For the input k-point (`KPT`) file, the file should either +contain the k-point coordinates and weights or the mesh size for creating the k-point gird. Both +options are allowed in `ABACUS`. ## Gamma-only Calculations -In ABACUS, we offer the option of running gamma-only calculations for LCAO basis by setting [gamma_only](./input-main.md#gamma_only) to be 1. Due to details of implementation, gamma-only calculation will be slightly faster than running a non gamma-only calculation and explicitly setting gamma point to be the only the k-point, but the results should be consistent. +In ABACUS, we offer the option of running gamma-only calculations for LCAO basis by setting +[gamma_only](./input-main.md#gamma_only) to be 1. Due to details of implementation, gamma-only +calculation will be slightly faster than running a non gamma-only calculation and explicitly setting +gamma point to be the only the k-point, but the results should be consistent. -> If gamma_only is set to 1, the KPT file will be overwritten. So make sure to turn off gamma_only for multi-k calculations. +> If gamma_only is set to 1, the KPT file will be overwritten. So make sure to turn off gamma_only +> for multi-k calculations. ## Generate k-mesh automatically -To generate k-mesh automatically, it requires the input subdivisions of the Brillouin zone -in each direction and the origin for the k-mesh. ABACUS uses the Monkhorst-Pack -method to generate k-mesh, and the following is an example input k-point (`KPT`) file used in -`ABACUS`. +To generate k-mesh automatically, it requires the input subdivisions of the Brillouin zone in each +direction and the origin for the k-mesh. ABACUS uses the Monkhorst-Pack method to generate k-mesh, +and the following is an example input k-point (`KPT`) file used in `ABACUS`. ``` K_POINTS //keyword for start @@ -27,22 +34,23 @@ Gamma //which kind of Monkhorst-Pack method, `Gamma' or `MP' //last three number: shift of the mesh ``` -In the above example, the first line is a keyword, and it can be set as `K_POINTS`, or `KPOINTS` or just `K`. -The second line is an integer, and its value determines how to get k-points. In this example, `0` means using Monkhorst-Pack (MP) method to generate k-points automatically. +In the above example, the first line is a keyword, and it can be set as `K_POINTS`, or `KPOINTS` or +just `K`. The second line is an integer, and its value determines how to get k-points. In this +example, `0` means using Monkhorst-Pack (MP) method to generate k-points automatically. -The third line tells the input type of k-points, `Gamma` or `MP`, different Monkhorst Pack -(MP) method. Monkhorst-Pack (MP) is a method which uses the uniform k-points sampling in -Brillouin-zone, while `Gamma` means the Γ-centered Monkhorst-Pack method. -The first three numbers of the last line are integers, which give the MP k grid dimensions, and -the rest three are real numbers, which give the offset of the k grid. In this example, the numbers -`0 0 0` means that there is no offset, and this is the a standard 2by2by2 k grid. +The third line tells the input type of k-points, `Gamma` or `MP`, different Monkhorst Pack (MP) +method. Monkhorst-Pack (MP) is a method which uses the uniform k-points sampling in Brillouin-zone, +while `Gamma` means the Γ-centered Monkhorst-Pack method. The first three numbers of the last line +are integers, which give the MP k grid dimensions, and the rest three are real numbers, which give +the offset of the k grid. In this example, the numbers `0 0 0` means that there is no offset, and +this is the a standard 2by2by2 k grid. [back to top](#the-kpt-file) ## Set k-points explicitly -If the user wants to set up the k-points explicitly, the input k-point file should contain -the k-point coordinates and weights. An example is given as follows: +If the user wants to set up the k-points explicitly, the input k-point file should contain the +k-point coordinates and weights. An example is given as follows: ``` K_POINTS //keyword for start @@ -60,17 +68,26 @@ Direct //`Direct' or `Cartesian' coordinate ### K-point Weights and Symmetry -When explicitly setting k-points, you can specify custom weights for each k-point. These weights determine the contribution of each k-point to the total energy and density calculations. +When explicitly setting k-points, you can specify custom weights for each k-point. These weights +determine the contribution of each k-point to the total energy and density calculations. **Important notes about k-point weights:** -1. **Custom weights are preserved**: When using explicit k-point lists (non-Monkhorst-Pack), ABACUS preserves the custom weights you specify, even when symmetry operations are applied to reduce the k-points to the irreducible Brillouin zone (IBZ). +1. **Custom weights are preserved**: When using explicit k-point lists (non-Monkhorst-Pack), ABACUS + preserves the custom weights you specify, even when symmetry operations are applied to reduce the + k-points to the irreducible Brillouin zone (IBZ). -2. **Symmetry reduction**: When [`symmetry`](./input-main.md#symmetry) is set to 1, ABACUS will analyze the crystal symmetry and reduce the k-point set to the irreducible Brillouin zone. During this reduction: - - For **Monkhorst-Pack grids** (automatically generated): All k-points have uniform weights (1/N where N is the total number of k-points) - - For **explicit k-point lists**: Custom weights are preserved and properly combined when symmetry-equivalent k-points are merged +1. **Symmetry reduction**: When [`symmetry`](./input-main.md#symmetry) is set to 1, ABACUS will + analyze the crystal symmetry and reduce the k-point set to the irreducible Brillouin zone. During + this reduction: -3. **Weight normalization**: After symmetry reduction, k-point weights are normalized so that their sum equals `degspin` (2 for non-spin-polarized calculations, 1 for spin-polarized calculations). + - For **Monkhorst-Pack grids** (automatically generated): All k-points have uniform weights (1/N + where N is the total number of k-points) + - For **explicit k-point lists**: Custom weights are preserved and properly combined when + symmetry-equivalent k-points are merged + +1. **Weight normalization**: After symmetry reduction, k-point weights are normalized so that their + sum equals `degspin` (2 for non-spin-polarized calculations, 1 for spin-polarized calculations). **Example with custom weights:** @@ -86,20 +103,23 @@ Direct ``` In this example, different k-points have different weights, which might be useful for: + - Special sampling schemes - Convergence testing with specific k-point importance - Custom integration methods -> **Note**: When using custom weights with symmetry, ensure that your weight distribution is consistent with the crystal symmetry. ABACUS will preserve your weights during IBZ reduction, but inconsistent weights may lead to unexpected results. +> **Note**: When using custom weights with symmetry, ensure that your weight distribution is +> consistent with the crystal symmetry. ABACUS will preserve your weights during IBZ reduction, but +> inconsistent weights may lead to unexpected results. [back to top](#the-kpt-file) ## Band structure calculations ABACUS uses specified high-symmetry directions of the Brillouin zone for band structure -calculations. The third line of k-point file should start with 'Line' or 'Line_Cartesian' for -line mode. 'Line' means the positions below are in Direct coordinates, while 'Line_Cartesian' -means in Cartesian coordinates: +calculations. The third line of k-point file should start with 'Line' or 'Line_Cartesian' for line +mode. 'Line' means the positions below are in Direct coordinates, while 'Line_Cartesian' means in +Cartesian coordinates: ``` K_POINTS // keyword for start @@ -113,7 +133,7 @@ Line // line-mode 0.0 0.0 0.0 1 // G ``` -The fourth line and the following are special k-point coordinates and number of k-points -between this special k-point and the next. +The fourth line and the following are special k-point coordinates and number of k-points between +this special k-point and the next. [back to top](#the-kpt-file) diff --git a/docs/advanced/input_files/stru.md b/docs/advanced/input_files/stru.md index a30064351a4..ad59678632e 100644 --- a/docs/advanced/input_files/stru.md +++ b/docs/advanced/input_files/stru.md @@ -14,12 +14,15 @@ ## Examples -The `STRU` file contains the information about the lattice geometry, the name(s) and/or location(s) of the pseudopotential and numerical orbital files, as well as the structural information about the system. -We supply two ways of specifying the lattice geometry. Below are two examples of the `STRU` file for the same system: +The `STRU` file contains the information about the lattice geometry, the name(s) and/or location(s) +of the pseudopotential and numerical orbital files, as well as the structural information about the +system. We supply two ways of specifying the lattice geometry. Below are two examples of the `STRU` +file for the same system: ### No latname -For this example, no need to supply any input to the variable `latname` in the INPUT file. (See [input parameters](input-main.md#latname).) +For this example, no need to supply any input to the variable `latname` in the INPUT file. (See +[input parameters](input-main.md#latname).) ``` ATOMIC_SPECIES @@ -47,8 +50,10 @@ Si // Element type ### latname fcc -We see that this example is a silicon fcc lattice. Apart from setting the lattice vectors manually, we also provide another solution where only the Bravais lattice type is required, and the lattice vectors will be generated automatically. For this example, we need to set `latname="fcc"` in the INPUT file. (See [input parameters](input-main.md#latname).) -And the `STRU` file becomes: +We see that this example is a silicon fcc lattice. Apart from setting the lattice vectors manually, +we also provide another solution where only the Bravais lattice type is required, and the lattice +vectors will be generated automatically. For this example, we need to set `latname="fcc"` in the +INPUT file. (See [input parameters](input-main.md#latname).) And the `STRU` file becomes: ``` ATOMIC_SPECIES @@ -79,265 +84,377 @@ information that comes below. ### ATOMIC_SPECIES - This section provides information about the type of chemical elements contained the unit cell. Each line defines one type of element. The user should specify the name, the mass, and the pseudopotential file used for each element. The mass of the elment is only used in molecular dynamics simulations. For electronic-structure calculations, the actual mass value isn’t important. - In the above example, we see information is provided for the element `Si`: +This section provides information about the type of chemical elements contained the unit cell. Each +line defines one type of element. The user should specify the name, the mass, and the +pseudopotential file used for each element. The mass of the elment is only used in molecular +dynamics simulations. For electronic-structure calculations, the actual mass value isn’t important. +In the above example, we see information is provided for the element `Si`: - ``` - Si 28.00 Si_ONCV_PBE-1.0.upf upf201 // label; mass; pseudo_file; pseudo_type - ``` - Here `Si_ONCV_PBE-1.0.upf` is the pseudopotential file. When the path is not specified, the file is assumed to be located in work directory. Otherwise, please explicitly specify the location of the pseudopotential files. +``` +Si 28.00 Si_ONCV_PBE-1.0.upf upf201 // label; mass; pseudo_file; pseudo_type +``` + +Here `Si_ONCV_PBE-1.0.upf` is the pseudopotential file. When the path is not specified, the file is +assumed to be located in work directory. Otherwise, please explicitly specify the location of the +pseudopotential files. - After the pseudopotential file, `upf201` is the type of pseudopotential. There are five options: `upf`(.UPF format), `upf201`(the new .UPF format), `vwr`(.vwr format), `blps`(bulk-derived local pseudopotential), and `auto`(automatically identified). If no pseudopotential type is assigned, the default value is `auto`, and the pseudopotential type will be automatically identified. +After the pseudopotential file, `upf201` is the type of pseudopotential. There are five options: +`upf`(.UPF format), `upf201`(the new .UPF format), `vwr`(.vwr format), `blps`(bulk-derived local +pseudopotential), and `auto`(automatically identified). If no pseudopotential type is assigned, the +default value is `auto`, and the pseudopotential type will be automatically identified. - When [esolver_type](./input-main.md#esolver_type) is set to `lj` or `dp`, the keyword `pseudo_file` and `pseudo_type` is needless. +When [esolver_type](./input-main.md#esolver_type) is set to `lj` or `dp`, the keyword `pseudo_file` +and `pseudo_type` is needless. - Different types of pseudopotentials can be used for different elements, but note that the XC functionals assigned by all pseudopotentials should be the same one. If not, the choice of XC functional must be set explicitly using the [dft_functional](./input-main.md#dft_functional) keyword. +Different types of pseudopotentials can be used for different elements, but note that the XC +functionals assigned by all pseudopotentials should be the same one. If not, the choice of XC +functional must be set explicitly using the [dft_functional](./input-main.md#dft_functional) +keyword. - Common sources of the pseudopotential files include: +Common sources of the pseudopotential files include: - 1. [Quantum ESPRESSO](http://www.quantum-espresso.org/pseudopotentials/). - 2. [SG15-ONCV](http://quantum-simulation.org/potentials/sg15_oncv/upf/). - 3. [DOJO](http://www.pseudo-dojo.org/). - 4. [BLPS](https://github.com/PrincetonUniversity/BLPSLibrary). - 5. For additional pseudopotential options and to view the basic benchmark test results of these pseudopotentials in ABACUS, please refer to the [Benchmarks website](https://kirk0830.github.io/ABACUS-Pseudopot-Nao-Square/pseudopotential/pseudopotential.html) +1. [Quantum ESPRESSO](http://www.quantum-espresso.org/pseudopotentials/). +1. [SG15-ONCV](http://quantum-simulation.org/potentials/sg15_oncv/upf/). +1. [DOJO](http://www.pseudo-dojo.org/). +1. [BLPS](https://github.com/PrincetonUniversity/BLPSLibrary). +1. For additional pseudopotential options and to view the basic benchmark test results of these + pseudopotentials in ABACUS, please refer to the + [Benchmarks website](https://kirk0830.github.io/ABACUS-Pseudopot-Nao-Square/pseudopotential/pseudopotential.html) ### NUMERICAL_ORBITAL - Numerical atomic orbitals are only needed for `LCAO` calculations. Thus this section will be neglected in calcultions with plane wave basis. In the above example, numerical atomic orbitals is specified for the element `Si`: +Numerical atomic orbitals are only needed for `LCAO` calculations. Thus this section will be +neglected in calcultions with plane wave basis. In the above example, numerical atomic orbitals is +specified for the element `Si`: - ``` - Si_gga_8au_60Ry_2s2p1d.orb //numerical_orbital_file - ``` - ‘Si_gga_8au_60Ry_2s2p1d.orb’ is name of the numerical orbital file. Again here the path is not specified, which means that this file is located in the work directory. +``` +Si_gga_8au_60Ry_2s2p1d.orb //numerical_orbital_file +``` - Numerical atomic orbitals may be downloaded from the [official website](http://abacus.ustc.edu.cn/pseudo/list.htm). - Recommendation for Pseudopotential and Orbital Sets -For general usage requirements, the APNSv1.0 pseudopotential and orbital set is recommended. You can access it via [AIS square website](https://www.aissquare.com/datasets/detail?pageType=datasets&name=ABACUS-APNS-PPORBs-v1%253Apre-release&id=326) +‘Si_gga_8au_60Ry_2s2p1d.orb’ is name of the numerical orbital file. Again here the path is not +specified, which means that this file is located in the work directory. + +Numerical atomic orbitals may be downloaded from the +[official website](http://abacus.ustc.edu.cn/pseudo/list.htm). Recommendation for Pseudopotential +and Orbital Sets For general usage requirements, the APNSv1.0 pseudopotential and orbital set is +recommended. You can access it via +[AIS square website](https://www.aissquare.com/datasets/detail?pageType=datasets&name=ABACUS-APNS-PPORBs-v1%253Apre-release&id=326) ### LATTICE_CONSTANT - The lattice constant of the system in unit of Bohr. +The lattice constant of the system in unit of Bohr. + ### LATTICE_VECTORS - The lattice vectors of the unit cell. It is a 3by3 matrix written in 3 lines. Please note that *the lattice vectors given here are scaled by the lattice constant*. This section must be removed if the type Bravais lattice is specified using the input parameter `latname`. (See [input parameters](input-main.md#latname).) +The lattice vectors of the unit cell. It is a 3by3 matrix written in 3 lines. Please note that *the +lattice vectors given here are scaled by the lattice constant*. This section must be removed if the +type Bravais lattice is specified using the input parameter `latname`. (See +[input parameters](input-main.md#latname).) + ### LATTICE_PARAMETERS - This section is only relevant when `latname` (see [input parameters](input-main.md#latname)) is used to specify the Bravais lattice type. The example above is a fcc lattice, where no additional information except the lattice constant is required to determine the geometry of the lattice. +This section is only relevant when `latname` (see [input parameters](input-main.md#latname)) is used +to specify the Bravais lattice type. The example above is a fcc lattice, where no additional +information except the lattice constant is required to determine the geometry of the lattice. - However, for other types of Bravais lattice, other parameters might be necessary. In that case, the section `LATTICE_PARAMETERS` must be present. It contains **one single line** with some parameters (separated by blank space if multiple parameters are needed), where the number of parameters required depends on specific type of lattice. +However, for other types of Bravais lattice, other parameters might be necessary. In that case, the +section `LATTICE_PARAMETERS` must be present. It contains **one single line** with some parameters +(separated by blank space if multiple parameters are needed), where the number of parameters +required depends on specific type of lattice. - The three lattice vectors v1, v2, v3 (in units of lattice constant) are generated in the following way: +The three lattice vectors v1, v2, v3 (in units of lattice constant) are generated in the following +way: - - latname = "sc": the LATTICE_PARAMETERS section is not required: +- latname = "sc": the LATTICE_PARAMETERS section is not required: - ``` - v1 = (1, 0, 0) - v2 = (0, 1, 0) - v3 = (0, 0, 1) - ``` - - latname = "fcc": the LATTICE_PARAMETERS section is not required: + ``` + v1 = (1, 0, 0) + v2 = (0, 1, 0) + v3 = (0, 0, 1) + ``` - ``` - v1 = (-0.5, 0, 0.5) - v2 = (0, 0.5, 0.5) - v3 = (-0.5, 0.5, 0) - ``` - - latname = "bcc" : the LATTICE_PARAMETERS section is not required: +- latname = "fcc": the LATTICE_PARAMETERS section is not required: - ``` - v1 = (0.5, 0.5, 0.5) - v2 = (-0.5, 0.5, 0.5) - v3 = (-0.5, -0.5, 0.5) - ``` - - latname = "hexagonal" : One single parameter is required in the LATTICE_PARAMETERS section, being the ratio between axis length c/a. Denote it by x then: + ``` + v1 = (-0.5, 0, 0.5) + v2 = (0, 0.5, 0.5) + v3 = (-0.5, 0.5, 0) + ``` - ``` - v1 = (1.0, 0, 0) - v2 = (-0.5, sqrt(3)/2, 0) - v3 = (0, 0, x) - ``` - - latname = "trigonal" : One single parameter is required in the LATTICE_PARAMETERS section, which specifies cosγ with γ being the angle between any pair of crystallographic vectors. Denote it by x then: +- latname = "bcc" : the LATTICE_PARAMETERS section is not required: - ``` - v1 = (tx, -ty, tz) - v2 = (0, 2ty, tz) - v3 = (-tx, -ty, tz) - ``` - where tx=sqrt((1-x)/2), ty=sqrt((1-x)/6), and tz=sqrt((1+2x)/3). - - latname = "st" (simple tetragonal) : One single parameter is required in the LATTICE_PARAMETERS section, which gives ratio between axis length c/a. Denote it by x then: + ``` + v1 = (0.5, 0.5, 0.5) + v2 = (-0.5, 0.5, 0.5) + v3 = (-0.5, -0.5, 0.5) + ``` - ``` - v1 = (1, 0, 0) - v2 = (0, 1, 0) - v3 = (0, 0, x) - ``` - - latname = "bct" (body-centered tetragonal) : One single parameter is required in the LATTICE_PARAMETERS section, which gives ratio between axis length c/a. Denote it by x then: +- latname = "hexagonal" : One single parameter is required in the LATTICE_PARAMETERS section, being + the ratio between axis length c/a. Denote it by x then: - ``` - v1 = (0.5, -0.5, x) - v2 = (0.5, 0.5, x) - v3 = (-0.5, -0.5, x) - ``` - - latname = "so" (simple orthorhombic) : Two parameters are required in the LATTICE_PARAMETERS section, which gives ratios between axis length b/a and c/a. Denote them by x, y then: + ``` + v1 = (1.0, 0, 0) + v2 = (-0.5, sqrt(3)/2, 0) + v3 = (0, 0, x) + ``` - ``` - v1 = (1, 0, 0) - v2 = (0, x, 0) - v3 = (0, 0, y) - ``` - - latname = "baco" (base-centered orthorhombic) : Two parameters are required in the LATTICE_PARAMETERS section, which gives ratios between axis length b/a and c/a. Denote them by x, y then: +- latname = "trigonal" : One single parameter is required in the LATTICE_PARAMETERS section, which + specifies cosγ with γ being the angle between any pair of crystallographic vectors. Denote it by x + then: - ``` - v1 = (0.5, x/2, 0) - v2 = (-0.5, x/2, 0) - v3 = (0, 0, y) - ``` - - latname = "fco" (face-centered orthorhombic) : Two parameters are required in the LATTICE_PARAMETERS section, which gives ratios between axis length b/a and c/a. Denote them by x, y then: + ``` + v1 = (tx, -ty, tz) + v2 = (0, 2ty, tz) + v3 = (-tx, -ty, tz) + ``` - ``` - v1 = (0.5, 0, y/2) - v2 = (0.5, x/2, 0) - v3 = (0, x/2, y/2) - ``` - - latname = "bco" (body-centered orthorhombic) : Two parameters are required in the LATTICE_PARAMETERS section, which gives ratios between lattice vector length b/a and c/a. Denote them by x, y then: + where tx=sqrt((1-x)/2), ty=sqrt((1-x)/6), and tz=sqrt((1+2x)/3). - ``` - v1 = (0.5, x/2, y/2) - v2 = (-0.5, x/2, y/2) - v3 = (-0.5, -x/2, y/2) - ``` - - latname = "sm" (simple monoclinic) : Three parameters are required in the LATTICE_PARAMETERS section, which are the ratios of lattice vector length b/a, c/a as well as the cosine of angle between axis a and b. Denote them by x, y, z then: +- latname = "st" (simple tetragonal) : One single parameter is required in the LATTICE_PARAMETERS + section, which gives ratio between axis length c/a. Denote it by x then: - ``` - v1 = (1, 0, 0) - v2 = (x*z, x*sqrt(1-z^2, 0) - v3 = (0, 0, y) - ``` - - latname = "bacm" (base-centered monoclinic) : Three parameters are required in the LATTICE_PARAMETERS section, which are the ratios of lattice vector length b/a, c/a as well as the cosine of angle between axis a and b. Denote them by x, y, z then: + ``` + v1 = (1, 0, 0) + v2 = (0, 1, 0) + v3 = (0, 0, x) + ``` + +- latname = "bct" (body-centered tetragonal) : One single parameter is required in the + LATTICE_PARAMETERS section, which gives ratio between axis length c/a. Denote it by x then: + + ``` + v1 = (0.5, -0.5, x) + v2 = (0.5, 0.5, x) + v3 = (-0.5, -0.5, x) + ``` + +- latname = "so" (simple orthorhombic) : Two parameters are required in the LATTICE_PARAMETERS + section, which gives ratios between axis length b/a and c/a. Denote them by x, y then: + + ``` + v1 = (1, 0, 0) + v2 = (0, x, 0) + v3 = (0, 0, y) + ``` + +- latname = "baco" (base-centered orthorhombic) : Two parameters are required in the + LATTICE_PARAMETERS section, which gives ratios between axis length b/a and c/a. Denote them by x, + y then: + + ``` + v1 = (0.5, x/2, 0) + v2 = (-0.5, x/2, 0) + v3 = (0, 0, y) + ``` + +- latname = "fco" (face-centered orthorhombic) : Two parameters are required in the + LATTICE_PARAMETERS section, which gives ratios between axis length b/a and c/a. Denote them by x, + y then: + + ``` + v1 = (0.5, 0, y/2) + v2 = (0.5, x/2, 0) + v3 = (0, x/2, y/2) + ``` + +- latname = "bco" (body-centered orthorhombic) : Two parameters are required in the + LATTICE_PARAMETERS section, which gives ratios between lattice vector length b/a and c/a. Denote + them by x, y then: + + ``` + v1 = (0.5, x/2, y/2) + v2 = (-0.5, x/2, y/2) + v3 = (-0.5, -x/2, y/2) + ``` + +- latname = "sm" (simple monoclinic) : Three parameters are required in the LATTICE_PARAMETERS + section, which are the ratios of lattice vector length b/a, c/a as well as the cosine of angle + between axis a and b. Denote them by x, y, z then: + + ``` + v1 = (1, 0, 0) + v2 = (x*z, x*sqrt(1-z^2, 0) + v3 = (0, 0, y) + ``` + +- latname = "bacm" (base-centered monoclinic) : Three parameters are required in the + LATTICE_PARAMETERS section, which are the ratios of lattice vector length b/a, c/a as well as the + cosine of angle between axis a and b. Denote them by x, y, z then: + + ``` + v1 = (0.5, 0, -y/2) + v2 = (x*z, x*sqrt(1-z^2), 0) + v3 = (0.5, 0, y/2) + ``` + +- latname = "triclinic" : Five parameters are required in the LATTICE_PARAMETERS section, namely the + ratios b/a, c/a; the cosines of angle ab, ac, bc. Denote them by x,y,m,n,l, then: + + ``` + v1 = (1, 0, 0) + v2 = (x*m, x*sqrt(1-m^2), 0) + v3 = (y*n, y*(l-n*m/sqrt(1-m^2)), y*fac) + ``` + + where $fac=\frac{\sqrt{1+2*m*n*l-m^2 -n^2 -l^2 }}{\sqrt{1-m^2}}$ + +### ATOMIC_POSITIONS + +This section specifies the positions and other information of individual atoms. + +The first line signifies method that atom positions are given, the following options are supported: + +- `Direct` : coordinates of atom positions below would in fraction coordinates. +- `Cartesian` : Cartesian coordinates in unit of 'LATTICE_CONSTANT'. +- `Cartesian_au` : Cartesian coordinates in unit of Bohr, same as setting of `Cartesian` with + `LATTICE_CONSTANT` = 1.0 . +- `Cartesian_angstrom` : Cartesian coordinates in unit of Angstrom, same as setting of `Cartesian` + with `LATTICE_CONSTANT` = 1.889726125457828 . +- `Cartesian_angstrom_center_xy` : Cartesian coordinates in unit of Angstrom, with Direct coordinate + (0.5, 0.5, 0.0) as reference. +- `Cartesian_angstrom_center_xz` : Cartesian coordinates in unit of Angstrom, with Direct coordinate + (0.5, 0.0, 0.5) as reference.. +- `Cartesian_angstrom_center_yz` : Cartesian coordinates in unit of Angstrom, with Direct coordinate + (0.0, 0.5, 0.5) as reference.. +- `Cartesian_angstrom_center_xyz` : Cartesian coordinates in unit of Angstrom, with Direct + coordinate (0.5, 0.5, 0.5) as reference.. + +The following three lines tells the elemental type (`Fe`), the initial magnetic moment (`1.0`), and +the number of atoms for this particular element (`2`) repsectively. Notice this magnetic moment will +be a default value for every atom of this type but will be overrided if one define it for each atom +by keyword(see below). + +The last two lines in this example are the coordinates of atomic positions. There are three numbers +in each line, which specifies the atomic positions, following by other parameters marked by +keywords. + +### More Key Words + +Several other parameters could be defined after the atom position using key words : + +- `m` or NO key word: three numbers, which take value in 0 or 1, control how the atom move in + geometry relaxation calculations. In example below, the numbers `0 0 0` following the coordinates + of the first atom means this atom are *not allowed* to move in all three directions, and the + numbers `1 1 1` following the coordinates of the second atom means this atom *can* move in all + three directions. + +- `v` or `vel` or `velocity`: set the three components of initial velocity of atoms, used only for + restarting MD calculations (e.g., `v 1.0 1.0 1.0`). + +- `mag` or `magmom` : set the start magnetization for each atom. In colinear case only one number + should be given. In non-colinear case one have two choice:either set one number for the norm of + magnetization here and specify two polar angle later(e. g. see below), or set three number for the + xyz commponent of magnetization here (e. g. `mag 0.0 0.0 1.0`). Note that if this parameter is + set, the initial magnetic moment setting in the second line will be overrided. + + - `angle1`: in non-colinear case, specify the angle between z-axis and real spin, in angle measure + instead of radian measure + + - `angle2`: in non-colinear case, specify angle between x-axis and real spin in projection in + xy-plane , in angle measure instead of radian measure + + e.g.: ``` - v1 = (0.5, 0, -y/2) - v2 = (x*z, x*sqrt(1-z^2), 0) - v3 = (0.5, 0, y/2) + Fe + 1.0 + 2 + 0.0 0.0 0.0 m 0 0 0 mag 1.0 angle1 90 angle2 0 + 0.5 0.5 0.5 m 1 1 1 mag 1.0 angle1 90 angle2 180 ``` - - latname = "triclinic" : Five parameters are required in the LATTICE_PARAMETERS section, namely the ratios b/a, c/a; the cosines of angle ab, ac, bc. Denote them by x,y,m,n,l, then: + + - Default: If users do not specalize a finite magnetic moment for all atoms in a magnetic + calculations (`nspin==2 || nspin == 4`), e.g.: ``` - v1 = (1, 0, 0) - v2 = (x*m, x*sqrt(1-m^2), 0) - v3 = (y*n, y*(l-n*m/sqrt(1-m^2)), y*fac) + Fe + 0.0 + 2 + 0.0 0.0 0.0 m 0 0 0 + 0.5 0.5 0.5 m 1 1 1 + + O + 0.0 + 2 + 0.0 0.0 0.0 m 0 0 0 + 0.5 0.5 0.5 m 1 1 1 ``` - where $fac=\frac{\sqrt{1+2*m*n*l-m^2 -n^2 -l^2 }}{\sqrt{1-m^2}}$ -### ATOMIC_POSITIONS - This section specifies the positions and other information of individual atoms. + For `nspin==2`, we will autoset atomic magmon is `1.0`: - The first line signifies method that atom positions are given, the following options are supported: + ``` + Fe + 1.0 + 2 + 0.0 0.0 0.0 m 0 0 0 + 0.5 0.5 0.5 m 1 1 1 + + Fe + 1.0 + 2 + 0.0 0.0 0.0 m 0 0 0 + 0.5 0.5 0.5 m 1 1 1 + ``` - - `Direct` : coordinates of atom positions below would in fraction coordinates. - - `Cartesian` : Cartesian coordinates in unit of 'LATTICE_CONSTANT'. - - `Cartesian_au` : Cartesian coordinates in unit of Bohr, same as setting of `Cartesian` with `LATTICE_CONSTANT` = 1.0 . - - `Cartesian_angstrom` : Cartesian coordinates in unit of Angstrom, same as setting of `Cartesian` with `LATTICE_CONSTANT` = 1.889726125457828 . - - `Cartesian_angstrom_center_xy` : Cartesian coordinates in unit of Angstrom, with Direct coordinate (0.5, 0.5, 0.0) as reference. - - `Cartesian_angstrom_center_xz` : Cartesian coordinates in unit of Angstrom, with Direct coordinate (0.5, 0.0, 0.5) as reference.. - - `Cartesian_angstrom_center_yz` : Cartesian coordinates in unit of Angstrom, with Direct coordinate (0.0, 0.5, 0.5) as reference.. - - `Cartesian_angstrom_center_xyz` : Cartesian coordinates in unit of Angstrom, with Direct coordinate (0.5, 0.5, 0.5) as reference.. + For `nspin==4`, we will autoset atomic magmon as follow: - The following three lines tells the elemental type (`Fe`), the initial magnetic moment (`1.0`), and the number of atoms for this particular element (`2`) repsectively. Notice this magnetic moment will be a default value for every atom of this type but will be overrided if one define it for each atom by keyword(see below). + ``` + Fe + 0.0 + 2 + 0.0 0.0 0.0 m 0 0 0 mag 1 1 1 + 0.5 0.5 0.5 m 1 1 1 mag 1 1 1 + + O + 0.0 + 2 + 0.0 0.0 0.0 m 0 0 0 mag 1 1 1 + 0.5 0.5 0.5 m 1 1 1 mag 1 1 1 + ``` - The last two lines in this example are the coordinates of atomic positions. There are three numbers in each line, which specifies the atomic positions, following by other parameters marked by keywords. + However, this autoset will not be vaild once `STRU` specalize a finite magnetic for any single + atom. -### More Key Words +- `lambda`: Lagrange multiplier vector for spin constraint method. Can specify one value + (z-component) or three values for x, y, z components (e.g., `lambda 0.5` or `lambda 0.1 0.2 0.3`). + Values are in eV and will be converted to Rydberg internally. Used with spin-constrained DFT + (enable with `sc_mag_switch` in INPUT file). - Several other parameters could be defined after the atom position using key words : - - - `m` or NO key word: three numbers, which take value in 0 or 1, control how the atom move in geometry relaxation calculations. In example below, the numbers `0 0 0` following the coordinates of the first atom means this atom are *not allowed* to move in all three directions, and the numbers `1 1 1` following the coordinates of the second atom means this atom *can* move in all three directions. - - `v` or `vel` or `velocity`: set the three components of initial velocity of atoms, used only for restarting MD calculations (e.g., `v 1.0 1.0 1.0`). - - `mag` or `magmom` : set the start magnetization for each atom. In colinear case only one number should be given. In non-colinear case one have two choice:either set one number for the norm of magnetization here and specify two polar angle later(e. g. see below), or set three number for the xyz commponent of magnetization here (e. g. `mag 0.0 0.0 1.0`). Note that if this parameter is set, the initial magnetic moment setting in the second line will be overrided. - - `angle1`: in non-colinear case, specify the angle between z-axis and real spin, in angle measure instead of radian measure - - `angle2`: in non-colinear case, specify angle between x-axis and real spin in projection in xy-plane , in angle measure instead of radian measure - - e.g.: - - ``` - Fe - 1.0 - 2 - 0.0 0.0 0.0 m 0 0 0 mag 1.0 angle1 90 angle2 0 - 0.5 0.5 0.5 m 1 1 1 mag 1.0 angle1 90 angle2 180 - ``` - - - Default: If users do not specalize a finite magnetic moment for all atoms in a magnetic calculations (`nspin==2 || nspin == 4`), e.g.: - ``` - Fe - 0.0 - 2 - 0.0 0.0 0.0 m 0 0 0 - 0.5 0.5 0.5 m 1 1 1 - - O - 0.0 - 2 - 0.0 0.0 0.0 m 0 0 0 - 0.5 0.5 0.5 m 1 1 1 - ``` - For `nspin==2`, we will autoset atomic magmon is `1.0`: - ``` - Fe - 1.0 - 2 - 0.0 0.0 0.0 m 0 0 0 - 0.5 0.5 0.5 m 1 1 1 - - Fe - 1.0 - 2 - 0.0 0.0 0.0 m 0 0 0 - 0.5 0.5 0.5 m 1 1 1 - ``` - For `nspin==4`, we will autoset atomic magmon as follow: - ``` - Fe - 0.0 - 2 - 0.0 0.0 0.0 m 0 0 0 mag 1 1 1 - 0.5 0.5 0.5 m 1 1 1 mag 1 1 1 - - O - 0.0 - 2 - 0.0 0.0 0.0 m 0 0 0 mag 1 1 1 - 0.5 0.5 0.5 m 1 1 1 mag 1 1 1 - ``` - However, this autoset will not be vaild once `STRU` specalize a finite magnetic for any single atom. - - - `lambda`: Lagrange multiplier vector for spin constraint method. Can specify one value (z-component) or three values for x, y, z components (e.g., `lambda 0.5` or `lambda 0.1 0.2 0.3`). Values are in eV and will be converted to Rydberg internally. Used with spin-constrained DFT (enable with `sc_mag_switch` in INPUT file). - - - `sc`: set the spin constraint target magnetization for each atom. Can specify one value (z-component) or three values for x, y, z components (e.g., `sc 1.0` or `sc 0.5 0.5 1.0`). Used with spin-constrained DFT (enable with `sc_mag_switch` in INPUT file). +- `sc`: set the spin constraint target magnetization for each atom. Can specify one value + (z-component) or three values for x, y, z components (e.g., `sc 1.0` or `sc 0.5 0.5 1.0`). Used + with spin-constrained DFT (enable with `sc_mag_switch` in INPUT file). ### Important Notes for ATOMIC_POSITIONS 1. **Coordinate System Selection**: Choose the appropriate coordinate system based on your needs: + - Use `Direct` for fractional coordinates (most common for periodic systems) - Use `Cartesian_angstrom` when working with molecular structures or experimental data - - Use centered coordinate systems (`Cartesian_angstrom_center_xy/xz/yz/xyz`) for surface or slab calculations where you want to center the structure + - Use centered coordinate systems (`Cartesian_angstrom_center_xy/xz/yz/xyz`) for surface or slab + calculations where you want to center the structure + +1. **Magnetization Settings**: -2. **Magnetization Settings**: - For collinear calculations (`nspin=2`), only specify one magnetization value per atom - For non-collinear calculations (`nspin=4`), you can specify: - Three components directly: `mag 1.0 0.0 0.0` (mx, my, mz) - Magnitude with angles: `mag 1.0 angle1 90 angle2 0` (magnitude, polar angle, azimuthal angle) - - If no magnetization is specified for any atom, ABACUS will automatically set default values (1.0 for nspin=2, or (1,1,1) for nspin=4) + - If no magnetization is specified for any atom, ABACUS will automatically set default values + (1.0 for nspin=2, or (1,1,1) for nspin=4) + +1. **Movement Constraints**: -3. **Movement Constraints**: - Use `m 1 1 1` to allow the atom to move freely in all directions during relaxation - Use `m 0 0 0` to fix the atom completely - - Use `m 1 0 1` to allow movement only in x and z directions (useful for constraining surface atoms) + - Use `m 1 0 1` to allow movement only in x and z directions (useful for constraining surface + atoms) + +1. **Keyword Order**: The optional keywords (m, v, mag, angle1, angle2, lambda, sc) can appear in + any order after the atomic coordinates, but each keyword should only appear once per atom. -4. **Keyword Order**: The optional keywords (m, v, mag, angle1, angle2, lambda, sc) can appear in any order after the atomic coordinates, but each keyword should only appear once per atom. +1. **Common Mistakes to Avoid**: -5. **Common Mistakes to Avoid**: - Don't mix Direct and Cartesian coordinates in the same STRU file - Ensure the number of atoms specified matches the actual number of coordinate lines provided - When using vector magnetization (`mag x y z`), don't also specify angles for the same atom - - Remember that angles are in degrees, not radians \ No newline at end of file + - Remember that angles are in degrees, not radians diff --git a/docs/advanced/install.md b/docs/advanced/install.md index 0df93f602a5..30c509fe851 100644 --- a/docs/advanced/install.md +++ b/docs/advanced/install.md @@ -1,16 +1,20 @@ # Advanced Installation Options -This guide helps you install ABACUS with advanced features. Please make sure to read the [easy-installation guide](../quick_start/easy_install.md) before. +This guide helps you install ABACUS with advanced features. Please make sure to read the +[easy-installation guide](../quick_start/easy_install.md) before. ## Build with Libxc -ABACUS use exchange-correlation functionals by default. However, for some functionals (such as HSE hybrid functional), Libxc is required. +ABACUS use exchange-correlation functionals by default. However, for some functionals (such as HSE +hybrid functional), Libxc is required. Dependency: [Libxc](https://tddft.org/programs/libxc/) >= 5.1.7 . -> Note: Building Libxc from source with Makefile does NOT support using it in CMake here. Please compile Libxc with CMake instead. +> Note: Building Libxc from source with Makefile does NOT support using it in CMake here. Please +> compile Libxc with CMake instead. -If Libxc is not installed in standard path (i.e. installed with a custom prefix path), you can set `Libxc_DIR` to the corresponding directory. +If Libxc is not installed in standard path (i.e. installed with a custom prefix path), you can set +`Libxc_DIR` to the corresponding directory. ```bash cmake -B build -DLibxc_DIR=~/libxc @@ -18,10 +22,13 @@ cmake -B build -DLibxc_DIR=~/libxc ## Build with ML-ALGO -If machine learning algorithms, including DeePKS and machine learning based kinetic energy density functional (ML-KEDF) for OFDFT, is required for DFT calculation, the following prerequisites and steps are needed: +If machine learning algorithms, including DeePKS and machine learning based kinetic energy density +functional (ML-KEDF) for OFDFT, is required for DFT calculation, the following prerequisites and +steps are needed: - C++ compiler, supporting **C++14** (GCC >= 5 is sufficient) - CMake >= 3.18 +- Pass `-DENABLE_MLALGO=ON` to CMake. - [LibTorch](https://pytorch.org/) with cxx11 ABI supporting CPU or GPU - [Libnpy](https://github.com/llohse/libnpy/) @@ -29,39 +36,62 @@ If machine learning algorithms, including DeePKS and machine learning based kine cmake -B build -DENABLE_MLALGO=1 -DTorch_DIR=~/libtorch/share/cmake/Torch/ -Dlibnpy_INCLUDE_DIR=~/libnpy/include ``` +The following feature switches can be used together with `ENABLE_MLALGO`: + +- `ENABLE_DEEPKS=OFF`: Enable DeePKS support. +- `ENABLE_MLKEDF=OFF`: Enable machine-learning kinetic energy density functional support for OFDFT. + +For DeePKS calculations, see also the [DeePKS interface guide](interface/deepks.md). + > CMake will try to download Libnpy if it cannot be found locally. ## Build with DeePMD-kit -> Note: This part is only required if you want to load a trained DeeP Potential and run molecular dynamics with that. To train the DeeP Potential with DP-GEN, no extra prerequisite is needed and please refer to [this page](http://abacus.deepmodeling.com/en/latest/advanced/interface/dpgen.html) for ABACUS interface with DP-GEN. +> Note: This part is only required if you want to load a trained DeeP Potential and run molecular +> dynamics with that. To train the DeeP Potential with DP-GEN, no extra prerequisite is needed and +> please refer to +> [this page](http://abacus.deepmodeling.com/en/latest/advanced/interface/dpgen.html) for ABACUS +> interface with DP-GEN. -If the Deep Potential model is employed in Molecule Dynamics calculations, the following prerequisites and steps are needed: +If the Deep Potential model is employed in Molecule Dynamics calculations, the following +prerequisites and steps are needed: - [DeePMD-kit](https://github.com/deepmodeling/deepmd-kit) - [TensorFlow](https://www.tensorflow.org/) (optional) - [LibTorch](https://pytorch.org/) (optional) -In the simplest case, the `tensorflow_cc` and `torch` libraries are in the same directory as the `deepmd_c`/`deepmd_cc` libraries, then +In the simplest case, the `tensorflow_cc` and `torch` libraries are in the same directory as the +`deepmd_c`/`deepmd_cc` libraries, then + ```bash cmake -B build -DDeePMD_DIR=/dir_to_deepmd-kit ``` + DeePMD-kit supports TensorFlow backend but its libraries are placed at another directory, then ```bash cmake -B build -DDeePMD_DIR=/dir_to_deepmd-kit -DTensorFlow_DIR=/dir_to_tensorflow ``` -Similarly, DeePMD-kit supports PyTorch backend but its libraries are placed at another directory, then + +Similarly, DeePMD-kit supports PyTorch backend but its libraries are placed at another directory, +then + ```bash cmake -B build -DDeePMD_DIR=/dir_to_deepmd-kit -DTorch_DIR=/dir_to_pytorch ``` ## Build with NEP -This interface enables running MD simulations with the NEP model. It requires the [NEP_CPU](https://github.com/brucefan1983/NEP_CPU) library, which can be easily installed using toolchain as shown below: + +This interface enables running MD simulations with the NEP model. It requires the +[NEP_CPU](https://github.com/brucefan1983/NEP_CPU) library, which can be easily installed using +toolchain as shown below: + ```bash ./install_abacus_toolchain_new.sh --with-nep=install ``` To build ABACUS: + ```bash cmake -B build -DNEP_DIR=/path/to/nep_cpu ``` @@ -73,13 +103,19 @@ The new EXX implementation depends on two external libraries: - [LibRI](https://github.com/abacusmodeling/LibRI) - [LibComm](https://github.com/abacusmodeling/LibComm) -These two libraries are added as submodules in the [deps](https://github.com/deepmodeling/abacus-develop/tree/develop/deps) folder. Set `-DENABLE_LIBRI=ON` to build with these two libraries. +These two libraries are added as submodules in the +[deps](https://github.com/deepmodeling/abacus-develop/tree/develop/deps) folder. Set +`-DENABLE_LIBRI=ON` to build with these two libraries. If LibComm support is needed separately, set +`-DENABLE_LIBCOMM=ON`. -If you prefer using manually downloaded libraries, provide `-DLIBRI_DIR=${path to your LibRI folder} -DLIBCOMM_DIR=${path to your LibComm folder}`. +If you prefer using manually downloaded libraries, provide +`-DLIBRI_DIR=${path to your LibRI folder} -DLIBCOMM_DIR=${path to your LibComm folder}`. ## Build Unit Tests -To build tests for ABACUS, define `BUILD_TESTING` flag. You can also specify path to local installation of [Googletest](https://github.com/google/googletest) by setting `GTEST_DIR` flags. If not found in local, the configuration process will try to download it automatically. +To build tests for ABACUS, define `BUILD_TESTING` flag. You can also specify path to local +installation of [Googletest](https://github.com/google/googletest) by setting `GTEST_DIR` flags. If +not found in local, the configuration process will try to download it automatically. ```bash cmake -B build -DBUILD_TESTING=1 @@ -87,40 +123,67 @@ cmake -B build -DBUILD_TESTING=1 After building and installing, unit tests can be performed with `ctest`. -To run a subset of unit test, use `ctest -R ` to perform tests with name matched by given pattern. +To run a subset of unit test, use `ctest -R ` to perform tests with name matched +by given pattern. ## Build Performance Tests -To build performance tests for ABACUS, define `ENABLE_GOOGLEBENCH` flag. You can also specify the path to a local installation of [Google Benchmark](https://github.com/google/benchmark.git) by setting `BENCHMARK_DIR` flags. If not found locally, the configuration process will try to download it automatically. +To build performance tests for ABACUS, define `ENABLE_GOOGLEBENCH` flag. You can also specify the +path to a local installation of [Google Benchmark](https://github.com/google/benchmark.git) by +setting `BENCHMARK_DIR` flags. If not found locally, the configuration process will try to download +it automatically. ```bash cmake -B build -DENABLE_GOOGLEBENCH=1 ``` -Google Benchmark requires Google Test to build and run the tests. When setting `ENABLE_GOOGLEBENCH` to ON, `BUILD_TESTING` is automatically enabled. After building and installing, performance tests can be executed with `ctest`. +Google Benchmark requires Google Test to build and run the tests. When setting `ENABLE_GOOGLEBENCH` +to ON, `BUILD_TESTING` is automatically enabled. After building and installing, performance tests +can be executed with `ctest`. -## Build with CUDA support +## Build with accelerator support -### Extra prerequisites +### CUDA - [CUDA-Toolkit](https://developer.nvidia.com/cuda-toolkit) -To build NVIDIA GPU support for ABACUS, define `USE_CUDA` flag. You can also specify path to local installation of CUDA Toolkit by setting `CMAKE_CUDA_COMPILER` flags. +To build NVIDIA GPU support for ABACUS, define `USE_CUDA` flag. You can also specify path to local +installation of CUDA Toolkit by setting `CMAKE_CUDA_COMPILER` flags. ```bash cmake -B build -DUSE_CUDA=1 -DCMAKE_CUDA_COMPILER=${path to cuda toolkit}/bin/nvcc ``` -If you are confident that your MPI supports CUDA Aware, you can add `-DUSE_CUDA_MPI=ON`. In this case, the program will directly communicate data with the CUDA hardware, rather than transferring it to the CPU first before communication. But note that if CUDA Aware is not supported, adding `-DUSE_CUDA_MPI=ON` will cause the program to throw an error. +If you are confident that your MPI supports CUDA Aware, you can add `-DUSE_CUDA_MPI=ON`. In this +case, the program will directly communicate data with the CUDA hardware, rather than transferring it +to the CPU first before communication. But note that if CUDA Aware is not supported, adding +`-DUSE_CUDA_MPI=ON` will cause the program to throw an error. + +### Others + +In addition to `USE_CUDA`, several accelerator-related CMake options are available for specific +platforms or optional GPU libraries: + +- `USE_ROCM=OFF`: Enable ROCm/HIP support for supported AMD GPU platforms. +- `USE_CUDA_ON_DCU=OFF`: Build the CUDA-compatible accelerator code path on DCU platforms when the + corresponding toolchain is available. +- `USE_DSP=OFF`: Enable DSP-related support when building with a supported platform toolchain. +- `USE_SW=OFF`: Enable SW platform support when building with a supported platform toolchain. +- `ENABLE_CUSOLVERMP=OFF`: Enable cuSOLVERMp support for GPU-accelerated distributed eigensolvers. +- `ENABLE_NCCL_PARALLEL_DEVICE=OFF`: Enable NCCL-based parallel GPU communication support. + +These options require the corresponding vendor toolchains and libraries. They are disabled by +default and should only be enabled on supported platforms. ## Build math library from source -> Note: We recommend using the latest available compiler sets, since they offer faster implementations of math functions. +> Note: We recommend using the latest available compiler sets, since they offer faster +> implementations of math functions. -This flag is disabled by default. To build math functions from source code, define `USE_ABACUS_LIBM` flag. It is expected to get a better performance on legacy versions of `gcc` and `clang`. +This flag is disabled by default. To build math functions from source code, define `USE_ABACUS_LIBM` +flag. It is expected to get a better performance on legacy versions of `gcc` and `clang`. -Currently supported math functions: - `sin`, `cos`, `sincos`, `exp`, `cexp` +Currently supported math functions: `sin`, `cos`, `sincos`, `exp`, `cexp` ```bash cmake -B build -DUSE_ABACUS_LIBM=1 @@ -128,11 +191,16 @@ cmake -B build -DUSE_ABACUS_LIBM=1 ## Build with PEXSI support -ABACUS supports the PEXSI library for gamma only LCAO calculations. PEXSI version 2.0.0 is tested to work with ABACUS, please always use the latest version of PEXSI. +ABACUS supports the PEXSI library for gamma only LCAO calculations. PEXSI version 2.0.0 is tested to +work with ABACUS, please always use the latest version of PEXSI. -To build ABACUS with PEXSI support, you need to compile PEXSI (and its dependencies) first. Please refer to the [PEXSI Installation Guide](https://pexsi.readthedocs.io/en/latest/install.html) for more details. Note that PEXSI requires ParMETIS and SuperLU_DIST. +To build ABACUS with PEXSI support, you need to compile PEXSI (and its dependencies) first. Please +refer to the [PEXSI Installation Guide](https://pexsi.readthedocs.io/en/latest/install.html) for +more details. Note that PEXSI requires ParMETIS and SuperLU_DIST. -After compiling PEXSI, you can set `ENABLE_PEXSI` to `ON`. If the libraries are not installed in standard paths, you can set `PEXSI_DIR`, `ParMETIS_DIR` and `SuperLU_DIST_DIR` to the corresponding directories. +After compiling PEXSI, you can set `ENABLE_PEXSI` to `ON`. If the libraries are not installed in +standard paths, you can set `PEXSI_DIR`, `ParMETIS_DIR` and `SuperLU_DIST_DIR` to the corresponding +directories. ```bash cmake -B build -DENABLE_PEXSI=ON -DPEXSI_DIR=${path to PEXSI installation directory} -DParMETIS_DIR=${path to ParMETIS installation directory} -DSuperLU_DIST_DIR=${path to SuperLU_DIST installation directory} @@ -142,7 +210,8 @@ cmake -B build -DENABLE_PEXSI=ON -DPEXSI_DIR=${path to PEXSI installation direct > Note: We suggest using CMake to configure and compile. -To compile the ABACUS program using legacy `make`, users need to specify the location of the compilers, headers and libraries in `source/Makefile.vars`: +To compile the ABACUS program using legacy `make`, users need to specify the location of the +compilers, headers and libraries in `source/Makefile.vars`: ```makefile # This is the Makefile of ABACUS API @@ -214,7 +283,7 @@ CEREAL_DIR = /usr/local/include/cereal # LIBNPY_DIR = /usr/local ENABLE_MLALGO = OFF -# LIBXC_DIR = /public/soft/libxc +# LIBXC_DIR = /public/soft/libxc # DeePMD_DIR = ${deepmd_root} # TensorFlow_DIR = ${tensorflow_root} @@ -235,8 +304,8 @@ ENABLE_MLALGO = OFF #====================================================================== ``` -For example, below is a case where the Intel C++ compiler, Intel MPI and CEREAL are used, along with Intel MKL library. The file Makefile.vars can be set as -follows: +For example, below is a case where the Intel C++ compiler, Intel MPI and CEREAL are used, along with +Intel MKL library. The file Makefile.vars can be set as follows: ```makefile CXX = mpiicpc #(or CXX = icpc) @@ -245,7 +314,8 @@ ELPA_INCLUDE_DIR = ${ELPA_DIR}/include/elpa-2021.05.002 CEREAL_DIR = /public/soft/cereal ``` -When `CXX=mpiicpc`, a parallel version will be compiled. When `CXX=icpc`, a sequential version will be compiled. +When `CXX=mpiicpc`, a parallel version will be compiled. When `CXX=icpc`, a sequential version will +be compiled. Another example is where the Gnu C++ compiler, MPICH, OPENBLAS, ScaLAPACK, ELPA and CEREAL are used: @@ -259,7 +329,8 @@ ELPA_INCLUDE_DIR = ${ELPA_DIR}/include/elpa-2021.05.002 CEREAL_DIR = /public/soft/cereal ``` -When `CXX=mpicxx`, a parallel version will be compiled. When `CXX=g++`, a sequential version will be compiled. +When `CXX=mpicxx`, a parallel version will be compiled. When `CXX=g++`, a sequential version will be +compiled. Except modifying `Makefile.vars`, you can also directly use @@ -269,15 +340,21 @@ ELPA_INCLUDE_DIR=${ELPA_DIR}/include/elpa-2021.05.002 \ CEREAL_DIR=/public/soft/cereal ``` -ABACUS now support full version and pw version. Use `make` or `make abacus` to compile full version which supports LCAO calculations. Use `make pw` to compile pw version which only supports pw calculations. For pw version, `make pw CXX=mpiicpc`, you do not need to provide any libs. For `make pw CXX=mpicxx`, you need provide `FFTW_DIR` and `OPENBLAS_LIB_DIR`. +ABACUS now support full version and pw version. Use `make` or `make abacus` to compile full version +which supports LCAO calculations. Use `make pw` to compile pw version which only supports pw +calculations. For pw version, `make pw CXX=mpiicpc`, you do not need to provide any libs. For +`make pw CXX=mpicxx`, you need provide `FFTW_DIR` and `OPENBLAS_LIB_DIR`. After modifying the `Makefile.vars` file, execute `make` or `make -j12` to build the program. -After the compilation finishes without error messages (except perhaps for some warnings), an executable program `ABACUS.mpi` will be created in directory `bin/`. +After the compilation finishes without error messages (except perhaps for some warnings), an +executable program `ABACUS.mpi` will be created in directory `bin/`. ### Add Libxc Support -The program compiled using the above instructions do not link with LIBXC and use exchange-correlation functionals as written in the ABACUS program. However, for some functionals (such as HSE hybrid functional), LIBXC is required. +The program compiled using the above instructions do not link with LIBXC and use +exchange-correlation functionals as written in the ABACUS program. However, for some functionals +(such as HSE hybrid functional), LIBXC is required. To compile ABACUS with LIBXC, you need to define `LIBXC_DIR` in the file `Makefile.vars` or use @@ -289,7 +366,8 @@ directly. ### Add ML-ALGO Support -To compile ABACUS with machine learning algorithms, you need to set `ENABLE_MLALGO = ON`, and define `LIBTORCH_DIR` and `LIBNPY_DIR` in the file `Makefile.vars` or use +To compile ABACUS with machine learning algorithms, you need to set `ENABLE_MLALGO = ON`, and define +`LIBTORCH_DIR` and `LIBNPY_DIR` in the file `Makefile.vars` or use ```makefile make ENABLE_MLALGO=ON LIBTORCH_DIR=/opt/libtorch/ LIBNPY_DIR=/opt/libnpy/ @@ -297,30 +375,45 @@ make ENABLE_MLALGO=ON LIBTORCH_DIR=/opt/libtorch/ LIBNPY_DIR=/opt/libnpy/ directly. - ### Add DeePMD-kit Support -> Note: This part is only required if you want to load a trained DeeP Potential and run molecular dynamics with that. To train the DeeP Potential with DP-GEN, no extra prerequisite is needed and please refer to [this page](http://abacus.deepmodeling.com/en/latest/advanced/interface/dpgen.html) for ABACUS interface with DP-GEN. +> Note: This part is only required if you want to load a trained DeeP Potential and run molecular +> dynamics with that. To train the DeeP Potential with DP-GEN, no extra prerequisite is needed and +> please refer to +> [this page](http://abacus.deepmodeling.com/en/latest/advanced/interface/dpgen.html) for ABACUS +> interface with DP-GEN. + +To compile ABACUS with DeePMD-kit, you need to define `DeePMD_DIR` and `TensorFlow_DIR` (TensorFlow +Backend, optional) and/or `LIBTORCH_DIR` (PyTorch Backend, optional) in the file `Makefile.vars`. -To compile ABACUS with DeePMD-kit, you need to define `DeePMD_DIR` and `TensorFlow_DIR` (TensorFlow Backend, optional) and/or `LIBTORCH_DIR` (PyTorch Backend, optional) in the file `Makefile.vars`. +Or the `tensorflow_cc` and `torch` libraries are in the same directory as the `deepmd_c`/`deepmd_cc` +libraries, then -Or the `tensorflow_cc` and `torch` libraries are in the same directory as the `deepmd_c`/`deepmd_cc` libraries, then ```makefile make DeePMD_DIR=/dir_to_deepmd-kit ``` + DeePMD-kit supports TensorFlow backend but its libraries are placed at another directory, then ```makefile make DeePMD_DIR=/dir_to_deepmd-kit TensorFlow_DIR=/dir_to_tensorflow ``` -Similarly, DeePMD-kit supports PyTorch backend but its libraries are placed at another directory, then + +Similarly, DeePMD-kit supports PyTorch backend but its libraries are placed at another directory, +then + ```makefile make DeePMD_DIR=/dir_to_deepmd-kit Torch_DIR=/dir_to_pytorch ``` ### Add LibRI Support -To use new EXX, you need two libraries: [LibRI](https://github.com/abacusmodeling/LibRI) and [LibComm](https://github.com/abacusmodeling/LibComm) and need to define `LIBRI_DIR` and `LIBCOMM_DIR` in the file `Makefile.vars` or use + +To use new EXX, you need two libraries: [LibRI](https://github.com/abacusmodeling/LibRI) and +[LibComm](https://github.com/abacusmodeling/LibComm) and need to define `LIBRI_DIR` and +`LIBCOMM_DIR` in the file `Makefile.vars` or use + ```makefile make LIBRI_DIR=/public/software/LibRI LIBCOMM_DIR=/public/software/LibComm ``` + directly. diff --git a/docs/advanced/interface/Hefei-NAMD.md b/docs/advanced/interface/Hefei-NAMD.md index a45f49a5633..9f61e672a58 100644 --- a/docs/advanced/interface/Hefei-NAMD.md +++ b/docs/advanced/interface/Hefei-NAMD.md @@ -1,30 +1,43 @@ # Hefei-NAMD -[Hefei-NAMD](https://github.com/QijingZheng/Hefei-NAMD) Non-adiabatic molecular dynamics applies surface hopping to incorporate quantum mechanical effects into molecular dynamics simulations. Surface hopping partially incorporates the non-adiabatic effects by including excited adiabatic surfaces in the calculations, and allowing for ‘hops’ between these surfaces. +[Hefei-NAMD](https://github.com/QijingZheng/Hefei-NAMD) Non-adiabatic molecular dynamics applies +surface hopping to incorporate quantum mechanical effects into molecular dynamics simulations. +Surface hopping partially incorporates the non-adiabatic effects by including excited adiabatic +surfaces in the calculations, and allowing for ‘hops’ between these surfaces. -Detailed instructions on installing and running Hefei-NAMD can be found on its official [website](http://staff.ustc.edu.cn/~zqj/posts/Hefei-NAMD-Training/). +Detailed instructions on installing and running Hefei-NAMD can be found on its official +[website](http://staff.ustc.edu.cn/~zqj/posts/Hefei-NAMD-Training/). -ABACUS provides results of molecular dynamics simulations for Hefei-NAMD to do non-adiabatic molecular dynamics simulations. +ABACUS provides results of molecular dynamics simulations for Hefei-NAMD to do non-adiabatic +molecular dynamics simulations. The steps are as follows : + 1. Add output parameters in INPUT when running MD using ABACUS . + ``` out_wfc_lcao 1 out_mat_hs 1 ``` -Then we obtain output files of hamiltonian matrix, overlap matrix, and wavefunction to do NAMD simulation. + +Then we obtain output files of hamiltonian matrix, overlap matrix, and wavefunction to do NAMD +simulation. 2. Clone Hefei-NAMD codes optimized for ABACUS from [website](https://github.com/vtzf/abacus-namd). -3. Modify parameters in `Args.py` including directory of ABACUS output files and NAMD parameters. We can see detailed explanation for all parameters in `Args.py`. +1. Modify parameters in `Args.py` including directory of ABACUS output files and NAMD parameters. We + can see detailed explanation for all parameters in `Args.py`. + +1. Run `NAC.py` to prepare related files for NAMD simulations. -4. Run `NAC.py` to prepare related files for NAMD simulations. ``` sbatch sub_nac ``` -5. Run `SurfHop.py` to perform NAMD simulations. +5. Run `SurfHop.py` to perform NAMD simulations. + ``` sbatch sub_sh ``` + And results are under directory namddir in `Args.py`. diff --git a/docs/advanced/interface/ShengBTE.md b/docs/advanced/interface/ShengBTE.md index e8264aa891e..9acfb50a5c6 100644 --- a/docs/advanced/interface/ShengBTE.md +++ b/docs/advanced/interface/ShengBTE.md @@ -1,11 +1,19 @@ # ShengBTE + ## Introduction -This tutorial aims to introduce the process of performing density functional theory calculations using ABACUS and calculating lattice thermal conductivity using the ShengBTE software. During the entire calculation process, the following external software are also used: 1) Phonopy for calculating second-order force constants, 2) ASE for converting atomic structures, 3) ShengBTE's thirdorder program for calculating third-order force constants, and 4) finally using ShengBTE to calculate the material's lattice thermal conductivity. +This tutorial aims to introduce the process of performing density functional theory calculations +using ABACUS and calculating lattice thermal conductivity using the ShengBTE software. During the +entire calculation process, the following external software are also used: 1) Phonopy for +calculating second-order force constants, 2) ASE for converting atomic structures, 3) ShengBTE's +thirdorder program for calculating third-order force constants, and 4) finally using ShengBTE to +calculate the material's lattice thermal conductivity. -Here is the announcement of ShengBTE with ABACUS: [ShengBTE - The ABACUS DFT software can now be used with ShengBTE](https://www.shengbte.org/announcements/the-abacus-dft-software-can-now-be-used-with-shengbte) +Here is the announcement of ShengBTE with ABACUS: +[ShengBTE - The ABACUS DFT software can now be used with ShengBTE](https://www.shengbte.org/announcements/the-abacus-dft-software-can-now-be-used-with-shengbte) -Some external packages that need to be combined are mentioned above, and here it is recommended to read the relevant documentation and instructions of these packages: +Some external packages that need to be combined are mentioned above, and here it is recommended to +read the relevant documentation and instructions of these packages: ShengBTE:[https://bitbucket.org/sousaw/shengbte/src/master/](https://bitbucket.org/sousaw/shengbte/src/master/) @@ -13,23 +21,39 @@ phonopy:[http://abacus.deepmodeling.com/en/latest/advanced/interface/phonopy.h ASE:[http://abacus.deepmodeling.com/en/latest/advanced/interface/ase.html](http://abacus.deepmodeling.com/en/latest/advanced/interface/ase.html) -thirdorder: [https://bitbucket.org/sousaw/thirdorder/src/master/](https://bitbucket.org/sousaw/thirdorder/src/master/) +thirdorder: +[https://bitbucket.org/sousaw/thirdorder/src/master/](https://bitbucket.org/sousaw/thirdorder/src/master/) ## Prepare -The ABACUS software package provides an example of using ABACUS+ShengBTE to calculate the lattice thermal conductivity in the `examples/interface_ShengBTE` folder. The example includes two folders: `LCAO` (Linear Combination of Atomic Orbitals) which uses numerical atomic orbitals and `PW` (Plane wave) which uses plane wave basis vectors. Each folder contains three subfolders: `2nd`, `3rd`, and `shengbte`, which respectively store the relevant files for calculating second-order force constants using Phonopy (`2nd`), third-order force constants using the thirdorder program (`3rd`), and lattice thermal conductivity using ShengBTE (`shengbte`). +The ABACUS software package provides an example of using ABACUS+ShengBTE to calculate the lattice +thermal conductivity in the `examples/interface_ShengBTE` folder. The example includes two folders: +`LCAO` (Linear Combination of Atomic Orbitals) which uses numerical atomic orbitals and `PW` (Plane +wave) which uses plane wave basis vectors. Each folder contains three subfolders: `2nd`, `3rd`, and +`shengbte`, which respectively store the relevant files for calculating second-order force constants +using Phonopy (`2nd`), third-order force constants using the thirdorder program (`3rd`), and lattice +thermal conductivity using ShengBTE (`shengbte`). ## How to use -Taking the `LCAO` folder as an example, we provide the test case of a diamond structure Si structure containing 2 atoms with the norm-conserving pseudopotential `Si_ONCV_PBE-1.0.upf` and the atomic orbital file `Si_gga_7au_100Ry_2s2p1d.orb` (GGA functional, 7 a.u. cut-off radius, 100 Ry energy cut-off, and DZP orbitals containing 2s2p1d). +Taking the `LCAO` folder as an example, we provide the test case of a diamond structure Si structure +containing 2 atoms with the norm-conserving pseudopotential `Si_ONCV_PBE-1.0.upf` and the atomic +orbital file `Si_gga_7au_100Ry_2s2p1d.orb` (GGA functional, 7 a.u. cut-off radius, 100 Ry energy +cut-off, and DZP orbitals containing 2s2p1d). ### 1. Calculating the second-order force constants -It would be best to combine Phonopy and ASE with ABACUS to calculate the second-order force constants. First, enter the `2nd` folder. +It would be best to combine Phonopy and ASE with ABACUS to calculate the second-order force +constants. First, enter the `2nd` folder. ### 1.1 Structure optimization -Before performing lattice thermal conductivity calculations, it is necessary to optimize the atomic configuration of the simulated material system. The following is the atomic configuration file `STRU` obtained after structure optimization (relax) using ABACUS. In this example, for simplicity, a 2\*2\*2 Brillouin zone k-point sampling was used in the structure optimization process, with an energy cutoff value of 100 Ry for plane waves (the plane wave basis vector is also used in LCAO). Note that the actual calculation should use more convergent k-point sampling. +Before performing lattice thermal conductivity calculations, it is necessary to optimize the atomic +configuration of the simulated material system. The following is the atomic configuration file +`STRU` obtained after structure optimization (relax) using ABACUS. In this example, for simplicity, +a 2\*2\*2 Brillouin zone k-point sampling was used in the structure optimization process, with an +energy cutoff value of 100 Ry for plane waves (the plane wave basis vector is also used in LCAO). +Note that the actual calculation should use more convergent k-point sampling. ```bash ATOMIC_SPECIES @@ -58,7 +82,8 @@ Si #label ### 1.2 Calculating the second-order force constants -The Phonopy software is called to generate multiple atomic configurations of the supercell and corresponding perturbations needed for calculation with the following command: +The Phonopy software is called to generate multiple atomic configurations of the supercell and +corresponding perturbations needed for calculation with the following command: ```bash phonopy setting.conf --abacus -d @@ -71,21 +96,28 @@ DIM = 2 2 2 ATOM_NAME = Si ``` -In this Si example, we only need to generate one perturbed atomic configuration, `STRU-001`. Perform SCF calculations (SCF stands for Self-Consistent Field and represents the iterative self-consistent calculation of density functional theory) on all perturbed configurations (in this case, there is only one for Si) to obtain the forces on the atoms. Afterward, use the following command to generate the `FORCE_SET` file: +In this Si example, we only need to generate one perturbed atomic configuration, `STRU-001`. Perform +SCF calculations (SCF stands for Self-Consistent Field and represents the iterative self-consistent +calculation of density functional theory) on all perturbed configurations (in this case, there is +only one for Si) to obtain the forces on the atoms. Afterward, use the following command to generate +the `FORCE_SET` file: ```bash phonopy -f OUT.DIA-50/running_scf.log ``` -Tip: In the input file `INPUT` of ABACUS, you can set the variable `stru_file`, which corresponds to the atomic configuration file `STRU-001`, and ABACUS will read the structure file directly. +Tip: In the input file `INPUT` of ABACUS, you can set the variable `stru_file`, which corresponds to +the atomic configuration file `STRU-001`, and ABACUS will read the structure file directly. -Next, set the `band.conf` file to calculate the phonon spectrum and the second-order force constants: +Next, set the `band.conf` file to calculate the phonon spectrum and the second-order force +constants: ```bash phonopy -p band.conf --abacus ``` -The `band.conf` file mentioned here contains the following contents (you can refer to the Phonopy documentation for specific parameter meanings): +The `band.conf` file mentioned here contains the following contents (you can refer to the Phonopy +documentation for specific parameter meanings): ```bash ATOM_NAME = Si @@ -99,9 +131,13 @@ FORCE_CONSTANTS = WRITE FULL_FORCE_CONSTANTS = .TRUE. ``` -After this step, the Phonopy software will generate `band.yaml` (for plotting the phonon spectrum) and the `FORCE_CONSTANTS` file. The data contained in the `FORCE_CONSTANTS` file is the second-order force constants. It is important to set `FULL_FORCE_CONSTANTS = .TRUE.`, which outputs all the second-order force constants. Otherwise, there may be errors when ShengBTE reads the data. +After this step, the Phonopy software will generate `band.yaml` (for plotting the phonon spectrum) +and the `FORCE_CONSTANTS` file. The data contained in the `FORCE_CONSTANTS` file is the second-order +force constants. It is important to set `FULL_FORCE_CONSTANTS = .TRUE.`, which outputs all the +second-order force constants. Otherwise, there may be errors when ShengBTE reads the data. -In addition, you can use the following command to output the gnuplot format of the phonon spectrum for plotting: +In addition, you can use the following command to output the gnuplot format of the phonon spectrum +for plotting: ```bash phonopy-bandplot --gnuplot > pho.dat @@ -109,41 +145,63 @@ phonopy-bandplot --gnuplot > pho.dat ### 1.3 Post-processing -Note that ShengBTE software requires the unit of the data in the `FORCE_CONSTANTS_2ND` file to be eV/Å^2, but the unit of the `FORCE_CONSTANTS` calculated by ABACUS combined with Phonopy is eV/(Å*au), where au is the atomic unit system and 1 au = 0.52918 Å. You can use the provided `au2si.py` script in the `2nd` directory to convert the units and generate the `FORCE_CONSTANTS_2ND` file. The command is as follows: +Note that ShengBTE software requires the unit of the data in the `FORCE_CONSTANTS_2ND` file to be +eV/Å^2, but the unit of the `FORCE_CONSTANTS` calculated by ABACUS combined with Phonopy is +eV/(Å\*au), where au is the atomic unit system and 1 au = 0.52918 Å. You can use the provided +`au2si.py` script in the `2nd` directory to convert the units and generate the `FORCE_CONSTANTS_2ND` +file. The command is as follows: ```python python au2si.py ``` -The `FORCE_CONSTANTS_2ND` file is provided in the shengbte folder for reference to the calculation results. +The `FORCE_CONSTANTS_2ND` file is provided in the shengbte folder for reference to the calculation +results. ### 2. Calculating the third-order force constants -To calculate the third-order force constants, you need to combine with the thirdorder program and output the third-order force constant file `FORCE_CONSTANTS_3RD`. However, thirdorder currently only supports reading input and output files from VASP and QE. Therefore, we are using thirdorder by converting ABACUS's structure and output force files to `POSCAR` and `vasprun.xml`, respectively. Please enter the `3rd` folder first, and the specific steps will be described below. +To calculate the third-order force constants, you need to combine with the thirdorder program and +output the third-order force constant file `FORCE_CONSTANTS_3RD`. However, thirdorder currently only +supports reading input and output files from VASP and QE. Therefore, we are using thirdorder by +converting ABACUS's structure and output force files to `POSCAR` and `vasprun.xml`, respectively. +Please enter the `3rd` folder first, and the specific steps will be described below. ### 2.1 Obtaining perturbed configurations -First, convert the optimized `STRU` file from ABACUS software to `POSCAR` (the converted `POSCAR` file is already provided in the directory, or you can do this conversion by yourself). +First, convert the optimized `STRU` file from ABACUS software to `POSCAR` (the converted `POSCAR` +file is already provided in the directory, or you can do this conversion by yourself). -Then, run the `thirdorder_vasp.py` program to generate a series of atomic configuration files `3RD.POSCAR.*` after perturbation. For example, in this example, a total of 40 configurations were generated: +Then, run the `thirdorder_vasp.py` program to generate a series of atomic configuration files +`3RD.POSCAR.*` after perturbation. For example, in this example, a total of 40 configurations were +generated: ```bash thirdorder_vasp.py sow 2 2 2 -2 ``` -Run `pos2stru.py` to convert the above `POSCAR` to `STRU` file. Note that this script calls functions from the ASE software package (ASE needs to be installed in advance): +Run `pos2stru.py` to convert the above `POSCAR` to `STRU` file. Note that this script calls +functions from the ASE software package (ASE needs to be installed in advance): ```python python pos2stru.py ``` -Note: The dpdata software cannot be called here to perform the conversion. This is because the dpdata software forces the lattice to change into a lower triangular matrix, which is equivalent to rotating the lattice and leads to a corresponding rotation in the direction of the interatomic forces, which will cause errors. +Note: The dpdata software cannot be called here to perform the conversion. This is because the +dpdata software forces the lattice to change into a lower triangular matrix, which is equivalent to +rotating the lattice and leads to a corresponding rotation in the direction of the interatomic +forces, which will cause errors. ### 2.2 Calculation of atomic forces for perturbation configurations -You can refer to the `run_stru.sh` script provided in the directory to batch generate `SCF-*` folders and submit calculations. Here, ABACUS needs to perform SCF calculations on 40 atomic configurations, which may take some time. It is recommended to run each SCF separately in the `SCF-*` folder. The `scf_thr` parameter in INPUT file should be set to at least 1e-8 to obtain converged results. +You can refer to the `run_stru.sh` script provided in the directory to batch generate `SCF-*` +folders and submit calculations. Here, ABACUS needs to perform SCF calculations on 40 atomic +configurations, which may take some time. It is recommended to run each SCF separately in the +`SCF-*` folder. The `scf_thr` parameter in INPUT file should be set to at least 1e-8 to obtain +converged results. -After the calculations are complete, run `aba2vasp.py` to package the atomic forces calculated by ABACUS into the `vasprun.xml` format and place them in each `SCF-\*` folder with the following command: +After the calculations are complete, run `aba2vasp.py` to package the atomic forces calculated by +ABACUS into the `vasprun.xml` format and place them in each `SCF-\*` folder with the following +command: ```python python aba2vasp.py @@ -198,11 +256,17 @@ Finally, execute the following command: find SCF-* -name vasprun.xml|sort -n|thirdorder_vasp.py reap 2 2 2 -2 ``` -Then, the third-order force constant file `FORCE_CONSTANTS_3RD` can be obtained by running the above command. The `FORCE_CONSTANTS_3RD` file is provided in the shengbte folder for reference in calculating the results. +Then, the third-order force constant file `FORCE_CONSTANTS_3RD` can be obtained by running the above +command. The `FORCE_CONSTANTS_3RD` file is provided in the shengbte folder for reference in +calculating the results. ### 3. Run ShengBTE to obtain lattice thermal conductivity -Enter the `shengbte` folder, in which the three files `CONTROL` (parameter file of ShengBTE), `FORCE_CONSTANTS_2ND` (second-order force constant file), and `FORCE_CONSTANTS_3RD` (third-order force constant file) have been prepared. Next, run ShengBTE with the following command to obtain the lattice thermal conductivity, where the calculation results are given in the Ref folder for reference: +Enter the `shengbte` folder, in which the three files `CONTROL` (parameter file of ShengBTE), +`FORCE_CONSTANTS_2ND` (second-order force constant file), and `FORCE_CONSTANTS_3RD` (third-order +force constant file) have been prepared. Next, run ShengBTE with the following command to obtain the +lattice thermal conductivity, where the calculation results are given in the Ref folder for +reference: ```bash mpirun -n 10 ShengBTE @@ -210,4 +274,11 @@ mpirun -n 10 ShengBTE ## Conclusion -For using plane wave (PW) in ABACUS to perform ShengBTE calculations, similar procedures should be followed. However, the `scf_thr` parameter in the `INPUT` file for calculating the third-order force constant needs to be set to at least 1e-12. The experimental lattice thermal conductivity of Si at 300 K is around 150 W/(m K), while the calculated thermal conductivity of Si at 300 K is around 100 W/(m K) by using the provided example. This is because, as a demo, a 2\*2\*2 expanded cell and a 2\*2\*2 K-point are used in the example, but the results are not converged yet with respect to the given system size and k-points. In actual research, the size of the supercell and the sampling scheme of K-points need to be tested to obtain converged results. +For using plane wave (PW) in ABACUS to perform ShengBTE calculations, similar procedures should be +followed. However, the `scf_thr` parameter in the `INPUT` file for calculating the third-order force +constant needs to be set to at least 1e-12. The experimental lattice thermal conductivity of Si at +300 K is around 150 W/(m K), while the calculated thermal conductivity of Si at 300 K is around 100 +W/(m K) by using the provided example. This is because, as a demo, a 2\*2\*2 expanded cell and a +2\*2\*2 K-point are used in the example, but the results are not converged yet with respect to the +given system size and k-points. In actual research, the size of the supercell and the sampling +scheme of K-points need to be tested to obtain converged results. diff --git a/docs/advanced/interface/TB2J.md b/docs/advanced/interface/TB2J.md index 774c1091703..d1013572a74 100644 --- a/docs/advanced/interface/TB2J.md +++ b/docs/advanced/interface/TB2J.md @@ -2,7 +2,12 @@ ## Introduction -[TB2J](https://github.com/mailhexu/TB2J) is an open-source Python package for the automatic computation of magnetic interactions (including exchange and Dzyaloshinskii-Moriya) between atoms of magnetic crystals from density functional Hamiltonians based on Wannier functions or linear combinations of atomic orbitals. The program is based on Green’s function method with the local rigid spin rotation treated as a perturbation. The ABACUS interface has been added since TB2J version 0.8.0. +[TB2J](https://github.com/mailhexu/TB2J) is an open-source Python package for the automatic +computation of magnetic interactions (including exchange and Dzyaloshinskii-Moriya) between atoms of +magnetic crystals from density functional Hamiltonians based on Wannier functions or linear +combinations of atomic orbitals. The program is based on Green’s function method with the local +rigid spin rotation treated as a perturbation. The ABACUS interface has been added since TB2J +version 0.8.0. For more information, see the documentation on https://tb2j.readthedocs.io/en/latest/ @@ -23,24 +28,33 @@ python setup.py install ``` ## The Heisenberg model + The Heisenberg Hamiltonian in TB2J contains three different parts, which are: $E = -\sum_{i \neq j} \left[ J_{\text{iso}}^{ij} \vec{S}_i \cdot \vec{S}_j + \vec{S}_i J_{\text{ani}}^{ij} \vec{S}_j + \vec{D}_{ij} \cdot (\vec{S}_i \times \vec{S}_j) \right],$ -where $J_{\text{iso}}^{ij}$ represents the isotropic exchange, $J_{\text{ani}}^{ij}$ represents the symmetric anisotropic exhcange which is a 3 $\times$ 3 tensor with $J^{\text{ani}} = J^{\text{ani,T}}$, $\vec{D}_{ij}$ represents the Dzyaloshinskii-Moriya interaction (DMI). +where $J_{\text{iso}}^{ij}$ represents the isotropic exchange, $J_{\text{ani}}^{ij}$ represents the +symmetric anisotropic exhcange which is a 3 $\times$ 3 tensor with +$J^{\text{ani}} = J^{\text{ani,T}}$, $\vec{D}_{ij}$ represents the Dzyaloshinskii-Moriya interaction +(DMI). -> **Note:** Exchange parameters conventions for other Heisenberg Hamiltonian can be found in [Conventions of Heisenberg Model](https://tb2j.readthedocs.io/en/latest/src/convention.html). +> **Note:** Exchange parameters conventions for other Heisenberg Hamiltonian can be found in +> [Conventions of Heisenberg Model](https://tb2j.readthedocs.io/en/latest/src/convention.html). ## How to use -With the LCAO basis set, TB2J can directly take the output and compute the exchange parameters. For the PW and LCAO-in-PW basis set, the Wannier90 interace can be used instead. In this tutorial we will use LCAO. +With the LCAO basis set, TB2J can directly take the output and compute the exchange parameters. For +the PW and LCAO-in-PW basis set, the Wannier90 interace can be used instead. In this tutorial we +will use LCAO. ### Collinear calculation without SOC -We take Fe as an example to illustrate how to use ABACUS to generate the input files required for TB2J. +We take Fe as an example to illustrate how to use ABACUS to generate the input files required for +TB2J. + +#### 1. Perform ABACUS calculation. -#### 1. Perform ABACUS calculation. - `INPUT` file: +`INPUT` file: ``` INPUT_PARAMETERS @@ -84,6 +98,7 @@ out_mat_hs2 1 ``` `STRU` file: + ``` ATOMIC_SPECIES Fe 55.845 Fe_ONCV_PBE_FR-1.0.upf @@ -110,21 +125,30 @@ Fe ``` and `KPT` file: + ``` K_POINTS 0 Gamma 8 8 8 0 0 0 ``` -After the key parameter `out_mat_hs2` is turned on, the Hamiltonian matrix $H(R)$ (in $Ry$) and overlap matrix $S(R)$ will be written into files in the directory `OUT.${suffix}` . In the INPUT, the line: + +After the key parameter `out_mat_hs2` is turned on, the Hamiltonian matrix $H(R)$ (in $Ry$) and +overlap matrix $S(R)$ will be written into files in the directory `OUT.${suffix}` . In the INPUT, +the line: ``` suffix Fe ``` -specifies the suffix of the output, in this calculation, we set the path to the directory of the DFT calculation, which is the current directory (".") and the suffix to Fe. +specifies the suffix of the output, in this calculation, we set the path to the directory of the DFT +calculation, which is the current directory (".") and the suffix to Fe. -> **Note (ABACUS v3.9.0.25+):** Starting from ABACUS v3.9.0.25, the output format has changed to standard CSR format with filenames `hrs1_nao.csr`, `hrs2_nao.csr` (for nspin=2), and `srs1_nao.csr`. The parameter `out_mat_hs2` now supports optional precision control: `out_mat_hs2 1 8` (default 8 digits). TB2J v0.9.0+ is required to read the new format. For older TB2J versions, please use ABACUS v3.8.x or earlier. +> **Note (ABACUS v3.9.0.25+):** Starting from ABACUS v3.9.0.25, the output format has changed to +> standard CSR format with filenames `hrs1_nao.csr`, `hrs2_nao.csr` (for nspin=2), and +> `srs1_nao.csr`. The parameter `out_mat_hs2` now supports optional precision control: +> `out_mat_hs2 1 8` (default 8 digits). TB2J v0.9.0+ is required to read the new format. For older +> TB2J versions, please use ABACUS v3.8.x or earlier. #### 2. Perform TB2J calculation: @@ -132,17 +156,27 @@ specifies the suffix of the output, in this calculation, we set the path to the abacus2J.py --path . --suffix Fe --elements Fe --kmesh 7 7 7 ``` -This first reads the atomic structures from the `STRU` file, then reads the Hamiltonian and overlap matrices. For ABACUS v3.9.0.25+, the matrices are stored in `hrs1_nao.csr`, `hrs2_nao.csr` (nspin=2), and `srs1_nao.csr` files. For older versions, they are in `data-HR-*` and `data-SR-*` files. It also reads the fermi energy from the `OUT.Fe/running_scf.log` file. +This first reads the atomic structures from the `STRU` file, then reads the Hamiltonian and overlap +matrices. For ABACUS v3.9.0.25+, the matrices are stored in `hrs1_nao.csr`, `hrs2_nao.csr` +(nspin=2), and `srs1_nao.csr` files. For older versions, they are in `data-HR-*` and `data-SR-*` +files. It also reads the fermi energy from the `OUT.Fe/running_scf.log` file. -With the command above, we can calculate the $J$ with a $7 \times 7 \times 7$ k-point grid. This allows for the calculation of exchange between spin pairs between $7 \times 7 \times 7$ supercell. Note: the kmesh is not dense enough for a practical calculation. For a very dense k-mesh, the `--rcut` option can be used to set the maximum distance of the magnetic interactions and thus reduce the computation cost. But be sure that the cutoff is not too small. +With the command above, we can calculate the $J$ with a $7 \times 7 \times 7$ k-point grid. This +allows for the calculation of exchange between spin pairs between $7 \times 7 \times 7$ supercell. +Note: the kmesh is not dense enough for a practical calculation. For a very dense k-mesh, the +`--rcut` option can be used to set the maximum distance of the magnetic interactions and thus reduce +the computation cost. But be sure that the cutoff is not too small. -The description of the output files in `TB2J_results` can be found in the [TB2J documentation](https://tb2j.readthedocs.io/en/latest/src/output.html). We can find the exchange parameters with `Fe` by : +The description of the output files in `TB2J_results` can be found in the +[TB2J documentation](https://tb2j.readthedocs.io/en/latest/src/output.html). We can find the +exchange parameters with `Fe` by : ```bash grep "Fe" exchange.out ``` -the following contents showing the first, second and third nearest neighbor exchange parameters as 18.6873, 9.9213 and 0.8963 meV, resoectively. More equivalent exchange parameters are also shown. +the following contents showing the first, second and third nearest neighbor exchange parameters as +18.6873, 9.9213 and 0.8963 meV, resoectively. More equivalent exchange parameters are also shown. ``` Fe1 Fe2 ( -1, -1, -1) 18.6873 (-1.433, -1.433, -1.433) 2.482 @@ -179,28 +213,34 @@ the following contents showing the first, second and third nearest neighbor exch Fe2 Fe2 ( -1, 0, -1) 0.8970 (-2.866, 0.000, -2.866) 4.053 ``` -Several other formats of the exchange parameters are also provided in the `TB2J_results` directory , which can be used in spin dynamics code, e.g. [MULTIBINIT](https://docs.abinit.org/tutorial/spin_model/), [Vampire](https://vampire.york.ac.uk/). +Several other formats of the exchange parameters are also provided in the `TB2J_results` directory , +which can be used in spin dynamics code, e.g. +[MULTIBINIT](https://docs.abinit.org/tutorial/spin_model/), [Vampire](https://vampire.york.ac.uk/). ### Non-collinear calculation with SOC -The DMI and anisotropic exchange are result of the SOC, therefore requires the DFT calculation to be done with SOC enabled. To get the full set of exchange parameters, a "rotate and merge" procedure is needed, in which several DFT calculations with either the structure or the spin rotated are needed. For each of the non-collinear calcualtion, we compute the exchange parameters from the DFT calculation with the same command as in the collienar case. +The DMI and anisotropic exchange are result of the SOC, therefore requires the DFT calculation to be +done with SOC enabled. To get the full set of exchange parameters, a "rotate and merge" procedure is +needed, in which several DFT calculations with either the structure or the spin rotated are needed. +For each of the non-collinear calcualtion, we compute the exchange parameters from the DFT +calculation with the same command as in the collienar case. ```bash abacus2J.py --path . --suffix Fe --elements Fe --kmesh 7 7 7 ``` -And then the "TB2J_merge.py" command can be used to get the final spin interaction parameters. - +And then the "TB2J_merge.py" command can be used to get the final spin interaction parameters. ### Parameters of abacus2J.py -We can use the command +We can use the command ```bash abacus2J.py --help ``` -to view the parameters and the usage of them in abacus2J.py. +to view the parameters and the usage of them in abacus2J.py. ### Acknowledgments + We thanks to Xu He to provide critical interface support. diff --git a/docs/advanced/interface/Wannier90.md b/docs/advanced/interface/Wannier90.md index 5d898a1f20c..b0f5689186e 100644 --- a/docs/advanced/interface/Wannier90.md +++ b/docs/advanced/interface/Wannier90.md @@ -1,131 +1,156 @@ # Wannier90 -[Wannier90](http://www.wannier.org/) is a useful package to generating the maximally-localized Wannier functions (MLWFs), which can be used to compute advanced electronic properties. Some post-processing tools (such as WannierTools, etc.) will use MLWFs for further analysis and calculations. - -Currently ABACUS provides an interface to Wannier90 package. The users are assumed to be familiar with the use of Wannier90. The ABACUS-Wannier90 interface is suitable for nspin=1, 2, 4 (including lspinorb=1). - -To construct the MLWFs using the wave functions of ABACUS generally requires four steps. Here we use the diamond as an example which can be found in [examples/interface_wannier90/](https://github.com/abacusmodeling/abacus-develop/tree/develop/examples/interface_wannier90). - -1. Enter the `ABACUS_towannier90_pw/` folder, prepare a Wannier90 input file `diamond.win`, which is the main input file for Wannier90. Then To generate `diamond.nnkp` file by running Wannier90, which ABACUS will read later: - - ``` - wannier90 -pp diamond.win - ``` - - The content of `diamond.win` is as follows: - - ``` - num_wann = 4 - num_iter = 20 - - wannier_plot=.true. - wannier_plot_supercell = 3 - wvfn_formatted = .true. - - begin atoms_frac - C -0.12500 -0.1250 -0.125000 - C 0.12500 0.1250 0.125000 - end atoms_frac - - begin projections - f=0.0,0.0,0.0:s - f=0.0,0.0,0.5:s - f=0.0,0.5,0.0:s - f=0.5,0.0,0.0:s - end projections - - begin unit_cell_cart - -1.613990 0.000000 1.613990 - 0.000000 1.613990 1.613990 - -1.613990 1.613990 0.000000 - end unit_cell_cart - - mp_grid : 4 4 4 - - begin kpoints - 0.0000 0.0000 0.0000 - 0.0000 0.2500 0.0000 - 0.0000 0.5000 0.0000 - 0.0000 0.7500 0.0000 - ... - end kpoints - ``` - -2. Do a self-consistent calculation and get the converged charge density: - - ``` - cp INPUT-scf INPUT - cp KPT-scf KPT - mpirun -np 4 abacus - ``` - - -3. Do a non-self-consistent calculation: - - ``` - cp INPUT-nscf INPUT - cp KPT-nscf KPT - mpirun -np 4 abacus - ``` - - below are the INPUT file (nscf): - - ``` - INPUT_PARAMETERS - - pseudo_dir ../../../tests/PP_ORB - orbital_dir ../../../tests/PP_ORB - ntype 1 - ecutwfc 50 - nbands 4 - smearing_method fixed - calculation nscf - scf_nmax 50 - pw_diag_thr 1.0e-12 - scf_thr 1.0e-13 - init_chg file - symmetry -1 - towannier90 1 - nnkpfile diamond.nnkp - basis_type pw - out_wannier_unk 0 - ``` - - There are seven interface-related parameters in the `INPUT` file: - - - [towannier90](../input_files/input-main.md#towannier90): `1`, generate files for wannier90 code; `0`, do not generate. - - [nnkpfile](../input_files/input-main.md#nnkpfile) : the name of the file generated by running "wannier90 -pp ...". - - [wannier_spin](../input_files/input-main.md#wannier_spin): If you use nspin=2, `up`: calculate the Wannier functions for the spin up components ; `down`: calculate the Wannier functions spin down components. - - [out_wannier_mmn](../input_files/input-main.md#out_wannier_mmn): control whether to output the "*.mmn" file. - - [out_wannier_amn](../input_files/input-main.md#out_wannier_amn): control whether to output the "*.amn" file. - - [out_wannier_eig](../input_files/input-main.md#out_wannier_eig): control whether to output the "*.eig" file. - - [out_wannier_unk](../input_files/input-main.md#out_wannier_unk): control whether to output the "UNK.*" file. - - [out_wannier_wvfn_formatted](../input_files/input-main.md#out_wannier_wvfn_formatted): control what format of the Wannier function file to output, `true`: output the formatted text file; `false`: output the binary file. Note that the `wvfn_formatted` option in `*.win` file (input file of Wannier90) has to be set accordingly with this option. - - **Note: You need to turn off the symmetry during the entire nscf calculation.** - - To setup the `KPT` file according to the `diamond.win` file, which is similar to "begin kpoints ..." in the `diamond.win` file: - - ``` - K_POINTS - 64 - Direct - 0.0000 0.0000 0.0000 0.0156250 - 0.0000 0.2500 0.0000 0.0156250 - 0.0000 0.5000 0.0000 0.0156250 - 0.0000 0.7500 0.0000 0.0156250 - ... - ``` - - After the nscf calculation, ABACUS will generate `diamond.amn`, `diamond.mmn`, `diamond.eig`, `UNK` files in the `OUT.` folder which are input files needed by Wannier90 code. - -4. Copy `.amn`, `.mmn`, `.eig`, `UNK` file to `wannier/` folder, to get the MLWFs by running Wannier90: - - ``` - wannier90 diamond.win - ``` +[Wannier90](http://www.wannier.org/) is a useful package to generating the maximally-localized +Wannier functions (MLWFs), which can be used to compute advanced electronic properties. Some +post-processing tools (such as WannierTools, etc.) will use MLWFs for further analysis and +calculations. + +Currently ABACUS provides an interface to Wannier90 package. The users are assumed to be familiar +with the use of Wannier90. The ABACUS-Wannier90 interface is suitable for nspin=1, 2, 4 (including +lspinorb=1). + +To construct the MLWFs using the wave functions of ABACUS generally requires four steps. Here we use +the diamond as an example which can be found in +[examples/interface_wannier90/](https://github.com/abacusmodeling/abacus-develop/tree/develop/examples/interface_wannier90). + +1. Enter the `ABACUS_towannier90_pw/` folder, prepare a Wannier90 input file `diamond.win`, which is + the main input file for Wannier90. Then To generate `diamond.nnkp` file by running Wannier90, + which ABACUS will read later: + + ``` + wannier90 -pp diamond.win + ``` + + The content of `diamond.win` is as follows: + + ``` + num_wann = 4 + num_iter = 20 + + wannier_plot=.true. + wannier_plot_supercell = 3 + wvfn_formatted = .true. + + begin atoms_frac + C -0.12500 -0.1250 -0.125000 + C 0.12500 0.1250 0.125000 + end atoms_frac + + begin projections + f=0.0,0.0,0.0:s + f=0.0,0.0,0.5:s + f=0.0,0.5,0.0:s + f=0.5,0.0,0.0:s + end projections + + begin unit_cell_cart + -1.613990 0.000000 1.613990 + 0.000000 1.613990 1.613990 + -1.613990 1.613990 0.000000 + end unit_cell_cart + + mp_grid : 4 4 4 + + begin kpoints + 0.0000 0.0000 0.0000 + 0.0000 0.2500 0.0000 + 0.0000 0.5000 0.0000 + 0.0000 0.7500 0.0000 + ... + end kpoints + ``` + +1. Do a self-consistent calculation and get the converged charge density: + + ``` + cp INPUT-scf INPUT + cp KPT-scf KPT + mpirun -np 4 abacus + ``` + +1. Do a non-self-consistent calculation: + + ``` + cp INPUT-nscf INPUT + cp KPT-nscf KPT + mpirun -np 4 abacus + ``` + + below are the INPUT file (nscf): + + ``` + INPUT_PARAMETERS + + pseudo_dir ../../../tests/PP_ORB + orbital_dir ../../../tests/PP_ORB + ntype 1 + ecutwfc 50 + nbands 4 + smearing_method fixed + calculation nscf + scf_nmax 50 + pw_diag_thr 1.0e-12 + scf_thr 1.0e-13 + init_chg file + symmetry -1 + towannier90 1 + nnkpfile diamond.nnkp + basis_type pw + out_wannier_unk 0 + ``` + + There are seven interface-related parameters in the `INPUT` file: + + - [towannier90](../input_files/input-main.md#towannier90): `1`, generate files for wannier90 + code; `0`, do not generate. + - [nnkpfile](../input_files/input-main.md#nnkpfile) : the name of the file generated by running + "wannier90 -pp ...". + - [wannier_spin](../input_files/input-main.md#wannier_spin): If you use nspin=2, `up`: calculate + the Wannier functions for the spin up components ; `down`: calculate the Wannier functions spin + down components. + - [out_wannier_mmn](../input_files/input-main.md#out_wannier_mmn): control whether to output the + "\*.mmn" file. + - [out_wannier_amn](../input_files/input-main.md#out_wannier_amn): control whether to output the + "\*.amn" file. + - [out_wannier_eig](../input_files/input-main.md#out_wannier_eig): control whether to output the + "\*.eig" file. + - [out_wannier_unk](../input_files/input-main.md#out_wannier_unk): control whether to output the + "UNK.\*" file. + - [out_wannier_wvfn_formatted](../input_files/input-main.md#out_wannier_wvfn_formatted): control + what format of the Wannier function file to output, `true`: output the formatted text file; + `false`: output the binary file. Note that the `wvfn_formatted` option in `*.win` file (input + file of Wannier90) has to be set accordingly with this option. + + **Note: You need to turn off the symmetry during the entire nscf calculation.** + + To setup the `KPT` file according to the `diamond.win` file, which is similar to "begin kpoints + ..." in the `diamond.win` file: + + ``` + K_POINTS + 64 + Direct + 0.0000 0.0000 0.0000 0.0156250 + 0.0000 0.2500 0.0000 0.0156250 + 0.0000 0.5000 0.0000 0.0156250 + 0.0000 0.7500 0.0000 0.0156250 + ... + ``` + + After the nscf calculation, ABACUS will generate `diamond.amn`, `diamond.mmn`, `diamond.eig`, + `UNK` files in the `OUT.` folder which are input files needed by Wannier90 code. + +1. Copy `.amn`, `.mmn`, `.eig`, `UNK` file to `wannier/` folder, to get the MLWFs by running + Wannier90: + + ``` + wannier90 diamond.win + ``` Notes: - The ABACUS-wannier90 interface can be used in both PW and LCAO basis. -- If you want to plot the Wannier function, you must set `wvfn_formatted = .true.` in `diamond.win`, otherwise Wannier90 code cannot read files generated by ABACUS because these files are not binary files. You also have to generate the `diamond.amn` and `UNK` files for the plot. Otherwise, the two types of file are not necessary. +- If you want to plot the Wannier function, you must set `wvfn_formatted = .true.` in `diamond.win`, + otherwise Wannier90 code cannot read files generated by ABACUS because these files are not binary + files. You also have to generate the `diamond.amn` and `UNK` files for the plot. Otherwise, the + two types of file are not necessary. diff --git a/docs/advanced/interface/ase.md b/docs/advanced/interface/ase.md index e9b7b062809..b4109c41d04 100644 --- a/docs/advanced/interface/ase.md +++ b/docs/advanced/interface/ase.md @@ -2,13 +2,22 @@ ## Introduction -[ASE](https://wiki.fysik.dtu.dk/ase/) (Atomic Simulation Environment) performs as a powerful Pythonic platform for atomistic simulations, in which there are plenty of functionalties supported, such as various geometry optimization algorithms for finding both the minimum energy point and the transition states, including BFGS, BFGSLineSearch, FIRE, NEB, AUTO-NEB, etc, and various molecular dynamics techniques, including thermostats (Langevin, CSVR, Nose-Hoover Chain, etc) and metadynamics (via the interface with Plumed). +[ASE](https://wiki.fysik.dtu.dk/ase/) (Atomic Simulation Environment) performs as a powerful +Pythonic platform for atomistic simulations, in which there are plenty of functionalties supported, +such as various geometry optimization algorithms for finding both the minimum energy point and the +transition states, including BFGS, BFGSLineSearch, FIRE, NEB, AUTO-NEB, etc, and various molecular +dynamics techniques, including thermostats (Langevin, CSVR, Nose-Hoover Chain, etc) and metadynamics +(via the interface with Plumed). -Due to the growing number of softwares and machine-learning forcefields, we turn to maintain the interface with ASE by our own, while a legacy version of ASE interface can still be found at [our GitLab repository of ase-abacus](https://gitlab.com/1041176461/ase-abacus ). +Due to the growing number of softwares and machine-learning forcefields, we turn to maintain the +interface with ASE by our own, while a legacy version of ASE interface can still be found at +[our GitLab repository of ase-abacus](https://gitlab.com/1041176461/ase-abacus). ## Installation -We strongly recommend you create a virtual environment for the installation of Python packages of abacus, such as `conda` or `venv`, to avoid conflicts with other packages, for example, with the `conda`: +We strongly recommend you create a virtual environment for the installation of Python packages of +abacus, such as `conda` or `venv`, to avoid conflicts with other packages, for example, with the +`conda`: ```bash conda create -n abacus python=3.10 @@ -24,8 +33,8 @@ pip install . ## ABACUS Calculator -Present calculator implementation requires a "profile" to act as an interface between the Python runtime and the file system. -Instantiate an `AbacusProfile` object with proper settings: +Present calculator implementation requires a "profile" to act as an interface between the Python +runtime and the file system. Instantiate an `AbacusProfile` object with proper settings: ```python from abacuslite import AbacusProfile @@ -36,8 +45,9 @@ aprof = AbacusProfile( orbital_dir='/path/to/folder/of/orbitals', # OPTIONAL! ) ``` -, by such lines, you build the interface between the computational environment and the Python runtime. -This interface can be reused in multiple calculations. + +, by such lines, you build the interface between the computational environment and the Python +runtime. This interface can be reused in multiple calculations. Then, you can instantiate the `Abacus` calculator with the profile by: @@ -63,7 +73,10 @@ abacus = Abacus( } ) ``` -, where except the `directory`, you can focus on the setting of ABACUS itself. In `inp`, you can set everything as you do in INPUT file of ABACUS. The kpoint sampling can also be set by the `kpts` parameter, like: + +, where except the `directory`, you can focus on the setting of ABACUS itself. In `inp`, you can set +everything as you do in INPUT file of ABACUS. The kpoint sampling can also be set by the `kpts` +parameter, like: ```python abacus = Abacus( @@ -77,7 +90,8 @@ abacus = Abacus( ) ``` -If with the `tempfile` module, you can create an abacus instance whose directory will be automatically removed when leaves from the context: +If with the `tempfile` module, you can create an abacus instance whose directory will be +automatically removed when leaves from the context: ```python import tempfile @@ -99,15 +113,20 @@ with tempfile.TemporaryDirectory() as tmpdir: ## Perform Calculations -In the new implementation, we limit the range of functionalties supported to mainly include the necessary ones, such as the SCF calculation, the energy and force/stress evaluation. The other features, such as starting the molecule dynamics directly in ABACUS from Python, is not supported anymore. Instead, it is encouraged to use the ASE tools to perform the molecule dynamics. +In the new implementation, we limit the range of functionalties supported to mainly include the +necessary ones, such as the SCF calculation, the energy and force/stress evaluation. The other +features, such as starting the molecule dynamics directly in ABACUS from Python, is not supported +anymore. Instead, it is encouraged to use the ASE tools to perform the molecule dynamics. Please read the examples in `interfaces/ASE_interface/examples/` for more details. ## SPAP Analysis -[SPAP](https://github.com/chuanxun/StructurePrototypeAnalysisPackage) (Structure Prototype Analysis Package) is written by Dr. Chuanxun Su to analyze symmetry and compare similarity of large amount of atomic structures. The coordination characterization function (CCF) is used to -measure structural similarity. An unique and advanced clustering method is developed to automatically classify structures into groups. - +[SPAP](https://github.com/chuanxun/StructurePrototypeAnalysisPackage) (Structure Prototype Analysis +Package) is written by Dr. Chuanxun Su to analyze symmetry and compare similarity of large amount of +atomic structures. The coordination characterization function (CCF) is used to measure structural +similarity. An unique and advanced clustering method is developed to automatically classify +structures into groups. If you use this program and method in your research, please read and cite the publication: diff --git a/docs/advanced/interface/candela.md b/docs/advanced/interface/candela.md index 753b305aee2..649145b6748 100644 --- a/docs/advanced/interface/candela.md +++ b/docs/advanced/interface/candela.md @@ -1,19 +1,26 @@ # CANDELA -[CANDELA](https://github.com/MCresearch/Candela) is short for Collection of ANalysis DEsigned for Large-scale Atomic simulations. -It is developed by MCresearch to conduct analyses on MD trajectory in different formats. -Right now the program only supports analysis of pair distribution function (PDF), static structure factor (SSF) and mean square displacement (MSD). -The minimum supported version of ABACUS is 3.2.0. - -## Requirements for using CANDELA -For Detailed usage of CANDELA, please refer to the [official document](https://candela-docs.readthedocs.io/en/latest/). -There are two things which need special attention in using CANDELA with ABACUS. -First, the input file of CANDELA only takes the name of `INPUT`, the same as ABACUS input file, so you should not run CANDELA in the same folder where you run ABACUS. -Second, to use CANDELA to postprocess ABACUS MD trajectory, the following parameters have to be specified in the `INPUT` file of CANDELA in addition to other required parameters: +[CANDELA](https://github.com/MCresearch/Candela) is short for Collection of ANalysis DEsigned for +Large-scale Atomic simulations. It is developed by MCresearch to conduct analyses on MD trajectory +in different formats. Right now the program only supports analysis of pair distribution function +(PDF), static structure factor (SSF) and mean square displacement (MSD). The minimum supported +version of ABACUS is 3.2.0. + +## Requirements for using CANDELA + +For Detailed usage of CANDELA, please refer to the +[official document](https://candela-docs.readthedocs.io/en/latest/). There are two things which need +special attention in using CANDELA with ABACUS. First, the input file of CANDELA only takes the name +of `INPUT`, the same as ABACUS input file, so you should not run CANDELA in the same folder where +you run ABACUS. Second, to use CANDELA to postprocess ABACUS MD trajectory, the following parameters +have to be specified in the `INPUT` file of CANDELA in addition to other required parameters: + 1. `geo_in_type` has to be set to `ABACUS`; -2. `msd_dt` has to be specified in unit of picosecond, especially in the case of `calculation` = `msd`; -3. `geo_directory` has to be set to the path to the `MD_dump` file in the `OUT.xxx` folder. -As a result, a CANDELA `INPUT` file for calculating PDF from ABACUS should be something like this: +1. `msd_dt` has to be specified in unit of picosecond, especially in the case of `calculation` = + `msd`; +1. `geo_directory` has to be set to the path to the `MD_dump` file in the `OUT.xxx` folder. As a + result, a CANDELA `INPUT` file for calculating PDF from ABACUS should be something like this: + ``` calculation pdf # Pair Distribution Function. system Al @@ -36,4 +43,5 @@ struf_dgx 0.05 struf_ng 200 ``` -More examples of CANDELA `INPUT` with ABACUS can be found in the [test](https://github.com/MCresearch/Candela/tree/main/test) directory. \ No newline at end of file +More examples of CANDELA `INPUT` with ABACUS can be found in the +[test](https://github.com/MCresearch/Candela/tree/main/test) directory. diff --git a/docs/advanced/interface/deeph.md b/docs/advanced/interface/deeph.md index aa60ab6de59..ad073c65dab 100644 --- a/docs/advanced/interface/deeph.md +++ b/docs/advanced/interface/deeph.md @@ -1,32 +1,52 @@ # DeepH -[DeepH](https://doi.org/10.1038/s43588-022-00265-6) applies meaching learning to predict the Hamiltonian in atomic basis representation. For such purpose, DeepH uses the Hamiltonian and overlap matrices from DFT calculations. Here we introduce how to extract relevant information from ABACUS for the purpose of DeepH training and prediction. +[DeepH](https://doi.org/10.1038/s43588-022-00265-6) applies meaching learning to predict the +Hamiltonian in atomic basis representation. For such purpose, DeepH uses the Hamiltonian and overlap +matrices from DFT calculations. Here we introduce how to extract relevant information from ABACUS +for the purpose of DeepH training and prediction. -Detailed instructions on installing and running DeepH can be found on its official [website](https://deeph-pack.deepmodeling.com/en/latest/#deeph). An [example](https://deeph-pack.deepmodeling.com/en/latest/demo/demo3.html) for using DeepH with ABACUS is also provided. +Detailed instructions on installing and running DeepH can be found on its official +[website](https://deeph-pack.deepmodeling.com/en/latest/#deeph). An +[example](https://deeph-pack.deepmodeling.com/en/latest/demo/demo3.html) for using DeepH with ABACUS +is also provided. -Here I intend not to repeat information from the above sources, but to add some minor details related to the setting of ABACUS `INPUT` files. +Here I intend not to repeat information from the above sources, but to add some minor details +related to the setting of ABACUS `INPUT` files. > Note: Use the LCAO basis for DeepH-related calculations -As mentioned in the README.md file in the above-mentioned example, there are two stages where users need to run ABACUS calculations. +As mentioned in the README.md file in the above-mentioned example, there are two stages where users +need to run ABACUS calculations. -The first stage is during the data preparation phase, where we need to run a series of SCF calculations and output the Hamiltonian and overlap matrices. For such purpose, one needs to add the following line in the `INPUT` file: +The first stage is during the data preparation phase, where we need to run a series of SCF +calculations and output the Hamiltonian and overlap matrices. For such purpose, one needs to add the +following line in the `INPUT` file: ``` out_mat_hs2 1 ``` -**For ABACUS v3.9.0.25+:** Files named `hrs1_nao.csr`, `hrs2_nao.csr` (for nspin=2), and `srs1_nao.csr` will be generated in `OUT.${suffix}/` directory, containing the Hamiltonian and overlap matrices in standard CSR format. You can optionally specify precision: `out_mat_hs2 1 8` (default 8 digits). +**For ABACUS v3.9.0.25+:** Files named `hrs1_nao.csr`, `hrs2_nao.csr` (for nspin=2), and +`srs1_nao.csr` will be generated in `OUT.${suffix}/` directory, containing the Hamiltonian and +overlap matrices in standard CSR format. You can optionally specify precision: `out_mat_hs2 1 8` +(default 8 digits). -**For ABACUS v3.8.x and earlier:** Files named `data-HR-sparse_SPIN${x}.csr` and `data-SR-sparse_SPIN${x}.csr` will be generated, where `${x}` takes value of 0 or 1 based on the spin component. +**For ABACUS v3.8.x and earlier:** Files named `data-HR-sparse_SPIN${x}.csr` and +`data-SR-sparse_SPIN${x}.csr` will be generated, where `${x}` takes value of 0 or 1 based on the +spin component. -> **Note:** DeepH v1.0.0+ is required to read the new CSR format from ABACUS v3.9.0.25+. For older DeepH versions, please use ABACUS v3.8.x or earlier. +> **Note:** DeepH v1.0.0+ is required to read the new CSR format from ABACUS v3.9.0.25+. For older +> DeepH versions, please use ABACUS v3.8.x or earlier. -More details on this keyword can be found in the [list of input keywords](../input_files/input-main.md#out_mat_hs2). +More details on this keyword can be found in the +[list of input keywords](../input_files/input-main.md#out_mat_hs2). -The second stage is during the inference phase. After DeepH training completes, we can apply the model to predict the Hamiltonian on other systems. For that purpose, we also need the overlap matrices from the new systems, but no SCF calculation is required. +The second stage is during the inference phase. After DeepH training completes, we can apply the +model to predict the Hamiltonian on other systems. For that purpose, we also need the overlap +matrices from the new systems, but no SCF calculation is required. -For that purpose, in `INPUT` file we need to make the following specification of the keyword `calculation`: +For that purpose, in `INPUT` file we need to make the following specification of the keyword +`calculation`: ``` calculation get_S diff --git a/docs/advanced/interface/deepks.md b/docs/advanced/interface/deepks.md index 3fb2cb5b4ce..e271aad8d27 100644 --- a/docs/advanced/interface/deepks.md +++ b/docs/advanced/interface/deepks.md @@ -1,14 +1,26 @@ # DeePKS -[DeePKS](https://pubs.acs.org/doi/10.1021/acs.jctc.0c00872) is a machine-learning (ML) aided density funcitonal model that fits the energy difference between highly accurate but computationally demanding method and effcient but less accurate method via neural-network. Common high-precision methods include hybrid functionals or CCSD-T, while common low-precision methods are LDA/GGA. - -As such, the trained DeePKS model can provide highly accurate energetics (and forces/band gap/density) with relatively low computational cost, and can therefore act as a bridge to connect expensive quantum mechanic data and machine-learning-based potentials. -While the original framework of DeePKS is for molecular systems, please refer to this [J. Phys. Chem. A 126.49 (2022): 9154-9164](https://pubs.acs.org/doi/abs/10.1021/acs.jpca.2c05000) for the application of DeePKS in periodic systems. - -Detailed instructions on installing and running DeePKS can be found on this [website](https://deepks-kit.readthedocs.io/en/latest/index.html). The DeePKS-related keywords in `INPUT` file can be found [here](http://abacus.deepmodeling.com/en/latest/advanced/input_files/input-main.html#deepks). An [example](https://github.com/deepmodeling/deepks-kit/tree/abacus/examples/water_single_lda2pbe_abacus) for training DeePKS model with ABACUS is also provided. For practical applications, users can refer to a series of [Notebooks](https://bohrium.dp.tech/collections/1921409690). These Notebooks provide detailed instructions on how to train and use the DeePKS model using perovskite as an example. Currently, these tutorials are available in Chinese, but we plan to release corresponding English versions in the near future. - - +[DeePKS](https://pubs.acs.org/doi/10.1021/acs.jctc.0c00872) is a machine-learning (ML) aided density +funcitonal model that fits the energy difference between highly accurate but computationally +demanding method and effcient but less accurate method via neural-network. Common high-precision +methods include hybrid functionals or CCSD-T, while common low-precision methods are LDA/GGA. + +As such, the trained DeePKS model can provide highly accurate energetics (and forces/band +gap/density) with relatively low computational cost, and can therefore act as a bridge to connect +expensive quantum mechanic data and machine-learning-based potentials. While the original framework +of DeePKS is for molecular systems, please refer to this +[J. Phys. Chem. A 126.49 (2022): 9154-9164](https://pubs.acs.org/doi/abs/10.1021/acs.jpca.2c05000) +for the application of DeePKS in periodic systems. + +Detailed instructions on installing and running DeePKS can be found on this +[website](https://deepks-kit.readthedocs.io/en/latest/index.html). The DeePKS-related keywords in +`INPUT` file can be found +[here](http://abacus.deepmodeling.com/en/latest/advanced/input_files/input-main.html#deepks). An +[example](https://github.com/deepmodeling/deepks-kit/tree/abacus/examples/water_single_lda2pbe_abacus) +for training DeePKS model with ABACUS is also provided. For practical applications, users can refer +to a series of [Notebooks](https://bohrium.dp.tech/collections/1921409690). These Notebooks provide +detailed instructions on how to train and use the DeePKS model using perovskite as an example. +Currently, these tutorials are available in Chinese, but we plan to release corresponding English +versions in the near future. > Note: DeePKS calculations can only be performed by the LCAO basis. - - diff --git a/docs/advanced/interface/deeptb.md b/docs/advanced/interface/deeptb.md index 13cdf406dc2..6a004d57154 100644 --- a/docs/advanced/interface/deeptb.md +++ b/docs/advanced/interface/deeptb.md @@ -1,5 +1,17 @@ # DeePTB -[DeePTB](https://github.com/deepmodeling/DeePTB) is an innovative Python package that uses deep learning to accelerate ab initio electronic structure simulations. It offers versatile, accurate, and efficient simulations for a wide range of materials and phenomena. Trained on small systems, DeePTB can predict electronic structures of large systems, handle structural perturbations, and integrate with molecular dynamics for finite temperature simulations, providing comprehensive insights into atomic and electronic behavior. See more details in [DeePTB-SK: Nat Commun 15, 6772 (2024)](https://www.nature.com/articles/s41467-024-51006-4) and [DeePTB-E3: arXiv:2407.06053](https://arxiv.org/pdf/2407.06053). +[DeePTB](https://github.com/deepmodeling/DeePTB) is an innovative Python package that uses deep +learning to accelerate ab initio electronic structure simulations. It offers versatile, accurate, +and efficient simulations for a wide range of materials and phenomena. Trained on small systems, +DeePTB can predict electronic structures of large systems, handle structural perturbations, and +integrate with molecular dynamics for finite temperature simulations, providing comprehensive +insights into atomic and electronic behavior. See more details in +[DeePTB-SK: Nat Commun 15, 6772 (2024)](https://www.nature.com/articles/s41467-024-51006-4) and +[DeePTB-E3: arXiv:2407.06053](https://arxiv.org/pdf/2407.06053). -DeePTB trains the model based on the Structure, Eigenvalues, Hamiltonian, Density matrix, and Overlap matrix from first-principles calcualtions. DeePTB team provides the interfaces [dftio](https://github.com/deepmodeling/dftio) with other first-principles softwares. [dftio](https://github.com/deepmodeling/dftio) fully supports the interfaces with ABACUS, and can transfer the Structure, Eigenvalues, Hamiltonian, Density matrix, and Overlap matrix from ABACUS into the format used in [DeePTB](https://github.com/deepmodeling/DeePTB). +DeePTB trains the model based on the Structure, Eigenvalues, Hamiltonian, Density matrix, and +Overlap matrix from first-principles calcualtions. DeePTB team provides the interfaces +[dftio](https://github.com/deepmodeling/dftio) with other first-principles softwares. +[dftio](https://github.com/deepmodeling/dftio) fully supports the interfaces with ABACUS, and can +transfer the Structure, Eigenvalues, Hamiltonian, Density matrix, and Overlap matrix from ABACUS +into the format used in [DeePTB](https://github.com/deepmodeling/DeePTB). diff --git a/docs/advanced/interface/dpgen.md b/docs/advanced/interface/dpgen.md index bcfb1b1cb79..336d58fef66 100644 --- a/docs/advanced/interface/dpgen.md +++ b/docs/advanced/interface/dpgen.md @@ -1,17 +1,24 @@ # DP-GEN - -[DP-GEN](https://github.com/deepmodeling/dpgen), the deep potential generator, is a package designed to generate deep learning based model of interatomic potential energy and force fields (Yuzhi Zhang, Haidi Wang, Weijie Chen, Jinzhe Zeng, Linfeng Zhang, Han Wang, and Weinan E, DP-GEN: A concurrent learning platform for the generation of reliable deep learning based potential energy models, Computer Physics Communications, 2020, 107206). ABACUS can now interface with DP-GEN to generate deep potentials and perform autotests. The minimum recommended version is ABACUS 3.0, dpdata 0.2.8, and dpgen 0.10.7 . In the following part, we take the FCC aluminum as an example. +[DP-GEN](https://github.com/deepmodeling/dpgen), the deep potential generator, is a package designed +to generate deep learning based model of interatomic potential energy and force fields (Yuzhi Zhang, +Haidi Wang, Weijie Chen, Jinzhe Zeng, Linfeng Zhang, Han Wang, and Weinan E, DP-GEN: A concurrent +learning platform for the generation of reliable deep learning based potential energy models, +Computer Physics Communications, 2020, 107206). ABACUS can now interface with DP-GEN to generate +deep potentials and perform autotests. The minimum recommended version is ABACUS 3.0, dpdata 0.2.8, +and dpgen 0.10.7 . In the following part, we take the FCC aluminum as an example. ## init_bulk and run This example can be found in examples/dpgen-example/init_and_run directory. -Firstly, one needs to prepare input files for ABACUS calculation, e.g., “INPUT”, "INPUT.md", "KPT", "Al.STRU", "Al_ONCV_PBE-1.0.upf", which are the main input file containing input tags, k-point mesh, crystal structure and pseudoptential, respectively. "INPUT" is for scf calculation, and "INPUT.md" is for AIMD (ab-initio molecular dynamic) calculation. +Firstly, one needs to prepare input files for ABACUS calculation, e.g., “INPUT”, "INPUT.md", "KPT", +"Al.STRU", "Al_ONCV_PBE-1.0.upf", which are the main input file containing input tags, k-point mesh, +crystal structure and pseudoptential, respectively. "INPUT" is for scf calculation, and "INPUT.md" +is for AIMD (ab-initio molecular dynamic) calculation. Secondly, for the "dpgen init_bulk" step, an `init.json` file should be provided: - ```json { "init_fp_style": "ABACUS", # abacus interface @@ -37,6 +44,7 @@ Secondly, for the "dpgen init_bulk" step, an `init.json` file should be provided ``` Next, for the "dpgen run" step, the following `run_param.json` should be provided. + ```json { "type_map": [ @@ -186,9 +194,12 @@ Next, for the "dpgen run" step, the following `run_param.json` should be provide This example can be found in examples/dpgen-example/autotest directory. -`dpgen autotest` supports to perform `relaxation`,`eos` (equation of state),`elastic`,`surface`,`vacancy`, and `interstitial` calculations with ABACUS. A `property.json` and `machine.json` file need to be provided. For example, +`dpgen autotest` supports to perform `relaxation`,`eos` (equation of +state),`elastic`,`surface`,`vacancy`, and `interstitial` calculations with ABACUS. A `property.json` +and `machine.json` file need to be provided. For example, `property.json`: + ```json { @@ -362,8 +373,10 @@ This example can be found in examples/dpgen-example/autotest directory. ``` -For each property, the command `dpgen autotest make property.json` will generate the input files, `dpgen autotest run property.json machine.json` will run the corresponding tasks, and `dpgen autotest post property.json` will collect the final results. +For each property, the command `dpgen autotest make property.json` will generate the input files, +`dpgen autotest run property.json machine.json` will run the corresponding tasks, and +`dpgen autotest post property.json` will collect the final results. Notes: -- The ABACUS-DPGEN interface can be used in both pw and lcao basis. +- The ABACUS-DPGEN interface can be used in both pw and lcao basis. diff --git a/docs/advanced/interface/migration-guide-csr-format.md b/docs/advanced/interface/migration-guide-csr-format.md index b93b02c2d01..02252d63c55 100644 --- a/docs/advanced/interface/migration-guide-csr-format.md +++ b/docs/advanced/interface/migration-guide-csr-format.md @@ -2,9 +2,12 @@ ## Overview -Starting from ABACUS v3.9.0.25, the output format for Hamiltonian H(R) and overlap S(R) matrices has been unified to use standard CSR (Compressed Sparse Row) format, matching the format used by `out_dmr` for density matrices. +Starting from ABACUS v3.9.0.25, the output format for Hamiltonian H(R) and overlap S(R) matrices has +been unified to use standard CSR (Compressed Sparse Row) format, matching the format used by +`out_dmr` for density matrices. This change affects downstream tools that read H(R) and S(R) matrices, including: + - TB2J (magnetic exchange parameters) - DeepH (machine learning Hamiltonian) - pyATB (tight-binding analysis) @@ -15,6 +18,7 @@ This change affects downstream tools that read H(R) and S(R) matrices, including ### File Names **Old format (ABACUS ≤ v3.8.x):** + ``` OUT.${suffix}/data-HR-sparse_SPIN0.csr OUT.${suffix}/data-HR-sparse_SPIN1.csr (nspin=2 only) @@ -22,6 +26,7 @@ OUT.${suffix}/data-SR-sparse_SPIN0.csr ``` **New format (ABACUS ≥ v3.9.0.25):** + ``` OUT.${suffix}/hrs1_nao.csr OUT.${suffix}/hrs2_nao.csr (nspin=2 only) @@ -33,6 +38,7 @@ OUT.${suffix}/srs1_nao.csr Both old and new formats use CSR structure, but with different headers and metadata. #### Old Format Header + ``` STEP: 0 Matrix Dimension of H(R): 26 @@ -42,6 +48,7 @@ Matrix number of H(R): 183 ``` #### New Format Header + ``` --- Ionic Step 1 --- # print H matrix in real space H(R) @@ -81,11 +88,14 @@ Matrix number of H(R): 183 ### Key Differences -1. **UnitCell Information**: New format includes complete unit cell information (lattice vectors, atomic positions) -2. **Header Format**: New format uses descriptive comments with `#` prefix -3. **Section Labels**: New format explicitly labels CSR sections ("# CSR values", "# CSR column indices", "# CSR row pointers") -4. **Ionic Step**: New format uses "Ionic Step N" instead of "STEP: N" -5. **Precision Control**: New format supports optional precision parameter: `out_mat_hs2 1 12` (default 8) +1. **UnitCell Information**: New format includes complete unit cell information (lattice vectors, + atomic positions) +1. **Header Format**: New format uses descriptive comments with `#` prefix +1. **Section Labels**: New format explicitly labels CSR sections ("# CSR values", "# CSR column + indices", "# CSR row pointers") +1. **Ionic Step**: New format uses "Ionic Step N" instead of "STEP: N" +1. **Precision Control**: New format supports optional precision parameter: `out_mat_hs2 1 12` + (default 8) ## Migration Steps for Tool Developers @@ -251,11 +261,13 @@ def read_hamiltonian(filename): **Required version:** TB2J v0.9.0+ **Changes needed:** + - Update file name detection to look for `hrs*_nao.csr` and `srs*_nao.csr` - Update parser to handle new header format with UnitCell information - Update parser to skip comment lines starting with `#` **Example:** + ```python # In abacus2J.py or relevant parser def find_hr_files(path, suffix): @@ -282,6 +294,7 @@ def find_hr_files(path, suffix): **Required version:** DeepH v1.0.0+ **Changes needed:** + - Update `parse_abacus.py` to handle new file names - Update CSR parser to skip UnitCell section - Update parser to handle comment lines with `#` prefix @@ -289,6 +302,7 @@ def find_hr_files(path, suffix): ### pyATB **Changes needed:** + - Update file I/O module to detect and parse new format - Add format version detection - Maintain backward compatibility with old format @@ -309,7 +323,8 @@ abacus_new > log_new ### 2. Verify Numerical Equivalence -The CSR data (values, indices, pointers) should be numerically identical between old and new formats, only the header differs. +The CSR data (values, indices, pointers) should be numerically identical between old and new +formats, only the header differs. ```python def compare_csr_data(old_file, new_file): @@ -352,17 +367,20 @@ This affects the output format of floating-point values in the CSR data. ## Support and Resources - **ABACUS Documentation:** [https://abacus.deepmodeling.com/](https://abacus.deepmodeling.com/) -- **GitHub Issues:** [https://github.com/deepmodeling/abacus-develop/issues](https://github.com/deepmodeling/abacus-develop/issues) +- **GitHub Issues:** + [https://github.com/deepmodeling/abacus-develop/issues](https://github.com/deepmodeling/abacus-develop/issues) - **Design Document:** `docs/plans/2026-02-28-unify-out-mat-hs2-design.md` - **Implementation Plan:** `docs/plans/2026-02-28-unify-out-mat-hs2-plan.md` ## Summary The new CSR format provides: + - ✅ Unified interface with `out_dmr` output - ✅ Complete UnitCell information in output files - ✅ Precision control for output values - ✅ Better documentation with inline comments - ✅ Clearer section labels for easier parsing -Tool developers should update their parsers to support the new format while maintaining backward compatibility with the old format for users running older ABACUS versions. +Tool developers should update their parsers to support the new format while maintaining backward +compatibility with the old format for users running older ABACUS versions. diff --git a/docs/advanced/interface/phonopy.md b/docs/advanced/interface/phonopy.md index f514ec5ab41..9a82cc887d4 100644 --- a/docs/advanced/interface/phonopy.md +++ b/docs/advanced/interface/phonopy.md @@ -1,6 +1,8 @@ # Phonopy -[Phonopy](https://phonopy.github.io/phonopy) is a powerful package to calculate phonon and related properties. The ABACUS interface has been added in Phonopy v.2.19.1. In the following, we take the FCC aluminum as an example: +[Phonopy](https://phonopy.github.io/phonopy) is a powerful package to calculate phonon and related +properties. The ABACUS interface has been added in Phonopy v.2.19.1. In the following, we take the +FCC aluminum as an example: 1. To obtain supercells ($2\times 2\times 2$) with displacements, run phonopy: @@ -8,7 +10,9 @@ phonopy -d --dim="2 2 2" --abacus ``` -2. Calculate forces on atoms in the supercells with displacements. For each SCF calculation, you should specify `stru_file` with `STRU-{number}` and `cal_force=1` in INPUT in order to calculate force using ABACUS. Be careful not to relax the structures +2. Calculate forces on atoms in the supercells with displacements. For each SCF calculation, you + should specify `stru_file` with `STRU-{number}` and `cal_force=1` in INPUT in order to calculate + force using ABACUS. Be careful not to relax the structures ``` echo 'stru_file ./STRU-001' >> INPUT diff --git a/docs/advanced/interface/pyabacus.md b/docs/advanced/interface/pyabacus.md index ffe32d43502..d6a98684bdf 100644 --- a/docs/advanced/interface/pyabacus.md +++ b/docs/advanced/interface/pyabacus.md @@ -1,6 +1,7 @@ # PyABACUS -PyABACUS is the official Python interface for ABACUS, providing a convenient way to run DFT calculations directly from Python scripts. +PyABACUS is the official Python interface for ABACUS, providing a convenient way to run DFT +calculations directly from Python scripts. ## Installation @@ -13,7 +14,8 @@ pip install -e . ### With C++ Driver Support -For full functionality including direct library calls (faster than subprocess), build ABACUS with Python bindings: +For full functionality including direct library calls (faster than subprocess), build ABACUS with +Python bindings: ```bash cmake -B build -DENABLE_PYABACUS=ON -DENABLE_LCAO=ON @@ -21,7 +23,8 @@ cmake --build build -j8 pip install -e python/pyabacus ``` -**Note:** The `pyabacus` package on PyPI is a different project and is NOT related to ABACUS. Please install from source as shown above. +**Note:** The `pyabacus` package on PyPI is a different project and is NOT related to ABACUS. Please +install from source as shown above. ## Quick Start @@ -70,6 +73,7 @@ result = pyabacus.abacus( ``` This is equivalent to running: + ```bash OMP_NUM_THREADS=2 mpirun -np 4 abacus ``` @@ -107,20 +111,20 @@ def abacus( **Parameters:** -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `input_dir` | str | `"."` | Directory containing INPUT, STRU, KPT files | -| `input_file` | str | None | Explicit path to INPUT file | -| `stru_file` | str | None | Explicit path to STRU file | -| `kpt_file` | str | None | Explicit path to KPT file | -| `pseudo_dir` | str | None | Directory containing pseudopotentials | -| `orbital_dir` | str | None | Directory containing orbital files (LCAO) | -| `output_dir` | str | `"OUT.PYABACUS"` | Directory for output files | -| `calculate_force` | bool | True | Whether to calculate forces | -| `calculate_stress` | bool | False | Whether to calculate stress tensor | -| `verbosity` | int | 1 | Output level (0=silent, 1=normal, 2=verbose) | -| `nprocs` | int | 1 | Number of MPI processes | -| `nthreads` | int | 1 | Number of OpenMP threads | +| Parameter | Type | Default | Description | +| ------------------ | ---- | ---------------- | -------------------------------------------- | +| `input_dir` | str | `"."` | Directory containing INPUT, STRU, KPT files | +| `input_file` | str | None | Explicit path to INPUT file | +| `stru_file` | str | None | Explicit path to STRU file | +| `kpt_file` | str | None | Explicit path to KPT file | +| `pseudo_dir` | str | None | Directory containing pseudopotentials | +| `orbital_dir` | str | None | Directory containing orbital files (LCAO) | +| `output_dir` | str | `"OUT.PYABACUS"` | Directory for output files | +| `calculate_force` | bool | True | Whether to calculate forces | +| `calculate_stress` | bool | False | Whether to calculate stress tensor | +| `verbosity` | int | 1 | Output level (0=silent, 1=normal, 2=verbose) | +| `nprocs` | int | 1 | Number of MPI processes | +| `nthreads` | int | 1 | Number of OpenMP threads | **Returns:** `CalculationResult` object @@ -130,37 +134,37 @@ Container for calculation results. **Attributes:** -| Attribute | Type | Description | -|-----------|------|-------------| -| `converged` | bool | Whether SCF converged | -| `niter` | int | Number of SCF iterations | -| `drho` | float | Final charge density difference | -| `etot` | float | Total energy (Ry) | -| `etot_ev` | float | Total energy (eV) | -| `forces` | ndarray | Forces on atoms (nat, 3) in Ry/Bohr | -| `forces_ev_ang` | ndarray | Forces in eV/Angstrom | -| `stress` | ndarray | Stress tensor (3, 3) in kbar | -| `fermi_energy` | float | Fermi energy (eV) | -| `bandgap` | float | Band gap (eV) | -| `nat` | int | Number of atoms | -| `ntype` | int | Number of atom types | -| `nbands` | int | Number of bands | -| `nks` | int | Number of k-points | -| `output_dir` | str | Path to output directory (OUT.$suffix) | -| `log_file` | str | Path to the main log file | -| `output_files` | dict | Dictionary of output files (filename -> path) | +| Attribute | Type | Description | +| --------------- | ------- | --------------------------------------------- | +| `converged` | bool | Whether SCF converged | +| `niter` | int | Number of SCF iterations | +| `drho` | float | Final charge density difference | +| `etot` | float | Total energy (Ry) | +| `etot_ev` | float | Total energy (eV) | +| `forces` | ndarray | Forces on atoms (nat, 3) in Ry/Bohr | +| `forces_ev_ang` | ndarray | Forces in eV/Angstrom | +| `stress` | ndarray | Stress tensor (3, 3) in kbar | +| `fermi_energy` | float | Fermi energy (eV) | +| `bandgap` | float | Band gap (eV) | +| `nat` | int | Number of atoms | +| `ntype` | int | Number of atom types | +| `nbands` | int | Number of bands | +| `nks` | int | Number of k-points | +| `output_dir` | str | Path to output directory (OUT.\$suffix) | +| `log_file` | str | Path to the main log file | +| `output_files` | dict | Dictionary of output files (filename -> path) | **Methods:** -| Method | Description | -|--------|-------------| -| `summary()` | Return a formatted summary string | -| `energies` | Dictionary of all energy components | -| `has_forces` | Whether forces are available | -| `has_stress` | Whether stress is available | -| `has_output_dir` | Whether output directory exists | +| Method | Description | +| ----------------------- | ------------------------------------- | +| `summary()` | Return a formatted summary string | +| `energies` | Dictionary of all energy components | +| `has_forces` | Whether forces are available | +| `has_stress` | Whether stress is available | +| `has_output_dir` | Whether output directory exists | | `get_output_file(name)` | Get full path to specific output file | -| `list_output_files()` | List all output file names | +| `list_output_files()` | List all output file names | ## Output File Tracking @@ -188,16 +192,16 @@ if bands_file: ### Common Output Files -| File | Description | -|------|-------------| -| `running_scf.log` | Main calculation log | -| `BANDS_1.dat` | Band structure data | -| `PDOS` | Projected density of states | -| `CHARGE.cube` | Charge density in cube format | -| `SPIN1_CHG.cube` | Spin-up charge density | -| `SPIN2_CHG.cube` | Spin-down charge density | -| `istate.info` | Band eigenvalues and occupations | -| `kpoints` | K-point information | +| File | Description | +| ----------------- | -------------------------------- | +| `running_scf.log` | Main calculation log | +| `BANDS_1.dat` | Band structure data | +| `PDOS` | Projected density of states | +| `CHARGE.cube` | Charge density in cube format | +| `SPIN1_CHG.cube` | Spin-up charge density | +| `SPIN2_CHG.cube` | Spin-down charge density | +| `istate.info` | Band eigenvalues and occupations | +| `kpoints` | K-point information | ## Convenience Functions @@ -277,25 +281,29 @@ for system, data in results.items(): ### ABACUS executable not found If you see "ABACUS executable not found", ensure: + 1. ABACUS is installed and in your PATH -2. Or build with C++ driver support (see Installation) +1. Or build with C++ driver support (see Installation) ### MPI not found If you see "mpirun/mpiexec not found" when using `nprocs > 1`: + 1. Install MPI (OpenMPI or MPICH) -2. Ensure `mpirun` or `mpiexec` is in your PATH -3. Or set `nprocs=1` to run without MPI +1. Ensure `mpirun` or `mpiexec` is in your PATH +1. Or set `nprocs=1` to run without MPI ### Import errors If `import pyabacus` fails: + 1. Ensure pyabacus is installed: `pip install pyabacus` -2. Check Python version compatibility (Python 3.8+) +1. Check Python version compatibility (Python 3.8+) ### Calculation not converging Check the log file for details: + ```python result = pyabacus.abacus("./problem_case/") if not result.converged: @@ -308,6 +316,7 @@ if not result.converged: ### Forces or stress not available Forces and stress are parsed from the ABACUS output log. Ensure: + 1. `cal_force` is set in your INPUT file for forces -2. `cal_stress` is set in your INPUT file for stress -3. The calculation completed successfully +1. `cal_stress` is set in your INPUT file for stress +1. The calculation completed successfully diff --git a/docs/advanced/interface/pyatb.md b/docs/advanced/interface/pyatb.md index 7c1ed0b9f2f..c8e30d97a0d 100644 --- a/docs/advanced/interface/pyatb.md +++ b/docs/advanced/interface/pyatb.md @@ -1,110 +1,127 @@ -# PYATB - -## Introduction - -[PYATB](https://github.com/pyatb/pyatb) (Python ab initio tight binding simulation package) is an open-source software package designed for computing electronic structures and related properties based on the ab initio tight binding Hamiltonian. The Hamiltonian can be directly obtained after conducting self-consistent calculations with ABACUS using numerical atomic orbital (NAO) bases. The package comprises three modules - Bands, Geometric, and Optical, each providing a comprehensive set of tools for analyzing different aspects of a material's electronic structure. - -## Installation - -```bash -git clone https://github.com/pyatb/pyatb.git -cd pyatb -python setup.py install --record log -``` - -To customize the `setup.py` file, you must make changes to the **CXX** and **LAPACK_DIR** variables in line with your environment. **CXX** denotes the C++ compiler you intend to use, for instance, icpc (note that it should not be the mpi version). Furthermore, **LAPACK_DIR** is used to specify the Intel MKL path. - -After completing the installation process, you can access the `pyatb` executable and corresponding module, which can be imported using the `import pyatb` command. - -## How to use - -We take Bi$_2$Se$_3$ as an example to illustrate how to use ABACUS to generate the tight binding Hamiltonian required for PYATB, and then perform calculations related to PYATB functions. - -1. Perform ABACUS self consistent calculation: - -``` -INPUT_PARAMETERS - -# System variables -suffix Bi2Se3 -ntype 2 -calculation scf -esolver_type ksdft -symmetry 1 -init_chg atomic - -# Plane wave related variables -ecutwfc 100 - -# Electronic structure -basis_type lcao -ks_solver genelpa -nspin 4 -smearing_method gauss -smearing_sigma 0.02 -mixing_type broyden -mixing_beta 0.7 -scf_nmax 200 -scf_thr 1e-8 -lspinorb 1 -noncolin 0 - -# Variables related to output information -out_chg 1 -out_mat_hs2 1 -out_mat_r 1 -``` - -After the key parameters `out_mat_hs2` and `out_mat_r` are turned on, ABACUS will generate files containing the Hamiltonian matrix $H(R)$, overlap matrix $S(R)$, and dipole matrix $r(R)$ after completing the self-consistent calculation. These parameters can be found in the ABACUS `INPUT` file. - -2. Copy the HR, SR, and rR files output by ABACUS's self-consistent calculation, which are located in the `OUT*` directory and named `data-HR-sparse_SPIN0.csr`, `data-SR-sparse_SPIN0.csr`, and `data-rR-sparse.csr`, respectively. Copy these files to the working directory and write the `Input` file for PYATB: - -``` -INPUT_PARAMETERS -{ - nspin 4 - package ABACUS - fermi_energy 9.557219691497478 - fermi_energy_unit eV - HR_route data-HR-sparse_SPIN0.csr - SR_route data-SR-sparse_SPIN0.csr - rR_route data-rR-sparse.csr - HR_unit Ry - rR_unit Bohr - max_kpoint_num 8000 -} - -LATTICE -{ - lattice_constant 1.8897162 - lattice_constant_unit Bohr - lattice_vector - -2.069 -3.583614 0.000000 - 2.069 -3.583614 0.000000 - 0.000 2.389075 9.546667 -} - -BAND_STRUCTURE -{ - wf_collect 0 - kpoint_mode line - kpoint_num 5 - high_symmetry_kpoint - 0.00000 0.00000 0.0000 100 # G - 0.00000 0.00000 0.5000 100 # Z - 0.50000 0.50000 0.0000 100 # F - 0.00000 0.00000 0.0000 100 # G - 0.50000 0.00000 0.0000 1 # L -} -``` - -For specific input file writing, please refer to PYATB's quick start. - -3. Perform PYATB calculation: - -``` -export OMP_NUM_THREADS=2 -mpirun -np 6 pyatb -``` - -After the calculation is completed, the band structure data and figures of Bi$_2$Se$_3$ can be found in the `Out/Band_Structure` folder. \ No newline at end of file +# PYATB + +## Introduction + +[PYATB](https://github.com/pyatb/pyatb) (Python ab initio tight binding simulation package) is an +open-source software package designed for computing electronic structures and related properties +based on the ab initio tight binding Hamiltonian. The Hamiltonian can be directly obtained after +conducting self-consistent calculations with ABACUS using numerical atomic orbital (NAO) bases. The +package comprises three modules - Bands, Geometric, and Optical, each providing a comprehensive set +of tools for analyzing different aspects of a material's electronic structure. + +## Installation + +```bash +git clone https://github.com/pyatb/pyatb.git +cd pyatb +python setup.py install --record log +``` + +To customize the `setup.py` file, you must make changes to the **CXX** and **LAPACK_DIR** variables +in line with your environment. **CXX** denotes the C++ compiler you intend to use, for instance, +icpc (note that it should not be the mpi version). Furthermore, **LAPACK_DIR** is used to specify +the Intel MKL path. + +After completing the installation process, you can access the `pyatb` executable and corresponding +module, which can be imported using the `import pyatb` command. + +## How to use + +We take Bi$_2$Se$_3$ as an example to illustrate how to use ABACUS to generate the tight binding +Hamiltonian required for PYATB, and then perform calculations related to PYATB functions. + +1. Perform ABACUS self consistent calculation: + +``` +INPUT_PARAMETERS + +# System variables +suffix Bi2Se3 +ntype 2 +calculation scf +esolver_type ksdft +symmetry 1 +init_chg atomic + +# Plane wave related variables +ecutwfc 100 + +# Electronic structure +basis_type lcao +ks_solver genelpa +nspin 4 +smearing_method gauss +smearing_sigma 0.02 +mixing_type broyden +mixing_beta 0.7 +scf_nmax 200 +scf_thr 1e-8 +lspinorb 1 +noncolin 0 + +# Variables related to output information +out_chg 1 +out_mat_hs2 1 +out_mat_r 1 +``` + +After the key parameters `out_mat_hs2` and `out_mat_r` are turned on, ABACUS will generate files +containing the Hamiltonian matrix $H(R)$, overlap matrix $S(R)$, and dipole matrix $r(R)$ after +completing the self-consistent calculation. These parameters can be found in the ABACUS `INPUT` +file. + +2. Copy the HR, SR, and rR files output by ABACUS's self-consistent calculation, which are located + in the `OUT*` directory and named `data-HR-sparse_SPIN0.csr`, `data-SR-sparse_SPIN0.csr`, and + `data-rR-sparse.csr`, respectively. Copy these files to the working directory and write the + `Input` file for PYATB: + +``` +INPUT_PARAMETERS +{ + nspin 4 + package ABACUS + fermi_energy 9.557219691497478 + fermi_energy_unit eV + HR_route data-HR-sparse_SPIN0.csr + SR_route data-SR-sparse_SPIN0.csr + rR_route data-rR-sparse.csr + HR_unit Ry + rR_unit Bohr + max_kpoint_num 8000 +} + +LATTICE +{ + lattice_constant 1.8897162 + lattice_constant_unit Bohr + lattice_vector + -2.069 -3.583614 0.000000 + 2.069 -3.583614 0.000000 + 0.000 2.389075 9.546667 +} + +BAND_STRUCTURE +{ + wf_collect 0 + kpoint_mode line + kpoint_num 5 + high_symmetry_kpoint + 0.00000 0.00000 0.0000 100 # G + 0.00000 0.00000 0.5000 100 # Z + 0.50000 0.50000 0.0000 100 # F + 0.00000 0.00000 0.0000 100 # G + 0.50000 0.00000 0.0000 1 # L +} +``` + +For specific input file writing, please refer to PYATB's quick start. + +3. Perform PYATB calculation: + +``` +export OMP_NUM_THREADS=2 +mpirun -np 6 pyatb +``` + +After the calculation is completed, the band structure data and figures of Bi$_2$Se$_3$ can be found +in the `Out/Band_Structure` folder. diff --git a/docs/advanced/json/json_add.md b/docs/advanced/json/json_add.md index 826b77119f1..f986a78a0bc 100644 --- a/docs/advanced/json/json_add.md +++ b/docs/advanced/json/json_add.md @@ -8,62 +8,66 @@ - [Object Type](#object-type) - [Array Type](#array-type) - [Array Modification Instructions](#array-modification-instructions) -2. [Json Codes Addition Guidelines](#2-json-codes-addition-guidelines) +1. [Json Codes Addition Guidelines](#2-json-codes-addition-guidelines) - [Abacus JSON Functionality Code Structure](#abacus-json-functionality-code-structure) - [Add JSON code principles](#add-json-code-principles) - - # 1. Abacus-Json Usage Instructions -In Abacus, the main utility functions for manipulating JSON trees are outlined below. These functions are used to add objects to Abacus JSON trees. - -Function signature: -void AbacusJson::add_json (std::vector keys, const T& value,bool IsArray) -Where: -- `keys` is a vector of string dictionaries, representing the node paths where values are to be added in the JSON tree. -- `value` is a generic value type, including int, bool, double, string, or rapidjson value type, indicating the value to be added to the Abacus JSON. -- `IsArray` is a boolean object, indicating whether the current node being added is an array. `true` represents an array node, while `false` represents a non-array node. +In Abacus, the main utility functions for manipulating JSON trees are outlined below. These +functions are used to add objects to Abacus JSON trees. -Example usage: -const std::string version = "v3.5.2"; -AbacusJson::add_json({"general_info", "version"}, version, false); +Function signature: void AbacusJson::add_json (std::vector keys, const T& value,bool +IsArray) Where: +- `keys` is a vector of string dictionaries, representing the node paths where values are to be + added in the JSON tree. +- `value` is a generic value type, including int, bool, double, string, or rapidjson value type, + indicating the value to be added to the Abacus JSON. +- `IsArray` is a boolean object, indicating whether the current node being added is an array. `true` + represents an array node, while `false` represents a non-array node. +Example usage: const std::string version = "v3.5.2"; AbacusJson::add_json({"general_info", +"version"}, version, false); ## Normal usage -### Add/Modify a value to object json node (key2 is a object node): +### Add/Modify a value to object json node (key2 is a object node): + ```cpp Json::AbacusJson::add_json({"key1","key2"}, 3.1415,false); ``` ### Pushback a value to array json node (key2 is a array node): + ```cpp Json::AbacusJson::add_json({"key1","key2"}, 3.1415,true); ``` -Through this function alone, the addition of the majority of JSON parameters can be achieved. However, for complex array types, additional operations are required. - +Through this function alone, the addition of the majority of JSON parameters can be achieved. +However, for complex array types, additional operations are required. ## Initialization and Assignment Functions for Different Value Types in Arrays ### Object Type: -Since the object type consists of key-value pairs, four member functions are divided based on whether key and val are of type std::string. + +Since the object type consists of key-value pairs, four member functions are divided based on +whether key and val are of type std::string. - JaddStringV(str,val): key is not string, val is string - JaddStringK(str,val): key is string, val is not string - JaddStringKV(str,val): both key and val are string - JaddNormal(str,val): both key and val are not string - ### Array Type: + For array types, the following member functions are used directly. - JPushBack(val): val is not string - JPushBackString(val): val is string -For example, to add nodes to a JSON tree with multiple arrays in Abacus, the following code is needed: +For example, to add nodes to a JSON tree with multiple arrays in Abacus, the following code is +needed: ```cpp // add key-val to an object array @@ -88,21 +92,20 @@ object0.JPushBack(3); Json::AbacusJson::add_json({"Darray"}, object0,true); ``` - - - - ## Array Modification Instructions For values that need to be modified in arrays, the following method can be used: -- The index number of the array starts at 0, if it's negative, it's going from back to front. eg. If the index is -1, it means that the last element of the array is modified: + +- The index number of the array starts at 0, if it's negative, it's going from back to front. eg. If + the index is -1, it means that the last element of the array is modified: - If the path contains an array, use the array index directly. ```cpp AbacusJson::add_json({"path",index }, value, is_array); ``` -Here, index is a number. index >= 0 indicates the index from the beginning of the array, while index < 0 indicates traversal from the end of the array. +Here, index is a number. index >= 0 indicates the index from the beginning of the array, while index +< 0 indicates traversal from the end of the array. For example, to modify the value of "vasp" to "cp2k" in the following JSON tree: @@ -120,25 +123,26 @@ For example, to modify the value of "vasp" to "cp2k" in the following JSON tree: } } ``` -The relative path of "vasp" in layman's terms is Json - key6 - key7[0]. To use the JSON modification method in abacus, simply change the index [0] to "0". + +The relative path of "vasp" in layman's terms is Json - key6 - key7[0]. To use the JSON modification +method in abacus, simply change the index [0] to "0". ```cpp AbacusJson::add_json({"Json","key6","key7",1}, "cp2k" , false); ``` If traversal is done from the end: + ```cpp AbacusJson::add_json({"Json","key6","key7",-2}, "cp2k", false); ``` An error is reported if index exceeds the array length! + ```cpp AbacusJson::add_json({"Json","key6","key7",3}, "cp2k", false); ``` - - - # 2. Abacus Json Codes Addition Guidelines ## Abacus JSON Functionality Code Structure @@ -146,23 +150,30 @@ AbacusJson::add_json({"Json","key6","key7",3}, "cp2k", false); The current code structure of JSON functionality in Abacus is roughly as follows: - source/source_io - - para_json.cpp: Contains JSON generation and output interfaces directly called by the device in Abacus. - - json_output/: Contains the functionality encapsulation class `abacusjson.cpp` of RapidJSON in Abacus and code classes for parameter generation in various JSON modules. + - para_json.cpp: Contains JSON generation and output interfaces directly called by the device in + Abacus. + - json_output/: Contains the functionality encapsulation class `abacusjson.cpp` of RapidJSON in + Abacus and code classes for parameter generation in various JSON modules. - test: Code testing files in `json_output`. - ## Add JSON code principles: + In Abacus JSON addition, the following principles need to be followed: -1. Whenever possible, code to be added in the module should be written in the `json_output` module (there may also be cases where parameters cannot be directly obtained through parameter passing in `json_output`), and then called in the path `para_json.cpp` -> `device.cpp` or other main execution paths. (Ensure minimal impact on other modules as much as possible) - -2. For parameters that can be obtained without depending on other modules, do not reference parameter values saved in other modules. (Such as `mpi_num`, `start_time`) +1. Whenever possible, code to be added in the module should be written in the `json_output` module + (there may also be cases where parameters cannot be directly obtained through parameter passing + in `json_output`), and then called in the path `para_json.cpp` -> `device.cpp` or other main + execution paths. (Ensure minimal impact on other modules as much as possible) + +1. For parameters that can be obtained without depending on other modules, do not reference + parameter values saved in other modules. (Such as `mpi_num`, `start_time`) -3. Use classes as function parameters as much as possible instead of using global classes for obtained parameters. (For example, in `gen_general_info`, `Input`) +1. Use classes as function parameters as much as possible instead of using global classes for + obtained parameters. (For example, in `gen_general_info`, `Input`) -4. After adding parameters, supplement test code in `source_io/json_output/test`. +1. After adding parameters, supplement test code in `source_io/json_output/test`. -For the current JSON file, there are two JSON modules: `init` and `general_info`, `output_info`. +For the current JSON file, there are two JSON modules: `init` and `general_info`, `output_info`. Taking `general_info` as an example, the code to be added is as follows: ```cpp @@ -216,4 +227,4 @@ void gen_general_info(const Parameter& param) } #endif } // namespace Json -``` \ No newline at end of file +``` diff --git a/docs/advanced/json/json_para.md b/docs/advanced/json/json_para.md index 1ae86190fc7..adb7d8fd7ff 100644 --- a/docs/advanced/json/json_para.md +++ b/docs/advanced/json/json_para.md @@ -10,10 +10,12 @@ ## Overview -This JSON template provides input and output configurations for ABACUS. It contains parameters for the execution of the program and the output of results, primarily for recording computational processes and outcomes for post processing. - -Notice: one need to add the option `-DENABLE_RAPIDJSON=ON` when compiling ABACUS to enable the output of "abacus.json". +This JSON template provides input and output configurations for ABACUS. It contains parameters for +the execution of the program and the output of results, primarily for recording computational +processes and outcomes for post processing. +Notice: one need to add the option `-DENABLE_RAPIDJSON=ON` when compiling ABACUS to enable the +output of "abacus.json". ## General Information @@ -32,17 +34,19 @@ Notice: one need to add the option `-DENABLE_RAPIDJSON=ON` when compiling ABACUS - `kpt_file` - [str] The name of the k-point file. ## Input -- A dictionary of parameters and their values as defined by the user in the INPUT file. (This part of the content will not be output in the current version yet.) +- A dictionary of parameters and their values as defined by the user in the INPUT file. (This part + of the content will not be output in the current version yet.) ## Init - -- `Input` - Lists the value of all input parameters. (This part of the content will not be output in the current version yet.) +- `Input` - Lists the value of all input parameters. (This part of the content will not be output in + the current version yet.) - `point_group` - [str] the Schoenflies name of the point group. - `point_group_in_space` - [str] the Schoenflies name of the point group in the space group. - `nkstot`, `nkstot_ibz` - [int] Total number of k-points and total number of irreducible k-points. -- `nelectron_each_type` - [object(str-int)] The number of valence electron for each atom type, e.g., `{"C": 2, "H":1}`. +- `nelectron_each_type` - [object(str-int)] The number of valence electron for each atom type, e.g., + `{"C": 2, "H":1}`. - `nelectron` - [int] Total number of electrons. - `nband` - [int] Number of bands. - `natom` - [int] Total number of atoms. @@ -51,29 +55,32 @@ Notice: one need to add the option `-DENABLE_RAPIDJSON=ON` when compiling ABACUS - `element` - [array(object(str:str))] The element of each atom type. - `cell` - [array(array(double))] The lattice vector. Unit in Angstrom. - `coordinate` - [array(array(double))] The cartesian coordinates of each atom. Unit in Angstrom. -- `mag` - [array(double)] The magnetic moments for each atom. +- `mag` - [array(double)] The magnetic moments for each atom. - `pp` - [object(str-str)] The pseudopotential file of each atom type. - `orb` - [object(str-str)] The orbital file of each atom type. - ## Output -An array of dicts, including information about each self-consistent field (SCF) step, such as energy, convergence, and configuration: +An array of dicts, including information about each self-consistent field (SCF) step, such as +energy, convergence, and configuration: - `energy`, `e_fermi` - [double] The total energy and Fermi energy. Unit in eV. -- `force` - [array(array(double))] The forces calculated on each atom. Unit in eV/Angstrom. +- `force` - [array(array(double))] The forces calculated on each atom. Unit in eV/Angstrom. - `stress` - [array(array(double))] The stress tensor. Unit in Kbar. - `cell` - [array(array(double))] The cell parameters. Unit in Angstrom. -- `coordinate` - [array(array(double))] The coordinates of the atoms in the box after the simulation. -- `total_mag` , `absolute_mag` , `mag` - [double] The total magnetic moment; total absolute magnetic moment; and a list of magnetic moments for each atom, respectively. +- `coordinate` - [array(array(double))] The coordinates of the atoms in the box after the + simulation. +- `total_mag` , `absolute_mag` , `mag` - [double] The total magnetic moment; total absolute magnetic + moment; and a list of magnetic moments for each atom, respectively. - `scf_converge` - [bool] A boolean indicating whether the scf optimization has converged. - `scf` - [array(object(str:double)] A list of each scf step, each item contains: - - `energy` - [double] The total energy. Unit in eV. + - `energy` - [double] The total energy. Unit in eV. - `ediff` - [double] The energy difference between the current and previous step. Unit in eV. - `drho` - [double] The charge density difference between the current and previous step. - `time` - [double] The time used for the current step. Unit in seconds. ## Final Structure + Parameters regarding the final converged results and the optimized geometry: - `energy` - [double] The final energy. @@ -81,5 +88,7 @@ Parameters regarding the final converged results and the optimized geometry: - `cell` - [array(array(double))] The resulting cell parameters. - `coordinate` - [array(array(double))] The final atomic coordinates. - `relax_converge` - [bool] A boolean indicating whether the geometry optimization has converged. -- `dos` - [array(array(array(double)))] The state energy, and the dimension is NSPIN\*NKPOINT\*NBAND. -- `dos_weight` - [array(array(array(double)))] The weight of each state, and the dimension is same as `dos`. \ No newline at end of file +- `dos` - [array(array(array(double)))] The state energy, and the dimension is + NSPIN\*NKPOINT\*NBAND. +- `dos_weight` - [array(array(array(double)))] The weight of each state, and the dimension is same + as `dos`. diff --git a/docs/advanced/md.md b/docs/advanced/md.md index 56b7072cc60..38b3f665ceb 100644 --- a/docs/advanced/md.md +++ b/docs/advanced/md.md @@ -1,94 +1,164 @@ # Molecular Dynamics -Molecular dynamics (MD) is a computer simulation method for analyzing the physical movements of atoms and molecules. The atoms and molecules are allowed to interact for a fixed period of time, giving a view of the dynamic "evolution" of the system. In the most common version, the trajectories of atoms and molecules are determined by numerically solving Newton's equations of motion for a system of interacting particles, where forces between the particles and their potential energies are calculated using first-principles calculations (first-principles molecular dynamics, FPMD), or interatomic potentials and molecular mechanics force fields (classical molecular dynamics, CMD). - -By setting [calculation](./input_files/input-main.md#calculation) to be `md`, ABACUS currently provides several different MD evolution methods, which is specified by keyword [md_type](./input_files/input-main.md#md_type) in the `INPUT` file: - - - fire: a MD-based relaxation algorithm, see [details](#fire) here - - nve: NVE ensemble with velocity Verlet algorithm - - nvt: NVT ensemble - - npt: Nose-Hoover style NPT ensemble - - langevin: NVT ensemble with Langevin thermostat - - msst: MSST method - -When [md_type](./input_files/input-main.md#md_type) is set to nvt, [md_thermostat](./input_files/input-main.md#md_thermostat) is used to specify the temperature control method used in NVT ensemble. - - - nhc: Nose-Hoover chain - - anderson: Anderson thermostat - - berendsen: Berendsen thermostat - - rescaling: velocity Rescaling method 1 - - rescale_v: velocity Rescaling method 2 - -When [md_type](./input_files/input-main.md#md_type) is set to npt, [md_pmode](./input_files/input-main.md#md_pmode) is used to specify the cell fluctuation mode in NPT ensemble based on the Nose-Hoover style non-Hamiltonian equations of motion. - - - iso: isotropic cell fluctuations - - aniso: anisotropic cell fluctuations - - tri: non-orthogonal (triclinic) simulation box - -Furthermore, ABACUS also provides a [list of keywords](./input_files/input-main.md#molecular-dynamics) to control relevant parmeters used in MD simulations. - -The MD output information will be written into the file `MD_dump`, in which the atomic forces, atomic velocities, and lattice virial are controlled by keyword [dump_force](./input_files/input-main.md#dump_force), [dump_vel](./input_files/input-main.md#dump_vel), and [dump_virial](./input_files/input-main.md#dump_virial), respectively. - -[Examples](../../examples/md/lcao_gammaonly_Si8/) of MD simulations are also provided. -There are eight INPUT files corresponding to eight different MD evolution methods in the directory. -For examlpe, `INPUT_0` shows how to employ the NVE simulation. - -To run any of the fix cases, users may enter the directory, copy the corresponding input file to `INPUT`, and run ABACUS. +Molecular dynamics (MD) is a computer simulation method for analyzing the physical movements of +atoms and molecules. The atoms and molecules are allowed to interact for a fixed period of time, +giving a view of the dynamic "evolution" of the system. In the most common version, the trajectories +of atoms and molecules are determined by numerically solving Newton's equations of motion for a +system of interacting particles, where forces between the particles and their potential energies are +calculated using first-principles calculations (first-principles molecular dynamics, FPMD), or +interatomic potentials and molecular mechanics force fields (classical molecular dynamics, CMD). + +By setting [calculation](./input_files/input-main.md#calculation) to be `md`, ABACUS currently +provides several different MD evolution methods, which is specified by keyword +[md_type](./input_files/input-main.md#md_type) in the `INPUT` file: + +- fire: a MD-based relaxation algorithm, see [details](#fire) here +- nve: NVE ensemble with velocity Verlet algorithm +- nvt: NVT ensemble +- npt: Nose-Hoover style NPT ensemble +- langevin: NVT ensemble with Langevin thermostat +- msst: MSST method + +When [md_type](./input_files/input-main.md#md_type) is set to nvt, +[md_thermostat](./input_files/input-main.md#md_thermostat) is used to specify the temperature +control method used in NVT ensemble. + +- nhc: Nose-Hoover chain +- anderson: Anderson thermostat +- berendsen: Berendsen thermostat +- rescaling: velocity Rescaling method 1 +- rescale_v: velocity Rescaling method 2 + +When [md_type](./input_files/input-main.md#md_type) is set to npt, +[md_pmode](./input_files/input-main.md#md_pmode) is used to specify the cell fluctuation mode in NPT +ensemble based on the Nose-Hoover style non-Hamiltonian equations of motion. + +- iso: isotropic cell fluctuations +- aniso: anisotropic cell fluctuations +- tri: non-orthogonal (triclinic) simulation box + +Furthermore, ABACUS also provides a +[list of keywords](./input_files/input-main.md#molecular-dynamics) to control relevant parmeters +used in MD simulations. + +The MD output information will be written into the file `MD_dump`, in which the atomic forces, +atomic velocities, and lattice virial are controlled by keyword +[dump_force](./input_files/input-main.md#dump_force), +[dump_vel](./input_files/input-main.md#dump_vel), and +[dump_virial](./input_files/input-main.md#dump_virial), respectively. + +[Examples](../../examples/md/lcao_gammaonly_Si8/) of MD simulations are also provided. There are +eight INPUT files corresponding to eight different MD evolution methods in the directory. For +examlpe, `INPUT_0` shows how to employ the NVE simulation. + +To run any of the fix cases, users may enter the directory, copy the corresponding input file to +`INPUT`, and run ABACUS. ## FIRE -[FIRE](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.97.170201) (fast inertial relaxation engine) is a MD-based minimization algorithm. It is based on conventional molecular dynamics with additional velocity modifications and adaptive time steps. The MD trajectory will descend to an energy-minimum. -## NVE +[FIRE](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.97.170201) (fast inertial +relaxation engine) is a MD-based minimization algorithm. It is based on conventional molecular +dynamics with additional velocity modifications and adaptive time steps. The MD trajectory will +descend to an energy-minimum. -NVE ensemble (i. e. microcanonical ensemble) is a statistical ensemble that represents the possible states of a mechanical system whose total energy is exactly specified. The system is assumed to be isolated in the sense that it cannot exchange energy or particles with its environment, so that the energy of the system does not change with time. +## NVE -The primary macroscopic variables of the microcanonical ensemble are the total number of particles in the system (symbol: N), the system's volume (symbol: V), as well as the total energy in the system (symbol: E). Each of these is assumed to be constant in the ensemble. +NVE ensemble (i. e. microcanonical ensemble) is a statistical ensemble that represents the possible +states of a mechanical system whose total energy is exactly specified. The system is assumed to be +isolated in the sense that it cannot exchange energy or particles with its environment, so that the +energy of the system does not change with time. -Currently NVE ensemble in ABACUS is implemented based on the [velocity verlet algorithm](https://aip.scitation.org/doi/abs/10.1063/1.442716). +The primary macroscopic variables of the microcanonical ensemble are the total number of particles +in the system (symbol: N), the system's volume (symbol: V), as well as the total energy in the +system (symbol: E). Each of these is assumed to be constant in the ensemble. +Currently NVE ensemble in ABACUS is implemented based on the +[velocity verlet algorithm](https://aip.scitation.org/doi/abs/10.1063/1.442716). ## Nose Hoover Chain -NVT ensemble (i. e. canonical ensemble) is the statistical ensemble that represents the possible states of a mechanical system in thermal equilibrium with a heat bath at a fixed temperature. The system can exchange energy with the heat bath, so that the states of the system will differ in total energy. - -The principal thermodynamic variable of the canonical ensemble, determining the probability distribution of states, is the absolute temperature (symbol: T). The ensemble typically also depends on mechanical variables such as the number of particles in the system (symbol: N) and the system's volume (symbol: V), each of which influence the nature of the system's internal states. An ensemble with these three parameters is sometimes called the NVT ensemble. +NVT ensemble (i. e. canonical ensemble) is the statistical ensemble that represents the possible +states of a mechanical system in thermal equilibrium with a heat bath at a fixed temperature. The +system can exchange energy with the heat bath, so that the states of the system will differ in total +energy. +The principal thermodynamic variable of the canonical ensemble, determining the probability +distribution of states, is the absolute temperature (symbol: T). The ensemble typically also depends +on mechanical variables such as the number of particles in the system (symbol: N) and the system's +volume (symbol: V), each of which influence the nature of the system's internal states. An ensemble +with these three parameters is sometimes called the NVT ensemble. -The isothermal–isobaric ensemble (constant temperature and constant pressure ensemble), also called NPT ensemble, is a statistical mechanical ensemble that maintains the number of particles N, constant temperature T, and constant pressure P. This ensemble plays an important role in chemistry as chemical reactions are usually carried out under constant pressure condition. The NPT ensemble is also useful for measuring the equation of state of model systems whose virial expansion for pressure cannot be evaluated, or systems near first-order phase transitions. - -ABACUS perform time integration on [Nose-Hoover style non-Hamiltonian equations of motion](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.31.1695) which are designed to generate positions and velocities sampled from NVT and NPT ensemble. - +The isothermal–isobaric ensemble (constant temperature and constant pressure ensemble), also called +NPT ensemble, is a statistical mechanical ensemble that maintains the number of particles N, +constant temperature T, and constant pressure P. This ensemble plays an important role in chemistry +as chemical reactions are usually carried out under constant pressure condition. The NPT ensemble is +also useful for measuring the equation of state of model systems whose virial expansion for pressure +cannot be evaluated, or systems near first-order phase transitions. +ABACUS perform time integration on +[Nose-Hoover style non-Hamiltonian equations of motion](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.31.1695) +which are designed to generate positions and velocities sampled from NVT and NPT ensemble. ## Langevin -[Langevin thermostat](https://en.wikipedia.org/wiki/Langevin_dynamics) can be used for molecular dynamics equations by assuming that the atoms being simulated are embedded in a sea of much smaller fictional particles. In many instances of solute-solvent systems, the behavior of the solute is desired, and the behavior of the solvent is non-interesting(e.g. proteins, DNA, nanoparticles in solution). In these cases, the solvent influences the dynamics of the solute(typically nanoparticles) via random collisions, and by imposing a frictional drag force on the motion of the nanoparticle in the solvent. The damping factor and the random force combine to give the correct NVT ensemble. +[Langevin thermostat](https://en.wikipedia.org/wiki/Langevin_dynamics) can be used for molecular +dynamics equations by assuming that the atoms being simulated are embedded in a sea of much smaller +fictional particles. In many instances of solute-solvent systems, the behavior of the solute is +desired, and the behavior of the solvent is non-interesting(e.g. proteins, DNA, nanoparticles in +solution). In these cases, the solvent influences the dynamics of the solute(typically +nanoparticles) via random collisions, and by imposing a frictional drag force on the motion of the +nanoparticle in the solvent. The damping factor and the random force combine to give the correct NVT +ensemble. ## Anderson -[Anderson thermostat](https://aip.scitation.org/doi/abs/10.1063/1.439486) couples the system to a heat bath that imposes the desired temperature to simulate the NVT ensemble. The coupling to a heat bath is represented by stochastic collision that act occasionally on randomly selected particles. +[Anderson thermostat](https://aip.scitation.org/doi/abs/10.1063/1.439486) couples the system to a +heat bath that imposes the desired temperature to simulate the NVT ensemble. The coupling to a heat +bath is represented by stochastic collision that act occasionally on randomly selected particles. ## Berendsen -Reset the temperature of a group of atoms by using a [Berendsen thermostat](https://aip.scitation.org/doi/10.1063/1.448118), which rescales their velocities every timestep. In this scheme, the system is weakly coupled to a heat bath with some temperature. Though the thermostat does not generate a correct canonical ensemble (especially for small systems), for large systems on the order of hundreds or thousands of atoms/molecules, the approximation yields roughly correct results for most calculated properties. +Reset the temperature of a group of atoms by using a +[Berendsen thermostat](https://aip.scitation.org/doi/10.1063/1.448118), which rescales their +velocities every timestep. In this scheme, the system is weakly coupled to a heat bath with some +temperature. Though the thermostat does not generate a correct canonical ensemble (especially for +small systems), for large systems on the order of hundreds or thousands of atoms/molecules, the +approximation yields roughly correct results for most calculated properties. ## Rescaling -Reset the temperature of a group of atoms by explicitly rescaling their velocities. Velocities are rescaled if the current and target temperature differ more than [md_tolerance](./input_files/input-main.md#md_tolerance) (Kelvin). +Reset the temperature of a group of atoms by explicitly rescaling their velocities. Velocities are +rescaled if the current and target temperature differ more than +[md_tolerance](./input_files/input-main.md#md_tolerance) (Kelvin). ## Rescale_v -Reset the temperature of a group of atoms by explicitly rescaling their velocities. Every [md_nraise](./input_files/input-main.md#md_nraise) steps the current temperature is rescaled to target temperature. +Reset the temperature of a group of atoms by explicitly rescaling their velocities. Every +[md_nraise](./input_files/input-main.md#md_nraise) steps the current temperature is rescaled to +target temperature. ## MSST -ABACUS performs the [Multi-Scale Shock Technique (MSST) integration](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.90.235503) to update positions and velocities each timestep to mimic a compressive shock wave passing over the system. The MSST varies the cell volume and temperature in such a way as to restrain the system to the shock Hugoniot and the Rayleigh line. These restraints correspond to the macroscopic conservation laws dictated by a shock front. + +ABACUS performs the +[Multi-Scale Shock Technique (MSST) integration](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.90.235503) +to update positions and velocities each timestep to mimic a compressive shock wave passing over the +system. The MSST varies the cell volume and temperature in such a way as to restrain the system to +the shock Hugoniot and the Rayleigh line. These restraints correspond to the macroscopic +conservation laws dictated by a shock front. ## DPMD -Compiling ABACUS with [DeePMD-kit](https://github.com/deepmodeling/deepmd-kit), MD calculations based on machine learning DP model is enabled. -To employ DPMD calculations, [esolver_type](./input_files/input-main.md#esolver_type) should be set to `dp`. -And the filename of DP model is specified by keyword [pot_file](./input_files/input-main.md#pot_file). +Compiling ABACUS with [DeePMD-kit](https://github.com/deepmodeling/deepmd-kit), MD calculations +based on machine learning DP model is enabled. + +To employ DPMD calculations, [esolver_type](./input_files/input-main.md#esolver_type) should be set +to `dp`. And the filename of DP model is specified by keyword +[pot_file](./input_files/input-main.md#pot_file). ## NEP -If ABACUS is compiled with the Neuroevolution Potential ([NEP](https://gpumd.org/potentials/nep.html)), MD simulations using NEP models are enabled. To use this feature, set [esolver_type](./input_files/input-main.md#esolver_type) to `nep` and specify the potential file path with the [pot_file](./input_files/input-main.md#pot_file) keyword in your INPUT file. \ No newline at end of file +If ABACUS is compiled with the Neuroevolution Potential +([NEP](https://gpumd.org/potentials/nep.html)), MD simulations using NEP models are enabled. To use +this feature, set [esolver_type](./input_files/input-main.md#esolver_type) to `nep` and specify the +potential file path with the [pot_file](./input_files/input-main.md#pot_file) keyword in your INPUT +file. diff --git a/docs/advanced/opt.md b/docs/advanced/opt.md index 4f0bdf32a0c..638bb22773b 100644 --- a/docs/advanced/opt.md +++ b/docs/advanced/opt.md @@ -1,14 +1,24 @@ # Geometry Optimization -By setting `calculation` to be `relax` or `cell-relax`, ABACUS supports structural relaxation and variable-cell relaxation. +By setting `calculation` to be `relax` or `cell-relax`, ABACUS supports structural relaxation and +variable-cell relaxation. -ABACUS provides two implementations for variable-cell relaxation, controlled by the [relax_new](./input_files/input-main.md#relax_new) parameter: +ABACUS provides two implementations for variable-cell relaxation, controlled by the +[relax_new](./input_files/input-main.md#relax_new) parameter: -- **New implementation** (`relax_new = True`, default since v3.8): Uses a simultaneous conjugate gradient (CG) optimization for both ionic positions and cell parameters. Both degrees of freedom are optimized together in each step. +- **New implementation** (`relax_new = True`, default since v3.8): Uses a simultaneous conjugate + gradient (CG) optimization for both ionic positions and cell parameters. Both degrees of freedom + are optimized together in each step. -- **Old implementation** (`relax_new = False`): Follows a nested procedure where fixed-cell structural relaxation is performed first, followed by an update of the cell parameters, and the process is repeated until convergence is achieved. +- **Old implementation** (`relax_new = False`): Follows a nested procedure where fixed-cell + structural relaxation is performed first, followed by an update of the cell parameters, and the + process is repeated until convergence is achieved. + +An example of the variable cell relaxation can be found in our +[repository](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/relax/pw_al), +which is provided with the reference output file log.ref. When using the old implementation +(`relax_new = False`), each ionic step is labelled in the following manner: -An example of the variable cell relaxation can be found in our [repository](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/relax/pw_al), which is provided with the reference output file log.ref. When using the old implementation (`relax_new = False`), each ionic step is labelled in the following manner: ``` ------------------------------------------- RELAX CELL : 3 @@ -16,69 +26,102 @@ An example of the variable cell relaxation can be found in our [repository](http ------------------------------------------- ``` -indicating that this is the first ionic step of the 3rd cell configuration, and it is the 15-th ionic step in total. - +indicating that this is the first ionic step of the 3rd cell configuration, and it is the 15-th +ionic step in total. ## Optimization Algorithms -ABACUS offers multiple optimization algorithms for structural relaxation, which can be selected using the [relax_method](./input_files/input-main.md#relax_method) keyword. The available algorithms and their behavior depend on the [relax_new](./input_files/input-main.md#relax_new) setting: +ABACUS offers multiple optimization algorithms for structural relaxation, which can be selected +using the [relax_method](./input_files/input-main.md#relax_method) keyword. The available algorithms +and their behavior depend on the [relax_new](./input_files/input-main.md#relax_new) setting: ### Algorithm Availability **New implementation** (`relax_new = True`, default): -- **CG (Conjugate Gradient)**: Simultaneous optimization of both ionic positions and cell parameters using CG with line search. This is the only algorithm available for the new implementation. + +- **CG (Conjugate Gradient)**: Simultaneous optimization of both ionic positions and cell parameters + using CG with line search. This is the only algorithm available for the new implementation. **Old implementation** (`relax_new = False`): -- **CG (Conjugate Gradient)**: For ionic relaxation; CG is also used for cell parameter optimization in the nested procedure + +- **CG (Conjugate Gradient)**: For ionic relaxation; CG is also used for cell parameter optimization + in the nested procedure - **BFGS**: Quasi-Newton method for ionic relaxation - **LBFGS**: Limited-memory BFGS for ionic relaxation - **SD (Steepest Descent)**: Simple gradient descent for ionic relaxation -- **CG-BFGS**: Mixed method that starts with CG and switches to BFGS when force convergence reaches the threshold set by [relax_cg_thr](./input_files/input-main.md#relax_cg_thr) +- **CG-BFGS**: Mixed method that starts with CG and switches to BFGS when force convergence reaches + the threshold set by [relax_cg_thr](./input_files/input-main.md#relax_cg_thr) -We also provide a [list of keywords](./input_files/input-main.md#geometry-relaxation) for controlling the relaxation process. +We also provide a [list of keywords](./input_files/input-main.md#geometry-relaxation) for +controlling the relaxation process. ### BFGS method -The [BFGS method](https://en.wikipedia.org/wiki/Broyden%E2%80%93Fletcher%E2%80%93Goldfarb%E2%80%93Shanno_algorithm) is a quasi-Newton method for solving nonlinear optimization problems. It belongs to the class of quasi-Newton methods where the Hessian matrix is approximated during the optimization process. If the initial point is not far from the extrema, BFGS tends to work better than gradient-based methods. +The +[BFGS method](https://en.wikipedia.org/wiki/Broyden%E2%80%93Fletcher%E2%80%93Goldfarb%E2%80%93Shanno_algorithm) +is a quasi-Newton method for solving nonlinear optimization problems. It belongs to the class of +quasi-Newton methods where the Hessian matrix is approximated during the optimization process. If +the initial point is not far from the extrema, BFGS tends to work better than gradient-based +methods. **Note**: BFGS is only available with the old implementation (`relax_new = False`). -ABACUS provides two BFGS implementations, controlled by the second element of [relax_method](./input_files/input-main.md#relax_method): +ABACUS provides two BFGS implementations, controlled by the second element of +[relax_method](./input_files/input-main.md#relax_method): -- **Default BFGS** (`relax_method = bfgs 2` or `relax_method = bfgs`): Updates the inverse of the approximate Hessian matrix B directly. This is the recommended implementation. +- **Default BFGS** (`relax_method = bfgs 2` or `relax_method = bfgs`): Updates the inverse of the + approximate Hessian matrix B directly. This is the recommended implementation. -- **Traditional BFGS** (`relax_method = bfgs 1`): Updates the approximate Hessian matrix B itself, then obtains the inverse by solving matrix eigenvalues and taking their reciprocals. Both methods are mathematically equivalent, but in some cases the traditional variant may perform better. +- **Traditional BFGS** (`relax_method = bfgs 1`): Updates the approximate Hessian matrix B itself, + then obtains the inverse by solving matrix eigenvalues and taking their reciprocals. Both methods + are mathematically equivalent, but in some cases the traditional variant may perform better. ### LBFGS method -The [L-BFGS (Limited-memory BFGS)](https://en.wikipedia.org/wiki/Limited-memory_BFGS) method is a memory-efficient variant of BFGS that stores only a few vectors representing the Hessian approximation instead of the full matrix. This makes it particularly suitable for large systems with many atoms. +The [L-BFGS (Limited-memory BFGS)](https://en.wikipedia.org/wiki/Limited-memory_BFGS) method is a +memory-efficient variant of BFGS that stores only a few vectors representing the Hessian +approximation instead of the full matrix. This makes it particularly suitable for large systems with +many atoms. -**Note**: LBFGS is only available with the old implementation (`relax_new = False`). Set `relax_method = lbfgs` to use this method. +**Note**: LBFGS is only available with the old implementation (`relax_new = False`). Set +`relax_method = lbfgs` to use this method. ### SD method -The [SD (steepest descent) method](https://en.wikipedia.org/wiki/Gradient_descent) is one of the simplest first-order optimization methods, where in each step the motion is along the direction of the gradient, where the function descends the fastest. +The [SD (steepest descent) method](https://en.wikipedia.org/wiki/Gradient_descent) is one of the +simplest first-order optimization methods, where in each step the motion is along the direction of +the gradient, where the function descends the fastest. **Note**: SD is only available with the old implementation (`relax_new = False`). -In practice, the SD method may take many iterations to converge, and is generally not recommended for production calculations. +In practice, the SD method may take many iterations to converge, and is generally not recommended +for production calculations. ### CG method -The [CG (conjugate gradient) method](https://en.wikipedia.org/wiki/Conjugate_gradient_method) is one of the most widely used methods for solving optimization problems. +The [CG (conjugate gradient) method](https://en.wikipedia.org/wiki/Conjugate_gradient_method) is one +of the most widely used methods for solving optimization problems. ABACUS provides two implementations of the CG method: -- **New CG implementation** (`relax_new = True`, default): Performs simultaneous optimization of both ionic positions and cell parameters using a line search algorithm. This implementation is more efficient for `cell-relax` calculations as it optimizes all degrees of freedom together. The step size can be controlled by [relax_scale_force](./input_files/input-main.md#relax_scale_force). +- **New CG implementation** (`relax_new = True`, default): Performs simultaneous optimization of + both ionic positions and cell parameters using a line search algorithm. This implementation is + more efficient for `cell-relax` calculations as it optimizes all degrees of freedom together. The + step size can be controlled by [relax_scale_force](./input_files/input-main.md#relax_scale_force). -- **Old CG implementation** (`relax_new = False`): Uses a nested procedure where ionic positions are optimized first using CG, followed by cell parameter optimization (also using CG) in `cell-relax` calculations. This is the traditional approach where the two optimization steps are separated. +- **Old CG implementation** (`relax_new = False`): Uses a nested procedure where ionic positions are + optimized first using CG, followed by cell parameter optimization (also using CG) in `cell-relax` + calculations. This is the traditional approach where the two optimization steps are separated. ## Constrained Optimization -Apart from conventional optimization where all degrees of freedom are allowed to move, we also offer the option of doing constrained optimization in ABACUS. +Apart from conventional optimization where all degrees of freedom are allowed to move, we also offer +the option of doing constrained optimization in ABACUS. + +### Fixing Atomic Positions -### Fixing Atomic Positions -Users may note that in the above-mentioned example, the atomic positions in STRU file are given along with three integers: +Users may note that in the above-mentioned example, the atomic positions in STRU file are given +along with three integers: ``` Al @@ -90,7 +133,9 @@ Al 0.00 0.50 0.50 1 1 1 ``` -For relaxation calculations, the three integers denote whether the corresponding degree of freedom is allowed to move. For example, if we replace the STRU file by: +For relaxation calculations, the three integers denote whether the corresponding degree of freedom +is allowed to move. For example, if we replace the STRU file by: + ``` Al 0.0 @@ -103,25 +148,33 @@ Al then the first Al atom will not be allowed to move in z direction. -Fixing atomic position is sometimes helpful during relaxation of isolated molecule/cluster, to prevent the system from drifting in space. +Fixing atomic position is sometimes helpful during relaxation of isolated molecule/cluster, to +prevent the system from drifting in space. ### Fixing Cell Parameters -Sometimes we want to do variable-cell relaxation with some of the cell degrees of freedom fixed. This is achieved by keywords such as [fixed_axes](./input_files/input-main.md#fixed_axes), [fixed_ibrav](./input_files/input-main.md#fixed_ibrav) and [fixed_atoms](./input_files/input-main.md#fixed_atoms). +Sometimes we want to do variable-cell relaxation with some of the cell degrees of freedom fixed. +This is achieved by keywords such as [fixed_axes](./input_files/input-main.md#fixed_axes), +[fixed_ibrav](./input_files/input-main.md#fixed_ibrav) and +[fixed_atoms](./input_files/input-main.md#fixed_atoms). **Available constraints by implementation:** - **New implementation** (`relax_new = True`): + - `fixed_axes = "shape"`: Only allows volume changes (hydrostatic pressure), cell shape is fixed - `fixed_axes = "volume"`: Allows shape changes but keeps volume constant - `fixed_axes = "a"`, `"b"`, `"c"`, etc.: Fix specific lattice vectors or combinations - `fixed_ibrav = True`: Maintain the Bravais lattice type during relaxation - **Old implementation** (`relax_new = False`): - - **All `fixed_axes` options now supported**: "shape", "volume", "a", "b", "c", "ab", "ac", "bc", "abc" + + - **All `fixed_axes` options now supported**: "shape", "volume", "a", "b", "c", "ab", "ac", "bc", + "abc" - **`fixed_ibrav` now supported**: Maintains Bravais lattice type during relaxation - Can combine `fixed_axes` with `fixed_ibrav` for constrained relaxation - - **Implementation approach**: Uses post-update constraint enforcement (volume rescaling and lattice reconstruction after each CG step) + - **Implementation approach**: Uses post-update constraint enforcement (volume rescaling and + lattice reconstruction after each CG step) **VASP ISIF correspondence:** @@ -137,9 +190,11 @@ If you are familiar with the `ISIF` option from VASP, here is the correspondence ### Stop Geometry Optimization Manually -It is usually difficult to converge when calculating large systems, but people do not want to give up this calculation result. -Providing a file named `EXIT`: +It is usually difficult to converge when calculating large systems, but people do not want to give +up this calculation result. Providing a file named `EXIT`: + ``` stop_ion true ``` -ABACUS will end normally and produce a complete file. \ No newline at end of file + +ABACUS will end normally and produce a complete file. diff --git a/docs/advanced/output_files/output-specification.md b/docs/advanced/output_files/output-specification.md index 27a9d8376ec..fcf9117d638 100644 --- a/docs/advanced/output_files/output-specification.md +++ b/docs/advanced/output_files/output-specification.md @@ -2,11 +2,16 @@ ## 1. Background and Motivation -ABACUS is an integrated software package designed to provide a cohesive user experience. To achieve this goal, **we are establishing unified output file standards** that all developers should follow. +ABACUS is an integrated software package designed to provide a cohesive user experience. To achieve +this goal, **we are establishing unified output file standards** that all developers should follow. -Recent versions of ABACUS have been working on standardizing all output file naming conventions. This work is ongoing, and if there are discrepancies between actual file names and this document, please refer to the latest documentation. +Recent versions of ABACUS have been working on standardizing all output file naming conventions. +This work is ongoing, and if there are discrepancies between actual file names and this document, +please refer to the latest documentation. -All output file naming conventions can be found in the online documentation (with corresponding 3.10-LTS file names): [ABACUS Input Documentation](https://abacus.deepmodeling.com/en/latest/advanced/input_files/input-main.html) +All output file naming conventions can be found in the online documentation (with corresponding +3.10-LTS file names): +[ABACUS Input Documentation](https://abacus.deepmodeling.com/en/latest/advanced/input_files/input-main.html) ## 2. File Naming Conventions @@ -15,78 +20,82 @@ All output file naming conventions can be found in the online documentation (wit **Rule 1:** All ABACUS output files are stored in the `OUT.{suffix}/` directory. **Rule 2:** File extensions by category: -| Extension | Description | -|-----------|-------------| -| `.txt` | Text file | -| `.dat` | Binary file | -| `.csr` | Sparse matrix format | -| `.cube` | 3D spatial data format | -**Rule 3:** For special output quantities (e.g., wavefunctions), add `_pw` or `_nao` to distinguish between plane wave basis and numerical atomic orbital basis. +| Extension | Description | +| --------- | ---------------------- | +| `.txt` | Text file | +| `.dat` | Binary file | +| `.csr` | Sparse matrix format | +| `.cube` | 3D spatial data format | + +**Rule 3:** For special output quantities (e.g., wavefunctions), add `_pw` or `_nao` to distinguish +between plane wave basis and numerical atomic orbital basis. **Rule 4:** File names are lowercase. Physical quantities appear at the beginning: -| Prefix | Physical Quantity | -|--------|-------------------| -| `chg` | Charge density | -| `pot` | Potential | -| `eig` | Eigenvalue / Energy level | -| `wf` | Wavefunction | -| `dm` | Density matrix | -| `h` | Hamiltonian matrix H | -| `s` | Overlap matrix S | -| `t` | Kinetic energy operator | -| `r` | Position operator or Bravais lattice vector R | -| `k` | k-point in Brillouin zone | -| `xyz` | Three spatial directions | -| `ini` | Initial state (before electronic iteration) | +| Prefix | Physical Quantity | +| ------ | --------------------------------------------- | +| `chg` | Charge density | +| `pot` | Potential | +| `eig` | Eigenvalue / Energy level | +| `wf` | Wavefunction | +| `dm` | Density matrix | +| `h` | Hamiltonian matrix H | +| `s` | Overlap matrix S | +| `t` | Kinetic energy operator | +| `r` | Position operator or Bravais lattice vector R | +| `k` | k-point in Brillouin zone | +| `xyz` | Three spatial directions | +| `ini` | Initial state (before electronic iteration) | **Rule 5:** Suffixes following the physical quantity: -| Suffix | Meaning | -|--------|---------| +| Suffix | Meaning | +| ---------------------- | ------------------------------------------------------------------------ | | `s1`, `s2`, `s3`, `s4` | Spin channel (1, 2 for collinear; 1, 2, 3, 4 for non-collinear with SOC) | -| `s12` | Non-collinear spin calculation | -| `k#` | k-point index (e.g., `k1`, `k2`) | -| `g#` | Ionic step index for relax/md (e.g., `g1`, `g2`) | +| `s12` | Non-collinear spin calculation | +| `k#` | k-point index (e.g., `k1`, `k2`) | +| `g#` | Ionic step index for relax/md (e.g., `g1`, `g2`) | **Important:** + - All index numbers start from 1 (not 0) - For Gamma-only algorithm in LCAO, no `k` index is included - Overlap matrix `s` does not distinguish spin, so only one matrix is output ### 2.2 Examples -| File Name | Interpretation | -|-----------|----------------| -| `chgs1.cube` | Charge density, spin 1 | -| `chgs2.cube` | Charge density, spin 2 | -| `chgs3.cube` | Charge density, spin 3 (non-collinear with SOC) | -| `pots1.cube` | Local potential, spin 1 | -| `eig_occ.txt` | Eigenvalues and occupations | -| `doss1g1_nao.txt` | DOS, spin 1, geometry step 1, NAO basis | -| `wf_pw.dat` | Wavefunction, plane wave basis | -| `sr.csr` | Overlap matrix in real space (no spin index) | +| File Name | Interpretation | +| ----------------- | ----------------------------------------------- | +| `chgs1.cube` | Charge density, spin 1 | +| `chgs2.cube` | Charge density, spin 2 | +| `chgs3.cube` | Charge density, spin 3 (non-collinear with SOC) | +| `pots1.cube` | Local potential, spin 1 | +| `eig_occ.txt` | Eigenvalues and occupations | +| `doss1g1_nao.txt` | DOS, spin 1, geometry step 1, NAO basis | +| `wf_pw.dat` | Wavefunction, plane wave basis | +| `sr.csr` | Overlap matrix in real space (no spin index) | ### 2.3 Common Output Files -| File Name | Description | -|-----------|-------------| -| `running_scf.log` | SCF iteration log | -| `dos.txt` | Density of states | -| `eig_occ.txt` | Eigenvalues and occupations | -| `mulliken.txt` | Mulliken population analysis | -| `band.txt` | Band structure | +| File Name | Description | +| -------------------------- | ------------------------------- | +| `running_scf.log` | SCF iteration log | +| `dos.txt` | Density of states | +| `eig_occ.txt` | Eigenvalues and occupations | +| `mulliken.txt` | Mulliken population analysis | +| `band.txt` | Band structure | | `chgs1.cube`, `chgs2.cube` | Charge density (spin 1, spin 2) | -| `chg.cube` | Total charge density | -| `taus1.cube`, `taus2.cube` | Kinetic energy density (tau) | -| `pots1.cube`, `pots2.cube` | Local potential | +| `chg.cube` | Total charge density | +| `taus1.cube`, `taus2.cube` | Kinetic energy density (tau) | +| `pots1.cube`, `pots2.cube` | Local potential | ## 3. File Format Standards ### 3.1 Header Section with Comments **Every output file should include `#` comment lines** to explain: + - Data meaning - Units - Source module @@ -101,6 +110,7 @@ All output file naming conventions can be found in the online documentation (wit ``` **Example:** + ``` 1 # ionic step 8207 # number of points @@ -111,18 +121,20 @@ All output file naming conventions can be found in the online documentation (wit ### 3.2 Data Section -| Requirement | Description | -|-------------|-------------| -| **Separator** | Use spaces for column alignment | +| Requirement | Description | +| ------------- | ----------------------------------------------- | +| **Separator** | Use spaces for column alignment | | **Precision** | Controlled by input parameter (see Section 3.4) | -| **Units** | Always specify units in header or column names | -| **Comments** | Use `#` for comment lines | +| **Units** | Always specify units in header or column names | +| **Comments** | Use `#` for comment lines | ### 3.3 Compact Data Layout -**Avoid sparse format with single value per line.** Instead, output 6-8 values per line with proper alignment: +**Avoid sparse format with single value per line.** Instead, output 6-8 values per line with proper +alignment: **Bad (sparse):** + ``` 1.234567 2.345678 @@ -131,6 +143,7 @@ All output file naming conventions can be found in the online documentation (wit ``` **Good (compact):** + ``` 1.234567 2.345678 3.456789 4.567890 5.678901 6.789012 7.890123 8.901234 @@ -141,13 +154,16 @@ All output file naming conventions can be found in the online documentation (wit Output precision should be controllable via input parameters, similar to `out_chg` and `out_pot`: **Example (from `out_pot`):** + ``` out_pot 1 8 ``` + - First integer: output type (1 = output total local potential) - Second integer: precision (number of significant digits, default 8) **Implementation pattern:** + ```cpp // In input parameters int out_type = 0; // output type @@ -163,10 +179,10 @@ ofs << std::setprecision(out_precision) << value; Current integration tests have output files with tens of thousands of lines. Recommendations: -| Issue | Solution | -|-------|----------| -| Too many output files | Consolidate related data into fewer files | -| Files too large | Reduce output frequency, use compact format | +| Issue | Solution | +| --------------------- | ------------------------------------------------- | +| Too many output files | Consolidate related data into fewer files | +| Files too large | Reduce output frequency, use compact format | | Redundant information | Avoid repeating header information in every block | ### 4.2 Balance Test Coverage and Efficiency @@ -179,20 +195,20 @@ Current integration tests have output files with tens of thousands of lines. Rec ### 5.1 Standard Names (Keep Short: 3-8 Characters) -| Physical Quantity | Recommended Name | Unit | -|-------------------|------------------|------| -| Total energy | `etot` | eV | -| Kinetic energy | `ekin` | eV | -| Potential energy | `epot` | eV | -| Force | `force` | eV/Angstrom | -| Stress | `stress` | kBar | -| Charge | `chg` | e | -| Magnetization | `mag` | μB | -| Band index | `n` | - | -| k-point | `kpt` | - | -| Spin | `spin` | - | -| Occupation | `occ` | - | -| Energy level | `eig` | eV | +| Physical Quantity | Recommended Name | Unit | +| ----------------- | ---------------- | ----------- | +| Total energy | `etot` | eV | +| Kinetic energy | `ekin` | eV | +| Potential energy | `epot` | eV | +| Force | `force` | eV/Angstrom | +| Stress | `stress` | kBar | +| Charge | `chg` | e | +| Magnetization | `mag` | μB | +| Band index | `n` | - | +| k-point | `kpt` | - | +| Spin | `spin` | - | +| Occupation | `occ` | - | +| Energy level | `eig` | eV | ### 5.2 Naming Style @@ -259,42 +275,42 @@ void OutputMyData::write(const std::string& filename, int precision) ### 7.2 Key Points 1. **Keep file names short (3-8 characters)** -2. **Add `#` comment lines for data meaning, units, and source module** -3. **Use compact format: 6-8 values per line** -4. **Make precision controllable via input parameter** -5. **Use `std::setw()` for column alignment** +1. **Add `#` comment lines for data meaning, units, and source module** +1. **Use compact format: 6-8 values per line** +1. **Make precision controllable via input parameter** +1. **Use `std::setw()` for column alignment** ## 8. Existing Good Examples -| File | Location | Strengths | -|------|----------|-----------| -| `chgs1.cube` | `tests/03_NAO_multik/scf_out_chg_tau/OUT.autotest/` | Short name, spin index convention | -| `dos.txt` | `tests/03_NAO_multik/scf_out_dos_spin2/OUT.autotest/` | Clear header with metadata | -| `eig_occ.txt` | Same as above | Clear block structure for spin/k-point | -| `mulliken.txt` | `tests/03_NAO_multik/scf_out_mul/OUT.autotest/` | Clear atom separators | +| File | Location | Strengths | +| -------------- | ----------------------------------------------------- | -------------------------------------- | +| `chgs1.cube` | `tests/03_NAO_multik/scf_out_chg_tau/OUT.autotest/` | Short name, spin index convention | +| `dos.txt` | `tests/03_NAO_multik/scf_out_dos_spin2/OUT.autotest/` | Clear header with metadata | +| `eig_occ.txt` | Same as above | Clear block structure for spin/k-point | +| `mulliken.txt` | `tests/03_NAO_multik/scf_out_mul/OUT.autotest/` | Clear atom separators | ## 9. Review Process For new output formats: 1. Check if similar output already exists - reuse format if possible -2. Follow this specification -3. Add documentation in `docs/advanced/output_files/` -4. Submit PR with output sample for review +1. Follow this specification +1. Add documentation in `docs/advanced/output_files/` +1. Submit PR with output sample for review ## 10. Summary -| Aspect | Requirement | -|--------|-------------| -| Directory | All outputs in `OUT.{suffix}/` | -| File name | **Short (3-8 chars)**, lowercase, physical quantity prefix | -| Extensions | `.txt`, `.dat`, `.csr`, `.cube` | -| Basis suffix | `_pw` or `_nao` for basis-specific outputs | -| Spin index | `s1`, `s2`, `s3`, `s4` (SOC), `s12` (non-collinear) | -| Numbering | Start from 1, not 0 | -| Header | `#` comments with meaning, units, source module | -| Data | **Compact: 6-8 values per line**, space-separated | -| Precision | Controllable via input parameter | -| Volume | Reasonable file size, avoid excessive output | +| Aspect | Requirement | +| ------------ | ---------------------------------------------------------- | +| Directory | All outputs in `OUT.{suffix}/` | +| File name | **Short (3-8 chars)**, lowercase, physical quantity prefix | +| Extensions | `.txt`, `.dat`, `.csr`, `.cube` | +| Basis suffix | `_pw` or `_nao` for basis-specific outputs | +| Spin index | `s1`, `s2`, `s3`, `s4` (SOC), `s12` (non-collinear) | +| Numbering | Start from 1, not 0 | +| Header | `#` comments with meaning, units, source module | +| Data | **Compact: 6-8 values per line**, space-separated | +| Precision | Controllable via input parameter | +| Volume | Reasonable file size, avoid excessive output | **Remember: ABACUS outputs should present a unified, professional interface to users.** diff --git a/docs/advanced/output_files/running_scf.log.md b/docs/advanced/output_files/running_scf.log.md index 07d16a4f545..95ba1b24bd1 100644 --- a/docs/advanced/output_files/running_scf.log.md +++ b/docs/advanced/output_files/running_scf.log.md @@ -1,6 +1,6 @@ # The running_scf.log file -- [The running\_scf.log file](#the-running_scf.log-file) +- [The running_scf.log file](#the-running_scf.log-file) - [Reading information](#reading-information) - [Reading version information](#reading-version-information) - [Reading general information](#reading-general-information) @@ -18,16 +18,15 @@ - [Results summary](#results-summary) - [TOTAL-FORCE](#total-force) - [TOTAL-STRESS](#total-stress) - - [FINAL\_ETOT\_IS](#final_etot_is) + - [FINAL_ETOT_IS](#final_etot_is) - [TIME STATISTICS](#time-statistics) - [MEMORY STATISTICS](#memory-statistics) - [Start and end times](#start-and-end-times) - - - ## Reading information + ### Reading version information + ``` ABACUS v3.7.0 Atomic-orbital Based Ab-initio Computation at UStc @@ -51,10 +50,10 @@ Start Time is Thu Jul 18 11:34:56 2024 // The start time of the ABACUS calculation. ``` +______________________________________________________________________ - ------------------------------------------------------------------------------------- ### Reading general information + ``` READING GENERAL INFORMATION // The following section is reading general settings and preparing the computation. @@ -84,6 +83,7 @@ RUNNING WITH DEVICE : CPU / Intel(R) Xeon(R) Platinum ``` ### Reading unitcell + ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>= | | @@ -177,6 +177,7 @@ Reciprocal vectors: (Cartesian coordinate: in unit of 2 pi/a_0) ``` ### Reading pseudopotentials files + ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | | @@ -271,8 +272,11 @@ Warning_Memory_Consuming allocated: FFT::grid 6.5918 MB // A warning about the memory consumption for the Fast Fourier Transform (FFT) grid. ``` + ## Setup Tasks + ### Setup plane waves of charge/potential + ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | | @@ -356,6 +360,7 @@ DONE : SETUP UNITCELL Time : 0.611609 (SEC) ``` ### Doing symmetry analysis + ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | | @@ -438,6 +443,7 @@ DONE : SYMMETRY Time : 0.781568 (SEC) ``` ### Setup K-points + ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | | @@ -520,8 +526,8 @@ K-POINTS DIRECT COORDINATES // The time taken to initialize the k-points. ``` - ### Setup plane waves of wave functions + ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | | @@ -605,8 +611,11 @@ SELF-CONSISTENT ------------------------------------------- // The beginning of the self-consistent field (SCF) calculation section. ``` + ## Running scf processes + ### Search adjacent atoms (init) + ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | | @@ -687,6 +696,7 @@ DONE : INIT SCF Time : 4.10934 (SEC) ``` ### Scf iteration + ``` LC AO ALGORITHM --------------- ION= 1 ELEC= 1-------------------------------- @@ -889,7 +899,9 @@ Density error is 6.53205775131e-08 // The error in the electron density has become very small, indicating near-convergence of the SCF cycle. // Additional iterations of the SCF calculation, showing the gradual convergence of the density error and energies. ``` + ### Scf results + ``` ---------------------------------------------------------- @@ -1151,8 +1163,11 @@ correction force for each atom along direction 2 is 2.49665e-14 correction force for each atom along direction 3 is -3.50742e-14 // The correction forces applied to each atom in the unit cell along the three principal directions. ``` + ## Results summary + ### TOTAL-FORCE + ``` ------------------------------------------------------------------------------------------ TOTAL-FORCE (eV/Angstrom) @@ -1187,6 +1202,7 @@ correction force for each atom along direction 3 is -3.50742e-14 ``` ### TOTAL-STRESS + ``` ---------------------------------------------------------------- TOTAL-STRESS (KBAR) @@ -1202,6 +1218,7 @@ TOTAL-PRESSURE: 20.928031 KBAR ``` ### FINAL_ETOT_IS + ``` -------------------------------------------- !FINAL_ETOT_IS -40425.5513255625628517 eV @@ -1209,9 +1226,8 @@ TOTAL-PRESSURE: 20.928031 KBAR // The final total energy of the system after the SCF calculation, expressed in electron volts. ``` - - ### TIME STATISTICS + ``` TIME STATISTICS -------------------------------------------------------------------------------- @@ -1330,6 +1346,7 @@ TIME STATISTICS ``` ### MEMORY STATISTICS + ``` NAME-------------------------|MEMORY(MB)-------- @@ -1382,8 +1399,10 @@ NAME-------------------------|MEMORY(MB)-------- ``` ### Start and end times -``` + +```` Start Time : Thu Jul 18 11:34:56 2024 Finish Time : Thu Jul 18 11:43:20 2024 Total Time : 0 h 8 mins 24 secs -// The start and end times of the calculation, along with the total duration. \ No newline at end of file +// The start and end times of the calculation, along with the total duration.``` +```` diff --git a/docs/advanced/pp_orb.md b/docs/advanced/pp_orb.md index 4cfe750096b..c6b2c75d21f 100644 --- a/docs/advanced/pp_orb.md +++ b/docs/advanced/pp_orb.md @@ -2,55 +2,87 @@ ## Basis Set -ABACUS supports both PW and LCAO basis set, controlled by keyword [basis_type](./input_files/input-main.md#basis_type) in INPUT file. +ABACUS supports both PW and LCAO basis set, controlled by keyword +[basis_type](./input_files/input-main.md#basis_type) in INPUT file. -The default value of basis_type is pw. The size of pw basis set is controlled by imposing an upper bound for the [kinetic energy cutoff](./input_files/input-main.md#ecutwfc) of the plane wave. +The default value of basis_type is pw. The size of pw basis set is controlled by imposing an upper +bound for the [kinetic energy cutoff](./input_files/input-main.md#ecutwfc) of the plane wave. -When choosing lcao basis set, users need to prepare a set of atomic orbitals. Such files may be downloaded from the [official website](http://abacus.ustc.edu.cn/pseudo/list.htm). For more information, also check the `NUMERICAL_ORBITAL` section in the specification of the [STRU file](./input_files/stru.md). +When choosing lcao basis set, users need to prepare a set of atomic orbitals. Such files may be +downloaded from the [official website](http://abacus.ustc.edu.cn/pseudo/list.htm). For more +information, also check the `NUMERICAL_ORBITAL` section in the specification of the +[STRU file](./input_files/stru.md). -The angular part of orbitals are real spherical harmonics defined (in terms of conventional spherical harmonics in quantum mechanical literature) as +The angular part of orbitals are real spherical harmonics defined (in terms of conventional +spherical harmonics in quantum mechanical literature) as $$Y_{lm} = \left\{\begin{matrix}\sqrt{2}~\text{Im} Y_l^{|m|} & m \lt 0 \\[6pt] Y_l^0 & m = 0 \\[6pt] \sqrt{2}~\text{Re}Y_{l}^{|m|} & m \gt 0\end{matrix}\right. $$ -Note that real spherical harmonics adopted by ABACUS differ from some other definition, e.g. [Table of spherical harmonics - Wikipedia](https://en.wikipedia.org/wiki/Table_of_spherical_harmonics#Real_spherical_harmonics), by a factor of $(-1)^m$. - -Inside ABACUS, orbitals in LCAO basis are arranged lexicographically by species-position-l-zeta-m **except for the intra-m ordering**. Specifically, orbitals are first ordered by their atomic species in accordance with the `ATOMIC_SPECIES` section of the STRU file. For orbitals of the same species, orbitals belonging to each atom are put together, with their overall order following the `ATOMIC_POSITIONS` section of the STRU file. Orbitals on each atom are further ascendingly ordered by their angular momentum (s,p,d,f,...), followed by an order based on their their zeta number. Finally, m is ordered as 0, 1, -1, 2, 2, $\ldots$, l, -l, which is the only exception of the lexicographic order. +Note that real spherical harmonics adopted by ABACUS differ from some other definition, e.g. +[Table of spherical harmonics - Wikipedia](https://en.wikipedia.org/wiki/Table_of_spherical_harmonics#Real_spherical_harmonics), +by a factor of $(-1)^m$. +Inside ABACUS, orbitals in LCAO basis are arranged lexicographically by species-position-l-zeta-m +**except for the intra-m ordering**. Specifically, orbitals are first ordered by their atomic +species in accordance with the `ATOMIC_SPECIES` section of the STRU file. For orbitals of the same +species, orbitals belonging to each atom are put together, with their overall order following the +`ATOMIC_POSITIONS` section of the STRU file. Orbitals on each atom are further ascendingly ordered +by their angular momentum (s,p,d,f,...), followed by an order based on their their zeta number. +Finally, m is ordered as 0, 1, -1, 2, 2, $\ldots$, l, -l, which is the only exception of the +lexicographic order. ## Generating atomic orbital bases -Users may also generate ABACUS numerical atomic obitals based on their own flavor. The theoretical background of orbital generation can be found in following works: +Users may also generate ABACUS numerical atomic obitals based on their own flavor. The theoretical +background of orbital generation can be found in following works: -- Spillage: [Chen M, Guo G C, He L. Systematically improvable optimized atomic basis sets for ab initio calculations[J]. Journal of Physics: Condensed Matter, 2010, 22(44): 445501.](https://iopscience.iop.org/article/10.1088/0953-8984/22/44/445501) -- PTG DPSI: [Lin P, Ren X, He L. Strategy for constructing compact numerical atomic orbital basis sets by incorporating the gradients of reference wavefunctions[J]. Physical Review B, 2021, 103(23): 235131.](https://journals.aps.org/prb/abstract/10.1103/PhysRevB.103.235131) +- Spillage: + [Chen M, Guo G C, He L. Systematically improvable optimized atomic basis sets for ab initio calculations[J]. Journal of Physics: Condensed Matter, 2010, 22(44): 445501.](https://iopscience.iop.org/article/10.1088/0953-8984/22/44/445501) +- PTG DPSI: + [Lin P, Ren X, He L. Strategy for constructing compact numerical atomic orbital basis sets by incorporating the gradients of reference wavefunctions[J]. Physical Review B, 2021, 103(23): 235131.](https://journals.aps.org/prb/abstract/10.1103/PhysRevB.103.235131) Guidelines for generating atomic orbital bases are as follows: -- [Numerical Atomic Orbitals 1: the nomenclature and usage of numerical atomic orbitals in ABACUS](https://mcresearch.github.io/abacus-user-guide/abacus-nac1.html) (Chinese) -- [Numerical Atomic Orbitals 2: generate numerical atomic orbitals based on given norm-conserving pseudopotential](https://mcresearch.github.io/abacus-user-guide/abacus-nac1.html) (Chinese) -- [Numerical Atomic Orbitals 3: generate high-precision numerical atomic orbitals](https://mcresearch.github.io/abacus-user-guide/abacus-nac1.html) (Chinese) +- [Numerical Atomic Orbitals 1: the nomenclature and usage of numerical atomic orbitals in ABACUS](https://mcresearch.github.io/abacus-user-guide/abacus-nac1.html) + (Chinese) +- [Numerical Atomic Orbitals 2: generate numerical atomic orbitals based on given norm-conserving pseudopotential](https://mcresearch.github.io/abacus-user-guide/abacus-nac1.html) + (Chinese) +- [Numerical Atomic Orbitals 3: generate high-precision numerical atomic orbitals](https://mcresearch.github.io/abacus-user-guide/abacus-nac1.html) + (Chinese) -Stable orbital generation programs can be found in guidelines above, there is also another developing version of orbital generation program, in which algorithms are consecutively improved: [Github repository of ABACUS ORBGEN project](https://github.com/kirk0830/ABACUS-ORBGEN), the usage of which can be found in README (in English) file. +Stable orbital generation programs can be found in guidelines above, there is also another +developing version of orbital generation program, in which algorithms are consecutively improved: +[Github repository of ABACUS ORBGEN project](https://github.com/kirk0830/ABACUS-ORBGEN), the usage +of which can be found in README (in English) file. -*NOTE*: users are encouraged to cite the above works when numerical atomic orbitals and its generation codes are used in their research. +*NOTE*: users are encouraged to cite the above works when numerical atomic orbitals and its +generation codes are used in their research. ## BSSE Correction -For treating BSSE(Basis Set Superposition Error), we allow for the inclusion of "empty" or "ghost" atoms in the calculation. Namely, when expanding the Hamiltonian, basis sets on the atoms are used, while the ionic potentials on those atoms are not included when constructing the Hamiltonian. +For treating BSSE(Basis Set Superposition Error), we allow for the inclusion of "empty" or "ghost" +atoms in the calculation. Namely, when expanding the Hamiltonian, basis sets on the atoms are used, +while the ionic potentials on those atoms are not included when constructing the Hamiltonian. -An empty atom is defined in the `STRU` file when an element name contains the "empty" suffix, such as "H_empty", "O_empty" and so on. Here we provide an [example](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/bsse/water) of calculating the molecular formation energy of $H_2O$ with BSSE correction. +An empty atom is defined in the `STRU` file when an element name contains the "empty" suffix, such +as "H_empty", "O_empty" and so on. Here we provide an +[example](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/bsse/water) of +calculating the molecular formation energy of $H_2O$ with BSSE correction. In the example, we provide four STRU files: - STRU_0 : used along with ntype = 2;normal calculation of water molecule ($E(\text{H}_2\text{O})$) obtained total energy of -466.4838149140513 eV + - STRU_1 : used along with ntype = 2;calculation of single O atom ($E_O$) obtained total energy of -427.9084406198214 eV + - STRU_2 : used along with ntype = 3;calculation of 1st H atom ($E_{H1}$) obtained total energy of -12.59853381731160 eV + - STRU_3 : used along with ntype = 3;calculation of 2nd H atom ($E_{H2}$) obtained total energy of -12.59853378720844 eV @@ -64,16 +96,22 @@ $$ $$ ## Pseudopotentials + ### Supported formats -ABACUS supports both norm-conserving and ultrasoft pseudopotentials. For norm-conserving pseudopotentials, UPF, UPF2, VWR, and BLPS formats are supported. For ultrasoft pseudopotentials, UPF and UPF2 formats are supported. + +ABACUS supports both norm-conserving and ultrasoft pseudopotentials. For norm-conserving +pseudopotentials, UPF, UPF2, VWR, and BLPS formats are supported. For ultrasoft pseudopotentials, +UPF and UPF2 formats are supported. ### Pseudopotentials for SOC Calculations -When performing spin-orbit coupling (SOC) calculations with `lspinorb=1`, specific pseudopotential requirements must be met: +When performing spin-orbit coupling (SOC) calculations with `lspinorb=1`, specific pseudopotential +requirements must be met: #### Identifying SOC Pseudopotentials -Full-relativistic pseudopotentials suitable for SOC calculations can be identified by checking the UPF file header (`PP_HEADER` section): +Full-relativistic pseudopotentials suitable for SOC calculations can be identified by checking the +UPF file header (`PP_HEADER` section): ```xml ` section from the pseudopotential file: + In the original `INPUT` file, there is no specification of the `dft_functional` keyword. As a + result, we use the default option, that is to use the xc functional in the pseudopotential file, + `Si.pz-vbc.UPF`. We can take a look at the first few lines of the `` section from the + pseudopotential file: - ``` - - 0 Version Number - Si Element - NC Norm - Conserving pseudopotential - F Nonlinear Core Correction - SLA PZ NOGX NOGC PZ Exchange-Correlation functional - ``` + ``` + + 0 Version Number + Si Element + NC Norm - Conserving pseudopotential + F Nonlinear Core Correction + SLA PZ NOGX NOGC PZ Exchange-Correlation functional + ``` - From the line commented 'Exchange-Correlation functional', we see that this pseudopotential is generated using PZ functional. As a result, if we run ABACUS with the original setting, PZ functional will be used. + From the line commented 'Exchange-Correlation functional', we see that this pseudopotential is + generated using PZ functional. As a result, if we run ABACUS with the original setting, PZ + functional will be used. - > Note : for systems with multiple elements, if no `dft_functional` is specified, users should make sure that all pseudopotentials are using the same functional. Otherwise, the type of xc functional should be specified explicitly. + > Note : for systems with multiple elements, if no `dft_functional` is specified, users should + > make sure that all pseudopotentials are using the same functional. Otherwise, the type of xc + > functional should be specified explicitly. -2. **Using PBE** +1. **Using PBE** - On the other hand, users might also explicitly specify the xc functional through `dft_functional` parameter. For example, to use PBE functional, add the following line to `INPUT` file and rerun the calculation: + On the other hand, users might also explicitly specify the xc functional through `dft_functional` + parameter. For example, to use PBE functional, add the following line to `INPUT` file and rerun + the calculation: - ``` - dft_functional PBE - ``` + ``` + dft_functional PBE + ``` -3. **More functionals from LIBXC** +1. **More functionals from LIBXC** - ABACUS has its own implementation of the PBE functional as well as a few others, but our list is far from comprehensive. However, if ABACUS is compiled with LIBXC, we also support all the LDA, GGA and meta-GGA functionals provided therein. + ABACUS has its own implementation of the PBE functional as well as a few others, but our list is + far from comprehensive. However, if ABACUS is compiled with LIBXC, we also support all the LDA, + GGA and meta-GGA functionals provided therein. - For this part, users should compile the ABACUS code with LIBXC linked (version 5.1.7 or higher). + For this part, users should compile the ABACUS code with LIBXC linked (version 5.1.7 or higher). - To use SCAN functional, make the following modification to the `INPUT` file: + To use SCAN functional, make the following modification to the `INPUT` file: - ``` - dft_functional SCAN - ``` - - Note that in the case of PBE and SCAN, we are using 'short-hand' names to represent the entire functional, which is made up of individual exchange and correlation components. A complete list of 'short-hand' expressions supported by ABACUS can be found in [source code](../../../source/source_hamilt/module_xc/xc_functional.cpp). + ``` + dft_functional SCAN + ``` - Apart from the 'short-hand' names, ABACUS also allow supplying exchange-correlation functionals as combinations of LIBXC keywords for functional components, joined by plus sign, for example, setting: + Note that in the case of PBE and SCAN, we are using 'short-hand' names to represent the entire + functional, which is made up of individual exchange and correlation components. A complete list + of 'short-hand' expressions supported by ABACUS can be found in + [source code](../../../source/source_hamilt/module_xc/xc_functional.cpp). - ``` - dft_functional LDA_X_YUKAWA+LDA_C_1D_CSC - ``` - means we are using the short-range Yukawa attenuated exchange along with the Casula, Sorella & Senatore LDA correlation functional. + Apart from the 'short-hand' names, ABACUS also allow supplying exchange-correlation functionals + as combinations of LIBXC keywords for functional components, joined by plus sign, for example, + setting: - The list of LIBXC keywords can be found on its [website](https://www.tddft.org/programs/libxc/functionals/). + ``` + dft_functional LDA_X_YUKAWA+LDA_C_1D_CSC + ``` -4. **Temperature-dependent functional** + means we are using the short-range Yukawa attenuated exchange along with the Casula, Sorella & + Senatore LDA correlation functional. - In ABACUS, we provide temperature-dependent functionals through LIBXC. For such functionals, the keyword `xc_temperature` (unit is Rydberg) is used to specify the temperature, such as the following: + The list of LIBXC keywords can be found on its + [website](https://www.tddft.org/programs/libxc/functionals/). - ``` - dft_functional LDA_XC_CORRKSDT - xc_temperature 10 - ``` +1. **Temperature-dependent functional** -5. **Hybrid functional** + In ABACUS, we provide temperature-dependent functionals through LIBXC. For such functionals, the + keyword `xc_temperature` (unit is Rydberg) is used to specify the temperature, such as the + following: - ABACUS supports functionals with exact Hartree-Fock exchange in LCAO basis set only. The old INPUT parameter exx_hybrid_type for hybrid functionals has been absorbed into `dft_functional`. Options are `hf` (pure Hartree-Fock), `pbe0`(PBE0), `hse`, and `scan0`(SCAN0) (Note: in order to use HSE or SCAN0 functional, LIBXC is required). Note also that only HSE has been tested while other hybrid functionals have NOT been fully tested yet, and the maximum parallel cpus for running exx is N^4, with N being the number of atoms. + ``` + dft_functional LDA_XC_CORRKSDT + xc_temperature 10 + ``` - More information on the hybrid functional can be found from the section [Exact Exchange](../input_files/input-main.md#exact-exchange) in the list of input variables for more information. +1. **Hybrid functional** - An example HSE calculation is provided in this [directory](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/hse/lcao_Si2). Apart from the input files (`INPUT`, `STRU`, `KPT`), we further provide two files: running_scf.log_ref and log_ref, which contains reference for running_scf.log and standard output from the program, respectively. - -## DFT+*U* + ABACUS supports functionals with exact Hartree-Fock exchange in LCAO basis set only. The old + INPUT parameter exx_hybrid_type for hybrid functionals has been absorbed into `dft_functional`. + Options are `hf` (pure Hartree-Fock), `pbe0`(PBE0), `hse`, and `scan0`(SCAN0) (Note: in order to + use HSE or SCAN0 functional, LIBXC is required). Note also that only HSE has been tested while + other hybrid functionals have NOT been fully tested yet, and the maximum parallel cpus for + running exx is N^4, with N being the number of atoms. + + More information on the hybrid functional can be found from the section + [Exact Exchange](../input_files/input-main.md#exact-exchange) in the list of input variables for + more information. -Conventional functionals, e.g., L(S)DA and GGAs, encounter failures in strongly correlated systems, usually characterized by partially filled *d*/*f* shells. These include transition metals (TM) and their oxides, rare-earth compounds, and actinides, to name a few, where L(S)DA/GGAs typically yield quantitatively or even qualitatively wrong results. To address this failure, an efficient and successful method named DFT+*U*, which inherits the efficiency of L(S)DA/GGA but gains the strength of the Hubbard model in describing the physics of strongly correlatedsystems, has been developed. + An example HSE calculation is provided in this + [directory](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/hse/lcao_Si2). + Apart from the input files (`INPUT`, `STRU`, `KPT`), we further provide two files: + running_scf.log_ref and log_ref, which contains reference for running_scf.log and standard output + from the program, respectively. -Now the DFT+*U* method is accessible in ABACUS. The details of the DFT+*U* method could be found in this [paper](https://doi.org/10.1063/5.0090122). It should be noted that the DFT+*U* works only within the NAO scheme, which means that the value of the keyword `basis_type` must be lcao when DFT+*U* is called. To turn on DFT+*U*, users need to set the value of the `dft_plus_u` keyword in the `INPUT` file to be 1. All relevant parmeters used in DFT+*U* calculations are listed in the [DFT+*U* correction](../input_files/input-main.md#dftu-correction) part of the [list of keywords](../input_files/input-main.md). +## DFT+*U* -Examples of DFT+*U* calculations are provided in this [directory](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/dft_plus_u). +Conventional functionals, e.g., L(S)DA and GGAs, encounter failures in strongly correlated systems, +usually characterized by partially filled *d*/*f* shells. These include transition metals (TM) and +their oxides, rare-earth compounds, and actinides, to name a few, where L(S)DA/GGAs typically yield +quantitatively or even qualitatively wrong results. To address this failure, an efficient and +successful method named DFT+*U*, which inherits the efficiency of L(S)DA/GGA but gains the strength +of the Hubbard model in describing the physics of strongly correlatedsystems, has been developed. + +Now the DFT+*U* method is accessible in ABACUS. The details of the DFT+*U* method could be found in +this [paper](https://doi.org/10.1063/5.0090122). It should be noted that the DFT+*U* works only +within the NAO scheme, which means that the value of the keyword `basis_type` must be lcao when +DFT+*U* is called. To turn on DFT+*U*, users need to set the value of the `dft_plus_u` keyword in +the `INPUT` file to be 1. All relevant parmeters used in DFT+*U* calculations are listed in the +[DFT+*U* correction](../input_files/input-main.md#dftu-correction) part of the +[list of keywords](../input_files/input-main.md). + +Examples of DFT+*U* calculations are provided in this +[directory](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/dft_plus_u). diff --git a/docs/advanced/scf/converge.md b/docs/advanced/scf/converge.md index 4f77f2f3b7c..f46d12d4e96 100644 --- a/docs/advanced/scf/converge.md +++ b/docs/advanced/scf/converge.md @@ -1,31 +1,68 @@ # Converging SCF -As in any non-linear systems, numerical instabilities during SCF iterations may lead to nonconvergence. In ABACUS, we offer the following options to facilitate SCF convergence. +As in any non-linear systems, numerical instabilities during SCF iterations may lead to +nonconvergence. In ABACUS, we offer the following options to facilitate SCF convergence. ## Charge Mixing -In ABACUS, KS-DFT is solved by self-consistent field (SCF) iteration method. By mixing the electron density with that obtained from previous steps, numerical instabilities can be ameliorated while also accelerating convergence. ABACUS offers several mixing schemes, and users may make a selection by adjusting the [mixing_type](../input_files/input-main.md#mixing_type) keyword in INPUT file. +In ABACUS, KS-DFT is solved by self-consistent field (SCF) iteration method. By mixing the electron +density with that obtained from previous steps, numerical instabilities can be ameliorated while +also accelerating convergence. ABACUS offers several mixing schemes, and users may make a selection +by adjusting the [mixing_type](../input_files/input-main.md#mixing_type) keyword in INPUT file. -For each of the mixing types, we also provide variables for controlling relevant parameters, including `mixing_ndim`, `mixing_type`, `mixing_beta`, `mixing_gg0`, `mixing_beta_mag`, `mixing_gg0_mag`, `mixing_gg0_min`, `mixing_angle`. +For each of the mixing types, we also provide variables for controlling relevant parameters, +including `mixing_ndim`, `mixing_type`, `mixing_beta`, `mixing_gg0`, `mixing_beta_mag`, +`mixing_gg0_mag`, `mixing_gg0_min`, `mixing_angle`. -`mixing_ndim` is the mixing dimensions in DIIS (broyden or pulay) mixing. Gerenally, a larger `mixing_ndim` leads to a better convergence. the default choice `mixing_ndim=8` should work fine in most cases. For `mixing_type`, the default choice is `broyden`, which is slightly better than `Pulay` typically. Besides that, a large `mixing_beta` means a larger change in electron density for each SCF step. For well-behaved systems, a larger `mixing_beta` leads to faster convergence. However, for some difficult cases, a smaller `mixing_beta` is preferred to avoid numerical instabilities. +`mixing_ndim` is the mixing dimensions in DIIS (broyden or pulay) mixing. Gerenally, a larger +`mixing_ndim` leads to a better convergence. the default choice `mixing_ndim=8` should work fine in +most cases. For `mixing_type`, the default choice is `broyden`, which is slightly better than +`Pulay` typically. Besides that, a large `mixing_beta` means a larger change in electron density for +each SCF step. For well-behaved systems, a larger `mixing_beta` leads to faster convergence. +However, for some difficult cases, a smaller `mixing_beta` is preferred to avoid numerical +instabilities. -For most isolated systems, Kerker preconditioning is unnecessary. You can turn off it by setting `mixing_gg0 0.0` to get a faster convergence. +For most isolated systems, Kerker preconditioning is unnecessary. You can turn off it by setting +`mixing_gg0 0.0` to get a faster convergence. -For non-spin-polarized calculations, the default choices usually achieve convergence. If convergence issue arises in metallic systems, you can try different value of Kerker preconditioning [mixing_gg0](../input_files/input-main.md#mixing_gg0) and [mixing_gg0_min](../input_files/input-main.md#mixing_gg0_min), and try to reduce `mixing_beta`, which is 0.8 defaultly for `nspin=1`. +For non-spin-polarized calculations, the default choices usually achieve convergence. If convergence +issue arises in metallic systems, you can try different value of Kerker preconditioning +[mixing_gg0](../input_files/input-main.md#mixing_gg0) and +[mixing_gg0_min](../input_files/input-main.md#mixing_gg0_min), and try to reduce `mixing_beta`, +which is 0.8 defaultly for `nspin=1`. -For magnetic calculations, `mixing_beta_mag` and `mixing_gg0_mag` are activated. Considering collinear calculations, you can rely on the default value for most cases. If convergence issue arises, you can try to reduce `mixing_beta` and `mixing_beta_mag` together. For non-collinear calculations, tradtional broyden usually works, especially for a given magnetic configuration. If one is not interested in the energies of a given magnetic configuration but wants to determine the ground state by relaxing the magnetic moments’ directions, the standard Broyden mixing algorithm sometimes fails to find the correct magnetic configuration. If so, we can set [mixing_angle=1.0](../input_files/input-main.md#mixing_angle), which is a promising mixing method proposed by J. Phys. Soc. Jpn. 82 (2013) 114706. +For magnetic calculations, `mixing_beta_mag` and `mixing_gg0_mag` are activated. Considering +collinear calculations, you can rely on the default value for most cases. If convergence issue +arises, you can try to reduce `mixing_beta` and `mixing_beta_mag` together. For non-collinear +calculations, tradtional broyden usually works, especially for a given magnetic configuration. If +one is not interested in the energies of a given magnetic configuration but wants to determine the +ground state by relaxing the magnetic moments’ directions, the standard Broyden mixing algorithm +sometimes fails to find the correct magnetic configuration. If so, we can set +[mixing_angle=1.0](../input_files/input-main.md#mixing_angle), which is a promising mixing method +proposed by J. Phys. Soc. Jpn. 82 (2013) 114706. -An example showcasing different charge mixing methods can be found in our [repository](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/charge_mixing/pw_Al). Four INPUT files are provided, with description given in README. +An example showcasing different charge mixing methods can be found in our +[repository](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/charge_mixing/pw_Al). +Four INPUT files are provided, with description given in README. -As for DFT+U calculations, where the hamiltonian is not only dependent on charge density, but also dependent on density matrix. You can try `mixing_restart>0` and `mixing_dmr=1` to improve convergence. For case extremely hard to converge, you can use so-called U-Ramping method by setting a finite positive `uramping` with `mixing_restart>0` and `mixing_dmr=1`. +As for DFT+U calculations, where the hamiltonian is not only dependent on charge density, but also +dependent on density matrix. You can try `mixing_restart>0` and `mixing_dmr=1` to improve +convergence. For case extremely hard to converge, you can use so-called U-Ramping method by setting +a finite positive `uramping` with `mixing_restart>0` and `mixing_dmr=1`. ## Smearing -Thermal smearing is an efficient tool for accelerating SCF convergence by allowing fractional occupation of molecular orbitals near the band edge. It is important for metallic systems. +Thermal smearing is an efficient tool for accelerating SCF convergence by allowing fractional +occupation of molecular orbitals near the band edge. It is important for metallic systems. -In ABACUS, we provide a few smearing methods, which can be controlled using the keyword [smearing_method](../input_files/input-main.md#smearing_method). We also provide keyword `smearing_sigma` or `smearing_sigma_temp` to control the energy range of smearing. A larger value of smearing sigma leads to a more diffused occupation curve. +In ABACUS, we provide a few smearing methods, which can be controlled using the keyword +[smearing_method](../input_files/input-main.md#smearing_method). We also provide keyword +`smearing_sigma` or `smearing_sigma_temp` to control the energy range of smearing. A larger value of +smearing sigma leads to a more diffused occupation curve. -> Note : The two keywords `smearing_sigma` and `smearing_sigma_temp` should not be used concurrently. +> Note : The two keywords `smearing_sigma` and `smearing_sigma_temp` should not be used +> concurrently. -We provide an example showing the importance of smearing in our [repository](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/smearing/lcao_fe). Two INPUT fiels rae provided, with description given in README. \ No newline at end of file +We provide an example showing the importance of smearing in our +[repository](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/smearing/lcao_fe). +Two INPUT fiels rae provided, with description given in README. diff --git a/docs/advanced/scf/hsolver.md b/docs/advanced/scf/hsolver.md index 0cb02ce9dd9..95e2647968d 100644 --- a/docs/advanced/scf/hsolver.md +++ b/docs/advanced/scf/hsolver.md @@ -4,18 +4,37 @@ Method of explicit solving KS-equation can be chosen by variable "ks_solver" in INPUT file. -When "basis_type = pw", `ks_solver` can be `cg`, `bpcg` or `dav`. The default setting `cg` is recommended, which is band-by-band conjugate gradient diagonalization method. There is a large probability that the use of setting of `dav` , which is block Davidson diagonalization method, can be tried to improve performance. +When "basis_type = pw", `ks_solver` can be `cg`, `bpcg` or `dav`. The default setting `cg` is +recommended, which is band-by-band conjugate gradient diagonalization method. There is a large +probability that the use of setting of `dav` , which is block Davidson diagonalization method, can +be tried to improve performance. -When "basis_type = lcao", `ks_solver` can be `genelpa` or `scalapack_gvx`. The default setting `genelpa` is recommended, which is based on ELPA (EIGENVALUE SOLVERS FOR PETAFLOP APPLICATIONS) (https://elpa.mpcdf.mpg.de/) and the kernel is auto choosed by GENELPA(https://github.com/pplab/GenELPA), usually faster than the setting of "scalapack_gvx", which is based on ScaLAPACK(Scalable Linear Algebra PACKage) +When "basis_type = lcao", `ks_solver` can be `genelpa` or `scalapack_gvx`. The default setting +`genelpa` is recommended, which is based on ELPA (EIGENVALUE SOLVERS FOR PETAFLOP APPLICATIONS) +(https://elpa.mpcdf.mpg.de/) and the kernel is auto choosed by +GENELPA(https://github.com/pplab/GenELPA), usually faster than the setting of "scalapack_gvx", which +is based on ScaLAPACK(Scalable Linear Algebra PACKage) ## Stochasic DFT -We support stochastic DFT calculation (SDFT) or mixed stochastic-deterministic DFT (MDFT) with plane-wave basis [[Phys. Rev. B 106, 125132 (2022)](https://doi.org/10.1103/PhysRevB.106.125132)]. Different from traditional KSDFT with the explicit diagonalization method, SDFT and MDFT calculate physical quantities with trace of the corresponding operators. The advantages of SDFT and MDFT compared to the traditional KSDFT are the ability to simulate larger sizes and higher temperatures. In our package, SDFT and MDFT can be used by setting the `esolver_type` parameter to `sdft` for SCF calculations or MD calculations. To start with, you can refer to two [examples](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/stochastic) and an explanation of the [input variables](../input_files/input-main.md#electronic-structure-sdft). + +We support stochastic DFT calculation (SDFT) or mixed stochastic-deterministic DFT (MDFT) with +plane-wave basis \[[Phys. Rev. B 106, 125132 (2022)](https://doi.org/10.1103/PhysRevB.106.125132)\]. +Different from traditional KSDFT with the explicit diagonalization method, SDFT and MDFT calculate +physical quantities with trace of the corresponding operators. The advantages of SDFT and MDFT +compared to the traditional KSDFT are the ability to simulate larger sizes and higher temperatures. +In our package, SDFT and MDFT can be used by setting the `esolver_type` parameter to `sdft` for SCF +calculations or MD calculations. To start with, you can refer to two +[examples](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/stochastic) and an +explanation of the [input variables](../input_files/input-main.md#electronic-structure-sdft). When we have a hamiltonian, the electronic density can be calculated with: $\rho(\mathbf{r})={\rm Tr}[f(\hat{H})\ket{\mathbf{r}}\bra{\mathbf{r}}]$, -where the Fermi-Dirac function $f(\hat{H})=\frac{1}{1+\exp(\frac{\hat{H}-\mu}{kT})}$ and it can be calculated with the Chebyshev expansion. Here we only support the "fd" or "fermi-dirac" `smearing_method`, the parameter `smearing_sigma` is equal the temperature $T$ (in Ry) and `nche_sto` represents the order of the expansion. +where the Fermi-Dirac function $f(\hat{H})=\frac{1}{1+\exp(\frac{\hat{H}-\mu}{kT})}$ and it can be +calculated with the Chebyshev expansion. Here we only support the "fd" or "fermi-dirac" +`smearing_method`, the parameter `smearing_sigma` is equal the temperature $T$ (in Ry) and +`nche_sto` represents the order of the expansion. For physical quantities represented by operator $\hat{O}$, SDFT calculates its trace with: @@ -25,10 +44,13 @@ while MDFT calculates the trace as: ${\rm Tr}[\hat{O}]=\sum_{n=1}^{N_\phi}{\bra{\phi_n}\hat{O}\ket{\phi_n}}+\sum_{i=1}^{N_\chi}{\bra{\tilde \chi_i}\hat{O}\ket{\tilde \chi_i}}$, -where $\{\ket{\tilde\chi_i}\}$ are obtaiend by projecting stochastic orbitals onto the subspace orthogonal to KS orbitals $\{\phi_n\}$: +where $\{\ket{\tilde\chi_i}\}$ are obtaiend by projecting stochastic orbitals onto the subspace +orthogonal to KS orbitals $\{\phi_n\}$: $\ket{\tilde\chi_i}=\ket{\chi_i}-\sum_{n=1}^{N_\phi}\braket{\phi_n|\chi_i}\ket{\phi_n}$. -Here the number of KS orbitals $N_\phi$ is controlled by the parameter `nbands` while the number of stochastic orbitals $N_\chi$ is controlled by `nbands_sto`. +Here the number of KS orbitals $N_\phi$ is controlled by the parameter `nbands` while the number of +stochastic orbitals $N_\chi$ is controlled by `nbands_sto`. -Besides, although SDFT does not diagonalize the hamiltonian, it can also caluclate DOS and electronic conductivities with parameters `out_dos` and `cal_cond` separately. +Besides, although SDFT does not diagonalize the hamiltonian, it can also caluclate DOS and +electronic conductivities with parameters `out_dos` and `cal_cond` separately. diff --git a/docs/advanced/scf/initialization.md b/docs/advanced/scf/initialization.md index 8332c85b7f5..df2d9f9b33d 100644 --- a/docs/advanced/scf/initialization.md +++ b/docs/advanced/scf/initialization.md @@ -1,24 +1,42 @@ # Initializing SCF -Good initializing would abate the number of iteration steps in SCF. -Charge density should be initialed for constructing the initial hamiltonian operator. -In PW basis, wavefunction should be initialized for iterate diagonalization method. -In LCAO basis, wavefunction can be read to calculate initial charge density. The wavefunction itself does not have to be initialized. +Good initializing would abate the number of iteration steps in SCF. Charge density should be +initialed for constructing the initial hamiltonian operator. + +In PW basis, wavefunction should be initialized for iterate diagonalization method. In LCAO basis, +wavefunction can be read to calculate initial charge density. The wavefunction itself does not have +to be initialized. ## Charge Density + `init_chg` is used for choosing the method of charge density initialization. - - `atomic` : initial charge density by atomic charge density from pseudopotential file under keyword `PP_RHOATOM` - - `file` : initial charge density from files produced by previous calculations with [`out_chg 1`](../elec_properties/charge.md). - - `auto`: Abacus first attempts to read the density from a file; if not found, it defaults to using atomic density. - - `dm` (LCAO only): initial charge density from density matrix files in CSR format. For `nspin=1`, reads `dmrs1_nao.csr`. For `nspin=2` (spin-polarized), reads both `dmrs1_nao.csr` (spin-up) and `dmrs2_nao.csr` (spin-down). These files are generated by previous calculations with [`out_dmr 1`](../elec_properties/density_matrix.md). This method is particularly useful for restarting spin-polarized calculations. - - `hr` (LCAO only): initial charge density from Hamiltonian matrix files in CSR format. The Hamiltonian is read from file, then diagonalized to obtain wavefunctions and charge density. For `nspin=1`, reads `hrs1_nao.csr`. For `nspin=2` (spin-polarized), reads both `hrs1_nao.csr` (spin-up) and `hrs2_nao.csr` (spin-down). These files are generated by previous calculations with [`out_mat_hs2 1`](../input_files/input-main.md). + +- `atomic` : initial charge density by atomic charge density from pseudopotential file under keyword + `PP_RHOATOM` +- `file` : initial charge density from files produced by previous calculations with + [`out_chg 1`](../elec_properties/charge.md). +- `auto`: Abacus first attempts to read the density from a file; if not found, it defaults to using + atomic density. +- `dm` (LCAO only): initial charge density from density matrix files in CSR format. For `nspin=1`, + reads `dmrs1_nao.csr`. For `nspin=2` (spin-polarized), reads both `dmrs1_nao.csr` (spin-up) and + `dmrs2_nao.csr` (spin-down). These files are generated by previous calculations with + [`out_dmr 1`](../elec_properties/density_matrix.md). This method is particularly useful for + restarting spin-polarized calculations. +- `hr` (LCAO only): initial charge density from Hamiltonian matrix files in CSR format. The + Hamiltonian is read from file, then diagonalized to obtain wavefunctions and charge density. For + `nspin=1`, reads `hrs1_nao.csr`. For `nspin=2` (spin-polarized), reads both `hrs1_nao.csr` + (spin-up) and `hrs2_nao.csr` (spin-down). These files are generated by previous calculations with + [`out_mat_hs2 1`](../input_files/input-main.md). ## Wave function + `init_wfc` is used for choosing the method of wavefunction coefficient initialization. -When `basis_type=pw`, setting of `random` and `atomic` are supported. -Atomic wave function is read from pseudopotential file under keyword `PP_PSWFC`, if setting is `atomic` and number of band of atomic wavefunction less than `nbands` in INPUT file, the extra bands will be initialed by random. +When `basis_type=pw`, setting of `random` and `atomic` are supported. Atomic wave function is read +from pseudopotential file under keyword `PP_PSWFC`, if setting is `atomic` and number of band of +atomic wavefunction less than `nbands` in INPUT file, the extra bands will be initialed by random. -When `basis_type=lcao`, we further support reading of initial wavefunction by setting `init_wfc` to `file`. -In LCAO code, wave function is used to initialize density matrix and real-space charge density. -For such purpose, a file containing wavefunction must be prepared. Such files can be generated from previous calculations with [`out_wfc_lcao 1`](../elec_properties/wfc.md). +When `basis_type=lcao`, we further support reading of initial wavefunction by setting `init_wfc` to +`file`. In LCAO code, wave function is used to initialize density matrix and real-space charge +density. For such purpose, a file containing wavefunction must be prepared. Such files can be +generated from previous calculations with [`out_wfc_lcao 1`](../elec_properties/wfc.md). diff --git a/docs/advanced/scf/performance.md b/docs/advanced/scf/performance.md index cf3ebb907f3..957f8fac558 100644 --- a/docs/advanced/scf/performance.md +++ b/docs/advanced/scf/performance.md @@ -1,31 +1,46 @@ # Accelerating the Calculation -In ABACUS, we provide a few methods for accelerating the calculation. The parameters are usually set as default for calculations where there is not extreme concern for efficiency, as some of them may produce numerical issues under certain circumstances. In short, methods in this section should be used with care. It is better to calibrate the results against the default setting. +In ABACUS, we provide a few methods for accelerating the calculation. The parameters are usually set +as default for calculations where there is not extreme concern for efficiency, as some of them may +produce numerical issues under certain circumstances. In short, methods in this section should be +used with care. It is better to calibrate the results against the default setting. ## K-point Parallelization -In ABACUS, we offer k-point parallelization for calculations with PW basis, which should increase the efficiency when a large k-point mesh is used. +In ABACUS, we offer k-point parallelization for calculations with PW basis, which should increase +the efficiency when a large k-point mesh is used. -To use k-point parallelization, users may set keyword [kpar](../input_files/input-main.md#kpar) to be larger than 1. +To use k-point parallelization, users may set keyword [kpar](../input_files/input-main.md#kpar) to +be larger than 1. -> Note: It has been observed that k-point parallelization cannot work in conjunction with Davidson diagonalization. +> Note: It has been observed that k-point parallelization cannot work in conjunction with Davidson +> diagonalization. ## K-point Symmetry -Inclusion of k-point symmetry helps increasing the efficiency of calculations by reducing the effective number of k-points used. To turn on k-point symmetry, users may set keyword [symmetry](../input_files/input-main.md#symmetry) to be 1. +Inclusion of k-point symmetry helps increasing the efficiency of calculations by reducing the +effective number of k-points used. To turn on k-point symmetry, users may set keyword +[symmetry](../input_files/input-main.md#symmetry) to be 1. > Note: In ABACUS we only support point-group symmetry but not space-group symmetry. ## Accelerating Grid Integration -For LCAO calculation, the matrix elements of the local potential is evaluated using grid integration. In grid integration, we group real-space FFT grid points into boxes of dimension bx * by * bz, and then proceed with the boxes as the basis unit of calculation. +For LCAO calculation, the matrix elements of the local potential is evaluated using grid +integration. In grid integration, we group real-space FFT grid points into boxes of dimension bx \* +by * bz, and then proceed with the boxes as the basis unit of calculation. -Setting [bx, by, bz](../input_files/input-main.md#bx-by-bz) to be values other than default might help with the efficiency of grid integration. +Setting [bx, by, bz](../input_files/input-main.md#bx-by-bz) to be values other than default might +help with the efficiency of grid integration. -> Note: the choice of bx, by, bz should be integer factors of the dimension of the real space FFT grid in each direction. +> Note: the choice of bx, by, bz should be integer factors of the dimension of the real space FFT +> grid in each direction. ## Low Dimension Materials -In grid integration, we chose to parallelize the grid points along the z direction. Therefore, when using LCAO calculation for low dimension materials, it is recommended to put the material more evenly in z direction to avoid imbalanced workload on different MPI threads. +In grid integration, we chose to parallelize the grid points along the z direction. Therefore, when +using LCAO calculation for low dimension materials, it is recommended to put the material more +evenly in z direction to avoid imbalanced workload on different MPI threads. -Namely, when calculating 2D materials, it is better to put the material in xz or yz direction; while for 1D materials, it is better to align the material with the z direction. \ No newline at end of file +Namely, when calculating 2D materials, it is better to put the material in xz or yz direction; while +for 1D materials, it is better to align the material with the z direction. diff --git a/docs/advanced/scf/spin.md b/docs/advanced/scf/spin.md index 1749db156dc..5b517f2806e 100644 --- a/docs/advanced/scf/spin.md +++ b/docs/advanced/scf/spin.md @@ -1,83 +1,117 @@ # Spin-polarization and SOC ## Non-spin-polarized Calculations -Setting of **"nspin 1"** in INPUT file means calculation with non-polarized spin. -In this case, electrons with spin up and spin down have same occupations at every energy states, weights of bands per k point would be double. + +Setting of **"nspin 1"** in INPUT file means calculation with non-polarized spin. In this case, +electrons with spin up and spin down have same occupations at every energy states, weights of bands +per k point would be double. ## Collinear Spin Polarized Calculations -Setting of **"nspin 2"** in INPUT file means calculation with polarized spin along z-axis. -In this case, electrons with spin up and spin down will be calculated respectively, number of k points would be doubled. -Potential of electron and charge density will separate to spin-up case and spin-down case. -Magnetic moment Settings in [STRU files](../input_files/stru.md) are not ignored until **"nspin 2"** is set in INPUT file +Setting of **"nspin 2"** in INPUT file means calculation with polarized spin along z-axis. In this +case, electrons with spin up and spin down will be calculated respectively, number of k points would +be doubled. Potential of electron and charge density will separate to spin-up case and spin-down +case. + +Magnetic moment Settings in [STRU files](../input_files/stru.md) are not ignored until **"nspin 2"** +is set in INPUT file When **"nspin 2"** is set, the screen output file will contain magnetic moment information. e.g. + ``` ITER TMAG AMAG ETOT(eV) EDIFF(eV) DRHO TIME(s) GE1 4.16e+00 4.36e+00 -6.440173e+03 0.000000e+00 6.516e-02 1.973e+01 ``` -where "TMAG" refers to total magnetization and "AMAG" refers to average magnetization. -For more detailed orbital magnetic moment information, please use [Mulliken charge analysis](../elec_properties/Mulliken.md). + +where "TMAG" refers to total magnetization and "AMAG" refers to average magnetization. For more +detailed orbital magnetic moment information, please use +[Mulliken charge analysis](../elec_properties/Mulliken.md). ### Constraint DFT for collinear spin polarized calculations + For some special need, there are two method to constrain electronic spin. -1. **"ocp"** and **"ocp_set"** -If **"ocp=1"** and **"ocp_set"** is set in INPUT file, the occupations of states would be fixed by **"ocp_set"**, this method is often used for excited states calculation. Be careful that: when **"nspin=1"**, spin-up and spin-down electrons will both be set, and when **"nspin=2"**, you should set spin-up and spin-down respectively. +1. **"ocp"** and **"ocp_set"** If **"ocp=1"** and **"ocp_set"** is set in INPUT file, the + occupations of states would be fixed by **"ocp_set"**, this method is often used for excited + states calculation. Be careful that: when **"nspin=1"**, spin-up and spin-down electrons will + both be set, and when **"nspin=2"**, you should set spin-up and spin-down respectively. -2. **"nupdown"** -If **"nupdown"** is set to non-zero, number of spin-up and spin-down electrons will be fixed, and Fermi energy level will split to E_Fermi_up and E_Fermi_down. By the way, total magnetization will also be fixed, and will be the value of **"nupdown"**. +1. **"nupdown"** If **"nupdown"** is set to non-zero, number of spin-up and spin-down electrons will + be fixed, and Fermi energy level will split to E_Fermi_up and E_Fermi_down. By the way, total + magnetization will also be fixed, and will be the value of **"nupdown"**. ## Noncollinear Spin Polarized Calculations -The spin non-collinear polarization calculation corresponds to setting **"noncolin 1"**, in which case the coupling between spin up and spin down will be taken into account. -In this case, nspin is automatically set to 4, which is usually not required to be specified manually. -The weight of each band will not change, but the number of occupied states will be double. -If the nbands parameter is set manually, it is generally set to twice what it would be when nspin<4. -In general, non-collinear magnetic moment settings are often used in calculations considering [SOC effects](#soc-effects). When **"lspinorb 1"** in INPUT file, "nspin" is also automatically set to 4. +The spin non-collinear polarization calculation corresponds to setting **"noncolin 1"**, in which +case the coupling between spin up and spin down will be taken into account. In this case, nspin is +automatically set to 4, which is usually not required to be specified manually. The weight of each +band will not change, but the number of occupied states will be double. If the nbands parameter is +set manually, it is generally set to twice what it would be when nspin\<4. + +In general, non-collinear magnetic moment settings are often used in calculations considering +[SOC effects](#soc-effects). When **"lspinorb 1"** in INPUT file, "nspin" is also automatically set +to 4. Note: different settings for "noncolin" and "lspinorb" correspond to different calculations: -| noncolin | lspinorb | nspin | Effect | When to Use | -|----------|----------|-------|--------|-------------| -| 0 | 0 | <4 | No non-collinear magnetism, no SOC | Standard collinear spin-polarized or non-spin-polarized calculations | -| 0 | 0 | 4 | Same as above, but larger calculation | **Not recommended** - wastes computational resources | -| 1 | 0 | 4 | Non-collinear magnetism WITHOUT SOC | Systems with complex magnetic structures (e.g., spin spirals, frustrated magnets) where SOC is negligible | -| 0 | 1 | 4 | SOC WITH z-axis magnetism only | Non-magnetic materials with SOC (e.g., semiconductors with band splitting), or magnetic materials where magnetism is along z-axis | -| 1 | 1 | 4 | Both SOC AND non-collinear magnetism | Heavy-element magnetic materials where both SOC and non-collinear magnetism are important (e.g., magnetic anisotropy, Dzyaloshinskii-Moriya interaction) | +| noncolin | lspinorb | nspin | Effect | When to Use | +| -------- | -------- | ----- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0 | 0 | \<4 | No non-collinear magnetism, no SOC | Standard collinear spin-polarized or non-spin-polarized calculations | +| 0 | 0 | 4 | Same as above, but larger calculation | **Not recommended** - wastes computational resources | +| 1 | 0 | 4 | Non-collinear magnetism WITHOUT SOC | Systems with complex magnetic structures (e.g., spin spirals, frustrated magnets) where SOC is negligible | +| 0 | 1 | 4 | SOC WITH z-axis magnetism only | Non-magnetic materials with SOC (e.g., semiconductors with band splitting), or magnetic materials where magnetism is along z-axis | +| 1 | 1 | 4 | Both SOC AND non-collinear magnetism | Heavy-element magnetic materials where both SOC and non-collinear magnetism are important (e.g., magnetic anisotropy, Dzyaloshinskii-Moriya interaction) | -**Special case**: `noncolin=0, lspinorb=1` is commonly used for non-magnetic materials with SOC effects (e.g., topological insulators, semiconductors with spin-orbit splitting). In this case, the magnetization is NOT automatically set, implying no magnetic moments in the system. +**Special case**: `noncolin=0, lspinorb=1` is commonly used for non-magnetic materials with SOC +effects (e.g., topological insulators, semiconductors with spin-orbit splitting). In this case, the +magnetization is NOT automatically set, implying no magnetic moments in the system. ## For the continuation job -- Continuation job for "nspin 1" need file "SPIN1_CHG.cube" which is generated by setting "out_chg=1" in task before. By setting "init_chg file" in new job's INPUT file, charge density will start from file but not atomic. -- Continuation job for "nspin 2" need files "SPIN1_CHG.cube" and "SPIN2_CHG.cube" which are generated by "out_chg 1" with "nspin 2", and refer to spin-up and spin-down charge densities respectively. It should be note that reading "SPIN1_CHG.cube" only for the continuation target magnetic moment job is not supported now. -- Continuation job for "nspin 4" need files "SPIN%s_CHG.cube", where %s in {1,2,3,4}, which are generated by "out_chg 1" with any variable setting leading to 'nspin'=4, and refer to charge densities in Pauli spin matrixes. It should be note that reading charge density files printing by 'nspin'=2 case is supported, which means only $\sigma_{tot}$ and $\sigma_{z}$ are read. + +- Continuation job for "nspin 1" need file "SPIN1_CHG.cube" which is generated by setting + "out_chg=1" in task before. By setting "init_chg file" in new job's INPUT file, charge density + will start from file but not atomic. +- Continuation job for "nspin 2" need files "SPIN1_CHG.cube" and "SPIN2_CHG.cube" which are + generated by "out_chg 1" with "nspin 2", and refer to spin-up and spin-down charge densities + respectively. It should be note that reading "SPIN1_CHG.cube" only for the continuation target + magnetic moment job is not supported now. +- Continuation job for "nspin 4" need files "SPIN%s_CHG.cube", where %s in {1,2,3,4}, which are + generated by "out_chg 1" with any variable setting leading to 'nspin'=4, and refer to charge + densities in Pauli spin matrixes. It should be note that reading charge density files printing by + 'nspin'=2 case is supported, which means only $\sigma_{tot}$ and $\sigma_{z}$ are read. # SOC Effects + ## SOC + `lspinorb` is used for control whether or not SOC(spin-orbit coupling) effects should be considered. Both `basis_type=pw` and `basis_type=lcao` support `scf` and `nscf` calculation with SOC effects. -Atomic forces and cell stresses can be calculated with SOC effects (supported since ABACUS v3.9.0). +Atomic forces and cell stresses can be calculated with SOC effects (supported since ABACUS v3.9.0). ## Pseudopotentials and Numerical Atomic Orbitals + For Norm-Conserving pseudopotentials, there are differences between SOC version and non-SOC version. -Please check your pseudopotential files before calculating. -In `PP_HEADER` part, keyword `has_so=1` and `relativistic="full"` refer to SOC effects have been considered, -which would lead to different `PP_NONLOCAL` and `PP_PSWFC` parts. -Please be careful that `relativistic="full"` version can be used for SOC or non-SOC calculation, but `relativistic="scalar"` version only can be used for non-SOC calculation. -When full-relativistic pseudopotential is used for non-SOC calculation, ABACUS will automatically transform it to scalar-relativistic version. +Please check your pseudopotential files before calculating. In `PP_HEADER` part, keyword `has_so=1` +and `relativistic="full"` refer to SOC effects have been considered, which would lead to different +`PP_NONLOCAL` and `PP_PSWFC` parts. Please be careful that `relativistic="full"` version can be used +for SOC or non-SOC calculation, but `relativistic="scalar"` version only can be used for non-SOC +calculation. When full-relativistic pseudopotential is used for non-SOC calculation, ABACUS will +automatically transform it to scalar-relativistic version. -Numerical atomic orbitals in ABACUS are unrelated with spin, and same orbital file can be used for SOC and non-SOC calculation. +Numerical atomic orbitals in ABACUS are unrelated with spin, and same orbital file can be used for +SOC and non-SOC calculation. ## Partial-relativistic SOC Effect -Sometimes, for some real materials, both scalar-relativistic and full-relativistic can not describe the exact spin-orbit coupling. -Artificial modulation can help for these cases. -`soc_lambda`, which has value range [0.0, 1.0] , is used for modulate SOC effect. -In particular, `soc_lambda 0.0` refers to scalar-relativistic case and `soc_lambda 1.0` refers to full-relativistic case. +Sometimes, for some real materials, both scalar-relativistic and full-relativistic can not describe +the exact spin-orbit coupling. Artificial modulation can help for these cases. + +`soc_lambda`, which has value range [0.0, 1.0] , is used for modulate SOC effect. In particular, +`soc_lambda 0.0` refers to scalar-relativistic case and `soc_lambda 1.0` refers to full-relativistic +case. ## Pseudopotential Requirements for SOC @@ -86,10 +120,12 @@ When performing SOC calculations (`lspinorb=1`), specific pseudopotential requir ### Checking Pseudopotential Files In the UPF (Unified Pseudopotential Format) file header (`PP_HEADER` section), look for: + - `has_so="T"` or `has_so="1"`: Indicates SOC information is included - `relativistic="full"`: Indicates full-relativistic pseudopotential Example from a full-relativistic UPF file: + ``` =3.7,<3.8` is passed - through to conda). - - Detects the target distribution (`Ubuntu-22.04`) by querying the WSL - registry key `HKCU\Software\Microsoft\Windows\CurrentVersion\Lxss`. This - is immune to UTF-16 parsing pitfalls and to Store appx leftovers that - can make `wsl -d -- true` falsely report success. - - Calls `wsl --install -d Ubuntu-22.04 --no-launch` if the distro is - missing, then verifies the registry entry appeared. - - Invokes `provision.sh` inside the distribution, stripping any `\r` - bytes on the fly (`sed 's/\r$//' script | bash`) so Windows line - endings don't break shell parsing. - - Writes two small launcher `.cmd` files and adds them to the user PATH - via PowerShell (avoiding `setx`'s 1024-character truncation). - -2. **`provision.sh`** (runs as root inside the WSL distribution) + - Prompts for an ABACUS version (blank = latest on conda-forge; an exact version like `3.7.4` is + pinned; a match-spec like `>=3.7,<3.8` is passed through to conda). + - Detects the target distribution (`Ubuntu-22.04`) by querying the WSL registry key + `HKCU\Software\Microsoft\Windows\CurrentVersion\Lxss`. This is immune to UTF-16 parsing + pitfalls and to Store appx leftovers that can make `wsl -d -- true` falsely report + success. + - Calls `wsl --install -d Ubuntu-22.04 --no-launch` if the distro is missing, then verifies the + registry entry appeared. + - Invokes `provision.sh` inside the distribution, stripping any `\r` bytes on the fly + (`sed 's/\r$//' script | bash`) so Windows line endings don't break shell parsing. + - Writes two small launcher `.cmd` files and adds them to the user PATH via PowerShell (avoiding + `setx`'s 1024-character truncation). + +1. **`provision.sh`** (runs as root inside the WSL distribution) + - Optionally rewrites `/etc/apt/sources.list` to TUNA. - - `apt-get install`s a minimal set of prerequisites (curl, ca-certificates, - bzip2). - - Downloads the Miniforge installer (from GitHub or TUNA's GitHub-releases - mirror) and installs it to `/opt/abacus-miniforge`. - - `conda create -n abacus_env -c conda-forge abacus` (or the TUNA - conda-forge channel) — a single package pulls in the entire scientific - runtime. conda-forge ships `abacus` for `linux-64` and `linux-aarch64`, - which is exactly what WSL2 provides. - - Writes two system-wide launchers, `/usr/local/bin/abacus` and - `/usr/local/bin/abacus-mpi`, that activate the env and exec the real - binary. Both set `OMP_NUM_THREADS=1` by default to avoid thread - oversubscription. `abacus-mpi` additionally sets OpenMPI 4/5 + PRRTE - "allow run as root" environment variables and passes - `--allow-run-as-root` to `mpirun`, so the default WSL root user can - launch parallel jobs without creating a non-root user. - -3. **Windows launchers** (`abacus.cmd`, `abacus-mpi.cmd`) + - `apt-get install`s a minimal set of prerequisites (curl, ca-certificates, bzip2). + - Downloads the Miniforge installer (from GitHub or TUNA's GitHub-releases mirror) and installs + it to `/opt/abacus-miniforge`. + - `conda create -n abacus_env -c conda-forge abacus` (or the TUNA conda-forge channel) — a single + package pulls in the entire scientific runtime. conda-forge ships `abacus` for `linux-64` and + `linux-aarch64`, which is exactly what WSL2 provides. + - Writes two system-wide launchers, `/usr/local/bin/abacus` and `/usr/local/bin/abacus-mpi`, that + activate the env and exec the real binary. Both set `OMP_NUM_THREADS=1` by default to avoid + thread oversubscription. `abacus-mpi` additionally sets OpenMPI 4/5 + PRRTE "allow run as root" + environment variables and passes `--allow-run-as-root` to `mpirun`, so the default WSL root + user can launch parallel jobs without creating a non-root user. + +1. **Windows launchers** (`abacus.cmd`, `abacus-mpi.cmd`) + - Added to `%LOCALAPPDATA%\ABACUS\bin` and the user PATH. - - Each launcher sets `WSLENV=OMP_NUM_THREADS:MKL_NUM_THREADS:OPENBLAS_NUM_THREADS:...` - so thread-count overrides set on the Windows side are visible inside WSL. + - Each launcher sets `WSLENV=OMP_NUM_THREADS:MKL_NUM_THREADS:OPENBLAS_NUM_THREADS:...` so + thread-count overrides set on the Windows side are visible inside WSL. - Body is just: ``` wsl -d Ubuntu-22.04 --cd "%CD%" -- abacus %* ``` - `--cd "%CD%"` maps the current Windows directory (`C:\…\case`) to its - WSL path (`/mnt/c/…/case`), so users can `cd` into a case directory in - `cmd`/PowerShell/Terminal and just type `abacus`. - -4. **`uninstall-abacus.bat`** - - Reads `install-state.txt` (written by the installer) to learn whether - the Ubuntu-22.04 distribution was pre-existing or added by us. - - If it was added by us, prompts whether to `wsl --unregister` the entire - distribution, or to only wipe `/opt/abacus-miniforge` and the launchers. + `--cd "%CD%"` maps the current Windows directory (`C:\…\case`) to its WSL path + (`/mnt/c/…/case`), so users can `cd` into a case directory in `cmd`/PowerShell/Terminal and + just type `abacus`. + +1. **`uninstall-abacus.bat`** + + - Reads `install-state.txt` (written by the installer) to learn whether the Ubuntu-22.04 + distribution was pre-existing or added by us. + - If it was added by us, prompts whether to `wsl --unregister` the entire distribution, or to + only wipe `/opt/abacus-miniforge` and the launchers. - If it was pre-existing, only the ABACUS files inside are removed. - - Cleans Windows-side launchers and removes the bin directory from the - user PATH. - - Does **not** touch WSL itself (runtime, Windows optional features, or - other distributions). See *Uninstallation* below for how to fully - remove WSL if you want to. + - Cleans Windows-side launchers and removes the bin directory from the user PATH. + - Does **not** touch WSL itself (runtime, Windows optional features, or other distributions). See + *Uninstallation* below for how to fully remove WSL if you want to. ## Requirements @@ -83,22 +78,21 @@ The pipeline, end to end: - Administrator privileges for the first run (to enable WSL features). - Virtualization enabled in BIOS/UEFI. - ~2 GB free disk space (Ubuntu + conda env). -- Network access to GitHub and conda-forge, or to TUNA if you choose the - China mirror option. +- Network access to GitHub and conda-forge, or to TUNA if you choose the China mirror option. ## Installation 1. Clone or download this repository. -2. In `tools/windows/`, right-click `install-abacus.bat` → **Run as administrator**. -3. Answer the China-mirror prompt (`y` recommended inside Mainland China). - Then pick an ABACUS version when prompted (leave blank for the latest on - conda-forge; for a pinned install, type an exact version such as `3.7.4`). -4. If this is the first time WSL is installed on the machine, the script - will ask you to reboot and run it again. -5. Wait for `[*] Provisioning ABACUS …` to finish (5–15 minutes on first - run; most of it is the conda-forge download). -6. When you see `Installation complete!`, **open a new terminal window** - (so the updated PATH takes effect) and verify: +1. In `tools/windows/`, right-click `install-abacus.bat` → **Run as administrator**. +1. Answer the China-mirror prompt (`y` recommended inside Mainland China). Then pick an ABACUS + version when prompted (leave blank for the latest on conda-forge; for a pinned install, type an + exact version such as `3.7.4`). +1. If this is the first time WSL is installed on the machine, the script will ask you to reboot and + run it again. +1. Wait for `[*] Provisioning ABACUS …` to finish (5–15 minutes on first run; most of it is the + conda-forge download). +1. When you see `Installation complete!`, **open a new terminal window** (so the updated PATH takes + effect) and verify: ``` abacus --version ``` @@ -125,19 +119,18 @@ set OMP_NUM_THREADS=2 abacus-mpi -n 4 ``` -Set `OMP_NUM_THREADS` (and/or `MKL_NUM_THREADS`, `OPENBLAS_NUM_THREADS`) in -your Windows shell and the launcher will forward the value into WSL through -`WSLENV`. Unset, it defaults to 1 — a safe choice when running pure MPI. +Set `OMP_NUM_THREADS` (and/or `MKL_NUM_THREADS`, `OPENBLAS_NUM_THREADS`) in your Windows shell and +the launcher will forward the value into WSL through `WSLENV`. Unset, it defaults to 1 — a safe +choice when running pure MPI. -Interactive Linux shell (for advanced debugging, manually running -`mpirun`, inspecting logs, etc.): +Interactive Linux shell (for advanced debugging, manually running `mpirun`, inspecting logs, etc.): ``` wsl -d Ubuntu-22.04 ``` -Inside the shell you can `conda activate abacus_env` to get access to -`mpirun`, `mpiexec`, and other tools from the conda environment. +Inside the shell you can `conda activate abacus_env` to get access to `mpirun`, `mpiexec`, and other +tools from the conda environment. ## Uninstallation @@ -145,24 +138,21 @@ Inside the shell you can `conda activate abacus_env` to get access to Run `uninstall-abacus.bat`. This handles the common case: -- Removes `/opt/abacus-miniforge` and the `abacus` / `abacus-mpi` launchers - inside WSL. -- If the installer added the `Ubuntu-22.04` distribution, asks whether you - also want to `wsl --unregister` it (pick `y` to reclaim the disk space, - `n` to keep the Linux environment for other uses). -- Deletes `%LOCALAPPDATA%\ABACUS\` and removes its `bin\` directory from - your user PATH. +- Removes `/opt/abacus-miniforge` and the `abacus` / `abacus-mpi` launchers inside WSL. +- If the installer added the `Ubuntu-22.04` distribution, asks whether you also want to + `wsl --unregister` it (pick `y` to reclaim the disk space, `n` to keep the Linux environment for + other uses). +- Deletes `%LOCALAPPDATA%\ABACUS\` and removes its `bin\` directory from your user PATH. -This is enough for almost every user. WSL itself and any *other* WSL -distributions you have stay untouched — important because WSL is commonly -shared with Docker Desktop, VS Code Remote, and other toolchains. +This is enough for almost every user. WSL itself and any *other* WSL distributions you have stay +untouched — important because WSL is commonly shared with Docker Desktop, VS Code Remote, and other +toolchains. ### Nuclear: remove WSL itself -Only do this if you truly have no other use for WSL on this machine. -Removing WSL will break Docker Desktop, VS Code Remote-WSL, any other -Linux distros you have, and so on. Run the following in an elevated -PowerShell: +Only do this if you truly have no other use for WSL on this machine. Removing WSL will break Docker +Desktop, VS Code Remote-WSL, any other Linux distros you have, and so on. Run the following in an +elevated PowerShell: ```powershell # 1. Unregister every WSL distribution (this wipes all their files). @@ -191,19 +181,17 @@ Remove-Item "$env:UserProfile\.wslconfig" -ErrorAction SilentlyContinue Restart-Computer ``` -After the reboot `wsl.exe` no longer exists. If you also ran step 4, the -Hyper-V virtualization layer used by WSL2 is disabled. +After the reboot `wsl.exe` no longer exists. If you also ran step 4, the Hyper-V virtualization +layer used by WSL2 is disabled. -> On older Windows builds where `wsl --uninstall` is not available (WSL -> shipped via the in-box `wsl.exe` rather than the Store package), use -> `Get-AppxPackage *WindowsSubsystemForLinux* | Remove-AppxPackage` as a -> fallback for step 2. +> On older Windows builds where `wsl --uninstall` is not available (WSL shipped via the in-box +> `wsl.exe` rather than the Store package), use +> `Get-AppxPackage *WindowsSubsystemForLinux* | Remove-AppxPackage` as a fallback for step 2. ## Performance notes -- Files under `/mnt/c/...` are served through the 9P protocol and are - noticeably slower than native ext4. For heavy I/O (large SCF, MD - trajectories), run the case from inside the WSL filesystem: +- Files under `/mnt/c/...` are served through the 9P protocol and are noticeably slower than native + ext4. For heavy I/O (large SCF, MD trajectories), run the case from inside the WSL filesystem: ``` wsl -d Ubuntu-22.04 cp -r /mnt/c/path/to/case ~/case @@ -211,8 +199,8 @@ Hyper-V virtualization layer used by WSL2 is disabled. abacus ``` - The first `wsl` invocation after a boot triggers a 10–30 s VM cold start. -- OpenMPI runs all ranks inside a single WSL2 VM, so there is no network - overhead between ranks — you get near-native parallel performance. +- OpenMPI runs all ranks inside a single WSL2 VM, so there is no network overhead between ranks — + you get near-native parallel performance. ## File layout @@ -242,20 +230,16 @@ Inside WSL (Ubuntu-22.04): ## Design choices and trade-offs -- **Why WSL2 + conda-forge instead of a native Windows build?** ABACUS's - MPI + ScaLAPACK + ELPA stack has no reliable native Windows build. Going - through WSL2 lets us reuse the Linux binaries conda-forge already ships, - turning a multi-week porting problem into a 200-line shell script. -- **Why a dedicated `Ubuntu-22.04` distribution?** conda-forge ABACUS is - built against glibc from 22.04-era Ubuntu. Using `Ubuntu` (rolling) risks - mismatches; pinning the version keeps the install reproducible. -- **Why put conda under `/opt/abacus-miniforge` rather than `/root`?** - Clean uninstall path, clear ownership, and doesn't interfere with a - user's personal conda install if they later add one inside the same - distribution. -- **Why not ship a pre-built WSL rootfs?** Would cut first-run time from - ~10 min to ~1 min, but balloons the installer from a few KB of scripts - to 300–500 MB, requires CI infrastructure, and needs code signing to - avoid SmartScreen warnings. A scripted online installer is the - lowest-maintenance starting point; the pre-built rootfs path remains - open for a future v1. +- **Why WSL2 + conda-forge instead of a native Windows build?** ABACUS's MPI + ScaLAPACK + ELPA + stack has no reliable native Windows build. Going through WSL2 lets us reuse the Linux binaries + conda-forge already ships, turning a multi-week porting problem into a 200-line shell script. +- **Why a dedicated `Ubuntu-22.04` distribution?** conda-forge ABACUS is built against glibc from + 22.04-era Ubuntu. Using `Ubuntu` (rolling) risks mismatches; pinning the version keeps the install + reproducible. +- **Why put conda under `/opt/abacus-miniforge` rather than `/root`?** Clean uninstall path, clear + ownership, and doesn't interfere with a user's personal conda install if they later add one inside + the same distribution. +- **Why not ship a pre-built WSL rootfs?** Would cut first-run time from ~10 min to ~1 min, but + balloons the installer from a few KB of scripts to 300–500 MB, requires CI infrastructure, and + needs code signing to avoid SmartScreen warnings. A scripted online installer is the + lowest-maintenance starting point; the pre-built rootfs path remains open for a future v1. diff --git a/docs/community/cicd.md b/docs/community/cicd.md index 7479d0262df..80ca4a81185 100644 --- a/docs/community/cicd.md +++ b/docs/community/cicd.md @@ -1,31 +1,58 @@ # Lists of continuous integration (CI) actions -The directory `.github/workflows` contains the continuous integration (CI) actions for the project. The actions are written in YAML format and are executed by GitHub Actions. Check the [Actions page](https://github.com/deepmodeling/abacus-develop/actions) of the repo for the status of the actions. +The directory `.github/workflows` contains the continuous integration (CI) actions for the project. +The actions are written in YAML format and are executed by GitHub Actions. Check the +[Actions page](https://github.com/deepmodeling/abacus-develop/actions) of the repo for the status of +the actions. ## On Pull Request (PR) -The following CI actions are triggered on pull request (PR) creation or update (the user pushes a new commit to the incoming branch): - -- Integration test and unit tests (`test.yml`): This action builds ABACUS with all available features, runs integration tests, and runs unit tests. It also performs [static analysis](../CONTRIBUTING.md#code-formatting-style) with . -- Building tests with CMake (`build_test_cmake.yml`) and Makefile (`build_test_makefile.yml`): This action builds ABACUS with each feature separately, ensuring: (i) there are no conflicts between features, (ii) the compilation is successful whether the feature is enabled, and (iii) it works well on multiple platforms, i.e. with GNU+OpenBLAS toolchain and Intel+MKL toolchain. -- [Rerender the docs site](https://readthedocs.org/projects/abacus-rtd/builds/): This action rerenders the documentation site on Read the Docs. It is automatically triggered when the documentation is updated. -- Testing GPU features (`cuda.yml`): This action builds ABACUS with GPU support and runs several tests on the GPU. - -> Some tests are executed on self-hosted runners, which are maintained by the deepmodeling community. To save resources, the actions triggered by new commits may cancel the previous actions in the same PR. +The following CI actions are triggered on pull request (PR) creation or update (the user pushes a +new commit to the incoming branch): + +- Integration test and unit tests (`test.yml`): This action builds ABACUS with all available + features, runs integration tests, and runs unit tests. It also performs + [static analysis](../CONTRIBUTING.md#code-formatting-style) with \. +- Building tests with CMake (`build_test_cmake.yml`) and Makefile (`build_test_makefile.yml`): This + action builds ABACUS with each feature separately, ensuring: (i) there are no conflicts between + features, (ii) the compilation is successful whether the feature is enabled, and (iii) it works + well on multiple platforms, i.e. with GNU+OpenBLAS toolchain and Intel+MKL toolchain. +- [Rerender the docs site](https://readthedocs.org/projects/abacus-rtd/builds/): This action + rerenders the documentation site on Read the Docs. It is automatically triggered when the + documentation is updated. +- Testing GPU features (`cuda.yml`): This action builds ABACUS with GPU support and runs several + tests on the GPU. + +> Some tests are executed on self-hosted runners, which are maintained by the deepmodeling +> community. To save resources, the actions triggered by new commits may cancel the previous actions +> in the same PR. ## On PR Merge After the PR merges into the main branch, the following actions are triggered: -- Building Docker images (`devcontainer.yml`): This action builds the Docker images with latest codes and executables. The images are tagged as `abacus-gnu:latest`, `abacus-intel:latest`, and `abacus-cuda:latest`, and then pushed to the GitHub Container Registry (`ghcr.io/deepmodeling`) and AliCloud Container Registry (`registry.dp.tech/deepmodeling`, recommended for one having issue connecting to GitHub). For example: `docker pull ghcr.io/deepmodeling/abacus-intel:latest`. -- Generate doxygen site (`doxygen.yml`): This action generates the Doxygen site for the project. The site is published on [GitHub Pages](https://deepmodeling.github.io/abacus-develop/). -- Mirror the repo to Gitee (`mirror.yml`): This action mirrors the repo to [Gitee](https://gitee.com/deepmodeling/abacus-develop). +- Building Docker images (`devcontainer.yml`): This action builds the Docker images with latest + codes and executables. The images are tagged as `abacus-gnu:latest`, `abacus-intel:latest`, and + `abacus-cuda:latest`, and then pushed to the GitHub Container Registry (`ghcr.io/deepmodeling`) + and AliCloud Container Registry (`registry.dp.tech/deepmodeling`, recommended for one having issue + connecting to GitHub). For example: `docker pull ghcr.io/deepmodeling/abacus-intel:latest`. +- Generate doxygen site (`doxygen.yml`): This action generates the Doxygen site for the project. The + site is published on [GitHub Pages](https://deepmodeling.github.io/abacus-develop/). +- Mirror the repo to Gitee (`mirror.yml`): This action mirrors the repo to + [Gitee](https://gitee.com/deepmodeling/abacus-develop). ## On Routine -- Dynamic analysis (`dynamic_analysis.yml`): This action runs integration tests with [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) to detect memory errors. The action is scheduled to run **every Sunday**. The results are published to [the dashboard branch](https://github.com/deepmodeling/abacus-develop/blob/dashboard/README.md). +- Dynamic analysis (`dynamic_analysis.yml`): This action runs integration tests with + [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) to detect memory + errors. The action is scheduled to run **every Sunday**. The results are published to + [the dashboard branch](https://github.com/deepmodeling/abacus-develop/blob/dashboard/README.md). ## On Release -- Coverage test (`coverage.yml`): This action builds ABACUS with all available features, runs integration tests, and runs unit tests. It also measures the code coverage of the tests. The results are published at [codecov.io](https://app.codecov.io/gh/deepmodeling/abacus-develop). -- Building tagged Docker images (`devcontainer.yml`): Same as that action above; in addition the built image is tagged in the pattern of `abacus-intel:3.6.0`. For example: `docker pull ghcr.io/deepmodeling/abacus-intel:3.6.0`. +- Coverage test (`coverage.yml`): This action builds ABACUS with all available features, runs + integration tests, and runs unit tests. It also measures the code coverage of the tests. The + results are published at [codecov.io](https://app.codecov.io/gh/deepmodeling/abacus-develop). +- Building tagged Docker images (`devcontainer.yml`): Same as that action above; in addition the + built image is tagged in the pattern of `abacus-intel:3.6.0`. For example: + `docker pull ghcr.io/deepmodeling/abacus-intel:3.6.0`. diff --git a/docs/community/contribution_guide.md b/docs/community/contribution_guide.md index f64d7d8eb8d..cf887abd17a 100644 --- a/docs/community/contribution_guide.md +++ b/docs/community/contribution_guide.md @@ -2,15 +2,25 @@ ## Contribution Process -We welcome contributions from the open source community. The technical guide is provided in [Contributing to ABACUS](../CONTRIBUTING.md). Here is the basic contribution process: +We welcome contributions from the open source community. The technical guide is provided in +[Contributing to ABACUS](../CONTRIBUTING.md). Here is the basic contribution process: -- **Find out issues to work on.** -We assume you already have a good idea on what to do, otherwise the [issue tracker](https://github.com/deepmodeling/abacus-develop/issues) and [discussion](https://github.com/deepmodeling/abacus-develop/discussions) panel provide good starting points to find out what to work on and to get familiar with the project. +- **Find out issues to work on.** We assume you already have a good idea on what to do, otherwise + the [issue tracker](https://github.com/deepmodeling/abacus-develop/issues) and + [discussion](https://github.com/deepmodeling/abacus-develop/discussions) panel provide good + starting points to find out what to work on and to get familiar with the project. -- **Approach the issue.** -It is suggested to [submit new issues](https://github.com/deepmodeling/abacus-develop/issues/new/choose) before coding out changes to involve more discussions and suggestions from development team. Refer to the technical guide in [Contributing to ABACUS](../CONTRIBUTING.md) when needed. +- **Approach the issue.** It is suggested to + [submit new issues](https://github.com/deepmodeling/abacus-develop/issues/new/choose) before + coding out changes to involve more discussions and suggestions from development team. Refer to the + technical guide in [Contributing to ABACUS](../CONTRIBUTING.md) when needed. -- **Open a pull request.** The ABACUS developers review the pull request (PR) list regularly. If the work is not ready, convert it to draft until finished, then you can mark it as "Ready for review". It is suggested to open a new PR through forking a repo and creating a new branch on you Github account. A new PR should include as much information as possible in `description` when submmited. Unittests or CI tests are required for new PRs. +- **Open a pull request.** The ABACUS developers review the pull request (PR) list regularly. If the + work is not ready, convert it to draft until finished, then you can mark it as "Ready for review". + It is suggested to open a new PR through forking a repo and creating a new branch on you Github + account. A new PR should include as much information as possible in `description` when submmited. + Unittests or CI tests are required for new PRs. -- **Iterate the pull request.** -All pull requests need to be tested through CI before reviewing. A pull request might need to be iterated several times before accepted, so splitting a long PR into parts reduces reviewing difficulty for us. +- **Iterate the pull request.** All pull requests need to be tested through CI before reviewing. A + pull request might need to be iterated several times before accepted, so splitting a long PR into + parts reduces reviewing difficulty for us. diff --git a/docs/community/faq.md b/docs/community/faq.md index 1e372a180d5..6235207cc30 100644 --- a/docs/community/faq.md +++ b/docs/community/faq.md @@ -10,13 +10,16 @@ **1. What are the merits of ABACUS in respect of functionality, performance, and/or accuracy?** -Users are referred to the introduction of features of ABACUS in the [feature list](http://abacus.ustc.edu.cn/features/list.htm). +Users are referred to the introduction of features of ABACUS in the +[feature list](http://abacus.ustc.edu.cn/features/list.htm). **2. How to contact the ABACUS community?** -Users can contact the ABACUS community by join ABACUS WeChat or QQ group. One can quickly join the QQ group via group ID: 759914681 +Users can contact the ABACUS community by join ABACUS WeChat or QQ group. One can quickly join the +QQ group via group ID: 759914681 -If users have any questions or suggestions, please feel free to contact us in group or by raising issue in GitHub repo. +If users have any questions or suggestions, please feel free to contact us in group or by raising +issue in GitHub repo. ## Installation @@ -24,63 +27,97 @@ If users have any questions or suggestions, please feel free to contact us in gr **1. Why pseudopotential files must be provided in LCAO calculation?** -The pseudopotentials are used to approximate the potential of nuclear and core electrons, while the numerical orbitals are basis sets used to expand the Hamiltonian. So both pseudopotential and numerical orbital files are needed in LCAO calculation. +The pseudopotentials are used to approximate the potential of nuclear and core electrons, while the +numerical orbitals are basis sets used to expand the Hamiltonian. So both pseudopotential and +numerical orbital files are needed in LCAO calculation. **2. What is the correlation between pseudopotential and numerical orbital files?** -The numerical orbital files are generated for a specific pseudopotential. So the right numerical orbital files must be chosen for a specific pseudopotential. We suggest users choose numerical orbital files and the corresponding pseudopotential files from the [ABACUS website](http://abacus.ustc.edu.cn/pseudo/list.htm) because their accuracy has been tested. However, interesting users may also generate their own numerical orbitals for a specific type of pseudopential by using the tools provided in the [abacus-develop/tools](https://github.com/deepmodeling/abacus-develop/tree/develop/tools) directory. +The numerical orbital files are generated for a specific pseudopotential. So the right numerical +orbital files must be chosen for a specific pseudopotential. We suggest users choose numerical +orbital files and the corresponding pseudopotential files from the +[ABACUS website](http://abacus.ustc.edu.cn/pseudo/list.htm) because their accuracy has been tested. +However, interesting users may also generate their own numerical orbitals for a specific type of +pseudopential by using the tools provided in the +[abacus-develop/tools](https://github.com/deepmodeling/abacus-develop/tree/develop/tools) directory. -**3. How to set `ecutwfc` in LCAO calculation? Must it be 100 Ry for a numerical orbital file like `Cu_lda_7.0au_100Ry_2s2p2d`?** +**3. How to set `ecutwfc` in LCAO calculation? Must it be 100 Ry for a numerical orbital file like +`Cu_lda_7.0au_100Ry_2s2p2d`?** -It is recommended to set `ecutwfc` to the value that the numerical orbital file suggests, but it is not a must. The `ecutwfc` value only affects the number of FFT grids. +It is recommended to set `ecutwfc` to the value that the numerical orbital file suggests, but it is +not a must. The `ecutwfc` value only affects the number of FFT grids. **4. Does ABACUS support LCAO calculations accounting for external electric field effects?** -Yes, users are referred to documentation on [external electric field](../advanced/scf/advanced.md#external-electric-field). +Yes, users are referred to documentation on +[external electric field](../advanced/scf/advanced.md#external-electric-field). **5. Can ABACUS calculate non-periodic systems, such as ionic liquids?** -Non-periodic systems such as liquid systems can be calculated by using supercell and gamma-only calculation. +Non-periodic systems such as liquid systems can be calculated by using supercell and gamma-only +calculation. **6. How to perform spin-orbital coupling (SOC) calculations in ABACUS?** To perform SOC calculations in ABACUS, follow these steps: 1. **Set `lspinorb=1` in the INPUT file**: This enables spin-orbit coupling effects -2. **Use full-relativistic pseudopotentials**: SOC calculations require pseudopotentials with `has_so=true` in the UPF header - - Download full-relativistic versions of SG15_ONCV pseudopotentials from [quantum-simulation.org](http://quantum-simulation.org/potentials/sg15_oncv/upf/) +1. **Use full-relativistic pseudopotentials**: SOC calculations require pseudopotentials with + `has_so=true` in the UPF header + - Download full-relativistic versions of SG15_ONCV pseudopotentials from + [quantum-simulation.org](http://quantum-simulation.org/potentials/sg15_oncv/upf/) - Check the UPF file header for `relativistic="full"` and `has_so="T"` -3. **Verify automatic settings**: When `lspinorb=1` is set, `nspin` is automatically set to 4 and symmetry is automatically disabled +1. **Verify automatic settings**: When `lspinorb=1` is set, `nspin` is automatically set to 4 and + symmetry is automatically disabled -**Basis set support**: Both `basis_type=pw` (plane wave) and `basis_type=lcao` (numerical atomic orbitals) support SOC calculations for both SCF and NSCF. +**Basis set support**: Both `basis_type=pw` (plane wave) and `basis_type=lcao` (numerical atomic +orbitals) support SOC calculations for both SCF and NSCF. -**Force and stress calculations**: Atomic forces and cell stresses can be calculated with SOC (supported since ABACUS v3.9.0). +**Force and stress calculations**: Atomic forces and cell stresses can be calculated with SOC +(supported since ABACUS v3.9.0). -**Numerical atomic orbitals**: The numerical orbital files generated from scalar-relativistic pseudopotentials (available at [abacus.ustc.edu.cn](http://abacus.ustc.edu.cn/pseudo/list.htm)) can be used with full-relativistic pseudopotentials, as orbitals are spin-independent. +**Numerical atomic orbitals**: The numerical orbital files generated from scalar-relativistic +pseudopotentials (available at [abacus.ustc.edu.cn](http://abacus.ustc.edu.cn/pseudo/list.htm)) can +be used with full-relativistic pseudopotentials, as orbitals are spin-independent. -**Common error**: If you see "no soc upf used for lspinorb calculation", ensure you are using full-relativistic pseudopotentials with `has_so=true`. +**Common error**: If you see "no soc upf used for lspinorb calculation", ensure you are using +full-relativistic pseudopotentials with `has_so=true`. -For detailed information, examples, and troubleshooting, see [Spin-polarization and SOC](../advanced/scf/spin.md#soc-effects). +For detailed information, examples, and troubleshooting, see +[Spin-polarization and SOC](../advanced/scf/spin.md#soc-effects). **7. How to restart jobs in abacus?** -For restarting SCF calculations, users are referred to the documentation about [continuation of job](../advanced/scf/spin.md#for-the-continuation-job). For restarting MD calculations, please see [md_restart](../advanced/input_files/input-main.md#md_restart). +For restarting SCF calculations, users are referred to the documentation about +[continuation of job](../advanced/scf/spin.md#for-the-continuation-job). For restarting MD +calculations, please see [md_restart](../advanced/input_files/input-main.md#md_restart). -**8. Can DeePKS model be used for structural optimization calculation? What parameters need to be modified or called?** +**8. Can DeePKS model be used for structural optimization calculation? What parameters need to be +modified or called?** -If you train the DeePKS model with force labels, then the DeePKS model can provide force calculation with the same accuracy as your target method, and can thus be used for structural optimization. To do that, you just need to train the model with force label enabled. +If you train the DeePKS model with force labels, then the DeePKS model can provide force calculation +with the same accuracy as your target method, and can thus be used for structural optimization. To +do that, you just need to train the model with force label enabled. **9. How to estimate the max memory consumption?** -Run `/usr/bin/time -v mpirun -n 4 abacus`, and locate "Maximum resident set size" in the output log at the end. Please note that this value is the peak memory size of the main MPI process. +Run `/usr/bin/time -v mpirun -n 4 abacus`, and locate "Maximum resident set size" in the output log +at the end. Please note that this value is the peak memory size of the main MPI process. **10. Why there are two sigma (smearing_sigma and dos_sigma) in some examples for dos calculation?** - The tag `smearing_sigma` is used for SCF calculation, and does not affect NSCF calculation. The tag `dos_smearing` is only used for plotting density of states, which does affect SCF or NSCF results. So `smearing_sigma` should not be set in dos calculation. +The tag `smearing_sigma` is used for SCF calculation, and does not affect NSCF calculation. The tag +`dos_smearing` is only used for plotting density of states, which does affect SCF or NSCF results. +So `smearing_sigma` should not be set in dos calculation. -**11. How to set `nbands` and `ncpus`?** +**11. How to set `nbands` and `ncpus`?** -For both pw and LCAO calculations, the default value for `nbands` can be found [here](https://abacus.deepmodeling.com/en/latest/advanced/input_files/input-main.html#nbands). Note that the number of CPUs called for a parallel job (i.e., the number specified after the command `mpirun -n`) should be smaller than `nbands`, otherwise the job will fail with an error message `nbands < ncpus`. Note also that for LCAO calculations, `nbands` should always be smaller than `nlocal`, i.e., the number of the atomic orbital basis of the system. +For both pw and LCAO calculations, the default value for `nbands` can be found +[here](https://abacus.deepmodeling.com/en/latest/advanced/input_files/input-main.html#nbands). Note +that the number of CPUs called for a parallel job (i.e., the number specified after the command +`mpirun -n`) should be smaller than `nbands`, otherwise the job will fail with an error message +`nbands < ncpus`. Note also that for LCAO calculations, `nbands` should always be smaller than +`nlocal`, i.e., the number of the atomic orbital basis of the system. [back to top](#frequently-asked-questions) @@ -88,22 +125,37 @@ For both pw and LCAO calculations, the default value for `nbands` can be found [ **1. Why my calculation is pend by using mpirun?** -This is usually caused by overloading of CPUs' memory without specifying thread numbers. ABACUS detects available hardware threads, and provides these information at the beginning of the program if used threads mismatches with hardware availability. User should keep total used threads(i.e. the number of OpenMP threads times the number of MPI processes) no more than the count of available CPUs(can be determined by `lscpu`). Setting `export OMP_NUM_THREADS=1` will solve this problem, or one can use the command like `OMP_NUM_THREADS=1 mpirun -n 8 abacus` to rerun failed jobs. +This is usually caused by overloading of CPUs' memory without specifying thread numbers. ABACUS +detects available hardware threads, and provides these information at the beginning of the program +if used threads mismatches with hardware availability. User should keep total used threads(i.e. the +number of OpenMP threads times the number of MPI processes) no more than the count of available +CPUs(can be determined by `lscpu`). Setting `export OMP_NUM_THREADS=1` will solve this problem, or +one can use the command like `OMP_NUM_THREADS=1 mpirun -n 8 abacus` to rerun failed jobs. **2. My relaxation failed. How to deal with it?** -This is usually caused by the difficulty in converging charge density. Reducing charge mixing coefficient (`mixing_beta`) might help. For large systems up to hundreds of atoms, it is suggested to choose the Kerker mixing method by setting parameter "mixing_gg0" as "1.0". +This is usually caused by the difficulty in converging charge density. Reducing charge mixing +coefficient (`mixing_beta`) might help. For large systems up to hundreds of atoms, it is suggested +to choose the Kerker mixing method by setting parameter "mixing_gg0" as "1.0". -Sometimes, loose convergence threshold of charge density (parameter "scf_thr") will cause atomic forces not correctly enough, please set it at most "1e-7" for relaxation calculation. +Sometimes, loose convergence threshold of charge density (parameter "scf_thr") will cause atomic +forces not correctly enough, please set it at most "1e-7" for relaxation calculation. **3. Why the program is halted?** -If the program prompt something like "KILLED BY SIGNAL: 9 (Killed)", it may be caused by insufficient memory. You can use `dmesg` to print out system info regarding memory management, and check if there is "Out of memory: Killed" at the end of output info. Please try using less processes and threads for calculation, or modify the input parameters requiring less memory. +If the program prompt something like "KILLED BY SIGNAL: 9 (Killed)", it may be caused by +insufficient memory. You can use `dmesg` to print out system info regarding memory management, and +check if there is "Out of memory: Killed" at the end of output info. Please try using less processes +and threads for calculation, or modify the input parameters requiring less memory. -If the error message is "Segmentation fault", or there is no enough information on the error, please feel free to submit an issue. +If the error message is "Segmentation fault", or there is no enough information on the error, please +feel free to submit an issue. + +**4. Error "Read -1" when using mpirun in docker environment** This is a +[known issue](https://github.com/open-mpi/ompi/issues/4948) of OpenMPI running in a docker +container. In this case, please set environment variable +`OMPI_MCA_btl_vader_single_copy_mechanism=none`. -**4. Error "Read -1" when using mpirun in docker environment** -This is a [known issue](https://github.com/open-mpi/ompi/issues/4948) of OpenMPI running in a docker container. In this case, please set environment variable `OMPI_MCA_btl_vader_single_copy_mechanism=none`. ## Miscellaneous **1. How to visualize charge density file?** @@ -112,7 +164,9 @@ The output file SPIN1_CHG.cube can be visualized by using VESTA. **2. How to change cif file directly to STRU file?** -One way to change from cif to STRU is to use the [ASE-ABACUS](https://gitlab.com/1041176461/ase-abacus) interface. An example of the converting script is provided below: +One way to change from cif to STRU is to use the +[ASE-ABACUS](https://gitlab.com/1041176461/ase-abacus) interface. An example of the converting +script is provided below: ```python from ase.io import read, write @@ -129,10 +183,16 @@ write(cs_stru, cs_atoms, format='abacus', pp=pp, basis=basis) **3. What is the convergence criterion for the SCF process in ABACUS?** -ABACUS applies the density difference between two SCF steps (labeled as `DRHO` in the screen output) as the convergence criterion, which is considered as a more robust choice compared with the energy difference. `DRHO` is calculated via `DRHO = |rho(G)-rho_previous(G)|^2`. Note that the energy difference between two SCF steps (labed as `EDIFF`) is also printed out in the screen output. +ABACUS applies the density difference between two SCF steps (labeled as `DRHO` in the screen output) +as the convergence criterion, which is considered as a more robust choice compared with the energy +difference. `DRHO` is calculated via `DRHO = |rho(G)-rho_previous(G)|^2`. Note that the energy +difference between two SCF steps (labed as `EDIFF`) is also printed out in the screen output. **4. Why EDIFF is much slower than DRHO?** -For metaGGA calculations, it is normal because in addition to charge density, kinetic density also needs to be considered in metaGGA calculations. In this case, you can try set `mixing_tau = true`. If you find EDIFF is much slower than DRHO for non-metaGGA calculations, please start a new issue to us. +For metaGGA calculations, it is normal because in addition to charge density, kinetic density also +needs to be considered in metaGGA calculations. In this case, you can try set `mixing_tau = true`. +If you find EDIFF is much slower than DRHO for non-metaGGA calculations, please start a new issue to +us. [back to top](#frequently-asked-questions) diff --git a/docs/conf.py b/docs/conf.py index bf96df8cb7b..cb1b09f7013 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,9 +17,9 @@ # -- Project information ----------------------------------------------------- -project = 'ABACUS' -copyright = '2024, ABACUS' -author = 'ABACUS' +project = "ABACUS" +copyright = "2024, ABACUS" +author = "ABACUS" # The full version, including alpha/beta/rc tags # release = '2.3.5' @@ -31,8 +31,8 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'myst_parser', - 'deepmodeling_sphinx', + "myst_parser", + "deepmodeling_sphinx", ] myst_enable_extensions = [ "amsmath", @@ -52,7 +52,7 @@ myst_heading_anchors = 4 # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -65,8 +65,8 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_book_theme' -html_logo = 'abacus-logo.svg' +html_theme = "sphinx_book_theme" +html_logo = "abacus-logo.svg" # Theme options for sphinx-book-theme html_theme_options = { @@ -91,20 +91,21 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] -latex_engine = 'xelatex' -mathjax_path = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.min.js' +latex_engine = "xelatex" +mathjax_path = ( + "https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.min.js" +) # deepmodeling_current_site = 'Tutorials' -latex_elements = { - 'extraclassoptions':'openany,oneside' -} +latex_elements = {"extraclassoptions": "openany,oneside"} # -- Auto-generate INPUT keyword documentation from YAML parameter dump ------ from pathlib import Path + def generate_input_docs(app): """Auto-generate input-main.md from parameters.yaml before building. @@ -113,18 +114,23 @@ def generate_input_docs(app): # Then Sphinx calls this hook, which runs generate_input_main.py """ docs_dir = Path(__file__).resolve().parent - yaml_path = docs_dir / 'parameters.yaml' + yaml_path = docs_dir / "parameters.yaml" if not yaml_path.exists(): - print(f"Warning: {yaml_path} not found. " - "Run: abacus --generate-parameters-yaml > docs/parameters.yaml") + print( + f"Warning: {yaml_path} not found. " + "Run: abacus --generate-parameters-yaml > docs/parameters.yaml" + ) return import sys + sys.path.insert(0, str(docs_dir)) from generate_input_main import generate + generate( yaml_path=yaml_path, - output=docs_dir / 'advanced' / 'input_files' / 'input-main.md', + output=docs_dir / "advanced" / "input_files" / "input-main.md", ) + def setup(app): - app.connect('builder-inited', generate_input_docs) + app.connect("builder-inited", generate_input_docs) diff --git a/docs/developers_guide/basic_types_class.md b/docs/developers_guide/basic_types_class.md index c582665e96c..56b74a4e506 100644 --- a/docs/developers_guide/basic_types_class.md +++ b/docs/developers_guide/basic_types_class.md @@ -2,7 +2,9 @@ ## Overview -This document provides guidelines for designing and implementing basic tool classes in the ABACUS codebase, focusing on best practices for memory management, code style, and testing. These guidelines apply to all basic mathematical and utility classes, including but not limited to: +This document provides guidelines for designing and implementing basic tool classes in the ABACUS +codebase, focusing on best practices for memory management, code style, and testing. These +guidelines apply to all basic mathematical and utility classes, including but not limited to: - vector3.h - matrix.h @@ -16,7 +18,8 @@ This document provides guidelines for designing and implementing basic tool clas - formatter.h - math_chebyshev.h -While this guide uses `IntArray` as an example for illustration purposes, the principles and practices described here are applicable to all basic tool classes in ABACUS. +While this guide uses `IntArray` as an example for illustration purposes, the principles and +practices described here are applicable to all basic tool classes in ABACUS. ## Memory Management @@ -26,11 +29,13 @@ Always use try-catch blocks when allocating memory to handle `std::bad_alloc` ex ### 2. Two-Stage Memory Allocation -When reallocating memory (e.g., in `create` methods), use a two-stage approach to ensure that the original object remains valid if memory allocation fails. +When reallocating memory (e.g., in `create` methods), use a two-stage approach to ensure that the +original object remains valid if memory allocation fails. ### 3. Null Pointer Checks -Always check for null pointers before accessing memory, especially in methods that might be called on objects with failed memory allocation. +Always check for null pointers before accessing memory, especially in methods that might be called +on objects with failed memory allocation. ## Class Design @@ -50,7 +55,8 @@ Add boundary checks to prevent out-of-bounds access. ### 1. Brace Style -Use separate lines for braces, and always use braces for "if" and "for" statements, even if they contain one line of code +Use separate lines for braces, and always use braces for "if" and "for" statements, even if they +contain one line of code ### 2. Indentation @@ -58,7 +64,8 @@ Use spaces instead of tabs for indentation (4 spaces per indent level). ### 3. Comments -Use English for comments and document important functionality. Follow Doxygen-style documentation for classes and methods. +Use English for comments and document important functionality. Follow Doxygen-style documentation +for classes and methods. ## Code Quality @@ -79,6 +86,7 @@ Ensure all necessary header files are included, especially for functions like `a ### 1. Unit Tests Write comprehensive unit tests for all classes, including: + - Constructor tests - Method tests - Exception handling tests @@ -107,34 +115,42 @@ protected: ## Best Practices -1. **Single Responsibility Principle**: Each class should have a single, well-defined responsibility. -2. **Encapsulation**: Hide implementation details and expose only necessary interfaces. -3. **Error Handling**: Handle errors gracefully, especially memory allocation failures. -4. **Performance**: Use move semantics and other performance optimizations where appropriate. -5. **Testing**: Write comprehensive tests for all functionality. -6. **Code Style**: Follow consistent code style guidelines, including: +1. **Single Responsibility Principle**: Each class should have a single, well-defined + responsibility. +1. **Encapsulation**: Hide implementation details and expose only necessary interfaces. +1. **Error Handling**: Handle errors gracefully, especially memory allocation failures. +1. **Performance**: Use move semantics and other performance optimizations where appropriate. +1. **Testing**: Write comprehensive tests for all functionality. +1. **Code Style**: Follow consistent code style guidelines, including: - Always use braces for if and for statements - Use separate lines for braces - Use spaces instead of tabs for indentation - Use English for comments -7. **Code Quality**: Maintain high code quality by: +1. **Code Quality**: Maintain high code quality by: - Using named constants instead of magic numbers - Ensuring all necessary header files are included - Adding boundary checks to prevent out-of-bounds access -8. **Documentation**: Document classes and methods to improve maintainability. -9. **Compatibility**: Ensure code is compatible with C++11 standard. -10. **Portability**: Write code that works across different platforms. -11. **Reusability**: Design classes to be reusable in different contexts. +1. **Documentation**: Document classes and methods to improve maintainability. +1. **Compatibility**: Ensure code is compatible with C++11 standard. +1. **Portability**: Write code that works across different platforms. +1. **Reusability**: Design classes to be reusable in different contexts. ## Application to Other Basic Tool Classes -While this guide uses `IntArray` as an example, these principles apply to all basic tool classes in ABACUS. For example: +While this guide uses `IntArray` as an example, these principles apply to all basic tool classes in +ABACUS. For example: -- **vector3.h**: Apply the same memory management and error handling principles, with additional focus on vector operations and operator overloading. -- **matrix.h**: Extend the memory management practices to 2D arrays, with additional considerations for matrix operations. +- **vector3.h**: Apply the same memory management and error handling principles, with additional + focus on vector operations and operator overloading. +- **matrix.h**: Extend the memory management practices to 2D arrays, with additional considerations + for matrix operations. - **timer.h**: Focus on static member management and time measurement accuracy. -- **ndarray.h**: Apply the same principles to multi-dimensional arrays, with additional considerations for shape manipulation. -- **formatter.h**: Focus on string manipulation and formatting, with attention to performance and usability. -- **math_chebyshev.h**: Apply the principles to template classes, with additional focus on mathematical algorithm implementation. - -By following these guidelines, you can ensure that all basic tool classes in ABACUS are well-designed, robust, and maintainable. +- **ndarray.h**: Apply the same principles to multi-dimensional arrays, with additional + considerations for shape manipulation. +- **formatter.h**: Focus on string manipulation and formatting, with attention to performance and + usability. +- **math_chebyshev.h**: Apply the principles to template classes, with additional focus on + mathematical algorithm implementation. + +By following these guidelines, you can ensure that all basic tool classes in ABACUS are +well-designed, robust, and maintainable. diff --git a/docs/generate_input_main.py b/docs/generate_input_main.py index 16a9e398bbe..e64b2c5e6e6 100644 --- a/docs/generate_input_main.py +++ b/docs/generate_input_main.py @@ -75,7 +75,7 @@ def normalize_type(type_text: str) -> str: Normalize legacy type labels for cleaner generated docs. """ if not type_text: - return '' + return "" normalized = type_text.strip() aliases = { @@ -90,9 +90,9 @@ def escape_md_text(text: str) -> str: Escape markdown-sensitive angle brackets while avoiding double escaping. """ if text is None: - return '' + return "" normalized = html.unescape(str(text)) - return normalized.replace('<', '<').replace('>', '>') + return normalized.replace("<", "<").replace(">", ">") def format_description(desc: str) -> str: @@ -103,40 +103,40 @@ def format_description(desc: str) -> str: - Convert [WARNING] markers to blockquotes """ if not desc: - return '' + return "" # Prevent placeholder tokens like from being parsed as raw HTML # and breaking list/heading structure in rendered docs. desc = escape_md_text(desc) - lines = desc.split('\n') + lines = desc.split("\n") result_lines = [] for line in lines: # Convert * list items to - list items - line = re.sub(r'^(\s*)\*\s+', r'\1- ', line) + line = re.sub(r"^(\s*)\*\s+", r"\1- ", line) # Convert [NOTE] markers to blockquotes - if '[NOTE]' in line: - line = line.replace('[NOTE]', '> Note:') + if "[NOTE]" in line: + line = line.replace("[NOTE]", "> Note:") # Convert [WARNING] markers to blockquotes - if '[WARNING]' in line: - line = line.replace('[WARNING]', '> Warning:') + if "[WARNING]" in line: + line = line.replace("[WARNING]", "> Warning:") # Normalize doubled note/warning prefixes from legacy content - line = re.sub(r'>\s*Note:\s*Note\s*:?\s*', '> Note: ', line) - line = re.sub(r'>\s*Warning:\s*Warning\s*:?\s*', '> Warning: ', line) + line = re.sub(r">\s*Note:\s*Note\s*:?\s*", "> Note: ", line) + line = re.sub(r">\s*Warning:\s*Warning\s*:?\s*", "> Warning: ", line) result_lines.append(line) # Join and clean up - result = '\n'.join(result_lines) + result = "\n".join(result_lines) # Ensure list items have proper indentation (2 spaces for sub-items in markdown) - result = re.sub(r'\n- ', '\n - ', result) + result = re.sub(r"\n- ", "\n - ", result) # But not for the first item after a non-list line - result = re.sub(r'(\n[^-\s][^\n]*)\n - ', r'\1\n\n - ', result) + result = re.sub(r"(\n[^-\s][^\n]*)\n - ", r"\1\n\n - ", result) return result.strip() @@ -148,41 +148,41 @@ def generate_parameter_markdown(param: Dict[str, str]) -> str: lines = [f"### {param['name']}", ""] # Type - if param.get('type', '') != '': - type_text = escape_md_text(normalize_type(str(param['type']))) + if param.get("type", "") != "": + type_text = escape_md_text(normalize_type(str(param["type"]))) lines.append(f"- **Type**: {type_text}") # Availability (before description, as in original format) - if param.get('availability', '') != '': - availability_text = escape_md_text(str(param['availability'])) + if param.get("availability", "") != "": + availability_text = escape_md_text(str(param["availability"])) lines.append(f"- **Availability**: *{availability_text}*") # Description - if param.get('description', '') != '': - desc = format_description(str(param['description'])) + if param.get("description", "") != "": + desc = format_description(str(param["description"])) # If description has multiple lines/lists, format properly - if '\n' in desc: + if "\n" in desc: lines.append(f"- **Description**: {desc.split(chr(10))[0]}") - for line in desc.split('\n')[1:]: + for line in desc.split("\n")[1:]: if line.strip(): - lines.append(f" {line}" if not line.startswith(' ') else line) + lines.append(f" {line}" if not line.startswith(" ") else line) else: lines.append("") else: lines.append(f"- **Description**: {desc}") # Default - if param.get('default_value', '') != '': - default_text = escape_md_text(str(param['default_value'])) + if param.get("default_value", "") != "": + default_text = escape_md_text(str(param["default_value"])) lines.append(f"- **Default**: {default_text}") # Unit - if param.get('unit', '') != '': - unit_text = escape_md_text(str(param['unit'])) + if param.get("unit", "") != "": + unit_text = escape_md_text(str(param["unit"])) lines.append(f"- **Unit**: {unit_text}") lines.append("") - return '\n'.join(lines) + return "\n".join(lines) def generate_category_markdown(category: str, params: List[Dict[str, str]]) -> str: @@ -198,7 +198,7 @@ def generate_category_markdown(category: str, params: List[Dict[str, str]]) -> s lines.append("[back to top](#full-list-of-input-keywords)") lines.append("") - return '\n'.join(lines) + return "\n".join(lines) def generate_anchor(text: str) -> str: @@ -207,10 +207,10 @@ def generate_anchor(text: str) -> str: Converts to lowercase, replaces spaces with hyphens, removes special chars. """ anchor = text.lower() - anchor = re.sub(r'[^a-z0-9\s_-]', '', anchor) - anchor = re.sub(r'\s+', '-', anchor) - anchor = re.sub(r'-+', '-', anchor) - return anchor.strip('-') + anchor = re.sub(r"[^a-z0-9\s_-]", "", anchor) + anchor = re.sub(r"\s+", "-", anchor) + anchor = re.sub(r"-+", "-", anchor) + return anchor.strip("-") def generate_toc(sorted_categories: OrderedDict) -> str: @@ -225,11 +225,11 @@ def generate_toc(sorted_categories: OrderedDict) -> str: for param in params: # Escape underscores in parameter names for TOC display - display_name = param['name'].replace('_', r'\_') - param_anchor = generate_anchor(param['name']) + display_name = param["name"].replace("_", r"\_") + param_anchor = generate_anchor(param["name"]) lines.append(f" - [{display_name}](#{param_anchor})") - return '\n'.join(lines) + return "\n".join(lines) def generate(yaml_path: Path, output: Path, verbose: bool = False): @@ -242,16 +242,16 @@ def generate(yaml_path: Path, output: Path, verbose: bool = False): if not yaml_path.exists(): raise FileNotFoundError(f"YAML file not found: {yaml_path}") - with open(yaml_path, 'r') as f: + with open(yaml_path, "r") as f: data = yaml.safe_load(f) - all_params = data.get('parameters', []) + all_params = data.get("parameters", []) print(f"Total: {len(all_params)} documented parameters") # Group by category by_category: Dict[str, List[Dict[str, str]]] = OrderedDict() for param in all_params: - cat = param.get('category', 'Other') + cat = param.get("category", "Other") if cat not in by_category: by_category[cat] = [] by_category[cat].append(param) @@ -276,7 +276,7 @@ def generate(yaml_path: Path, output: Path, verbose: bool = False): "", "", generate_toc(sorted_categories), - "" + "", ] for category, params in sorted_categories.items(): @@ -285,7 +285,7 @@ def generate(yaml_path: Path, output: Path, verbose: bool = False): md_parts.append(generate_category_markdown(category, params)) # Write output - output_content = '\n'.join(md_parts) + output_content = "\n".join(md_parts) output.parent.mkdir(parents=True, exist_ok=True) output.write_text(output_content) @@ -295,28 +295,26 @@ def generate(yaml_path: Path, output: Path, verbose: bool = False): def main(): parser = argparse.ArgumentParser( - description='Generate input-main.md from YAML parameter dump' + description="Generate input-main.md from YAML parameter dump" ) parser.add_argument( - 'yaml_file', + "yaml_file", type=Path, - help='Path to parameters.yaml (generated by abacus --generate-parameters-yaml)' + help="Path to parameters.yaml (generated by abacus --generate-parameters-yaml)", ) parser.add_argument( - '--output', + "--output", type=Path, - default=Path(f'{DOC_FOLDER}/advanced/input_files/input-main.md'), - help='Output markdown file' + default=Path(f"{DOC_FOLDER}/advanced/input_files/input-main.md"), + help="Output markdown file", ) parser.add_argument( - '--verbose', '-v', - action='store_true', - help='Print verbose output' + "--verbose", "-v", action="store_true", help="Print verbose output" ) args = parser.parse_args() generate(args.yaml_file, args.output, args.verbose) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/docs/quick_start/easy_install.md b/docs/quick_start/easy_install.md index c9c33096691..2516ba776a2 100644 --- a/docs/quick_start/easy_install.md +++ b/docs/quick_start/easy_install.md @@ -1,20 +1,37 @@ # Easy Installation -This guide helps you install ABACUS with basic features. **For DeePKS, DeePMD and Libxc support, or building with `make`, please refer to [the advanced installation guide](../advanced/install.md)** after going through this page. We recommend building ABACUS with `cmake` to avoid dependency issues. We recommend compiling ABACUS (and possibly its requirements) from the source code using the latest compiler for the best performace. You can use [toolchain](#install-by-toolchain) to install ABACUS and dependencies in a source-code compilation way with convience. You can also deploy ABACUS **without building** by [Docker](#container-deployment) or [conda](#install-by-conda). Please note that ABACUS only supports Linux; for Windows users, please consider using [WSL](https://learn.microsoft.com/en-us/windows/wsl/) or docker. For a scripted one-click setup that provisions WSL2 and installs ABACUS inside it automatically, see [Windows One-Click Installer](./advanced/windows_installer.md). +This guide helps you install ABACUS with basic features. **For DeePKS, DeePMD and Libxc support, or +building with `make`, please refer to [the advanced installation guide](../advanced/install.md)** +after going through this page. We recommend building ABACUS with `cmake` to avoid dependency issues. +We recommend compiling ABACUS (and possibly its requirements) from the source code using the latest +compiler for the best performace. You can use [toolchain](#install-by-toolchain) to install ABACUS +and dependencies in a source-code compilation way with convience. You can also deploy ABACUS +**without building** by [Docker](#container-deployment) or [conda](#install-by-conda). Please note +that ABACUS only supports Linux; for Windows users, please consider using +[WSL](https://learn.microsoft.com/en-us/windows/wsl/) or docker. For a scripted one-click setup that +provisions WSL2 and installs ABACUS inside it automatically, see +[Windows One-Click Installer](./advanced/windows_installer.md). ## Get ABACUS source code ABACUS source code can be obtained via one of the following choices: - Clone the whole repo with git: `git clone https://github.com/deepmodeling/abacus-develop.git` -- Clone the minimum required part of repo: `git clone https://github.com/deepmodeling/abacus-develop.git --depth=1` -- Download the latest source code without git: `wget https://github.com/deepmodeling/abacus-develop/archive/refs/heads/develop.zip` -- Get the source code of a stable version [here](https://github.com/deepmodeling/abacus-develop/releases) -- If you have connection issues accessing GitHub, please try out our official [Gitee repo](https://gitee.com/deepmodeling/abacus-develop/): e.g. `git clone https://gitee.com/deepmodeling/abacus-develop.git`. This Gitee repo is updated synchronously with GitHub. +- Clone the minimum required part of repo: + `git clone https://github.com/deepmodeling/abacus-develop.git --depth=1` +- Download the latest source code without git: + `wget https://github.com/deepmodeling/abacus-develop/archive/refs/heads/develop.zip` +- Get the source code of a stable version + [here](https://github.com/deepmodeling/abacus-develop/releases) +- If you have connection issues accessing GitHub, please try out our official + [Gitee repo](https://gitee.com/deepmodeling/abacus-develop/): e.g. + `git clone https://gitee.com/deepmodeling/abacus-develop.git`. This Gitee repo is updated + synchronously with GitHub. ## Update to latest release by git -Please check the [release page](https://github.com/deepmodeling/abacus-develop/releases) for the release note of a new version. +Please check the [release page](https://github.com/deepmodeling/abacus-develop/releases) for the +release note of a new version. It is OK to download the new source code from beginning following the previous step. @@ -32,7 +49,8 @@ git checkout v3.x.x # Replace the tag with the latest version, like v3.10.0 git describe --tags # Verify if the tag has been successfully checked out ``` -Then proceed to the [Build and Install](#build-and-install) part. If you encountered errors, try remove the `build` directory first and reconfigure. +Then proceed to the [Build and Install](#build-and-install) part. If you encountered errors, try +remove the `build` directory first and reconfigure. To use the codes under active development: @@ -46,17 +64,25 @@ git pull To compile ABACUS, please make sure that the following prerequisites are present: - [CMake](https://cmake.org/) >= 3.16 . -- C++ compiler, supporting C++11. You can use [Intel® C++ compiler](https://software.intel.com/enus/c-compilers) or [GCC](https://gcc.gnu.org/). - -> GCC version 5 or later is always required. Intel compilers also use GCC headers and libraries[(ref)](https://www.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-reference/top/compatibility-and-portability/gcc-compatibility-and-interoperability.html#gcc-compatibility-and-interoperability_GUID-52CB6FE0-83DA-4028-9EF4-0DFAF1652736). - -- MPI library. The recommended versions are [Intel MPI](https://software.intel.com/enus/mpi-library), [MPICH](https://www.mpich.org/) or [Open MPI](https://www.open-mpi.org/). -- Fortran compiler if you are building `BLAS`, `LAPACK`, `ScaLAPACK`, and `ELPA` from source file. You can use [Intel® Fortran Compiler](https://www.intel.com/content/www/us/en/developer/tools/oneapi/fortran-compiler.html) or [GFortran](https://gcc.gnu.org/fortran/). +- C++ compiler, supporting C++11. You can use + [Intel® C++ compiler](https://software.intel.com/enus/c-compilers) or [GCC](https://gcc.gnu.org/). + +> GCC version 5 or later is always required. Intel compilers also use GCC headers and +> libraries[(ref)](https://www.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-reference/top/compatibility-and-portability/gcc-compatibility-and-interoperability.html#gcc-compatibility-and-interoperability_GUID-52CB6FE0-83DA-4028-9EF4-0DFAF1652736). + +- MPI library. The recommended versions are + [Intel MPI](https://software.intel.com/enus/mpi-library), [MPICH](https://www.mpich.org/) or + [Open MPI](https://www.open-mpi.org/). +- Fortran compiler if you are building `BLAS`, `LAPACK`, `ScaLAPACK`, and `ELPA` from source file. + You can use + [Intel® Fortran Compiler](https://www.intel.com/content/www/us/en/developer/tools/oneapi/fortran-compiler.html) + or [GFortran](https://gcc.gnu.org/fortran/). - [BLAS](http://www.netlib.org/blas/). You can use [OpenBLAS](https://www.openblas.net/). - [LAPACK](http://www.netlib.org/lapack/). - [FFTW3](http://www.fftw.org/). -These requirements support the calculation of plane-wave basis in ABACUS. For LCAO basis calculation, additional components are required: +These requirements support the calculation of plane-wave basis in ABACUS. For LCAO basis +calculation, additional components are required: - [ScaLAPACK](http://www.netlib.org/scalapack/). - [CEREAL](https://uscilab.github.io/cereal/). @@ -65,16 +91,27 @@ These requirements support the calculation of plane-wave basis in ABACUS. For LC ## Install by toolchain We offer a set of [toolchain](https://github.com/deepmodeling/abacus-develop/tree/develop/toolchain) -scripts to compile and install all the requirements and ABACUS itself -automatically and suitable for machine characteristic in an online or offline way. -The toolchain can be downloaded with ABACUS repo, and users can easily compile the requirements by running *toolchain_[gnu,intel,gcc-aocl,aocc-aocl].sh* and ABACUS itself by running *build_abacus_[gnu,intel,gcc-aocl,aocc-aocl].sh* script in the toolchain directory in `GNU`, `Intel-oneAPI` , `GCC-AMD AOCL` and `AMD AOCC-AOCL` toolchain. -Sometimes, ABACUS by toolchain installation may have better efficient performance due to the suitable compiled dependencies. One should read the [README in toolchain](https://github.com/deepmodeling/abacus-develop/tree/develop/toolchain/README.md) for most of the information before use, and related tutorials can be accessed via ABACUS WeChat platform. +scripts to compile and install all the requirements and ABACUS itself automatically and suitable for +machine characteristic in an online or offline way. The toolchain can be downloaded with ABACUS +repo, and users can easily compile the requirements by running +*toolchain\_[gnu,intel,gcc-aocl,aocc-aocl].sh* and ABACUS itself by running +*build_abacus\_[gnu,intel,gcc-aocl,aocc-aocl].sh* script in the toolchain directory in `GNU`, +`Intel-oneAPI` , `GCC-AMD AOCL` and `AMD AOCC-AOCL` toolchain. Sometimes, ABACUS by toolchain +installation may have better efficient performance due to the suitable compiled dependencies. One +should read the +[README in toolchain](https://github.com/deepmodeling/abacus-develop/tree/develop/toolchain/README.md) +for most of the information before use, and related tutorials can be accessed via ABACUS WeChat +platform. ## Install by conda Conda is a package management system with a separated environment, not requiring system privileges. -You can refer to [DeepModeling conda FAQ](https://docs.deepmodeling.com/faq/conda.html) for how to setup a conda environment. -A pre-built ABACUS binary with all requirements is available at [conda-forge](https://anaconda.org/conda-forge/abacus). It supports advanced features including Libxc, LibRI, and DeePKS. Conda will install the GPU-supported version of ABACUS if a valid GPU driver is present. Please refer to [the advanced installation guide](../advanced/install.md) for more details. +You can refer to [DeepModeling conda FAQ](https://docs.deepmodeling.com/faq/conda.html) for how to +setup a conda environment. A pre-built ABACUS binary with all requirements is available at +[conda-forge](https://anaconda.org/conda-forge/abacus). It supports advanced features including +Libxc, LibRI, and DeePKS. Conda will install the GPU-supported version of ABACUS if a valid GPU +driver is present. Please refer to [the advanced installation guide](../advanced/install.md) for +more details. ```bash # Install @@ -89,13 +126,18 @@ OMP_NUM_THREADS=1 mpirun -n 4 abacus conda update -n abacus_env abacus -c conda-forge ``` -> If OpenBLAS gives warning about OpenMP threads, please install conda package `"openblas=*=openmp*"` or `"libblas=*=*mkl"`. See [switching BLAS implementation in conda](https://conda-forge.org/docs/maintainer/knowledge_base.html#switching-blas-implementation). +> If OpenBLAS gives warning about OpenMP threads, please install conda package +> `"openblas=*=openmp*"` or `"libblas=*=*mkl"`. See +> [switching BLAS implementation in conda](https://conda-forge.org/docs/maintainer/knowledge_base.html#switching-blas-implementation). -> ABACUS supports `OpenMPI` and `MPICH` variant. Install `mpich` or `openmpi` package to switch MPI library if required. +> ABACUS supports `OpenMPI` and `MPICH` variant. Install `mpich` or `openmpi` package to switch MPI +> library if required. -For more details on building a conda package of ABACUS locally, please refer to the [conda recipe file](https://github.com/deepmodeling/abacus-develop/blob/develop/conda/meta.yaml). +For more details on building a conda package of ABACUS locally, please refer to the +[conda recipe file](https://github.com/deepmodeling/abacus-develop/blob/develop/conda/meta.yaml). -> Note: The [deepmodeling conda channel](https://anaconda.org/deepmodeling/abacus) offers historical versions of ABACUS. +> Note: The [deepmodeling conda channel](https://anaconda.org/deepmodeling/abacus) offers historical +> versions of ABACUS. ### Developing with conda @@ -113,30 +155,41 @@ export CMAKE_PREFIX_PATH=`python -c 'import torch;print(torch.utils.cmake_prefix # usually expands to `$CONDA_PREFIX/lib/python3.1/site-packages/torch/share/cmake` ``` -And, follow the instructions in [Build and Install](#build-and-install) part above withou manually setting paths to dependencies. -See [the advanced installation guide](../advanced/install.md) for more features. -Make sure the environment variables are set before running `cmake`. -Possible command: `cmake -B build -DENABLE_MLALGO=ON -DENABLE_LIBXC=ON -DENABLE_LIBRI=ON`. - +And, follow the instructions in [Build and Install](#build-and-install) part above withou manually +setting paths to dependencies. See [the advanced installation guide](../advanced/install.md) for +more features. Make sure the environment variables are set before running `cmake`. Possible command: +`cmake -B build -DENABLE_MLALGO=ON -DENABLE_LIBXC=ON -DENABLE_LIBRI=ON`. ## Install ABACUS manually ### Install requirements -Some of these packages can be installed with popular package management system via root permission if you have, such as `apt` and `yum`: +Some of these packages can be installed with popular package management system via root permission +if you have, such as `apt` and `yum`: ```bash sudo apt update && sudo apt install -y libopenblas-openmp-dev liblapack-dev libscalapack-mpi-dev libelpa-dev libfftw3-dev libcereal-dev libxc-dev g++ make cmake bc git pkgconf ``` -> Installing ELPA by apt only matches requirements on Ubuntu 22.04. For earlier linux distributions, you should build ELPA from source. +> Installing ELPA by apt only matches requirements on Ubuntu 22.04. For earlier linux distributions, +> you should build ELPA from source. -We recommend [Intel® oneAPI toolkit](https://software.intel.com/content/www/us/en/develop/tools/oneapi/commercial-base-hpc.html) (former Intel® Parallel Studio) as toolchain. The [Intel® oneAPI Base Toolkit](https://software.intel.com/content/www/us/en/develop/tools/oneapi/all-toolkits.html#base-kit) contains Intel® oneAPI Math Kernel Library (aka `MKL`), including `BLAS`, `LAPACK`, `ScaLAPACK` and `FFTW3`. The [Intel® oneAPI HPC Toolkit](https://software.intel.com/content/www/us/en/develop/tools/oneapi/all-toolkits.html#hpc-kit) contains Intel® MPI Library, and C++ compiler(including MPI compiler). -> Please note that building `elpa` with a different MPI library may cause conflict. -> Don't forget to [set environment variables](https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-intel-oneapi-render-linux/top/configure-your-system.html) before you start! `cmake` will use Intel MKL if the environment variable `MKLROOT` is set. +We recommend +[Intel® oneAPI toolkit](https://software.intel.com/content/www/us/en/develop/tools/oneapi/commercial-base-hpc.html) +(former Intel® Parallel Studio) as toolchain. The +[Intel® oneAPI Base Toolkit](https://software.intel.com/content/www/us/en/develop/tools/oneapi/all-toolkits.html#base-kit) +contains Intel® oneAPI Math Kernel Library (aka `MKL`), including `BLAS`, `LAPACK`, `ScaLAPACK` and +`FFTW3`. The +[Intel® oneAPI HPC Toolkit](https://software.intel.com/content/www/us/en/develop/tools/oneapi/all-toolkits.html#hpc-kit) +contains Intel® MPI Library, and C++ compiler(including MPI compiler). -Please refer to our [guide](https://github.com/deepmodeling/abacus-develop/wiki/Building-and-Running-ABACUS) on installing requirements. +> Please note that building `elpa` with a different MPI library may cause conflict. Don't forget to +> [set environment variables](https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-intel-oneapi-render-linux/top/configure-your-system.html) +> before you start! `cmake` will use Intel MKL if the environment variable `MKLROOT` is set. +Please refer to our +[guide](https://github.com/deepmodeling/abacus-develop/wiki/Building-and-Running-ABACUS) on +installing requirements. ### Configure @@ -147,37 +200,80 @@ cd abacus-develop cmake -B build [-D =] ... ``` -Here, 'build' is the path for building ABACUS; and '-D' is used for setting up some variables for CMake indicating optional components or requirement positions. +Here, 'build' is the path for building ABACUS; and '-D' is used for setting up some variables for +CMake indicating optional components or requirement positions. - `CMAKE_INSTALL_PREFIX`: the path of ABACUS binary to install; `/usr/local/bin/abacus` by default + - Compilers - - `CMAKE_CXX_COMPILER`: C++ compiler; usually `g++`(GNU C++ compiler) or `icpx`(Intel C++ compiler). Can also set from environment variable `CXX`. It is OK to use MPI compiler here. - - `MPI_CXX_COMPILER`: MPI wrapper for C++ compiler; usually `mpicxx` or `mpiicpx`(for Intel toolkits) or `mpiicpc`(for classic Intel Compiler Classic MPI before 2024.0). + + - `CMAKE_CXX_COMPILER`: C++ compiler; usually `g++`(GNU C++ compiler) or `icpx`(Intel C++ + compiler). Can also set from environment variable `CXX`. It is OK to use MPI compiler here. + - `MPI_CXX_COMPILER`: MPI wrapper for C++ compiler; usually `mpicxx` or `mpiicpx`(for Intel + toolkits) or `mpiicpc`(for classic Intel Compiler Classic MPI before 2024.0). + - Requirements: Unless indicated, CMake will try to find under default paths. - - `MKLROOT`: If environment variable `MKLROOT` exists, `cmake` will take MKL as a preference, i.e. not using `LAPACK`, `ScaLAPACK` and `FFTW`. To disable MKL, unset environment variable `MKLROOT`, or pass `-DMKLROOT=OFF` to `cmake`. + + - `MKLROOT`: If environment variable `MKLROOT` exists, `cmake` will take MKL as a preference, i.e. + not using `LAPACK`, `ScaLAPACK` and `FFTW`. To disable MKL, unset environment variable + `MKLROOT`, or pass `-DMKLROOT=OFF` to `cmake`. - `LAPACK_DIR`: Path to OpenBLAS library `libopenblas.so`(including BLAS and LAPACK) - `SCALAPACK_DIR`: Path to ScaLAPACK library `libscalapack.so` - `ELPA_DIR`: Path to ELPA install directory; should be the folder containing 'include' and 'lib'. - > Note: In ABACUS v3.5.1 or earlier, if you install ELPA from source , please add a symlink to avoid the additional include file folder with version name: `ln -s elpa/include/elpa-2021.05.002/elpa elpa/include/elpa` to help the build system find ELPA headers. + + > Note: In ABACUS v3.5.1 or earlier, if you install ELPA from source , please add a symlink to + > avoid the additional include file folder with version name: + > `ln -s elpa/include/elpa-2021.05.002/elpa elpa/include/elpa` to help the build system find ELPA + > headers. - `FFTW3_DIR`: Path to FFTW3. - - `CEREAL_INCLUDE_DIR`: Path to the parent folder of `cereal/cereal.hpp`. Will download from GitHub if absent. + - `CEREAL_INCLUDE_DIR`: Path to the parent folder of `cereal/cereal.hpp`. Will download from + GitHub if absent. - `Libxc_DIR`: (Optional) Path to Libxc. - > Note: In ABACUS v3.5.1 or earlier, Libxc built from source with Makefile is NOT supported; please compile Libxc with CMake instead. + + > Note: In ABACUS v3.5.1 or earlier, Libxc built from source with Makefile is NOT supported; + > please compile Libxc with CMake instead. + - `LIBRI_DIR`: (Optional) Path to LibRI. - `LIBCOMM_DIR`: (Optional) Path to LibComm. -- Components: The values of these variables should be 'ON', '1' or 'OFF', '0'. The default values are given below. - - `ENABLE_LCAO=ON`: Enable LCAO calculation. If SCALAPACK, ELPA or CEREAL is absent and only require plane-wave calculations, the feature of calculating LCAO basis can be turned off. - - `ENABLE_LIBXC=OFF`: [Enable Libxc](../advanced/install.md#add-libxc-support) to suppport variety of functionals. If `Libxc_DIR` is defined, `ENABLE_LIBXC` will set to 'ON'. - - `ENABLE_LIBRI=OFF`: [Enable LibRI](../advanced/install.md#add-libri-support) to suppport variety of functionals. If `LIBRI_DIR` and `LIBCOMM_DIR` is defined, `ENABLE_LIBRI` will set to 'ON'. +- Components: The values of these variables should be 'ON', '1' or 'OFF', '0'. The default values + are given below. + + - `ENABLE_LCAO=ON`: Enable LCAO calculation. If SCALAPACK, ELPA or CEREAL is absent and only + require plane-wave calculations, the feature of calculating LCAO basis can be turned off. + - `ENABLE_LIBXC=OFF`: [Enable Libxc](../advanced/install.md#add-libxc-support) to suppport variety + of functionals. If `Libxc_DIR` is defined, `ENABLE_LIBXC` will set to 'ON'. + - `ENABLE_LIBRI=OFF`: [Enable LibRI](../advanced/install.md#add-libri-support) to suppport variety + of functionals. If `LIBRI_DIR` and `LIBCOMM_DIR` is defined, `ENABLE_LIBRI` will set to 'ON'. - `USE_OPENMP=ON`: Enable OpenMP support. Building ABACUS without OpenMP is not fully tested yet. + - `ENABLE_MPI=ON`: Enable MPI parallel compilation. If set to `OFF`, a serial version of ABACUS + will be compiled. It now supports both PW and LCAO. + - `USE_ELPA=ON`: Use ELPA library in LCAO calculations. If this value is set to OFF, ABACUS can be + compiled without ELPA library. + - `ENABLE_FLOAT_FFTW=OFF`: Enable single-precision FFTW support when the corresponding FFTW + library is available. + - `ENABLE_FFT_TWO_CENTER=OFF`: Enable the two-center FFT implementation. + - `ENABLE_CNPY=OFF`: Enable CNPY support for reading and writing NumPy `.npy` data. + +- Other features: + + - `DEBUG_INFO=OFF`: Build with additional debug information. + - `COMMIT_INFO=ON`: Embed Git commit information into the executable when the source tree is + available. + - `GIT_SUBMODULE=ON`: Allow CMake to initialize or update required Git submodules during + configuration. + - `ENABLE_NATIVE_OPTIMIZATION=OFF`: Enable compiler optimizations targeting the native CPU + architecture. This may improve performance on the build machine, but the resulting binary may be + less portable. - `BUILD_TESTING=OFF`: [Build unit tests](../advanced/install.md#build-unit-tests). - - `ENABLE_GOOGLEBENCH=OFF`: [Build performance tests](../advanced/install.md#build-performance-tests) - - `ENABLE_MPI=ON`: Enable MPI parallel compilation. If set to `OFF`, a serial version of ABACUS will be compiled. It now supports both PW and LCAO. - - `ENABLE_COVERAGE=OFF`: Build ABACUS executable supporting [coverage analysis](../CONTRIBUTING.md#generating-code-coverage-report). This feature has a drastic impact on performance. - - `ENABLE_ASAN=OFF`: Build with Address Sanitizer. This feature would help detecting memory problems. - - `USE_ELPA=ON`: Use ELPA library in LCAO calculations. If this value is set to OFF, ABACUS can be compiled without ELPA library. + - `ENABLE_GOOGLEBENCH=OFF`: + [Build performance tests](../advanced/install.md#build-performance-tests) + - `ENABLE_COVERAGE=OFF`: Build ABACUS executable supporting + [coverage analysis](../CONTRIBUTING.md#generating-code-coverage-report). This feature has a + drastic impact on performance. + - `ENABLE_ASAN=OFF`: Build with Address Sanitizer. This feature would help detecting memory + problems. Here is an example: @@ -194,26 +290,30 @@ cmake --build build -j`nproc` cmake --install build ``` -You can change the number after `-j` on your need: set to the number of CPU cores(`nproc`) to reduce compilation time. +You can change the number after `-j` on your need: set to the number of CPU cores(`nproc`) to reduce +compilation time. ## Run ABACUS ### Load ABACUS -If ABACUS is installed into a custom directory using `CMAKE_INSTALL_PREFIX`, please add it to your environment variable `PATH` to locate the correct executable. -*(Note: `my-install-dir` should be changed to the location of your installed abacus:`/home/your-path/abacus/bin/`.)* +If ABACUS is installed into a custom directory using `CMAKE_INSTALL_PREFIX`, please add it to your +environment variable `PATH` to locate the correct executable. *(Note: `my-install-dir` should be +changed to the location of your installed abacus:`/home/your-path/abacus/bin/`.)* ```bash export PATH=/my-install-dir/:$PATH ``` -If ABACUS is installed by toolchain, there will be an environment script in the toolchain directory named as *abacus_env.sh*. You can source it to set the environment variables. +If ABACUS is installed by toolchain, there will be an environment script in the toolchain directory +named as *abacus_env.sh*. You can source it to set the environment variables. ```bash source /path/to/abacus/toolchain/abacus_env.sh ``` -If ABACUS is installed by conda, please make sure the conda environment is activated before running ABACUS. +If ABACUS is installed by conda, please make sure the conda environment is activated before running +ABACUS. ```bash conda activate abacus_env @@ -227,7 +327,8 @@ Please set OpenMP threads by setting environment variable: export OMP_NUM_THREADS=1 ``` -Enter a directory containing a `INPUT` file. Please make sure structure, pseudo potential, or orbital files indicated by `INPUT` is at the correct location. +Enter a directory containing a `INPUT` file. Please make sure structure, pseudo potential, or +orbital files indicated by `INPUT` is at the correct location. ```bash cd abacus-develop/examples/force/pw_Si2 @@ -239,8 +340,9 @@ Use 4 MPI processes to run, for example: mpirun -n 4 abacus ``` -The total thread count (i.e. OpenMP per-process thread count * MPI process count) should not exceed the number of cores in your machine. -To use 4 threads and 4 MPI processes, set the environment variable `OMP_NUM_THREADS` before running `mpirun`: +The total thread count (i.e. OpenMP per-process thread count * MPI process count) should not exceed +the number of cores in your machine. To use 4 threads and 4 MPI processes, set the environment +variable `OMP_NUM_THREADS` before running `mpirun`: ```bash OMP_NUM_THREADS=4 mpirun -n 4 abacus @@ -248,37 +350,66 @@ OMP_NUM_THREADS=4 mpirun -n 4 abacus In this case, the total thread count is 16. -> Notice: If the MPI library you are using is OpenMPI, which is commonly the case, when you set the number of processes to 1 or 2, OpenMPI will default to `--bind-to core`. This means that no matter how many threads you set, these threads will be restricted to run on 1 or 2 CPU cores. Therefore, setting a higher number of OpenMP threads might result in slower program execution. Hence, when using `mpirun -n` set to 1 or 2, it is recommended to set `--bind-to none` to avoid performance degradation. For example:`OMP_NUM_THREADS=6 mpirun --bind-to none -n 1 abacus`. The detailed binding strategy of OpenMPI can be referred to at https://docs.open-mpi.org/en/v5.0.x/man-openmpi/man1/mpirun.1.html#quick-summary. +> Notice: If the MPI library you are using is OpenMPI, which is commonly the case, when you set the +> number of processes to 1 or 2, OpenMPI will default to `--bind-to core`. This means that no matter +> how many threads you set, these threads will be restricted to run on 1 or 2 CPU cores. Therefore, +> setting a higher number of OpenMP threads might result in slower program execution. Hence, when +> using `mpirun -n` set to 1 or 2, it is recommended to set `--bind-to none` to avoid performance +> degradation. For example:`OMP_NUM_THREADS=6 mpirun --bind-to none -n 1 abacus`. The detailed +> binding strategy of OpenMPI can be referred to at +> https://docs.open-mpi.org/en/v5.0.x/man-openmpi/man1/mpirun.1.html#quick-summary. -ABACUS will try to determine the number of threads used by each process if `OMP_NUM_THREADS` is not set. However, it is **required** to set `OMP_NUM_THREADS` before running `mpirun` to avoid potential performance issues. +ABACUS will try to determine the number of threads used by each process if `OMP_NUM_THREADS` is not +set. However, it is **required** to set `OMP_NUM_THREADS` before running `mpirun` to avoid potential +performance issues. Please refer to [hands-on guide](./hands_on.md) for more instructions. -> Note: Some Intel CPU has a feature named Hyper-Threading(HT). This feature enables one physical core switch fastly between two logical threads. It would benefits from I/O bound tasks: when a thread is blocked by I/O, the CPU core can work on another thread. However, it helps little on CPU bound tasks, like ABACUS and many other scientific computing softwares. We recommend using the physical CPU core number. -> To determine if HT is turned on, execute `lscpu | grep 'per core'` and see if 'Thread(s) per core' is 2. +> Note: Some Intel CPU has a feature named Hyper-Threading(HT). This feature enables one physical +> core switch fastly between two logical threads. It would benefits from I/O bound tasks: when a +> thread is blocked by I/O, the CPU core can work on another thread. However, it helps little on CPU +> bound tasks, like ABACUS and many other scientific computing softwares. We recommend using the +> physical CPU core number. To determine if HT is turned on, execute `lscpu | grep 'per core'` and +> see if 'Thread(s) per core' is 2. ## Container Deployment -> Please note that containers target at developing and testing, but not massively parallel computing for production. Docker has a bad support to MPI, which may cause performance degradation. +> Please note that containers target at developing and testing, but not massively parallel computing +> for production. Docker has a bad support to MPI, which may cause performance degradation. -We've built a ready-for-use version of ABACUS with docker [here](https://github.com/deepmodeling/abacus-develop/pkgs/container/abacus). For a quick start: pull the image, prepare the data, run container. Instructions on using the image can be accessed in [Dockerfile](../../Dockerfile). A mirror is available by `docker pull registry.dp.tech/deepmodeling/abacus`. +We've built a ready-for-use version of ABACUS with docker +[here](https://github.com/deepmodeling/abacus-develop/pkgs/container/abacus). For a quick start: +pull the image, prepare the data, run container. Instructions on using the image can be accessed in +[Dockerfile](../../Dockerfile). A mirror is available by +`docker pull registry.dp.tech/deepmodeling/abacus`. -We also offer a pre-built docker image containing all the requirements for development. Please refer to our [Package Page](https://github.com/orgs/deepmodeling/packages?repo_name=abacus-develop). +We also offer a pre-built docker image containing all the requirements for development. Please refer +to our [Package Page](https://github.com/orgs/deepmodeling/packages?repo_name=abacus-develop). -The project is ready for VS Code development container. Please refer to [Developing inside a Container](https://code.visualstudio.com/docs/remote/containers#_quick-start-try-a-development-container). Choose `Open a Remote Window -> Clone a Repository in Container Volume` in VS Code command palette, and put the [git address](https://github.com/deepmodeling/abacus-develop.git) of `ABACUS` when prompted. +The project is ready for VS Code development container. Please refer to +[Developing inside a Container](https://code.visualstudio.com/docs/remote/containers#_quick-start-try-a-development-container). +Choose `Open a Remote Window -> Clone a Repository in Container Volume` in VS Code command palette, +and put the [git address](https://github.com/deepmodeling/abacus-develop.git) of `ABACUS` when +prompted. -For online development environment, we support [GitHub Codespaces](https://github.com/codespaces): [Create a new Codespace](https://github.com/codespaces/new?machine=basicLinux32gb&repo=334825694&ref=develop&devcontainer_path=.devcontainer%2Fdevcontainer.json&location=SouthEastAsia) +For online development environment, we support [GitHub Codespaces](https://github.com/codespaces): +[Create a new Codespace](https://github.com/codespaces/new?machine=basicLinux32gb&repo=334825694&ref=develop&devcontainer_path=.devcontainer%2Fdevcontainer.json&location=SouthEastAsia) -We also support [Gitpod](https://www.gitpod.io/): [Open in Gitpod](https://gitpod.io/#https://github.com/deepmodeling/abacus-develop) +We also support [Gitpod](https://www.gitpod.io/): +[Open in Gitpod](https://gitpod.io/#https://github.com/deepmodeling/abacus-develop) ## Command line options -Users can check the version of ABACUS by running the command `abacus --version`, the result will be like: +Users can check the version of ABACUS by running the command `abacus --version`, the result will be +like: + ``` ABACUS version v3.9.0.2 ``` -Users may check the correctness of the setting of parameters in the `INPUT` file by running the command `abacus --check-input`, the result will be like: +Users may check the correctness of the setting of parameters in the `INPUT` file by running the +command `abacus --check-input`, the result will be like: + ``` ABACUS v3.9.0.2 @@ -297,4 +428,4 @@ Users may check the correctness of the setting of parameters in the `INPUT` file ---------------------------------------------------------- ``` -Warnings will be given if there are any errors in the `INPUT` file. \ No newline at end of file +Warnings will be given if there are any errors in the `INPUT` file. diff --git a/docs/quick_start/hands_on.md b/docs/quick_start/hands_on.md index fe0111ea4c2..464937e3e32 100644 --- a/docs/quick_start/hands_on.md +++ b/docs/quick_start/hands_on.md @@ -4,7 +4,11 @@ ### A quick LCAO example -ABACUS is well known for its support of LCAO (Linear Combination of Atomic Orbital) basis set in calculating periodic condensed matter systems. It's a good choice to start from a LCAO example of self-consistent field (SCF) calculation. Here, FCC MgO has been chosen as a quick start example. The default name of a structure file in ABACUS is `STRU`. The `STRU` file for FCC MgO in a LCAO calculation is shown below: +ABACUS is well known for its support of LCAO (Linear Combination of Atomic Orbital) basis set in +calculating periodic condensed matter systems. It's a good choice to start from a LCAO example of +self-consistent field (SCF) calculation. Here, FCC MgO has been chosen as a quick start example. The +default name of a structure file in ABACUS is `STRU`. The `STRU` file for FCC MgO in a LCAO +calculation is shown below: ``` #This is the atom file containing all the information @@ -19,7 +23,7 @@ Mg_gga_8au_100Ry_4s2p1d.orb O_gga_8au_100Ry_2s2p1d.orb LATTICE_CONSTANT -1.8897259886 # 1.8897259886 Bohr = 1.0 Angstrom +1.8897259886 # 1.8897259886 Bohr = 1.0 Angstrom LATTICE_VECTORS 4.25648 0.00000 0.00000 @@ -44,21 +48,29 @@ O #Name of element 0.0 0.5 0.0 0 0 0 #x,y,z, move_x, move_y, move_z ``` -Next, the `INPUT` file is required, which sets all key parameters to direct ABACUS how to calculte and what to output: +Next, the `INPUT` file is required, which sets all key parameters to direct ABACUS how to calculte +and what to output: + ``` INPUT_PARAMETERS suffix MgO pseudo_dir ./ -orbital_dir ./ +orbital_dir ./ ecutwfc 100 # Rydberg -scf_thr 1e-6 # SCF criterion +scf_thr 1e-6 # SCF criterion basis_type lcao -calculation scf # this is the key parameter telling abacus to do a scf calculation +calculation scf # this is the key parameter telling abacus to do a scf calculation ``` -The pseudopotential files of `Mg_ONCV_PBE-1.0.upf` and `O_ONCV_PBE-1.0.upf` should be provided under the directory of `pseudo_dir` defined in `INPUT` (the default directory is "./"), and the orbital files `Mg_gga_8au_100Ry_4s2p1d.orb` and `O_gga_8au_100Ry_2s2p1d.orb` under the directory of `orbital_dir` also defined in `INPUT` (the default directory is "./"). The pseudopotential and orbital files can be downloaded from the [ABACUS website](http://abacus.ustc.edu.cn/pseudo/list.htm). +The pseudopotential files of `Mg_ONCV_PBE-1.0.upf` and `O_ONCV_PBE-1.0.upf` should be provided under +the directory of `pseudo_dir` defined in `INPUT` (the default directory is "./"), and the orbital +files `Mg_gga_8au_100Ry_4s2p1d.orb` and `O_gga_8au_100Ry_2s2p1d.orb` under the directory of +`orbital_dir` also defined in `INPUT` (the default directory is "./"). The pseudopotential and +orbital files can be downloaded from the +[ABACUS website](http://abacus.ustc.edu.cn/pseudo/list.htm). -The final mandatory input file is called `KPT`, which sets the reciprocal space k-mesh. Below is an example: +The final mandatory input file is called `KPT`, which sets the reciprocal space k-mesh. Below is an +example: ``` K_POINTS @@ -67,7 +79,8 @@ Gamma 4 4 4 0 0 0 ``` -After all the above input files have been set, one should be able to run the first quick example. The simplest way is to use the command line, e.g.: +After all the above input files have been set, one should be able to run the first quick example. +The simplest way is to use the command line, e.g.: ``` OMP_NUM_THREADS=1 mpirun -np 2 abacus @@ -131,17 +144,20 @@ If ABAUCS finishes successfully, the total energy will be output in `OUT.MgO/run ### A quick PW example -In order to run a SCF calculation with PW (Plane Wave) basis set, one has only to change the tag `basis_type` from `lcao` to `pw` in the `INPUT` file, and no longer needs to provide orbital files under `NUMERICAL_ORBITAL` in the `STRU` file. +In order to run a SCF calculation with PW (Plane Wave) basis set, one has only to change the tag +`basis_type` from `lcao` to `pw` in the `INPUT` file, and no longer needs to provide orbital files +under `NUMERICAL_ORBITAL` in the `STRU` file. The `INPUT` file follows as: + ``` INPUT_PARAMETERS suffix MgO pseudo_dir ./ ecutwfc 100 # Rydberg -scf_thr 1e-6 # SCF criterion +scf_thr 1e-6 # SCF criterion basis_type pw # changes the type of basis set -calculation scf # this is the key parameter telling abacus to do a scf calculation +calculation scf # this is the key parameter telling abacus to do a scf calculation ``` And the `STRU` file will be: @@ -155,7 +171,7 @@ Mg 24.305 Mg_ONCV_PBE-1.0.upf # element name, atomic mass, pseudopotential fil O 15.999 O_ONCV_PBE-1.0.upf LATTICE_CONSTANT -1.8897259886 # 1.8897259886 Bohr = 1.0 Angstrom +1.8897259886 # 1.8897259886 Bohr = 1.0 Angstrom LATTICE_VECTORS 4.25648 0.00000 0.00000 @@ -180,7 +196,8 @@ O #Name of element 0.0 0.5 0.0 0 0 0 #x,y,z, move_x, move_y, move_z ``` -Use the same pseudopotential and `KPT` files as the above LCAO example. The final total energy will be output: +Use the same pseudopotential and `KPT` files as the above LCAO example. The final total energy will +be output: ``` -------------------------------------------- @@ -190,7 +207,10 @@ Use the same pseudopotential and `KPT` files as the above LCAO example. The fina ## Running Geometry Optimization -In order to run a full geometry optimization in ABACUS, the tag `calculation` in `INPUT` should be set to `cell-relax`. In addition, the convergence criteria for atomics force and cell stress can be set through the tags `force_thr_ev` and `stress_thr`, respectively. The maximum number of ionc steps is controlled by `relax_nmax`. +In order to run a full geometry optimization in ABACUS, the tag `calculation` in `INPUT` should be +set to `cell-relax`. In addition, the convergence criteria for atomics force and cell stress can be +set through the tags `force_thr_ev` and `stress_thr`, respectively. The maximum number of ionc steps +is controlled by `relax_nmax`. ### A quick LCAO example @@ -203,15 +223,17 @@ nelec 0.0 pseudo_dir ./ orbital_dir ./ ecutwfc 100 # Rydberg -scf_thr 1e-6 # SCF criterion +scf_thr 1e-6 # SCF criterion basis_type lcao -calculation cell-relax # this is the key parameter telling abacus to do a optimization calculation -force_thr_ev 0.01 # the threshold of the force convergence, in unit of eV/Angstrom -stress_thr 5 # the threshold of the stress convergence, in unit of kBar -relax_nmax 100 # the maximal number of ionic iteration steps -out_stru 1 +calculation cell-relax # this is the key parameter telling abacus to do a optimization calculation +force_thr_ev 0.01 # the threshold of the force convergence, in unit of eV/Angstrom +stress_thr 5 # the threshold of the stress convergence, in unit of kBar +relax_nmax 100 # the maximal number of ionic iteration steps +out_stru 1 ``` -Use the same `KPT`, `STRU`, pseudopotential, and orbital files as in the above SCF-LCAO example. The final optimized structure can be found in `STRU_NOW.cif` and `OUT.MgO/running_cell-relax.log`. + +Use the same `KPT`, `STRU`, pseudopotential, and orbital files as in the above SCF-LCAO example. The +final optimized structure can be found in `STRU_NOW.cif` and `OUT.MgO/running_cell-relax.log`. ### A quick PW example @@ -223,13 +245,14 @@ suffix MgO nelec 0.0 pseudo_dir ./ ecutwfc 100 # Rydberg -scf_thr 1e-6 # SCF criterion +scf_thr 1e-6 # SCF criterion basis_type pw -calculation cell-relax # this is the key parameter telling abacus to do a optimization calculation -force_thr_ev 0.01 # the threshold of the force convergence, in unit of eV/Angstrom -stress_thr 5 # the threshold of the stress convergence, in unit of kBar -relax_nmax 100 # the maximal number of ionic iteration steps -out_stru 1 +calculation cell-relax # this is the key parameter telling abacus to do a optimization calculation +force_thr_ev 0.01 # the threshold of the force convergence, in unit of eV/Angstrom +stress_thr 5 # the threshold of the stress convergence, in unit of kBar +relax_nmax 100 # the maximal number of ionic iteration steps +out_stru 1 ``` -Use the same `KPT`, `STRU`, and pseudopotential files as in the above SCF-PW examples. The final optimized structure can be found in `STRU_NOW.cif` and `STRU_ION_D` with different format. +Use the same `KPT`, `STRU`, and pseudopotential files as in the above SCF-PW examples. The final +optimized structure can be found in `STRU_NOW.cif` and `STRU_ION_D` with different format. diff --git a/docs/quick_start/input.md b/docs/quick_start/input.md index f4dfe068afc..edcbfba71c7 100644 --- a/docs/quick_start/input.md +++ b/docs/quick_start/input.md @@ -1,10 +1,13 @@ # Brief Introduction of the Input Files -The following files are the central input files for ABACUS. Before executing the program, please make sure these files are prepared and stored in the working directory. Here we give some simple descriptions. For more details, users should consult the Advanced session. +The following files are the central input files for ABACUS. Before executing the program, please +make sure these files are prepared and stored in the working directory. Here we give some simple +descriptions. For more details, users should consult the Advanced session. ## *INPUT* -The `INPUT` file contains parameters that control the type of calculation as well as a variety of settings. +The `INPUT` file contains parameters that control the type of calculation as well as a variety of +settings. Below is an example `INPUT` file with some of the most important parameters that need to be set: @@ -20,33 +23,50 @@ calculation scf # this is the key parameter telling abacus to do a out_chg 0 # only output binary charge file for restart ``` -The parameter list always starts with key word `INPUT_PARAMETERS`. Any content before `INPUT_PARAMETERS` will be ignored. +The parameter list always starts with key word `INPUT_PARAMETERS`. Any content before +`INPUT_PARAMETERS` will be ignored. Any line starting with `#` or `/` will also be ignored. -Each parameter value is provided by specifying the name of the input variable -and then putting the value after the name, separated by one or more blank characters(space or tab). The following characters (> 150) in the same line will be neglected. +Each parameter value is provided by specifying the name of the input variable and then putting the +value after the name, separated by one or more blank characters(space or tab). The following +characters (> 150) in the same line will be neglected. -Depending on the input variable, the value may be an integer, a real number or a string. The parameters can be given in any order, but only one parameter should be given per line. +Depending on the input variable, the value may be an integer, a real number or a string. The +parameters can be given in any order, but only one parameter should be given per line. -Furthermore, if a given parameter name appeared more than once in the input file, only the last value will be taken. +Furthermore, if a given parameter name appeared more than once in the input file, only the last +value will be taken. -> **Note:** if a parameter name is not recognized by the program, the program will stop with an error message. +> **Note:** if a parameter name is not recognized by the program, the program will stop with an +> error message. In the above example, the meanings of the parameters are: -- `suffix` : the name of the system, default `ABACUS`, and output files will be in OUT.{suffix} directory. +- `suffix` : the name of the system, default `ABACUS`, and output files will be in OUT.\{suffix} + directory. - `pseudo_dir` : the directory where pseudopotential files are provided. - `orbital_dir` : the directory where orbital files are provided. - `ecutwfc` : the plane-wave energy cutoff for the wave function expansion (UNIT: Rydberg). -- `scf_thr` : the threshold for the convergence of charge density (UNIT: Rydberg for PW, dimensionless for LCAO), we recommend `1e-7` for LCAO and `1e-9` for PW basis. -- `basis_type` : the type of basis set for expanding the electronic wave functions, one can set lcao or pw. +- `scf_thr` : the threshold for the convergence of charge density (UNIT: Rydberg for PW, + dimensionless for LCAO), we recommend `1e-7` for LCAO and `1e-9` for PW basis. +- `basis_type` : the type of basis set for expanding the electronic wave functions, one can set lcao + or pw. - `calculation` : the type of calculation to be performed by ABACUS -- `out_chg` : setting for output the charge density in real space grid, -1 for no output, 0 for binary output, 1 for binary and cube output. +- `out_chg` : setting for output the charge density in real space grid, -1 for no output, 0 for + binary output, 1 for binary and cube output. -For a complete list of input parameters, please consult this [instruction](../advanced/input_files/input-main.md). +For a complete list of input parameters, please consult this +[instruction](../advanced/input_files/input-main.md). -> **Note:** Users cannot change the filename "INPUT" to other names. Boolean paramerters such as `out_chg` can be set by using `True` and `False`, `1` and `0`, or `T` and `F`. It is case insensitive so that other preferences such as `true` and `false`, `TRUE` and `FALSE`, and `t` and `f` for setting boolean values are also supported. Specifically for the `out_chg`, `-1` option is also available, which means turn off the checkpoint of charge density in binary (always dumped in `OUT.{suffix}`, whose name ends with `CHARGE-DENSITY.restart`). Some parameters controlling the output also support a second option to control the output precision, e.g., `out_chg 1 8` will output the charge density on realspace grid with 8 digits after the decimal point. +> **Note:** Users cannot change the filename "INPUT" to other names. Boolean paramerters such as +> `out_chg` can be set by using `True` and `False`, `1` and `0`, or `T` and `F`. It is case +> insensitive so that other preferences such as `true` and `false`, `TRUE` and `FALSE`, and `t` and +> `f` for setting boolean values are also supported. Specifically for the `out_chg`, `-1` option is +> also available, which means turn off the checkpoint of charge density in binary (always dumped in +> `OUT.{suffix}`, whose name ends with `CHARGE-DENSITY.restart`). Some parameters controlling the +> output also support a second option to control the output precision, e.g., `out_chg 1 8` will +> output the charge density on realspace grid with 8 digits after the decimal point. ## Getting Help with Parameters @@ -99,7 +119,9 @@ Parameter lookups are case-insensitive, so `ECUTWFC`, `Ecutwfc`, and `ecutwfc` a ## *STRU* -The structure file contains structural information about the system, e.g., lattice constant, lattice vectors, and positions of the atoms within a unit cell. The positions can be given either in direct or Cartesian coordinates. +The structure file contains structural information about the system, e.g., lattice constant, lattice +vectors, and positions of the atoms within a unit cell. The positions can be given either in direct +or Cartesian coordinates. An example of the `STRU` file is given as follows : @@ -142,9 +164,14 @@ O #Name of element 0.0 0.5 0.0 0 0 0 #x,y,z, move_x, move_y, move_z ``` -> **Note:** users may choose a different name for their structure file using the keyword `stru_file`. The order of the pseudopotential file list and the numerical orbital list (if LCAO is applied) MUST be consistent with that of the atomic type given in `ATOMIC_POSITIONS`. +> **Note:** users may choose a different name for their structure file using the keyword +> `stru_file`. The order of the pseudopotential file list and the numerical orbital list (if LCAO is +> applied) MUST be consistent with that of the atomic type given in `ATOMIC_POSITIONS`. -> **Important:** When specifying atomic positions, you can use various coordinate systems (Direct, Cartesian, Cartesian_angstrom, etc.) and add optional properties like magnetization, velocity, and movement constraints. See the [detailed STRU documentation](../advanced/input_files/stru.md) for all available options and best practices. +> **Important:** When specifying atomic positions, you can use various coordinate systems (Direct, +> Cartesian, Cartesian_angstrom, etc.) and add optional properties like magnetization, velocity, and +> movement constraints. See the [detailed STRU documentation](../advanced/input_files/stru.md) for +> all available options and best practices. ## *KPT* @@ -165,12 +192,18 @@ For a more detailed description, please consult [here](../advanced/input_files/k - The pseudopotential files - Norm-conserving pseudopotentials are used in ABACUS, in the UPF file format.The filename of each element’s pseudopotential needs to be specified in the STRU file, together with the directory of the pseudopotential files unless they are already present in the working directory. + Norm-conserving pseudopotentials are used in ABACUS, in the UPF file format.The filename of each + element’s pseudopotential needs to be specified in the STRU file, together with the directory of + the pseudopotential files unless they are already present in the working directory. - More information on pseudopotentials is given [here](../advanced/pp_orb.md#pseudopotentials). + More information on pseudopotentials is given [here](../advanced/pp_orb.md#pseudopotentials). - The numerical orbital files - This part is only required in LCAO calculations. - The filename for each element’s numerical orbital basis needs to be specified in the STRU file, together with the directory of the orbital files unless they are already present in the working directory. - ABACUS provides numerical atomic basis sets of different accuracy levels for most elements commonly used. Users can download these basis sets from the [website](http://abacus.ustc.edu.cn/pseudo/list.htm). Moreover, users can generate numerical atomic orbitals by themselves, and the procedure is provided in this [short introduction](../advanced/pp_orb.md#generating-atomic-orbital-bases). + This part is only required in LCAO calculations. The filename for each element’s numerical orbital + basis needs to be specified in the STRU file, together with the directory of the orbital files + unless they are already present in the working directory. ABACUS provides numerical atomic basis + sets of different accuracy levels for most elements commonly used. Users can download these basis + sets from the [website](http://abacus.ustc.edu.cn/pseudo/list.htm). Moreover, users can generate + numerical atomic orbitals by themselves, and the procedure is provided in this + [short introduction](../advanced/pp_orb.md#generating-atomic-orbital-bases). diff --git a/docs/quick_start/output.md b/docs/quick_start/output.md index 74d2e552ac6..c30d3dfc873 100644 --- a/docs/quick_start/output.md +++ b/docs/quick_start/output.md @@ -1,37 +1,46 @@ # Brief Introduction of the Output Files -The following files are the central output files for ABACUS. After executing the program, you can obtain a log file containing the screen output, more detailed outputs are stored in the working directory `OUT.suffix` (Default one is `OUT.ABACUS`). Here we give some simple descriptions. +The following files are the central output files for ABACUS. After executing the program, you can +obtain a log file containing the screen output, more detailed outputs are stored in the working +directory `OUT.suffix` (Default one is `OUT.ABACUS`). Here we give some simple descriptions. ## *INPUT* Different from `INPUT` given by the users, `OUT.suffix/INPUT` contains all parameters in ABACUS. -> **Note:** `OUT.suffix/INPUT` contains the **actual parameters used in the calculation**, including: -> 1. **User-specified parameters** (explicitly defined in your input file or command-line arguments, overriding default parameters). -> 2. **System default parameters** (automatically applied when not explicitly provided by the user). +> **Note:** `OUT.suffix/INPUT` contains the **actual parameters used in the calculation**, +> including: +> +> 1. **User-specified parameters** (explicitly defined in your input file or command-line arguments, +> overriding default parameters). +> 1. **System default parameters** (automatically applied when not explicitly provided by the user). +This file ensures calculations can be fully reproduced, even if default values change in future +ABACUS versions. Also notice that in rare cases, a small number of parameters may be dynamically +reset to appropriate values during runtime. -This file ensures calculations can be fully reproduced, even if default values change in future ABACUS versions. -Also notice that in rare cases, a small number of parameters may be dynamically reset to appropriate values during runtime. - -For a complete list of input parameters, please consult this [instruction](../advanced/input_files/input-main.md). +For a complete list of input parameters, please consult this +[instruction](../advanced/input_files/input-main.md). ## *running_scf.log* -`running_scf.log` contains information on nearly all function calls made during the execution of ABACUS. +`running_scf.log` contains information on nearly all function calls made during the execution of +ABACUS. ## *KPT.info* -This file contains the information of all generated k-points, as well as the list of k-points actually used for calculations after considering symmetry. +This file contains the information of all generated k-points, as well as the list of k-points +actually used for calculations after considering symmetry. ## *eig.txt* -This file includes the energy levels and occupations computed for all k-points. -Note: In 3.10-LTS version, the file is named 'istate.info' +This file includes the energy levels and occupations computed for all k-points. Note: In 3.10-LTS +version, the file is named 'istate.info' ## *STRU.cif* -ABACUS generates a `.cif` format structure file based on the input file `STRU`, facilitating users to visualize with commonly used software. +ABACUS generates a `.cif` format structure file based on the input file `STRU`, facilitating users +to visualize with commonly used software. ## *warning.log* diff --git a/toolchain/README.md b/toolchain/README.md index 5f982a039e3..c8ca5e1851f 100644 --- a/toolchain/README.md +++ b/toolchain/README.md @@ -2,7 +2,7 @@ [![Version](https://img.shields.io/badge/version-2026.1-blue.svg)](https://github.com/deepmodeling/abacus-develop/tree/develop/toolchain) [![License](https://img.shields.io/badge/license-GPL--compatible-green.svg)](#license) -[![Platform](https://img.shields.io/badge/platform-Linux-lightgrey.svg)]() +[![Platform](https://img.shields.io/badge/platform-Linux-lightgrey.svg)](<>) > **Automated dependency management and compilation toolchain for ABACUS** @@ -23,17 +23,20 @@ ## Overview -The ABACUS Toolchain is an automated build system inspired by the cp2k-toolchain that simplifies the compilation and installation of ABACUS and its dependencies. It supports both online and offline installation modes, multiple compiler toolchains, and provides a streamlined path from dependency installation to ABACUS compilation. +The ABACUS Toolchain is an automated build system inspired by the cp2k-toolchain that simplifies the +compilation and installation of ABACUS and its dependencies. It supports both online and offline +installation modes, multiple compiler toolchains, and provides a streamlined path from dependency +installation to ABACUS compilation. ### Main Developer -**[QuantumMisaka](https://github.com/QuantumMisaka)** (Zhaoqing Liu) +**[QuantumMisaka](https://github.com/QuantumMisaka)** (Zhaoqing Liu)\ *Peking University, CCME* ## Features - ✅ **Multiple Toolchain Support**: GNU, Intel OneAPI, AMD AOCC/AOCL -- ✅ **Flexible Installation**: Online/offline modes with automatic dependency resolution +- ✅ **Flexible Installation**: Online/offline modes with automatic dependency resolution - ✅ **GPU Acceleration**: CUDA support for NVIDIA GPUs with ELPA and cuSolverMP - ✅ **MPI Implementations**: OpenMPI, MPICH, Intel MPI support - ✅ **Math Libraries**: OpenBLAS, Intel MKL, AMD AOCL integration @@ -102,11 +105,17 @@ Downloads packages automatically from official sources: ./toolchain_gnu.sh # Uses system package managers and official repositories ``` -Before running the toolchain, please make sure you have loaded the related environments and set the environment variables. -- You SHOULD source or module load related environments before use toolchain method for installation, especially for *intel*, *gcc-aocl* or *aocc-aocl* toolchain! For example, `module load mkl mpi icc compiler` for loading intel-oneapi envs. -- You SHOULD keep your environments systematic, for example, you CANNOT load intel-OneAPI environments while use gcc toolchain !!! +Before running the toolchain, please make sure you have loaded the related environments and set the +environment variables. + +- You SHOULD source or module load related environments before use toolchain method for + installation, especially for *intel*, *gcc-aocl* or *aocc-aocl* toolchain! For example, + `module load mkl mpi icc compiler` for loading intel-oneapi envs. +- You SHOULD keep your environments systematic, for example, you CANNOT load intel-OneAPI + environments while use gcc toolchain !!! **Package Sources:** + - **Build Tools:** - [GCC](https://mirrors.tuna.tsinghua.edu.cn/gnu/gcc/) - GNU Compiler Collection - [CMake](https://cmake.org/download/) - Cross-platform build system @@ -129,7 +138,8 @@ Before running the toolchain, please make sure you have loaded the related envir - [Cereal](https://github.com/USCiLab/cereal) - C++ serialization library - [RapidJSON](https://github.com/Tencent/rapidjson) - Fast JSON parser/generator - **Reference mirror:** [CP2K static downloads](https://www.cp2k.org/static/downloads) -- All package from GitHub will be downloaded by `wget` from `codeload.github.com`, which bypass the difficulty of CN Internet in some extent. +- All package from GitHub will be downloaded by `wget` from `codeload.github.com`, which bypass the + difficulty of CN Internet in some extent. ### Offline Installation @@ -148,6 +158,7 @@ mkdir build The downloading process can be facilitated via `./toolchain_gnu.sh --pack-run`. Also, for users in China, we provide a Gitee mirror repository with pre-downloaded packages: + ```bash # Clone the Gitee repository in toolchain directory git clone https://gitee.com/jamesmisaka/abacus_toolchain_build.git @@ -158,23 +169,28 @@ mv abacus_toolchain_build/* build/ ### Hybrid Installation -Mix online and offline packages as needed - the toolchain automatically detects locally available packages and downloads missing ones. +Mix online and offline packages as needed - the toolchain automatically detects locally available +packages and downloads missing ones. ## Supported Toolchains ### GNU Toolchain + - **Compilers**: System GCC (≥5.0) or installed GCC - **MPI**: OpenMPI or MPICH - **Math**: OpenBLAS + ScaLAPACK - **Features**: Most stable, widely compatible ### Intel Toolchain -- **Compilers**: Intel OneAPI (icx/icpx/ifx or classic icc/icpc/ifort) with system/installed GCC (≥5.0) + +- **Compilers**: Intel OneAPI (icx/icpx/ifx or classic icc/icpc/ifort) with system/installed GCC + (≥5.0) - **MPI**: Intel MPI - **Math**: Intel MKL - **Features**: Optimized performance for Intel Machine ### AMD Toolchain + - **Compilers**: AMD AOCC or system/installed GCC - **Math**: AMD AOCL (Optimized math libraries) - **Features**: AMD processor optimization (e.g., Zen3+) @@ -183,46 +199,53 @@ Mix online and offline packages as needed - the toolchain automatically detects ### Supported Packages -| Package | Version (main/alt) | Purpose | License | Default | -|---------|-------------------|---------|---------|---------| -| **Build Tools** ||||| -| CMake | 3.31.7 / 3.30.5 | Build system | BSD-3-Clause | Install | -| GCC | 13.2.0 / 11.4.0 | C/C++ compiler | GPL-3.0-or-later WITH GCC-exception-3.1 | Install | -| **MPI Libraries** ||||| -| OpenMPI | 5.0.10 / 4.1.8 | MPI implementation | BSD-3-Clause-Open-MPI | Install | -| MPICH | 5.0.1 / 4.3.2 | Alternative MPI | mpich2 (BSD-like) | Alternative | -| **Math Libraries** ||||| -| OpenBLAS | 0.3.33 / 0.3.30 | Linear algebra | BSD-3-Clause | Install | -| ScaLAPACK | 2.2.3 / 2.2.1 | Parallel linear algebra | BSD-3-Clause | Install | -| **Scientific Libraries** ||||| -| FFTW | 3.3.11 / 3.3.10 | Fast Fourier Transform | GPL-2.0-or-later | Install | -| LibXC | 7.0.0 / 6.2.2 | Exchange-correlation | MPL-2.0 | Install | -| ELPA | 2026.02.001 / 2024.05.001 | Eigenvalue solver | LGPL-3.0-only | Install | -| **Advanced Features** ||||| -| Cereal | pinned commit | C++ Serialization | BSD | Install | -| RapidJSON | pinned commit | JSON parsing | MIT | Install | -| LibRI | pinned commit | EXX calculations | GPL-3.0 | Install | -| LibComm | pinned commit | EXX calculations | GPL-3.0 | Install | -| LibTorch | 2.1.2 / 1.12.1 | MLALGO support | BSD-3-Clause | Optional | -| LibNPY | 1.0.1 / 1.0.1 | NumPy I/O | MIT | Optional | -| NEP | main | Neuroevolution potential | MIT | Optional | - -Also, [Intel-oneAPI](https://www.intel.cn/content/www/cn/zh/developer/tools/oneapi/toolkits.html) and AMD [AOCC](https://www.amd.com/zh-cn/developer/aocc.html) and [AOCL](https://www.amd.com/zh-cn/developer/aocl.html) are supported in toolchain by setting them to system option, but one should install them manually by server administrator. +| Package | Version (main/alt) | Purpose | License | Default | +| ------------------------ | ------------------------- | ------------------------ | --------------------------------------- | ----------- | +| **Build Tools** | | | | | +| CMake | 3.31.7 / 3.30.5 | Build system | BSD-3-Clause | Install | +| GCC | 13.2.0 / 11.4.0 | C/C++ compiler | GPL-3.0-or-later WITH GCC-exception-3.1 | Install | +| **MPI Libraries** | | | | | +| OpenMPI | 5.0.10 / 4.1.8 | MPI implementation | BSD-3-Clause-Open-MPI | Install | +| MPICH | 5.0.1 / 4.3.2 | Alternative MPI | mpich2 (BSD-like) | Alternative | +| **Math Libraries** | | | | | +| OpenBLAS | 0.3.33 / 0.3.30 | Linear algebra | BSD-3-Clause | Install | +| ScaLAPACK | 2.2.3 / 2.2.1 | Parallel linear algebra | BSD-3-Clause | Install | +| **Scientific Libraries** | | | | | +| FFTW | 3.3.11 / 3.3.10 | Fast Fourier Transform | GPL-2.0-or-later | Install | +| LibXC | 7.0.0 / 6.2.2 | Exchange-correlation | MPL-2.0 | Install | +| ELPA | 2026.02.001 / 2024.05.001 | Eigenvalue solver | LGPL-3.0-only | Install | +| **Advanced Features** | | | | | +| Cereal | pinned commit | C++ Serialization | BSD | Install | +| RapidJSON | pinned commit | JSON parsing | MIT | Install | +| LibRI | pinned commit | EXX calculations | GPL-3.0 | Install | +| LibComm | pinned commit | EXX calculations | GPL-3.0 | Install | +| LibTorch | 2.1.2 / 1.12.1 | MLALGO support | BSD-3-Clause | Optional | +| LibNPY | 1.0.1 / 1.0.1 | NumPy I/O | MIT | Optional | +| NEP | main | Neuroevolution potential | MIT | Optional | + +Also, [Intel-oneAPI](https://www.intel.cn/content/www/cn/zh/developer/tools/oneapi/toolkits.html) +and AMD [AOCC](https://www.amd.com/zh-cn/developer/aocc.html) and +[AOCL](https://www.amd.com/zh-cn/developer/aocl.html) are supported in toolchain by setting them to +system option, but one should install them manually by server administrator. ### Package Version Switching -The toolchain supports a dual-version system for most packages, providing both **main** (latest stable) and **alt** (alternative/legacy) versions. This allows users to choose between cutting-edge features and proven stability based on their specific requirements. +The toolchain supports a dual-version system for most packages, providing both **main** (latest +stable) and **alt** (alternative/legacy) versions. This allows users to choose between cutting-edge +features and proven stability based on their specific requirements. #### Version Selection Methods The `--package-version` parameter supports two flexible usage patterns: **Method 1: Multiple Independent Parameters** (Original support) + ```bash ./toolchain_gnu.sh --package-version libtorch:alt --package-version elpa:alt ``` **Method 2: Single Parameter with Multiple Key-Value Pairs** (Enhanced functionality) + ```bash ./toolchain_gnu.sh --package-version "libtorch:alt elpa:alt" ``` @@ -251,10 +274,12 @@ and other `toolchain_*.sh` scripts share the same version selection. #### Global Version Strategy - **Default Behavior**: All packages use their **main** versions unless explicitly overridden -- **Selective Override**: Use `--package-version` to specify alternative versions for specific packages -- **Consistency**: Version selections are validated against available options in `scripts/package_versions.sh` -- **Backward Compatibility**: Both usage methods are fully supported to ensure existing scripts continue to work - +- **Selective Override**: Use `--package-version` to specify alternative versions for specific + packages +- **Consistency**: Version selections are validated against available options in + `scripts/package_versions.sh` +- **Backward Compatibility**: Both usage methods are fully supported to ensure existing scripts + continue to work ### System Requirements @@ -289,12 +314,14 @@ cmake -B $BUILD_DIR \ #### Multi-GPU with ELPA 1. **Configure toolchain with CUDA:** + ```bash export CUDA_PATH=/path/to/CUDA ./toolchain_gnu.sh --enable-cuda --gpu-ver=70 # For V100 (compute capability 7.0) ``` 2. **Build with ELPA GPU support:** + ```bash cmake -B $BUILD_DIR \ -DUSE_CUDA=ON \ @@ -308,19 +335,24 @@ cuSolverMP requires NVIDIA HPC SDK. Follow these steps to build with cuSolverMP: 1. Load the NVHPC module: - - **For NVIDIA HPC SDK version < 25.9**: cuSolverMP relies on HPC-X for communication, so you need to load the `nvhpc-hpcx-cudaxx/xx.x` module. For example, with HPC SDK 25.3: + - **For NVIDIA HPC SDK version < 25.9**: cuSolverMP relies on HPC-X for communication, so you + need to load the `nvhpc-hpcx-cudaxx/xx.x` module. For example, with HPC SDK 25.3: + ```bash module use /opt/nvidia/hpc_sdk/modulefiles module load nvhpc-hpcx-cuda12/25.3 ``` - - **For NVIDIA HPC SDK version >= 25.9**: cuSolverMP uses NCCL for communication instead of HPC-X, so only the base `nvhpc/xx.x` module is needed. For example, with HPC SDK 26.1: + - **For NVIDIA HPC SDK version >= 25.9**: cuSolverMP uses NCCL for communication instead of + HPC-X, so only the base `nvhpc/xx.x` module is needed. For example, with HPC SDK 26.1: + ```bash module use /opt/nvidia/hpc_sdk/modulefiles module load nvhpc/26.1 ``` -2. Build with cuSolverMP enabled: +1. Build with cuSolverMP enabled: + ```bash cmake -B $BUILD_DIR \ -DUSE_CUDA=ON \ @@ -334,7 +366,11 @@ cmake -B $BUILD_DIR \ #### Intel OneAPI Problems -Most of the OneAPI problem arise from the newer version of Intel-OneAPI. For users who encounter OneAPI problem, one can get Intel-OneAPI in [QE-managed website](https://pranabdas.github.io/espresso/setup/hpc/#installing-intel-oneapi-libraries), and use this code to get Intel oneAPI Base Toolkit and HPC Toolkit: +Most of the OneAPI problem arise from the newer version of Intel-OneAPI. For users who encounter +OneAPI problem, one can get Intel-OneAPI in +[QE-managed website](https://pranabdas.github.io/espresso/setup/hpc/#installing-intel-oneapi-libraries), +and use this code to get Intel oneAPI Base Toolkit and HPC Toolkit: + ```shell wget https://registrationcenter-download.intel.com/akdlm/IRC_NAS/992857b9-624c-45de-9701-f6445d845359/l_BaseKit_p_2023.2.0.49397_offline.sh wget https://registrationcenter-download.intel.com/akdlm/IRC_NAS/0722521a-34b5-4c41-af3f-d5d14e88248d/l_HPCKit_p_2023.2.0.49440_offline.sh @@ -343,26 +379,41 @@ wget https://registrationcenter-download.intel.com/akdlm/IRC_NAS/0722521a-34b5-4 Related discussion here [#4976](https://github.com/deepmodeling/abacus-develop/issues/4976) **OneAPI 2025.0 Compatibility:** + - LibRI compatibility issues ([#6190](https://github.com/deepmodeling/abacus-develop/issues/6190)) -- Solution: Using the patch from Cereal and the master version of Cereal to fix the compatibility issue (included in toolchain). +- Solution: Using the patch from Cereal and the master version of Cereal to fix the compatibility + issue (included in toolchain). **ELPA on AMD servers with Intel compilers:** + ```bash # Use Intel classic compilers instead ./toolchain_intel.sh --with-intel-classic=yes ``` -Notice: `icc` and `icpc` from Intel Classic Compiler of Intel-oneAPI are not supported for 2024.0 and newer version. And Intel-OneAPI 2023.2.0 can be found in QE website. You need to download Base-toolkit for MKL and HPC-toolkit for MPi and compiler for Intel-OneAPI 2023.2.0, while in Intel-OneAPI 2024.x, only the HPC-toolkit is needed. +Notice: `icc` and `icpc` from Intel Classic Compiler of Intel-oneAPI are not supported for 2024.0 +and newer version. And Intel-OneAPI 2023.2.0 can be found in QE website. You need to download +Base-toolkit for MKL and HPC-toolkit for MPi and compiler for Intel-OneAPI 2023.2.0, while in +Intel-OneAPI 2024.x, only the HPC-toolkit is needed. #### AMD AOCC-AOCL problem -Use AOCC-AOCL to compile dependencies is permitted and usually get boosting in ABACUS efficiency. But you need to get rid of `flang` while compiling ELPA. Toolchain itself helps you make this `flang` shade in default of `aocc-aocl` toolchain, and you can manually use `flang` by setting `--with-flang=yes` in `toolchain_aocc-aocl.sh` to have a try, while toolchain helps you to bypass the possible errors in compiling ELPA with AOCC-AOCL, but the computing efficiency will be relatively lower compared to `gnu` or `gcc-aocl` toolchain. There are some issues related to the numeric instability of ABACUS compiled by AOCC-AOCL toolchain, see [#6420](https://github.com/deepmodeling/abacus-develop/issues/6420) +Use AOCC-AOCL to compile dependencies is permitted and usually get boosting in ABACUS efficiency. +But you need to get rid of `flang` while compiling ELPA. Toolchain itself helps you make this +`flang` shade in default of `aocc-aocl` toolchain, and you can manually use `flang` by setting +`--with-flang=yes` in `toolchain_aocc-aocl.sh` to have a try, while toolchain helps you to bypass +the possible errors in compiling ELPA with AOCC-AOCL, but the computing efficiency will be +relatively lower compared to `gnu` or `gcc-aocl` toolchain. There are some issues related to the +numeric instability of ABACUS compiled by AOCC-AOCL toolchain, see +[#6420](https://github.com/deepmodeling/abacus-develop/issues/6420) -The `gcc-aocl` toolchain will have no problem above for aocc-dependent aocl. However, the gcc-dependent aocl will have some package linking problem related to OpenMPI. Take it with caution. +The `gcc-aocl` toolchain will have no problem above for aocc-dependent aocl. However, the +gcc-dependent aocl will have some package linking problem related to OpenMPI. Take it with caution. #### OpenMPI Issues **Version 5 compatibility problems:** + ```bash # Use OpenMPI v4 instead ./toolchain_gnu.sh --package-version openmpi:alt @@ -371,12 +422,14 @@ The `gcc-aocl` toolchain will have no problem above for aocc-dependent aocl. How ``` **LibComm compilation with OpenMPI:** + - Fixed in toolchain 2025.2 which downlo the master branch of LibComm - Alternative: Use MPICH or Intel MPI #### Shell and Permission Issues **Line ending problems:** + ```bash ./pre_set.sh # Fixes line endings and permissions # Or manually: @@ -387,6 +440,7 @@ chmod +x *.sh #### Library Version Issues **LibTorch GLIBC errors:** + - Requires GLIBCXX_3.4.26 - Change version from 2.1.2 to 1.12.1 - Use `--package-version libtorch:alt` when calling toolchain @@ -395,16 +449,17 @@ chmod +x *.sh - Single parameter with multiple key-value pairs: `--package-version libtorch:alt elpa:alt` **DeepMD GLIBC errors:** + - Requires GCC ≥ 11.3.1 for GLIBCXX_3.4.29 - Upgrade system GCC or use newer toolchain ### Getting Help 1. **Check logs**: Look in `build/PKG_NAME/make.log` for compilation errors -2. **Reduce parallelism**: Use `NPROCS_OVERWRITE=N` environment variable to limit parallel processes -3. **System libraries**: Use `--with-PKG=system` for system-installed packages -4. **Clean installation**: Remove `install/` and `build/` directories to restart -5. **Certificate issues**: Use `DOWNLOAD_CERT_POLICY=skip` for download problems +1. **Reduce parallelism**: Use `NPROCS_OVERWRITE=N` environment variable to limit parallel processes +1. **System libraries**: Use `--with-PKG=system` for system-installed packages +1. **Clean installation**: Remove `install/` and `build/` directories to restart +1. **Certificate issues**: Use `DOWNLOAD_CERT_POLICY=skip` for download problems ## Advanced Usage @@ -453,7 +508,9 @@ export DOWNLOAD_CERT_POLICY=skip ./toolchain_gnu.sh ``` -**Smart Mode Behavior**: The default `smart` mode first attempts secure downloads with certificate verification. If this fails (e.g., due to corporate firewalls or outdated certificates), it automatically falls back to skipping certificate verification while providing clear user feedback. +**Smart Mode Behavior**: The default `smart` mode first attempts secure downloads with certificate +verification. If this fails (e.g., due to corporate firewalls or outdated certificates), it +automatically falls back to skipping certificate verification while providing clear user feedback. #### Parallel Compilation Control @@ -473,6 +530,7 @@ NPROCS_OVERWRITE=4 ./toolchain_gnu.sh --with-gcc --with-openmpi ``` **Use Cases**: + - **Resource-limited systems**: Reduce parallelism to avoid memory exhaustion - **Shared servers**: Limit resource usage to be considerate of other users - **CI/CD environments**: Match container resource limits @@ -483,7 +541,7 @@ NPROCS_OVERWRITE=4 ./toolchain_gnu.sh --with-gcc --with-openmpi The toolchain generates several setup files: - `install/setup`: Main environment setup -- `build/setup_PKG`: Individual package environments +- `build/setup_PKG`: Individual package environments - `abacus_env.sh`: ABACUS-specific environment (generated by build scripts) ## Developer Guide @@ -504,39 +562,42 @@ scripts/ ### Key Components -| File | Purpose | -|------|---------| -| `install_abacus_toolchain_new.sh` | Main orchestration script (new version) | -| `toolchain_*.sh` | Frontend scripts for specific toolchains | -| `scripts/lib/config_manager.sh` | Configuration management | -| `scripts/lib/package_manager.sh` | Package installation logic | -| `scripts/lib/user_interface.sh` | User interaction and output | -| `scripts/common_vars.sh` | Shared variables and defaults | -| `scripts/tool_kit.sh` | Utility functions and macros | -| `scripts/parse_if.py` | Parser for IF_XYZ constructs | +| File | Purpose | +| ---------------------------------- | --------------------------------------------------------------------- | +| `install_abacus_toolchain_new.sh` | Main orchestration script (new version) | +| `toolchain_*.sh` | Frontend scripts for specific toolchains | +| `scripts/lib/config_manager.sh` | Configuration management | +| `scripts/lib/package_manager.sh` | Package installation logic | +| `scripts/lib/user_interface.sh` | User interaction and output | +| `scripts/common_vars.sh` | Shared variables and defaults | +| `scripts/tool_kit.sh` | Utility functions and macros | +| `scripts/parse_if.py` | Parser for IF_XYZ constructs | | `install//install_successful` | Per-package install lock/checksum file generated by `write_checksums` | ### Script Structure Details -**Individual Package Scripts**: Each `scripts/stage*/install_PKG.sh` script is relatively independent and should: +**Individual Package Scripts**: Each `scripts/stage*/install_PKG.sh` script is relatively +independent and should: 1. **Generate setup files**: Write to both `build/setup_PKG` and `install/setup` + - `build/setup_PKG`: Variables for toolchain compilation and arch file flags - `install/setup`: Environment setup for compiling/running ABACUS -2. **Handle dependencies**: May depend on other libraries being installed with correct environment variables +1. **Handle dependencies**: May depend on other libraries being installed with correct environment + variables -3. **Use toolkit macros**: Leverage functionality from `scripts/tool_kit.sh` for common operations +1. **Use toolkit macros**: Leverage functionality from `scripts/tool_kit.sh` for common operations ### Package Installation Scripts Each `scripts/stage*/install_PKG.sh` script: 1. **Downloads** the package (if not available locally) -2. **Configures** build with appropriate flags -3. **Compiles** with error handling and logging -4. **Installs** to the toolchain directory -5. **Generates** setup files for environment configuration +1. **Configures** build with appropriate flags +1. **Compiles** with error handling and logging +1. **Installs** to the toolchain directory +1. **Generates** setup files for environment configuration ### Configuration System @@ -550,14 +611,16 @@ The `--with-PKG` options control how a package is going to be installed: - `--with-PKG=no`: Skip package installation entirely **System Search Paths**: When using `system` mode, the installation script searches in: + - `LD_LIBRARY_PATH`, `LD_RUN_PATH`, `LIBRARY_PATH` - `/usr/local/lib64`, `/usr/local/lib`, `/usr/lib64`, `/usr/lib` - For MKL libraries: `MKLROOT` environment variable **Troubleshooting System Libraries**: If `--with-PKG=system` cannot find the library: + 1. Use `module show PKG` to see module-defined paths -2. Find the root installation directory manually -3. Use `--with-PKG=/path/to/pkg` to specify exact location +1. Find the root installation directory manually +1. Use `--with-PKG=/path/to/pkg` to specify exact location #### Feature Control Options (`--enable-FEATURE`) @@ -573,15 +636,16 @@ For packages serving the same purpose, mode variables act as selectors: - `--mpi-mode=openmpi|mpich|intelmpi`: Choose MPI implementation - `--math-mode=openblas|mkl|aocl`: Choose math library -**Note**: While `--with-PKG` controls the installation method, the `PKG_MODE` variable picks which package to actually use, providing maximum flexibility. +**Note**: While `--with-PKG` controls the installation method, the `PKG_MODE` variable picks which +package to actually use, providing maximum flexibility. ### Adding New Packages 1. **Create installation script**: `scripts/stageN/install_newpkg.sh` -2. **Add to stage script**: Include in `scripts/stageN/install_stageN.sh` -3. **Update configuration**: Add options to `config_manager.sh` -4. **Add version info**: Update `scripts/package_versions.sh` -5. **Test thoroughly**: Verify with different toolchain combinations +1. **Add to stage script**: Include in `scripts/stageN/install_stageN.sh` +1. **Update configuration**: Add options to `config_manager.sh` +1. **Add version info**: Update `scripts/package_versions.sh` +1. **Test thoroughly**: Verify with different toolchain combinations ### Advanced Developer Features @@ -594,6 +658,7 @@ IF_XYZ(A | B) ``` This construct is parsed by `scripts/parse_if.py`: + - Evaluates to *A* if *XYZ* is passed as command line option - Evaluates to *B* if *XYZ* is not passed @@ -604,8 +669,9 @@ IF_XYZ(IF_ABC(flag1|flag2) | flag3) ``` This parses to: + - *flag1* if both *XYZ* and *ABC* are present -- *flag2* if only *XYZ* is present +- *flag2* if only *XYZ* is present - *flag3* if neither is present #### Portability Requirements @@ -649,7 +715,8 @@ check_gfortran_module module_name ### Best Practices - **Reuse toolkit functions**: Use macros from `scripts/tool_kit.sh` -- **Modular functionality**: Add new functionality as macros in `scripts/tool_kit.sh` rather than inline code +- **Modular functionality**: Add new functionality as macros in `scripts/tool_kit.sh` rather than + inline code - **Portable compiler flags**: Filter through `allowed_gcc_flags` and `allowed_gfortran_flags` - **Environment variables**: Use `${VAR:-default}` pattern for configurable defaults - **Lock files**: Create completion markers for resumable installation @@ -658,11 +725,15 @@ check_gfortran_module module_name ## License -The ABACUS Toolchain downloads and installs only [GPL-compatible](https://www.gnu.org/licenses/gpl-faq.html#WhatDoesCompatMean) packages. All included packages maintain their original licenses as listed in the Dependencies section above. +The ABACUS Toolchain downloads and installs only +[GPL-compatible](https://www.gnu.org/licenses/gpl-faq.html#WhatDoesCompatMean) packages. All +included packages maintain their original licenses as listed in the Dependencies section above. -**License Compatibility**: All packages use GPL-compatible licenses including BSD, MIT, LGPL, MPL-2.0, and GPL variants, ensuring seamless integration with GPL-licensed software. +**License Compatibility**: All packages use GPL-compatible licenses including BSD, MIT, LGPL, +MPL-2.0, and GPL variants, ensuring seamless integration with GPL-licensed software. -**Note**: Proprietary packages like Intel OneAPI (MKL/Compiler/MPI) and AMD AOCC/AOCL are supported but must be installed separately by the user. +**Note**: Proprietary packages like Intel OneAPI (MKL/Compiler/MPI) and AMD AOCC/AOCL are supported +but must be installed separately by the user. ## Contributing @@ -671,7 +742,7 @@ We welcome contributions to improve the ABACUS Toolchain! Here's how you can hel ### Reporting Issues 1. **Search existing issues** before creating new ones -2. **Provide detailed information**: +1. **Provide detailed information**: - Operating system and version - Compiler versions - Complete error messages and logs @@ -680,12 +751,12 @@ We welcome contributions to improve the ABACUS Toolchain! Here's how you can hel ### Contributing Code 1. **Fork the repository** and create a feature branch -2. **Follow coding standards**: +1. **Follow coding standards**: - Use consistent shell scripting style - Add comments for complex logic - Test with multiple toolchain combinations -3. **Update documentation** for new features -4. **Submit pull request** with clear description +1. **Update documentation** for new features +1. **Submit pull request** with clear description ### Development Setup @@ -701,11 +772,12 @@ cd abacus-develop/toolchain ### Areas for Contribution - 🔧 **New package support**: Add support for additional scientific libraries -- 🐛 **Bug fixes**: Resolve compatibility issues and installation problems +- 🐛 **Bug fixes**: Resolve compatibility issues and installation problems - 📚 **Documentation**: Improve guides and troubleshooting information - 🧪 **Testing**: Expand test coverage for different systems and configurations - 🚀 **Performance**: Optimize installation speed and resource usage ---- +______________________________________________________________________ -**For questions, issues, or contributions, please visit the [ABACUS GitHub repository](https://github.com/deepmodeling/abacus-develop).** +**For questions, issues, or contributions, please visit the +[ABACUS GitHub repository](https://github.com/deepmodeling/abacus-develop).** diff --git a/toolchain/build_abacus_aocc-aocl.sh b/toolchain/build_abacus_aocc-aocl.sh index 63c29b6eb2d..6ea7cfef956 100755 --- a/toolchain/build_abacus_aocc-aocl.sh +++ b/toolchain/build_abacus_aocc-aocl.sh @@ -63,7 +63,7 @@ cmake -B $BUILD_DIR -DCMAKE_INSTALL_PREFIX=$PREFIX \ # -DENABLE_MLALGO=1 \ # -DTorch_DIR=$LIBTORCH \ # -Dlibnpy_INCLUDE_DIR=$LIBNPY \ -# -DDeePMD_DIR=$DEEPMD \ +# -DDeePMD_DIR=$DEEPMD \ # -DENABLE_CUSOLVERMP=ON \ cmake --build $BUILD_DIR -j `nproc` diff --git a/toolchain/build_abacus_gcc-aocl.sh b/toolchain/build_abacus_gcc-aocl.sh index 1faf1843d25..77e6b321707 100755 --- a/toolchain/build_abacus_gcc-aocl.sh +++ b/toolchain/build_abacus_gcc-aocl.sh @@ -61,7 +61,7 @@ cmake -B $BUILD_DIR -DCMAKE_INSTALL_PREFIX=$PREFIX \ # -DENABLE_MLALGO=1 \ # -DTorch_DIR=$LIBTORCH \ # -Dlibnpy_INCLUDE_DIR=$LIBNPY \ -# -DDeePMD_DIR=$DEEPMD \ +# -DDeePMD_DIR=$DEEPMD \ # -DENABLE_CUSOLVERMP=ON \ cmake --build $BUILD_DIR -j `nproc` diff --git a/toolchain/build_abacus_gcc-mkl.sh b/toolchain/build_abacus_gcc-mkl.sh index e35f2be558f..ff7f735638c 100755 --- a/toolchain/build_abacus_gcc-mkl.sh +++ b/toolchain/build_abacus_gcc-mkl.sh @@ -57,7 +57,7 @@ cmake -B $BUILD_DIR -DCMAKE_INSTALL_PREFIX=$PREFIX \ # -DENABLE_MLALGO=1 \ # -DTorch_DIR=$LIBTORCH \ # -Dlibnpy_INCLUDE_DIR=$LIBNPY \ -# -DDeePMD_DIR=$DEEPMD \ +# -DDeePMD_DIR=$DEEPMD \ # -DENABLE_CUSOLVERMP=ON \ cmake --build $BUILD_DIR -j `nproc` diff --git a/toolchain/build_abacus_gnu.sh b/toolchain/build_abacus_gnu.sh index 69cf152c6ca..038cf1aa6a5 100755 --- a/toolchain/build_abacus_gnu.sh +++ b/toolchain/build_abacus_gnu.sh @@ -59,7 +59,7 @@ cmake -B $BUILD_DIR -DCMAKE_INSTALL_PREFIX=$PREFIX \ # -DENABLE_MLALGO=1 \ # -DTorch_DIR=$LIBTORCH \ # -Dlibnpy_INCLUDE_DIR=$LIBNPY \ -# -DDeePMD_DIR=$DEEPMD \ +# -DDeePMD_DIR=$DEEPMD \ # -DENABLE_CUSOLVERMP=ON \ cmake --build $BUILD_DIR -j `nproc` diff --git a/toolchain/build_abacus_intel.sh b/toolchain/build_abacus_intel.sh index d08118935fe..662ee1591c3 100755 --- a/toolchain/build_abacus_intel.sh +++ b/toolchain/build_abacus_intel.sh @@ -49,16 +49,16 @@ cmake -B $BUILD_DIR -DCMAKE_INSTALL_PREFIX=$PREFIX \ -DUSE_ELPA=ON \ -DENABLE_RAPIDJSON=ON \ -DRapidJSON_DIR=$RAPIDJSON \ - -DENABLE_LIBRI=ON \ + -DENABLE_LIBRI=ON \ -DLIBRI_DIR=$LIBRI \ - -DLIBCOMM_DIR=$LIBCOMM \ + -DLIBCOMM_DIR=$LIBCOMM \ -DUSE_CUDA=$USE_CUDA \ # -DCMAKE_CUDA_COMPILER=/path/to/cuda/bin/nvcc \ # -DNEP_DIR=$NEP_DIR \ # -DENABLE_MLALGO=1 \ # -DTorch_DIR=$LIBTORCH \ # -Dlibnpy_INCLUDE_DIR=$LIBNPY \ -# -DDeePMD_DIR=$DEEPMD \ +# -DDeePMD_DIR=$DEEPMD \ # -DENABLE_CUSOLVERMP=ON \ cmake --build $BUILD_DIR -j `nproc` diff --git a/toolchain/scripts/stage4/install_nep.sh b/toolchain/scripts/stage4/install_nep.sh index 2d0bbfdbe9d..2a3423dab69 100755 --- a/toolchain/scripts/stage4/install_nep.sh +++ b/toolchain/scripts/stage4/install_nep.sh @@ -71,22 +71,22 @@ all: \$(TARGET) # Rule to build the shared library \$(TARGET): \$(OBJS) - \$(CXX) -shared \$(OBJS) -o \$(TARGET) + \$(CXX) -shared \$(OBJS) -o \$(TARGET) # Rule to compile source files into object files %.o: %.cpp - \$(CXX) \$(CXXFLAGS) \$(INCLUDES) -c \$< -o \$@ + \$(CXX) \$(CXXFLAGS) \$(INCLUDES) -c \$< -o \$@ # Clean up build files clean: - rm -f \$(OBJS) \$(TARGET) + rm -f \$(OBJS) \$(TARGET) # Install target install: - mkdir -p \$(PREFIX)/lib - mkdir -p \$(PREFIX)/include - cp \$(TARGET) \$(PREFIX)/lib/ - cp src/*.h \$(PREFIX)/include/ + mkdir -p \$(PREFIX)/lib + mkdir -p \$(PREFIX)/include + cp \$(TARGET) \$(PREFIX)/lib/ + cp src/*.h \$(PREFIX)/include/ EOF make > make.log 2>&1 || tail -n ${LOG_LINES} make.log From 319dfd2a685ecaecb4b630308c64ab090c6e89f4 Mon Sep 17 00:00:00 2001 From: Growl Date: Wed, 13 May 2026 18:58:09 +0800 Subject: [PATCH 6/7] Make pretty (interfaces/, tools/) --- interfaces/ASE_interface/DEVELOP.md | 70 +- interfaces/ASE_interface/README.md | 30 +- .../ASE_interface/abacuslite/__init__.py | 9 +- interfaces/ASE_interface/abacuslite/core.py | 2 +- .../ASE_interface/abacuslite/io/generalio.py | 894 ++-- .../ASE_interface/abacuslite/io/latestio.py | 606 +-- .../ASE_interface/abacuslite/io/legacyio.py | 1016 +++-- .../abacuslite/io/testfiles/input-script | 24 +- .../io/testfiles/pw-symm0-nspin4-gamma-md_ | 14 +- .../abacuslite/utils/ksampling.py | 240 +- .../ASE_interface/examples/bandstructure.py | 54 +- .../ASE_interface/examples/cellrelax.py | 56 +- .../ASE_interface/examples/constraintmd.py | 77 +- interfaces/ASE_interface/examples/dos.py | 48 +- interfaces/ASE_interface/examples/md.py | 51 +- .../ASE_interface/examples/metadynamics.py | 122 +- interfaces/ASE_interface/examples/neb.py | 126 +- interfaces/ASE_interface/examples/relax.py | 48 +- interfaces/ASE_interface/examples/scf.py | 40 +- interfaces/ASE_interface/examples/soc.py | 75 +- interfaces/ASE_interface/tests/band.py | 35 +- interfaces/ASE_interface/tests/magnetic.py | 143 +- interfaces/ASE_interface/tests/md.py | 32 +- interfaces/ASE_interface/tests/relax.py | 29 +- interfaces/ASE_interface/tests/scf.py | 23 +- interfaces/DPGEN_interface/README.md | 39 +- interfaces/DPGEN_interface/autotest/INPUT.rlx | 2 +- .../DPGEN_interface/autotest/machine.json | 2 +- .../DPGEN_interface/autotest/property.json | 14 +- .../DPGEN_interface/init_and_run/INPUT.md | 30 +- .../DPGEN_interface/init_and_run/init.json | 38 +- .../DPGEN_interface/init_and_run/machine.json | 2 +- interfaces/HefeiNAMD_interface/README.md | 57 +- interfaces/Phonopy_interface/README.md | 40 +- .../Phonopy_interface/example01/STRU-001 | 2 +- .../ShengBTE_interface/01_pw/2nd/au2si.py | 8 +- .../ShengBTE_interface/01_pw/3rd/aba2vasp.py | 65 +- .../ShengBTE_interface/01_pw/3rd/pos2stru.py | 15 +- .../ShengBTE_interface/02_lcao/2nd/au2si.py | 8 +- .../02_lcao/3rd/aba2vasp.py | 65 +- .../02_lcao/3rd/pos2stru.py | 17 +- interfaces/ShengBTE_interface/README.md | 29 +- interfaces/Wannier90_interface/README.md | 75 +- .../Wannier90_interface/abacusw90/README.md | 75 +- .../abacusw90/interface.py | 4 +- .../Wannier90_interface/examples/01_lcao/STRU | 2 +- .../Wannier90_interface/examples/02_pw/STRU | 2 +- .../examples/03_lcao_in_pw/STRU | 2 +- .../examples_python/example_advanced.py | 10 +- .../examples_python/example_basic.py | 14 +- .../examples_python/example_pw.py | 6 +- tools/README.md | 4 +- tools/SIAB/Generate_Orbital_AllInOne.sh | 46 +- .../example_opt_abfs_bash/exx.py | 132 +- .../example_opt_abfs_bash/opt_orb.py | 184 +- .../example_opt_abfs_bash/read_stru.py | 383 +- .../example_opt_abfs_bash/set_dimer.py | 342 +- .../example_opt_abfs_bash/utils.py | 70 +- .../example_opt_lcao_bash/dis.py | 206 +- .../generate_orbital_mixstru.sh | 38 +- .../example_opt_lcao_bash/info.json | 36 +- .../example_opt_lcao_bash/info_linpz.json | 36 +- .../example_opt_lcao_bash/opt_orb.py | 65 +- .../example_opt_lcao_bash/opt_orb/C.dat | 212 +- .../opt_orb/ORBITAL_RESULTS.txt | 212 +- .../example_opt_lcao_bash/opt_orb/input.json | 2 +- .../opt_orb/running_stdout.log | 30 +- .../example_opt_lcao_bash/print_file.py | 354 +- .../example_opt_lcao_bash/read_info.py | 51 +- .../example_opt_lcao_bash/utils.py | 6 +- .../SIAB/PyTorchGradient/source/IO/func_C.py | 181 +- .../PyTorchGradient/source/IO/print_QSV.py | 59 +- .../source/IO/print_orbital.py | 207 +- .../PyTorchGradient/source/IO/read_QSV.py | 361 +- .../PyTorchGradient/source/IO/read_json.py | 117 +- tools/SIAB/PyTorchGradient/source/inverse.py | 111 +- tools/SIAB/PyTorchGradient/source/main.py | 142 +- .../PyTorchGradient/source/opt_orbital.py | 252 +- .../source/opt_orbital.py_real | 172 +- tools/SIAB/PyTorchGradient/source/orbital.py | 158 +- tools/SIAB/PyTorchGradient/source/pf.py | 3 +- .../PyTorchGradient/source/torch_complex.py | 216 +- .../source/unittest_inverse.py | 59 +- tools/SIAB/PyTorchGradient/source/util.py | 76 +- tools/SIAB/README.md | 23 +- tools/SIAB/SimulatedAnnealing/source/Makefile | 164 +- .../SIAB/SimulatedAnnealing/source/README.md | 12 +- .../source/src_parallel/parallel_common.cpp | 135 +- .../source/src_parallel/parallel_common.h | 31 +- .../source/src_parallel/parallel_global.cpp | 123 +- .../source/src_parallel/parallel_global.h | 52 +- .../source/src_parallel/parallel_kpoints.cpp | 469 +- .../source/src_parallel/parallel_kpoints.h | 45 +- .../source/src_parallel/parallel_reduce.cpp | 230 +- .../source/src_parallel/parallel_reduce.h | 54 +- .../source/src_pw/bessel_basis.cpp | 265 +- .../source/src_pw/bessel_basis.h | 48 +- .../source/src_pw/heapsort.cpp | 106 +- .../source/src_pw/heapsort.h | 6 +- .../source/src_pw/memory_calculation.cpp | 113 +- .../source/src_pw/memory_calculation.h | 12 +- .../source/src_pw/numerical_basis.cpp | 18 +- .../source/src_pw/numerical_basis.h | 19 +- .../source/src_pw/pw_basis.cpp | 745 ++- .../source/src_pw/pw_basis.h | 206 +- .../source/src_pw/pw_complement.cpp | 177 +- .../source/src_pw/pw_complement.h | 35 +- .../source/src_pw/ylm_real.cpp | 337 +- .../source/src_pw/ylm_real.h | 11 +- .../source/src_spillage/Calculate_C4.cpp | 987 ++-- .../source/src_spillage/Calculate_C4.h | 65 +- .../source/src_spillage/Coefficients.cpp | 313 +- .../source/src_spillage/Coefficients.h | 97 +- .../source/src_spillage/Inverse_Matrix_S.cpp | 73 +- .../source/src_spillage/Inverse_Matrix_S.h | 50 +- .../src_spillage/Inverse_Matrix_S_inline.h | 37 +- .../source/src_spillage/Metropolis.cpp | 231 +- .../source/src_spillage/Metropolis.h | 191 +- .../source/src_spillage/Metropolis_2.cpp | 830 ++-- .../source/src_spillage/Metropolis_Info.h | 47 +- .../source/src_spillage/MultiZeta.cpp | 338 +- .../source/src_spillage/MultiZeta.h | 45 +- .../source/src_spillage/Orthogonal.cpp | 224 +- .../source/src_spillage/Orthogonal.h | 14 +- .../source/src_spillage/Out_Orbital.cpp | 371 +- .../source/src_spillage/Out_Orbital.h | 26 +- .../source/src_spillage/Plot_Psi.cpp | 1133 +++-- .../source/src_spillage/Plot_Psi.h | 101 +- .../source/src_spillage/Psi_Second.cpp | 594 ++- .../source/src_spillage/Psi_Second.h | 108 +- .../source/src_spillage/ReadData.cpp | 918 ++-- .../source/src_spillage/ReadData.h | 61 +- .../Simulated_Annealing_Orbital.h | 256 +- .../source/src_spillage/SpillageStep.cpp | 1000 ++--- .../source/src_spillage/SpillageStep.h | 84 +- .../source/src_spillage/SpillageValue.cpp | 203 +- .../source/src_spillage/SpillageValue.h | 89 +- .../source/src_spillage/Step_Data.cpp | 171 +- .../source/src_spillage/Step_Data.h | 55 +- .../source/src_spillage/Type_Information.cpp | 135 +- .../source/src_spillage/Type_Information.h | 39 +- .../source/src_spillage/common.cpp | 132 +- .../source/src_spillage/common.h | 66 +- .../source/src_spillage/main.cpp | 105 +- .../source/src_spillage/read_INPUT.cpp | 801 ++-- .../source/src_spillage/read_INPUT.h | 54 +- .../source/src_spillage/tools.cpp | 77 +- .../source/src_spillage/tools.h | 36 +- .../source/src_tools/Gram_Schmidt_Orth.h | 278 +- .../src_tools/Gram_Schmidt_Orth_bak.cpp | 132 +- .../source/src_tools/Gram_Schmidt_Orth_bak.h | 108 +- .../source/src_tools/Random.h | 64 +- .../source/src_tools/Simulated_Annealing.cpp | 158 +- .../source/src_tools/Simulated_Annealing.h | 111 +- .../source/src_tools/complexarray.cpp | 170 +- .../source/src_tools/complexarray.h | 68 +- .../source/src_tools/complexmatrix.h | 207 +- .../source/src_tools/complexmatrix_inline.h | 680 ++- .../source/src_tools/intarray.cpp | 365 +- .../source/src_tools/intarray.h | 92 +- .../source/src_tools/inverse_matrix.cpp | 54 +- .../source/src_tools/inverse_matrix.h | 17 +- .../src_tools/inverse_matrix_iterate.cpp | 4 - .../source/src_tools/inverse_matrix_iterate.h | 107 +- .../src_tools/inverse_matrix_iterate_bak.cpp | 133 +- .../src_tools/inverse_matrix_iterate_inline.h | 138 +- .../src_tools/inverse_matrix_perturbe.cpp | 43 +- .../src_tools/inverse_matrix_perturbe.h | 57 +- .../source/src_tools/lapack_connector.h | 900 ++-- .../source/src_tools/mathzone.cpp | 775 ++-- .../source/src_tools/mathzone.h | 81 +- .../source/src_tools/matrix.cpp | 251 +- .../source/src_tools/matrix.h | 95 +- .../source/src_tools/matrix3.cpp | 416 +- .../source/src_tools/matrix3.h | 76 +- .../source/src_tools/realarray.cpp | 181 +- .../source/src_tools/realarray.h | 78 +- .../source/src_tools/timer.cpp | 375 +- .../source/src_tools/timer.h | 103 +- .../source/src_tools/vector3.h | 249 +- .../src_unittest/src_tools/common_test.h | 71 +- .../inverse_matrix_iterate_unittest.h | 47 +- .../inverse_matrix_perturbe_unittest.h | 135 +- .../src_tools/inverse_matrix_unittest.h | 28 +- .../src_unittest/src_tools/matrix_multiply.h | 88 +- .../SimulatedAnnealing/source/tests_p/INPUT | 72 +- .../SimulatedAnnealing/source/tests_s/INPUT | 8 +- tools/average_pot/aveElecStatPot.py | 29 +- tools/generate_orbital.sh | 1252 +++++- tools/molden/molden.py | 978 ++-- tools/opt_abfs_bash/exx.py | 132 +- tools/opt_abfs_bash/opt_orb.py | 184 +- tools/opt_abfs_bash/read_stru.py | 396 +- tools/opt_abfs_bash/set_dimer.py | 346 +- tools/opt_abfs_bash/utils.py | 70 +- tools/opt_lcao_bash/dis.py | 206 +- tools/opt_lcao_bash/opt_orb.py | 65 +- tools/opt_lcao_bash/print_file.py | 430 +- tools/opt_lcao_bash/read_info.py | 51 +- tools/opt_lcao_bash/utils.py | 6 +- tools/opt_orb_pytorch/IO/func_C.py | 162 +- tools/opt_orb_pytorch/IO/print_QSV.py | 59 +- tools/opt_orb_pytorch/IO/print_orbital.py | 100 +- tools/opt_orb_pytorch/IO/read_QSV.py | 361 +- tools/opt_orb_pytorch/IO/read_json.py | 117 +- tools/opt_orb_pytorch/inverse.py | 111 +- tools/opt_orb_pytorch/main.py | 100 +- tools/opt_orb_pytorch/opt_orbital.py | 252 +- tools/opt_orb_pytorch/opt_orbital.py_real | 172 +- tools/opt_orb_pytorch/orbital.py | 158 +- tools/opt_orb_pytorch/pf.py | 3 +- tools/opt_orb_pytorch/torch_complex.py | 216 +- tools/opt_orb_pytorch/unittest_inverse.py | 59 +- tools/opt_orb_pytorch/util.py | 76 +- tools/opt_orb_pytorch_dpsi/IO/cal_weight.py | 150 +- tools/opt_orb_pytorch_dpsi/IO/change_info.py | 199 +- tools/opt_orb_pytorch_dpsi/IO/func_C.py | 187 +- tools/opt_orb_pytorch_dpsi/IO/print_QSV.py | 59 +- .../opt_orb_pytorch_dpsi/IO/print_orbital.py | 211 +- tools/opt_orb_pytorch_dpsi/IO/read_QSV.py | 307 +- tools/opt_orb_pytorch_dpsi/IO/read_istate.py | 92 +- tools/opt_orb_pytorch_dpsi/IO/read_json.py | 159 +- tools/opt_orb_pytorch_dpsi/main.py | 342 +- tools/opt_orb_pytorch_dpsi/opt_orbital.py | 333 +- tools/opt_orb_pytorch_dpsi/orbital.py | 161 +- .../opt_orb_pytorch_dpsi/torch_complex_bak.py | 217 +- tools/opt_orb_pytorch_dpsi/util.py | 82 +- tools/plot-tools/README.md | 86 +- tools/plot-tools/abacus_plot/__init__.py | 4 +- tools/plot-tools/abacus_plot/band.py | 964 ++-- tools/plot-tools/abacus_plot/dos.py | 482 +- tools/plot-tools/abacus_plot/main.py | 153 +- tools/plot-tools/abacus_plot/utils.py | 100 +- tools/plot-tools/cube_manipulator.py | 229 +- tools/plot-tools/examples/Si/KLINES | 12 +- ...index-1-$p_x$.pdf => atom_index-1-p_x.pdf} | Bin ...index-1-$p_y$.pdf => atom_index-1-p_y.pdf} | Bin tools/plot-tools/setup.py | 22 +- tools/qo/README.md | 124 +- tools/qo/examples/STRU | 12 +- tools/qo/examples/reference/band/STRU | 12 +- tools/qo/examples/reference/scf/STRU | 12 +- tools/qo/postprocess.py | 396 +- tools/rt-tddft-tools/dipole.py | 133 +- .../examples/Absorpation-N2/ABACUS-INPUT | 64 +- .../examples/Absorpation-N2/Abs_plot.py | 11 +- .../examples/Absorpation-N2/efield_0.txt | 4000 ++++++++--------- .../examples/Absorpation-N2/efield_1.txt | 4000 ++++++++--------- .../ground-state-projection-Si/On1.dat | 202 +- .../ground-state-projection-Si/projection.py | 143 +- tools/rt-tddft-tools/overlap_generator.py | 208 +- tools/rt-tddft-tools/plot_absorption.py | 308 +- tools/rt-tddft-tools/projection.py | 145 +- tools/selective_dynamics/README.md | 5 + .../selective_dynamics/selective_dynamics.py | 133 +- tools/stm/plot.py | 38 +- tools/stm/stm.py | 66 +- tools/windows/README.md | 222 +- 258 files changed, 26530 insertions(+), 23964 deletions(-) mode change 120000 => 100755 tools/generate_orbital.sh rename tools/plot-tools/examples/Si/PBAND1_FIG/atom_index-1/{atom_index-1-$p_x$.pdf => atom_index-1-p_x.pdf} (100%) rename tools/plot-tools/examples/Si/PBAND1_FIG/atom_index-1/{atom_index-1-$p_y$.pdf => atom_index-1-p_y.pdf} (100%) diff --git a/interfaces/ASE_interface/DEVELOP.md b/interfaces/ASE_interface/DEVELOP.md index acb1f1384b4..2d13a7209c0 100644 --- a/interfaces/ASE_interface/DEVELOP.md +++ b/interfaces/ASE_interface/DEVELOP.md @@ -1,6 +1,7 @@ # Developer Guide Abacuslite has the following file structure: + ``` . ├── __init__.py @@ -23,45 +24,46 @@ This file contains the implementation of the Atomic Simulation Environment (ASE) ## io -This directory contains the input/output (I/O) functions for extracting information from ABACUS dumped files. A summary is here: +This directory contains the input/output (I/O) functions for extracting information from ABACUS +dumped files. A summary is here: ### Long-term-support (LTS) version -|Item|Regular expression|Example| -|----|----|----| -|esolver_type|'The esolver type has been set to : (\S+)'|`The esolver type has been set to : ksdft_pw`| -|nspin|'nspin\s+=\s+(\d+)'|`nspin = 4`| -|number of bands|'NBANDS\s+=\s+(\d+)'|`NBANDS = 40`| -|number of atoms|'TOTAL ATOM NUMBER\s*=\s*(\d+)'|`TOTAL ATOM NUMBER = 2`| -|lattice constant|'lattice constant \(Angstrom\)\s*=\s*(-?\d+(\.\d+)?)'|`lattice constant (Angstrom) = 0.529177`| -|lattice vectors|'^Lattice vectors: \(Cartesian coordinate: in unit of a_0\)$'|` Lattice vectors: (Cartesian coordinate: in unit of a_0)`| -|coordinate system|'^(DIRECT\|CARTESIAN) COORDINATES'|`DIRECT COORDINATES`| -|atomic positions|'^tau[c\|d]_([A-Z][a-z]?)\d+\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)*'|`taud_As1 0.2500000000 0.2500000000 0.2500000000 1.7321 0.0000000000 0.0000000000 0.0000000000`| -|eigenvalues|'\d+/\d+\s+kpoint\s+\(Cartesian\)\s+=\s+(-?\d(\.\d+)?(e-\d+)?)\s+(-?\d(\.\d+)?(e-\d+)?)\s+(-?\d(\.\d+)?(e-\d\|+)?)\s+\(\d+\s+pws\)'|` 1/1 kpoint (Cartesian) = 0.0000 0.0000 0.0000 (230 pws)`| -|atomic forces|'\s\*TOTAL\-FORCE\s\*\(eV\s*/Angstrom\)'|` TOTAL-FORCE (eV/Angstrom) `| -|total stress|'\s\*TOTAL\-STRESS\s\*\(KBAR\)'|` TOTAL-STRESS (KBAR) `| -|kpoints and weights|'\s\*(IBZ\|KPOINTS)\s+(DIRECT\|CARTESIAN)_X\s+(DIRECT\|CARTESIAN)_Y\s+(DIRECT\|CARTESIAN)_Z\s+WEIGHT(\s+ibz2bz)?'|` KPOINTS DIRECT_X DIRECT_Y DIRECT_Z WEIGHT`| -|energy|'\s*ENERGY\s+Rydberg\s+eV'|` Energy Rydberg eV `| -|total magnetism|'\s\*Total\sMagnetism\s\(uB\)(\s+x\s+y\s+z)?\s\*'|` Total Magnetism (uB) `| +| Item | Regular expression | Example | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| esolver_type | 'The esolver type has been set to : (\\S+)' | `The esolver type has been set to : ksdft_pw` | +| nspin | 'nspin\\s+=\\s+(\\d+)' | `nspin = 4` | +| number of bands | 'NBANDS\\s+=\\s+(\\d+)' | `NBANDS = 40` | +| number of atoms | 'TOTAL ATOM NUMBER\\s\*=\\s\*(\\d+)' | `TOTAL ATOM NUMBER = 2` | +| lattice constant | 'lattice constant (Angstrom)\\s\*=\\s\*(-?\\d+(.\\d+)?)' | `lattice constant (Angstrom) = 0.529177` | +| lattice vectors | '^Lattice vectors: (Cartesian coordinate: in unit of a_0)\$' | ` Lattice vectors: (Cartesian coordinate: in unit of a_0)` | +| coordinate system | '^(DIRECT\|CARTESIAN) COORDINATES' | `DIRECT COORDINATES` | +| atomic positions | '^tau[c\|d]\_([A-Z][a-z]?)\\d+\\s+(-?\\d+(.\\d+)?)\\s+(-?\\d+(.\\d+)?)\\s+(-?\\d+(.\\d+)?)\*' | `taud_As1 0.2500000000 0.2500000000 0.2500000000 1.7321 0.0000000000 0.0000000000 0.0000000000` | +| eigenvalues | '\\d+/\\d+\\s+kpoint\\s+(Cartesian)\\s+=\\s+(-?\\d(.\\d+)?(e-\\d+)?)\\s+(-?\\d(.\\d+)?(e-\\d+)?)\\s+(-?\\d(.\\d+)?(e-\\d\|+)?)\\s+(\\d+\\s+pws)' | ` 1/1 kpoint (Cartesian) = 0.0000 0.0000 0.0000 (230 pws)` | +| atomic forces | '\\s\*TOTAL-FORCE\\s\*(eV\\s\*/Angstrom)' | `TOTAL-FORCE (eV/Angstrom) ` | +| total stress | '\\s\*TOTAL-STRESS\\s\*(KBAR)' | `TOTAL-STRESS (KBAR) ` | +| kpoints and weights | '\\s\*(IBZ\|KPOINTS)\\s+(DIRECT\|CARTESIAN)\_X\\s+(DIRECT\|CARTESIAN)\_Y\\s+(DIRECT\|CARTESIAN)\_Z\\s+WEIGHT(\\s+ibz2bz)?' | ` KPOINTS DIRECT_X DIRECT_Y DIRECT_Z WEIGHT` | +| energy | '\\s\*ENERGY\\s+Rydberg\\s+eV' | ` Energy Rydberg eV ` | +| total magnetism | '\\s\*Total\\sMagnetism\\s(uB)(\\s+x\\s+y\\s+z)?\\s\*' | `Total Magnetism (uB) ` | ### Latest version -|Item|Regular expression|Example|Notes| -|----|----|----|----| -|esolver_type|'#ENERGY SOLVER#\s+(\S+)'|` #ENERGY SOLVER# ksdft_pw`|| -|nspin|'nspin\s+=\s+(\d+)'|`nspin = 4`|| -|number of bands|||has been removed| -|number of atoms|'TOTAL ATOM NUMBER\s*=\s*(\d+)'|`TOTAL ATOM NUMBER = 2`|| -|lattice constant|'lattice constant \(Angstrom\)\s*=\s*(-?\d+(\.\d+)?)'|`lattice constant (Angstrom) = 0.529177`|| -|lattice vectors|'^Lattice vectors: \(Cartesian coordinate: in unit of a_0\)$'|` Lattice vectors: (Cartesian coordinate: in unit of a_0)`|| -|coordinate system|'^(DIRECT\|CARTESIAN) COORDINATES'|`DIRECT COORDINATES`|| -|atomic positions|'atom\s+x\s+y\s+z\s+mag‘|` atom x y z mag`|"tauc/taud" suffix has been removed, therefore the way to read the coordinates changes to find the head of the table, then read the following `number of atoms` lines. On the other hand, if the `calculation` is set to `md`, ABACUS will not dump the atomic positions to running log anymore, instead, will read from the MD_dump file| -|eigenvalues|'spin=(\d)\s+k-point=(\d+)/(\d+)\s+Cartesian=\s*(-?\d(\.\d+)?(e-\d+)?)\s+(-?\d(\.\d+)?(e-\d+)?)\s+(-?\d(\.\d\|+)?(e-\d+)?)\s+\(\d+\s+plane wave\)'| spin=1 k-point=1/1 Cartesian=0.0000000 0.0000000 0.0000000 (1837 plane wave)|eigenvalues information has been removed from the running log, the file istate.info is renamed as eig_occ.txt, where the eigenvalues are read| -|atomic forces|'#\s\*TOTAL\-FORCE\s*\(eV\s*/Angstrom\)\s\*#'|` #TOTAL-FORCE (eV/Angstrom)#`|| -|total stress|'#\s\*TOTAL\-STRESS\s*\(kbar\)\s\*#'|` #TOTAL-STRESS (kbar)# `|| -|kpoints and weights|'\s*(IBZ\|KPOINTS)\s+(DIRECT\|CARTESIAN)_X\s+(DIRECT\|CARTESIAN)_Y\s+(DIRECT\|CARTESIAN)_Z\s+WEIGHT(\s+ibz2bz)?'|` KPOINTS DIRECT_X DIRECT_Y DIRECT_Z WEIGHT`|| -|energy|'\s*ENERGY\s+Rydberg\s+eV'|` Energy Rydberg eV `|| -|total magnetism|'\s\*Total\sMagnetism\s\(uB\)(\s+x\s+y\s+z)?\s\*'|` Total Magnetism (uB) `|| +| Item | Regular expression | Example | Notes | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| esolver_type | '#ENERGY SOLVER#\\s+(\\S+)' | ` #ENERGY SOLVER# ksdft_pw` | | +| nspin | 'nspin\\s+=\\s+(\\d+)' | `nspin = 4` | | +| number of bands | | | has been removed | +| number of atoms | 'TOTAL ATOM NUMBER\\s\*=\\s\*(\\d+)' | `TOTAL ATOM NUMBER = 2` | | +| lattice constant | 'lattice constant (Angstrom)\\s\*=\\s\*(-?\\d+(.\\d+)?)' | `lattice constant (Angstrom) = 0.529177` | | +| lattice vectors | '^Lattice vectors: (Cartesian coordinate: in unit of a_0)\$' | ` Lattice vectors: (Cartesian coordinate: in unit of a_0)` | | +| coordinate system | '^(DIRECT\|CARTESIAN) COORDINATES' | `DIRECT COORDINATES` | | +| atomic positions | 'atom\\s+x\\s+y\\s+z\\s+mag‘ | ` atom x y z mag` | "tauc/taud" suffix has been removed, therefore the way to read the coordinates changes to find the head of the table, then read the following `number of atoms` lines. On the other hand, if the `calculation` is set to `md`, ABACUS will not dump the atomic positions to running log anymore, instead, will read from the MD_dump file | +| eigenvalues | 'spin=(\\d)\\s+k-point=(\\d+)/(\\d+)\\s+Cartesian=\\s\*(-?\\d(.\\d+)?(e-\\d+)?)\\s+(-?\\d(.\\d+)?(e-\\d+)?)\\s+(-?\\d(.\\d\|+)?(e-\\d+)?)\\s+(\\d+\\s+plane wave)' | spin=1 k-point=1/1 Cartesian=0.0000000 0.0000000 0.0000000 (1837 plane wave) | eigenvalues information has been removed from the running log, the file istate.info is renamed as eig_occ.txt, where the eigenvalues are read | +| atomic forces | '#\\s\*TOTAL-FORCE\\s\*(eV\\s\*/Angstrom)\\s\*#' | ` #TOTAL-FORCE (eV/Angstrom)#` | | +| total stress | '#\\s\*TOTAL-STRESS\\s\*(kbar)\\s\*#' | `#TOTAL-STRESS (kbar)# ` | | +| kpoints and weights | '\\s\*(IBZ\|KPOINTS)\\s+(DIRECT\|CARTESIAN)\_X\\s+(DIRECT\|CARTESIAN)\_Y\\s+(DIRECT\|CARTESIAN)\_Z\\s+WEIGHT(\\s+ibz2bz)?' | ` KPOINTS DIRECT_X DIRECT_Y DIRECT_Z WEIGHT` | | +| energy | '\\s\*ENERGY\\s+Rydberg\\s+eV' | ` Energy Rydberg eV ` | | +| total magnetism | '\\s\*Total\\sMagnetism\\s(uB)(\\s+x\\s+y\\s+z)?\\s\*' | `Total Magnetism (uB) ` | | Please look at detailed implementations in the following files. @@ -87,4 +89,4 @@ This module contains the wrapper of k-point sampling functions and helper functi ## xtest.sh -This script can run all the unittests that programmed in all Python source files. \ No newline at end of file +This script can run all the unittests that programmed in all Python source files. diff --git a/interfaces/ASE_interface/README.md b/interfaces/ASE_interface/README.md index 824e69900de..61397f51600 100644 --- a/interfaces/ASE_interface/README.md +++ b/interfaces/ASE_interface/README.md @@ -2,14 +2,18 @@ ## Introduction -abacuslite is a lightweight plugin for ABACUS (Atomic-orbital Based Ab-initio Computation at UStc), implementing the ASE (Atomic Simulation Environment) calculator interface. +abacuslite is a lightweight plugin for ABACUS (Atomic-orbital Based Ab-initio Computation at UStc), +implementing the ASE (Atomic Simulation Environment) calculator interface. ### Key Features - **Lightweight Design**: Implemented as a plugin, no need to modify ASE core code -- **Version Compatibility**: No longer restricted to specific ASE versions, works with most ASE versions -- **ASE Integration**: Uses ASE as the running platform, making ABACUS a callable calculator within it -- **Function Support**: Currently only supports SCF (Self-Consistent Field) functionality, returning energy, forces, stress, etc. +- **Version Compatibility**: No longer restricted to specific ASE versions, works with most ASE + versions +- **ASE Integration**: Uses ASE as the running platform, making ABACUS a callable calculator within + it +- **Function Support**: Currently only supports SCF (Self-Consistent Field) functionality, returning + energy, forces, stress, etc. ## Installation @@ -24,14 +28,14 @@ pip install . Please refer to the example scripts in the `examples` folder. Recommended learning path: 1. **scf.py** - Basic SCF calculation example -2. **relax.py** - Atomic position relaxation calculation -3. **cellrelax.py** - Cell parameter relaxation calculation -4. **bandstructure.py** - Band structure calculation -5. **dos.py** - Density of states calculation -6. **md.py** - Molecular dynamics simulation -7. **constraintmd.py** - Constrained molecular dynamics simulation -8. **metadynamics.py** - Metadynamics simulation -9. **neb.py** - Nudged Elastic Band (NEB) calculation +1. **relax.py** - Atomic position relaxation calculation +1. **cellrelax.py** - Cell parameter relaxation calculation +1. **bandstructure.py** - Band structure calculation +1. **dos.py** - Density of states calculation +1. **md.py** - Molecular dynamics simulation +1. **constraintmd.py** - Constrained molecular dynamics simulation +1. **metadynamics.py** - Metadynamics simulation +1. **neb.py** - Nudged Elastic Band (NEB) calculation More usage examples will be provided in future versions. @@ -54,4 +58,4 @@ Thanks to the ABACUS development team for their support and contributions. If you have any questions or suggestions, please contact us through: -- GitHub: [deepmodeling/abacus-develop](https://github.com/deepmodeling/abacus-develop) \ No newline at end of file +- GitHub: [deepmodeling/abacus-develop](https://github.com/deepmodeling/abacus-develop) diff --git a/interfaces/ASE_interface/abacuslite/__init__.py b/interfaces/ASE_interface/abacuslite/__init__.py index fe361f81bad..5e2960c9137 100644 --- a/interfaces/ASE_interface/abacuslite/__init__.py +++ b/interfaces/ASE_interface/abacuslite/__init__.py @@ -1,6 +1,6 @@ -''' +""" interfaces to Atomic-orbital Based Ab-initio Computation at UStc (ABACUS), -for more information about this DFT calculator, +for more information about this DFT calculator, please refer to the Github official repository: https://github.com/deepmodeling/abacus-develop and online-manual: @@ -9,5 +9,6 @@ For a more complete ABACUS pre-/post-processing workflow package, please refer to the ABACUSTest package: https://github.com/pxlxingliang/abacus-test -''' -from .core import * \ No newline at end of file +""" + +from .core import * diff --git a/interfaces/ASE_interface/abacuslite/core.py b/interfaces/ASE_interface/abacuslite/core.py index f5697eb6c58..6a6879ead4a 100644 --- a/interfaces/ASE_interface/abacuslite/core.py +++ b/interfaces/ASE_interface/abacuslite/core.py @@ -633,4 +633,4 @@ def test_restart(self): self.assertAlmostEqual(e2, e) if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/interfaces/ASE_interface/abacuslite/io/generalio.py b/interfaces/ASE_interface/abacuslite/io/generalio.py index a2ba99e7f15..766290bb3f8 100644 --- a/interfaces/ASE_interface/abacuslite/io/generalio.py +++ b/interfaces/ASE_interface/abacuslite/io/generalio.py @@ -1,5 +1,6 @@ -'''public functions that can be used by both the LTS and the latest -version of ABACUS''' +"""public functions that can be used by both the LTS and the latest +version of ABACUS""" + import re import os import tempfile @@ -12,67 +13,76 @@ from ase.atoms import Atoms from ase.build import bulk from ase.data import chemical_symbols, atomic_masses + ATOM_MASS = dict(zip(chemical_symbols, atomic_masses.tolist())) + def load_pseudo(pseudo_dir: str) -> Dict[str, str]: - '''load the pseudopotential mapping from the pseudo_dir''' + """load the pseudopotential mapping from the pseudo_dir""" pseudo_dir = Path(pseudo_dir) - UPFPAT_ = r'^([A-Z][a-z]?)([^a-zA-Z]+\S+)?\.(upf|UPF)$' + UPFPAT_ = r"^([A-Z][a-z]?)([^a-zA-Z]+\S+)?\.(upf|UPF)$" # the file name is assumed to have the pattern: # [element symbol][delimeter][other things...][.upf|UPF] - return {re.match(UPFPAT_, f.name).group(1): f.name - for f in pseudo_dir.glob('*') - if re.match(UPFPAT_, f.name)} + return { + re.match(UPFPAT_, f.name).group(1): f.name + for f in pseudo_dir.glob("*") + if re.match(UPFPAT_, f.name) + } -def load_orbital(orbital_dir: str, efficiency: bool=True) -> Dict[str, str]: - '''load the ABACUS numerical atomic orbital mapping from the + +def load_orbital(orbital_dir: str, efficiency: bool = True) -> Dict[str, str]: + """load the ABACUS numerical atomic orbital mapping from the orbital dir. There may be the case that there is not only one orbitals find for one element, in this case, the second parameter - `efficiency` will take its effect: if true, use the "smaller" + `efficiency` will take its effect: if true, use the "smaller" one, otherwise, use the "larger" one - + Parameters ---------- orbital_dir : str The directory containing the orbital basis files. efficiency : bool, optional Whether to use the "smaller" one, default is True. - + Returns ------- Dict[str, str] The mapping from element symbol to orbital basis file name. - ''' + """ + # a small helper function def _basis_size(basis: List[str]) -> int: - SPECTRUM = 'spdfghi' - num, symb = zip(*[re.match(r'(\d+)([spdfghi])', b).groups() for b in basis]) - return sum((2*SPECTRUM.index(s) + 1) * int(n) for n, s in zip(num, symb)) - + SPECTRUM = "spdfghi" + num, symb = zip(*[re.match(r"(\d+)([spdfghi])", b).groups() for b in basis]) + return sum((2 * SPECTRUM.index(s) + 1) * int(n) for n, s in zip(num, symb)) + orbital_dir = Path(orbital_dir) - ORBPAT_ = r'^([A-Z][a-z]?)_gga_(\d+)au_(\d+(\.\d+)?)Ry_(\w+)\.orb$' + ORBPAT_ = r"^([A-Z][a-z]?)_gga_(\d+)au_(\d+(\.\d+)?)Ry_(\w+)\.orb$" # a correct parse would yield: # elem, rcut, ecut, components = re.match(ORBPAT_, f.name) tosort = {} - for f in orbital_dir.glob('*'): + for f in orbital_dir.glob("*"): m = re.match(ORBPAT_, f.name) if m: elem, rcut, ecut, _, components = m.groups() - components = re.findall(r'\d+[spdfghi]', components) + components = re.findall(r"\d+[spdfghi]", components) tosort.setdefault(elem, []).append( (f.name, int(rcut), float(ecut), _basis_size(components)) ) # sort the basis files by their size: first by components, then by rcut, then by ecut ib = 0 if efficiency else -1 - return {elem: sorted(basis, key=lambda b: (b[3], b[1], b[2]))[ib][0] - for elem, basis in tosort.items()} + return { + elem: sorted(basis, key=lambda b: (b[3], b[1], b[2]))[ib][0] + for elem, basis in tosort.items() + } + -def file_safe_backup(fn: Path, suffix: str = 'bak'): - '''for the case where there are already files with the same name, +def file_safe_backup(fn: Path, suffix: str = "bak"): + """for the case where there are already files with the same name, add a suffix to the file name, like `STRU.bak.0`. If there are already `STRU.bak.0`, rename the elder to `STRU.bak.1` and let the latest one be `STRU.bak.0`. - + Parameters ---------- fn : Path @@ -81,26 +91,29 @@ def file_safe_backup(fn: Path, suffix: str = 'bak'): function. suffix : str, optional The suffix to add to the file name. Default is 'bak' - ''' + """ assert isinstance(fn, Path) where = fn.parent # get the backup files - fbak = sorted(list(where.glob(f'{fn.name}.{suffix}.*')), - key=lambda p: int(p.name.split('.')[-1])) + fbak = sorted( + list(where.glob(f"{fn.name}.{suffix}.*")), + key=lambda p: int(p.name.split(".")[-1]), + ) if fbak: # rename the elder by adding 1 to the suffix - for i, f in enumerate(fbak[::-1]): # reverse order, to avoid overwrite - j = len(fbak) - i + 1 #: STRU.bak.i -> STRU.bak.i+1 - fname = f.name.replace(f'.{j}', f'.{j+1}') + for i, f in enumerate(fbak[::-1]): # reverse order, to avoid overwrite + j = len(fbak) - i + 1 #: STRU.bak.i -> STRU.bak.i+1 + fname = f.name.replace(f".{j}", f".{j+1}") f.rename(f.parent / fname) - + # backup the latest file, if there is one if fn.exists(): - fn.rename(fn.parent / f'{fn.name}.{suffix}.0') + fn.rename(fn.parent / f"{fn.name}.{suffix}.0") + -def _write_stru(job_dir, stru, fname='STRU'): - ''' +def _write_stru(job_dir, stru, fname="STRU"): + """ Generates a ABACUS STRU file from a STRU dict. Parameters @@ -113,76 +126,84 @@ def _write_stru(job_dir, stru, fname='STRU'): fname : str Name of the STRU file. - ''' - with open(Path(job_dir) / fname, 'w') as f: + """ + with open(Path(job_dir) / fname, "w") as f: - #============ ATOMIC_SPECIES ============ - f.write('ATOMIC_SPECIES\n') - width = {key + '_w' : max([len(str(s[key])) for s in stru['species']]) - for key in ['symbol', 'mass', 'pp_file']} - for s in stru['species']: - f.write('{symbol:<{symbol_w}} {mass:>{mass_w}} {pp_file:>{pp_file_w}}'.format(**s, **width)) - if 'pp_type' in s: + # ============ ATOMIC_SPECIES ============ + f.write("ATOMIC_SPECIES\n") + width = { + key + "_w": max([len(str(s[key])) for s in stru["species"]]) + for key in ["symbol", "mass", "pp_file"] + } + for s in stru["species"]: + f.write( + "{symbol:<{symbol_w}} {mass:>{mass_w}} {pp_file:>{pp_file_w}}".format( + **s, **width + ) + ) + if "pp_type" in s: f.write(f" {s['pp_type']}") - f.write('\n') + f.write("\n") - #============ NUMERICAL_ORBITAL ============ - if 'orb_file' in stru['species'][0]: - f.write('\nNUMERICAL_ORBITAL\n') - for s in stru['species']: + # ============ NUMERICAL_ORBITAL ============ + if "orb_file" in stru["species"][0]: + f.write("\nNUMERICAL_ORBITAL\n") + for s in stru["species"]: f.write(f"{s['orb_file']}\n") - - #============ LATTICE_CONSTANT/PARAMETER/VECTORS ============ - f.write('\nLATTICE_CONSTANT\n') + + # ============ LATTICE_CONSTANT/PARAMETER/VECTORS ============ + f.write("\nLATTICE_CONSTANT\n") f.write(f"{stru['lat']['const']}\n") - if 'vec' in stru['lat']: - f.write('\nLATTICE_VECTORS\n') - for v in stru['lat']['vec']: - f.write(f'{v[0]} {v[1]} {v[2]}\n') + if "vec" in stru["lat"]: + f.write("\nLATTICE_VECTORS\n") + for v in stru["lat"]["vec"]: + f.write(f"{v[0]} {v[1]} {v[2]}\n") - if 'param' in stru['lat']: - f.write('\nLATTICE_PARAMETER\n') - for param in stru['lat']['param']: - f.write(f'{param} ') - f.write('\n') + if "param" in stru["lat"]: + f.write("\nLATTICE_PARAMETER\n") + for param in stru["lat"]["param"]: + f.write(f"{param} ") + f.write("\n") - #============ ATOMIC_POSITIONS ============ - f.write('\nATOMIC_POSITIONS\n') + # ============ ATOMIC_POSITIONS ============ + f.write("\nATOMIC_POSITIONS\n") f.write(f"{stru['coord_type']}\n") - for s in stru['species']: + for s in stru["species"]: f.write(f"\n{s['symbol']}\n") f.write(f"{s['mag_each']}\n") f.write(f"{s['natom']}\n") - for atom in s['atom']: - f.write(' '.join(f'{x}' for x in atom['coord'])) + for atom in s["atom"]: + f.write(" ".join(f"{x}" for x in atom["coord"])) - for key in ['m', 'v']: # frozen atom / initial velocity + for key in ["m", "v"]: # frozen atom / initial velocity if key in atom: - f.write(f' {key}' + - ''.join(f' {x}' for x in atom[key])) + f.write(f" {key}" + "".join(f" {x}" for x in atom[key])) - if 'mag' in atom: - if not isinstance(atom['mag'], tuple): # collinear + if "mag" in atom: + if not isinstance(atom["mag"], tuple): # collinear f.write(f" mag {atom['mag']}") - else: # non-collinear - mag_coord_type, mag = atom['mag'] - assert mag_coord_type in ['Cartesian', 'Spherical'] - if mag_coord_type == 'Cartesian': - f.write(f' mag {mag[0]} {mag[1]} {mag[2]}') + else: # non-collinear + mag_coord_type, mag = atom["mag"] + assert mag_coord_type in ["Cartesian", "Spherical"] + if mag_coord_type == "Cartesian": + f.write(f" mag {mag[0]} {mag[1]} {mag[2]}") else: - f.write(f' mag {mag[0]} angle1 {mag[1]} angle2 {mag[2]}') + f.write(f" mag {mag[0]} angle1 {mag[1]} angle2 {mag[2]}") + + f.write("\n") - f.write('\n') -def write_stru(stru: Atoms, - outdir: str, - pp_file: Optional[Dict[str, str]], - orb_file: Optional[Dict[str, str]] = None, - fname: Optional[str] = 'STRU') -> str: - ''' +def write_stru( + stru: Atoms, + outdir: str, + pp_file: Optional[Dict[str, str]], + orb_file: Optional[Dict[str, str]] = None, + fname: Optional[str] = "STRU", +) -> str: + """ write the ABACUS STRU file from an Atoms object into outdir. Parameters @@ -206,15 +227,13 @@ def write_stru(stru: Atoms, ------- str The path to the written STRU file. - ''' - from ase.units import ( - Bohr as __BOHR__, - Angstrom as __ANGSTROM__ - ) + """ + from ase.units import Bohr as __BOHR__, Angstrom as __ANGSTROM__ + assert isinstance(stru, Atoms) - pp_file = pp_file or {} # can be None, for those non-ESolver_KS cases + pp_file = pp_file or {} # can be None, for those non-ESolver_KS cases - elem = stru.get_chemical_symbols() + elem = stru.get_chemical_symbols() # ABACUS requires the atoms ranged species-by-species, therefore # we need to sort the atoms by species ind = np.argsort(elem) @@ -222,46 +241,56 @@ def write_stru(stru: Atoms, elem = [elem[i] for i in ind] # handle the atomic magnetic moment (issue #6516) - magmoms = np.array([stru[i].magmom for i in ind]).reshape(len(stru), -1) # ncol in [1, 3] - magmoms = [{} if abs(np.linalg.norm(m)) <= 1e-10 - else {'mag': m[0] if len(m) == 1 else ('Cartesian', m.tolist())} - for m in magmoms] + magmoms = np.array([stru[i].magmom for i in ind]).reshape( + len(stru), -1 + ) # ncol in [1, 3] + magmoms = [ + ( + {} + if abs(np.linalg.norm(m)) <= 1e-10 + else {"mag": m[0] if len(m) == 1 else ("Cartesian", m.tolist())} + ) + for m in magmoms + ] elem_uniq, nat = np.unique(elem, return_counts=True) stru_dict = { - 'coord_type': 'Cartesian', - 'lat': { - 'const': __ANGSTROM__ / __BOHR__, - 'vec': np.array(stru.get_cell()).tolist() + "coord_type": "Cartesian", + "lat": { + "const": __ANGSTROM__ / __BOHR__, + "vec": np.array(stru.get_cell()).tolist(), }, - 'species': [ + "species": [ { - 'symbol': e, - 'mass': ATOM_MASS[e], - 'pp_file': pp_file.get(e, ''), - 'pp_type': '', - 'natom': n, - 'mag_each': 0.0, - 'atom': [ - magmoms[j] | { - 'coord': coords[j].tolist(), # coordinate - 'm': [1, 1, 1], # mobility - 'v': [0.0, 0.0, 0.0], # velocity - } for j in range(np.sum(nat[:i]), np.sum(nat[:i+1])) - ] + "symbol": e, + "mass": ATOM_MASS[e], + "pp_file": pp_file.get(e, ""), + "pp_type": "", + "natom": n, + "mag_each": 0.0, + "atom": [ + magmoms[j] + | { + "coord": coords[j].tolist(), # coordinate + "m": [1, 1, 1], # mobility + "v": [0.0, 0.0, 0.0], # velocity + } + for j in range(np.sum(nat[:i]), np.sum(nat[: i + 1])) + ], } for i, (n, e) in enumerate(zip(nat, elem_uniq)) - ] + ], } if orb_file is not None: - for s in stru_dict['species']: - s['orb_file'] = orb_file[s['symbol']] - + for s in stru_dict["species"]: + s["orb_file"] = orb_file[s["symbol"]] + _write_stru(outdir, stru_dict, fname) return (Path(outdir) / fname).resolve().as_posix() + def write_input(data: Dict[str, Any], fn: str) -> str: - ''' + """ write the ABACUS INPUT file from a Dict[str, Any] object Parameters @@ -276,53 +305,61 @@ def write_input(data: Dict[str, Any], fn: str) -> str: ------- str the absolute path of the written INPUT file - ''' - with open(fn, 'w') as f: - f.write('INPUT_PARAMETERS\n') + """ + with open(fn, "w") as f: + f.write("INPUT_PARAMETERS\n") for key, value in data.items(): - f.write(f'{key} {value}\n') - f.write('\n') # add a newline at the end + f.write(f"{key} {value}\n") + f.write("\n") # add a newline at the end return str(Path(fn).resolve()) + def _write_kline(data: Dict[str, Any], f: TextIOWrapper): - ''' + """ write the k-point file whose mode is "Line" - ''' - f.write('K_POINTS\n') + """ + f.write("K_POINTS\n") f.write(f"{data['nk']}\n") - f.write('Line_Cartesian\n' if data['coordinate'].lower() == 'cartesian' - else 'Line\n') - for k, nk in zip(data['kpoints'], data['nkinterpl']): + f.write( + "Line_Cartesian\n" if data["coordinate"].lower() == "cartesian" else "Line\n" + ) + for k, nk in zip(data["kpoints"], data["nkinterpl"]): f.write(f"{k[0]} {k[1]} {k[2]} {nk}\n") + def _write_ksampl_mp(data: Dict[str, Any], f: TextIOWrapper): - ''' + """ write the k-point file whose mode is automatically sampling with Monkhorst-Pack - ''' - f.write('K_POINTS\n') - f.write('0\n') - f.write("Gamma\n" if data['gamma-centered'] else "MP\n") - f.write(f"{data['nk'][0]} {data['nk'][1]} {data['nk'][2]} " - f"{data['kshift'][0]} {data['kshift'][1]} {data['kshift'][2]}\n") - + """ + f.write("K_POINTS\n") + f.write("0\n") + f.write("Gamma\n" if data["gamma-centered"] else "MP\n") + f.write( + f"{data['nk'][0]} {data['nk'][1]} {data['nk'][2]} " + f"{data['kshift'][0]} {data['kshift'][1]} {data['kshift'][2]}\n" + ) + + def _write_kpoint(data: Dict[str, Any], f: TextIOWrapper): - ''' + """ write the k-point file whose mode is specifying kpoints one-by-one - ''' - f.write('K_POINTS\n') + """ + f.write("K_POINTS\n") f.write(f"{data['nk']}\n") f.write(f"{data['coordinate'].capitalize()}\n") - nkinterpl = data.get('nkinterpl', [1 for _ in data['kpoints']]) - for k, nk in zip(data['kpoints'], data.get('nkinterpl', nkinterpl)): + nkinterpl = data.get("nkinterpl", [1 for _ in data["kpoints"]]) + for k, nk in zip(data["kpoints"], data.get("nkinterpl", nkinterpl)): f.write(f"{k[0]} {k[1]} {k[2]} {nk}\n") + def read_kpoint_from_running_log(fn: str) -> Dict[str, Any]: - '''Read the k-point information from the ABACUS running log file.''' - raise NotImplementedError('read_kpoint_from_running_log is not implemented yet.') + """Read the k-point information from the ABACUS running log file.""" + raise NotImplementedError("read_kpoint_from_running_log is not implemented yet.") + def write_kpt(data: Dict[str, Any], fn: str) -> str: - ''' + """ write the ABACUS KPT file from a Dict[str, Any] object Parameters @@ -337,23 +374,24 @@ def write_kpt(data: Dict[str, Any], fn: str) -> str: ------- str the absolute path of the written KPT file - ''' - assert 'mode' in data, 'KPT data must contain "mode" key' + """ + assert "mode" in data, 'KPT data must contain "mode" key' mywriter = { - # 'line': _write_kline, - 'mp-sampling': _write_ksampl_mp, - 'point': _write_kpoint + # 'line': _write_kline, + "mp-sampling": _write_ksampl_mp, + "point": _write_kpoint, } - assert data['mode'] in mywriter, \ - f'Invalid KPT mode {data["mode"]}, must be one of ' \ - f'{list(mywriter.keys())}' - with open(fn, 'w') as f: - mywriter[data['mode']](data, f) + assert data["mode"] in mywriter, ( + f'Invalid KPT mode {data["mode"]}, must be one of ' f"{list(mywriter.keys())}" + ) + with open(fn, "w") as f: + mywriter[data["mode"]](data, f) return str(Path(fn).resolve()) + def _parse_coord_line(line): - ''' + """ Parses a coordinate line (which may include extra parameters) in the ATOMIC_POSITIONS block. @@ -369,23 +407,23 @@ def _parse_coord_line(line): (see section "More Key Words" for details) - ''' + """ fields = line.split() - result = { 'coord' : [float(x) for x in fields[0:3]] } + result = {"coord": [float(x) for x in fields[0:3]]} idx = 3 while idx < len(fields): - if fields[idx].isdigit(): # no keyword, 0/1 -> frozen atom - result['m'] = [int(x) for x in fields[idx:idx+3]] + if fields[idx].isdigit(): # no keyword, 0/1 -> frozen atom + result["m"] = [int(x) for x in fields[idx : idx + 3]] idx += 3 - elif fields[idx] == 'm': # frozen atom - result['m'] = [int(x) for x in fields[idx+1:idx+4]] + elif fields[idx] == "m": # frozen atom + result["m"] = [int(x) for x in fields[idx + 1 : idx + 4]] idx += 4 - elif fields[idx] in ['v', 'vel', 'velocity']: # initial velocity - result['v'] = [float(x) for x in fields[idx+1:idx+4]] + elif fields[idx] in ["v", "vel", "velocity"]: # initial velocity + result["v"] = [float(x) for x in fields[idx + 1 : idx + 4]] idx += 4 - elif fields[idx] in ['mag', 'magmom']: - ''' + elif fields[idx] in ["mag", "magmom"]: + """ here we assume that frozen atom info cannot be placed after a collinear mag info without a keyword i.e., the following coordinate line @@ -393,36 +431,46 @@ def _parse_coord_line(line): is not allowed; one must explicitly specify 'm' in this case: 0.0 0.0 0.0 mag 1.0 m 0 0 0 - ''' - if idx + 2 < len(fields) and fields[idx+2] == 'angle1': - result['mag'] = ('Spherical', - list(map(float, fields[idx+1:idx+6:2]))) + """ + if idx + 2 < len(fields) and fields[idx + 2] == "angle1": + result["mag"] = ( + "Spherical", + list(map(float, fields[idx + 1 : idx + 6 : 2])), + ) idx += 6 - elif idx + 2 < len(fields) and fields[idx+2][0].isdigit(): - result['mag'] = ('Cartesian', - list(map(float, fields[idx+1:idx+4]))) + elif idx + 2 < len(fields) and fields[idx + 2][0].isdigit(): + result["mag"] = ( + "Cartesian", + list(map(float, fields[idx + 1 : idx + 4])), + ) idx += 4 - else: # collinear - result['mag'] = float(fields[idx+1]) + else: # collinear + result["mag"] = float(fields[idx + 1]) idx += 2 else: - raise ValueError('Error: unknown keyword %s'%fields[idx]) + raise ValueError("Error: unknown keyword %s" % fields[idx]) return result + def _atomic_positions_gen(lines): - ''' + """ Iteratively generates info per species from the ATOMIC_POSITIONS block. - ''' + """ natom = int(lines[2]) - yield {'symbol': lines[0], 'mag_each': float(lines[1]), 'natom': natom, - 'atom': [_parse_coord_line(line) for line in lines[3:3+natom]]} + yield { + "symbol": lines[0], + "mag_each": float(lines[1]), + "natom": natom, + "atom": [_parse_coord_line(line) for line in lines[3 : 3 + natom]], + } if len(lines) > 3 + natom: - yield from _atomic_positions_gen(lines[3+natom:]) + yield from _atomic_positions_gen(lines[3 + natom :]) + def read_stru(fn: str) -> Dict[str, Any]: - ''' + """ read the ABACUS STRU file and return a comprehensive Dict[str, Any] object. This function is implemented by @jinzx10 in ABACUS-CSW-NAO project. @@ -438,194 +486,219 @@ def read_stru(fn: str) -> Dict[str, Any]: 'species' : list of dict List of atomic species. Each dict contains 'symbol', 'mass', 'pp_file', and optionally 'pp_type'. - ''' - block_title = ['ATOMIC_SPECIES', - 'NUMERICAL_ORBITAL', - 'LATTICE_CONSTANT', - 'LATTICE_PARAMETER', - 'LATTICE_VECTORS', - 'ATOMIC_POSITIONS'] + """ + block_title = [ + "ATOMIC_SPECIES", + "NUMERICAL_ORBITAL", + "LATTICE_CONSTANT", + "LATTICE_PARAMETER", + "LATTICE_VECTORS", + "ATOMIC_POSITIONS", + ] def _trim(line): - return line.split('#')[0].split('//')[0].strip(' \t\n') + return line.split("#")[0].split("//")[0].strip(" \t\n") - with open(fn, 'r') as f: - lines = [_trim(line).replace('\t', ' ') - for line in f.readlines() if len(_trim(line)) > 0] + with open(fn, "r") as f: + lines = [ + _trim(line).replace("\t", " ") + for line in f.readlines() + if len(_trim(line)) > 0 + ] # break the content into blocks - delim = [i for i, line in enumerate(lines) if line in block_title] \ - + [len(lines)] - blocks = {lines[delim[i]] : lines[delim[i]+1:delim[i+1]] - for i in range(len(delim) - 1)} + delim = [i for i, line in enumerate(lines) if line in block_title] + [len(lines)] + blocks = { + lines[delim[i]]: lines[delim[i] + 1 : delim[i + 1]] + for i in range(len(delim) - 1) + } stru = {} - #============ LATTICE_CONSTANT/PARAMETER/VECTORS ============ - stru['lat'] = {'const': float(blocks['LATTICE_CONSTANT'][0])} - if 'LATTICE_VECTORS' in blocks: - stru['lat']['vec'] = [[float(x) for x in line.split()] - for line in blocks['LATTICE_VECTORS']] - elif 'LATTICE_PARAMETER' in blocks: - stru['lat']['param'] = [float(x) - for x in blocks['LATTICE_PARAMETERS'].split()] - - #============ ATOMIC_SPECIES ============ - stru['species'] = [dict(zip(['symbol', 'mass', 'pp_file', 'pp_type'], - line.split())) - for line in blocks['ATOMIC_SPECIES']] - for s in stru['species']: - s['mass'] = float(s['mass']) - - #============ NUMERICAL_ORBITAL ============ - if 'NUMERICAL_ORBITAL' in blocks: - for i, s in enumerate(stru['species']): - s['orb_file'] = blocks['NUMERICAL_ORBITAL'][i] - - #============ ATOMIC_POSITIONS ============ - stru['coord_type'] = blocks['ATOMIC_POSITIONS'][0] - index = { s['symbol'] : i for i, s in enumerate(stru['species']) } - for ap in _atomic_positions_gen(blocks['ATOMIC_POSITIONS'][1:]): - stru['species'][index[ap['symbol']]].update(ap) + # ============ LATTICE_CONSTANT/PARAMETER/VECTORS ============ + stru["lat"] = {"const": float(blocks["LATTICE_CONSTANT"][0])} + if "LATTICE_VECTORS" in blocks: + stru["lat"]["vec"] = [ + [float(x) for x in line.split()] for line in blocks["LATTICE_VECTORS"] + ] + elif "LATTICE_PARAMETER" in blocks: + stru["lat"]["param"] = [float(x) for x in blocks["LATTICE_PARAMETERS"].split()] + + # ============ ATOMIC_SPECIES ============ + stru["species"] = [ + dict(zip(["symbol", "mass", "pp_file", "pp_type"], line.split())) + for line in blocks["ATOMIC_SPECIES"] + ] + for s in stru["species"]: + s["mass"] = float(s["mass"]) + + # ============ NUMERICAL_ORBITAL ============ + if "NUMERICAL_ORBITAL" in blocks: + for i, s in enumerate(stru["species"]): + s["orb_file"] = blocks["NUMERICAL_ORBITAL"][i] + + # ============ ATOMIC_POSITIONS ============ + stru["coord_type"] = blocks["ATOMIC_POSITIONS"][0] + index = {s["symbol"]: i for i, s in enumerate(stru["species"])} + for ap in _atomic_positions_gen(blocks["ATOMIC_POSITIONS"][1:]): + stru["species"][index[ap["symbol"]]].update(ap) return stru + def read_input(fn: str) -> Dict[str, Any]: - ''' + """ read the ABACUS INPUT file and return a comprehensive Dict[str, Any] Parameters ---------- fn : str The path to the ABACUS INPUT file. - + Returns ------- dict - ''' + """ with open(fn) as f: raw = [l.strip() for l in f.readlines()] - raw = [l for l in raw - if l and not re.match(r'^(INPUT_PARAMETERS|#|//|!)', l)] - raw = [re.split(r'#|//|!', l)[0].strip() for l in raw] - raw = [re.split(r'\s+', l) for l in raw] + raw = [l for l in raw if l and not re.match(r"^(INPUT_PARAMETERS|#|//|!)", l)] + raw = [re.split(r"#|//|!", l)[0].strip() for l in raw] + raw = [re.split(r"\s+", l) for l in raw] + + return dict([(l[0], " ".join(l[1:])) for l in raw if len(l) > 0]) - return dict([(l[0], ' '.join(l[1:])) for l in raw if len(l) > 0]) def _read_kline(raw: List[str]) -> Dict[str, Any]: - ''' + """ read the k-point file whose mode is "Line", and return the parsed result - ''' - assert len(raw) >= 4, \ - f'Invalid KPT file, expected at least 4 lines, got {len(raw)}' - assert re.match(r'^\d+$', raw[1]), \ - f'Invalid KPT file, expected the second line to be an integer, ' \ - f'got {raw[1]}' - assert int(raw[1]) == len(raw) - 3, \ - f'Invalid KPT file, expected the second line to be the number of ' \ - f'k-points, got {raw[1]}, but found {len(raw)} k-points' - assert raw[2].lower().startswith('line'), \ - f'Invalid KPT file, expected "Line" in the third line, got {raw[2]}' - mymatch = [re.match(r'^(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+' - r'(\d+).*', l) - for l in raw[3:]] - assert all(m for m in mymatch), \ - 'Invalid KPT file, expected the k-points to be in the format ' \ - '"x y z n # comment"' + """ + assert len(raw) >= 4, f"Invalid KPT file, expected at least 4 lines, got {len(raw)}" + assert re.match(r"^\d+$", raw[1]), ( + f"Invalid KPT file, expected the second line to be an integer, " f"got {raw[1]}" + ) + assert int(raw[1]) == len(raw) - 3, ( + f"Invalid KPT file, expected the second line to be the number of " + f"k-points, got {raw[1]}, but found {len(raw)} k-points" + ) + assert ( + raw[2].lower().startswith("line") + ), f'Invalid KPT file, expected "Line" in the third line, got {raw[2]}' + mymatch = [ + re.match( + r"^(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+" r"(\d+).*", l + ) + for l in raw[3:] + ] + assert all(m for m in mymatch), ( + "Invalid KPT file, expected the k-points to be in the format " + '"x y z n # comment"' + ) print(raw) return { - 'mode': 'line', - 'coordinate': 'Cartesian' if raw[2].lower().endswith('cartesian') else 'Direct', - 'nk': int(raw[1]), - 'kpoints': [tuple([float(x) for x in m.groups()[:3]]) for m in mymatch], - 'nkinterpl': [int(m.groups()[6]) for m in mymatch] + "mode": "line", + "coordinate": "Cartesian" if raw[2].lower().endswith("cartesian") else "Direct", + "nk": int(raw[1]), + "kpoints": [tuple([float(x) for x in m.groups()[:3]]) for m in mymatch], + "nkinterpl": [int(m.groups()[6]) for m in mymatch], } + def _read_ksampl_mp(raw: List[str]) -> Dict[str, Any]: - ''' + """ read the k-point file whose mode is automatically sampling with Monkhorst-Pack scheme, and return the parsed result - ''' - assert len(raw) == 4, \ - f'Invalid KPT file, expected 4 lines, got {len(raw)}' - assert raw[2].lower() in ['gamma', 'mp'], \ - f'Invalid KPT file, expected "Gamma" or "MP" in the third line, ' \ - f'got {raw[2]}' + """ + assert len(raw) == 4, f"Invalid KPT file, expected 4 lines, got {len(raw)}" + assert raw[2].lower() in ["gamma", "mp"], ( + f'Invalid KPT file, expected "Gamma" or "MP" in the third line, ' + f"got {raw[2]}" + ) # the following may raise the ValueError if unpacking is not correct nk1, nk2, nk3, kshift1, kshift2, kshift3 = map(int, raw[3].split()) return { - 'mode': 'mp-sampling', - 'gamma-centered': bool(raw[2].lower() == 'gamma'), - 'nk': (nk1, nk2, nk3), - 'kshift': (kshift1, kshift2, kshift3) + "mode": "mp-sampling", + "gamma-centered": bool(raw[2].lower() == "gamma"), + "nk": (nk1, nk2, nk3), + "kshift": (kshift1, kshift2, kshift3), } + def _read_kpoint(raw: List[str]) -> Dict[str, Any]: - ''' + """ read the k-point file whose mode is specifying kpoints one-by-one, return the parsed result. - ''' - assert len(raw) >= 4, \ - f'Invalid KPT file, expected at least 4 lines, got {len(raw)}' - assert re.match(r'^\d+$', raw[1]), \ - f'Invalid KPT file, expected the second line to be an integer, ' \ - f'got {raw[1]}' - assert int(raw[1]) == len(raw) - 3, \ - f'Invalid KPT file, expected the second line to be the number of ' \ - f'k-points, got {raw[1]}, but found {len(raw)} k-points' - assert raw[2].lower() in ['direct', 'cartesian'], \ - f'Invalid KPT file, expected "Direct" or "Cartesian" in the third line, ' \ - f'got {raw[2]}' - mymatch = [re.match(r'^(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s*' - r'(\d+).*', l) - for l in raw[3:]] - assert all(m for m in mymatch), \ - 'Invalid KPT file, expected the k-points to be in the format ' \ - '"x y z n # comment"' + """ + assert len(raw) >= 4, f"Invalid KPT file, expected at least 4 lines, got {len(raw)}" + assert re.match(r"^\d+$", raw[1]), ( + f"Invalid KPT file, expected the second line to be an integer, " f"got {raw[1]}" + ) + assert int(raw[1]) == len(raw) - 3, ( + f"Invalid KPT file, expected the second line to be the number of " + f"k-points, got {raw[1]}, but found {len(raw)} k-points" + ) + assert raw[2].lower() in ["direct", "cartesian"], ( + f'Invalid KPT file, expected "Direct" or "Cartesian" in the third line, ' + f"got {raw[2]}" + ) + mymatch = [ + re.match( + r"^(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s*" r"(\d+).*", l + ) + for l in raw[3:] + ] + assert all(m for m in mymatch), ( + "Invalid KPT file, expected the k-points to be in the format " + '"x y z n # comment"' + ) return { - 'mode': 'point', - 'coordinate': 'Cartesian' if raw[2].lower() == 'cartesian' else 'Direct', - 'nk': int(raw[1]), - 'kpoints': [tuple(map(float, m.groups()[:3])) for m in mymatch], - 'weights': [int(m.groups()[6]) for m in mymatch] + "mode": "point", + "coordinate": "Cartesian" if raw[2].lower() == "cartesian" else "Direct", + "nk": int(raw[1]), + "kpoints": [tuple(map(float, m.groups()[:3])) for m in mymatch], + "weights": [int(m.groups()[6]) for m in mymatch], } + def read_kpt(fn: str) -> Dict[str, Any]: - ''' + """ read the ABACUS KPT file and return a comprehensive Dict[str, Any] Parameters ---------- fn : str The path to the ABACUS KPT file. - + Returns ------- dict A dictionary containing the k-point information. - ''' + """ with open(fn) as f: raw = [l.strip() for l in f.readlines()] raw = [l for l in raw if l] - parser_switch = {'line': _read_kline, - 'gamma': _read_ksampl_mp, 'mp': _read_ksampl_mp, - 'direct': _read_kpoint, 'cartesian': _read_kpoint} - assert raw[0] == 'K_POINTS', \ - f'Invalid KPT file {fn}, first line must be "K_POINTS"' + parser_switch = { + "line": _read_kline, + "gamma": _read_ksampl_mp, + "mp": _read_ksampl_mp, + "direct": _read_kpoint, + "cartesian": _read_kpoint, + } + assert raw[0] == "K_POINTS", f'Invalid KPT file {fn}, first line must be "K_POINTS"' # because there are modes like "Line_Cartesian", we need to # split the second line by '_' - return parser_switch[raw[2].lower().split('_')[0]](raw) + return parser_switch[raw[2].lower().split("_")[0]](raw) + class TestAbacusCalculatorIOUtil(unittest.TestCase): def setUp(self): here = Path(__file__).parent - self.testfiles = here / 'testfiles' + self.testfiles = here / "testfiles" def test_input_io(self): - fn = self.testfiles / 'input-script' + fn = self.testfiles / "input-script" data = read_input(fn) - with tempfile.NamedTemporaryFile(mode='w') as f: + with tempfile.NamedTemporaryFile(mode="w") as f: fn_ = Path(f.name) write_input(data, fn_.as_posix()) data_ = read_input(fn_.as_posix()) @@ -634,77 +707,75 @@ def test_input_io(self): def test_stru_io(self): from ase.units import Bohr, Angstrom - nacl = bulk('NaCl', 'rocksalt', a=5.64) + + nacl = bulk("NaCl", "rocksalt", a=5.64) write_stru( - nacl, - outdir=self.testfiles, - pp_file={ - 'Na': 'Na.pz-bhs.UPF', - 'Cl': 'Cl.pz-bhs.UPF' - }, + nacl, + outdir=self.testfiles, + pp_file={"Na": "Na.pz-bhs.UPF", "Cl": "Cl.pz-bhs.UPF"}, orb_file={ - 'Na': 'Na_gga_6au_100Ry_2s2p1d.orb', - 'Cl': 'Cl_gga_6au_100Ry_2s2p1d.orb', + "Na": "Na_gga_6au_100Ry_2s2p1d.orb", + "Cl": "Cl_gga_6au_100Ry_2s2p1d.orb", }, ) - stru_ = read_stru(self.testfiles / 'STRU') - (self.testfiles / 'STRU').unlink() - + stru_ = read_stru(self.testfiles / "STRU") + (self.testfiles / "STRU").unlink() + self.assertIsInstance(stru_, dict) - for k in ['lat', 'species', 'coord_type']: + for k in ["lat", "species", "coord_type"]: self.assertIn(k, stru_) - for k in ['const', 'vec']: - self.assertIn(k, stru_['lat']) - for k in ['symbol', 'mass', 'pp_file', 'orb_file', 'mag_each', 'natom', 'atom']: - for s in stru_['species']: + for k in ["const", "vec"]: + self.assertIn(k, stru_["lat"]) + for k in ["symbol", "mass", "pp_file", "orb_file", "mag_each", "natom", "atom"]: + for s in stru_["species"]: self.assertIn(k, s) - self.assertEqual(stru_['coord_type'], 'Cartesian') + self.assertEqual(stru_["coord_type"], "Cartesian") - self.assertEqual(stru_['lat']['const'], Angstrom / Bohr) - self.assertTrue(np.allclose(stru_['lat']['vec'], np.array(nacl.get_cell()))) - self.assertIsInstance(stru_['species'], list) + self.assertEqual(stru_["lat"]["const"], Angstrom / Bohr) + self.assertTrue(np.allclose(stru_["lat"]["vec"], np.array(nacl.get_cell()))) + self.assertIsInstance(stru_["species"], list) - for s in stru_['species']: + for s in stru_["species"]: self.assertIsInstance(s, dict) - self.assertEqual(s['natom'], 1) - self.assertIsInstance(s['atom'], list) - self.assertEqual(s['natom'], len(s['atom'])) - for a in s['atom']: + self.assertEqual(s["natom"], 1) + self.assertIsInstance(s["atom"], list) + self.assertEqual(s["natom"], len(s["atom"])) + for a in s["atom"]: self.assertIsInstance(a, dict) - for k in ['coord', 'm', 'v']: + for k in ["coord", "m", "v"]: self.assertIn(k, a) - self.assertEqual(a['m'], [1, 1, 1]) - self.assertEqual(a['v'], [0.0, 0.0, 0.0]) - - self.assertEqual(stru_['species'][0]['symbol'], 'Cl') - self.assertEqual(stru_['species'][1]['symbol'], 'Na') - self.assertEqual(stru_['species'][0]['mass'], ATOM_MASS['Cl']) - self.assertEqual(stru_['species'][1]['mass'], ATOM_MASS['Na']) - self.assertEqual(stru_['species'][0]['pp_file'], 'Cl.pz-bhs.UPF') - self.assertEqual(stru_['species'][1]['pp_file'], 'Na.pz-bhs.UPF') - self.assertEqual(stru_['species'][0]['orb_file'], 'Cl_gga_6au_100Ry_2s2p1d.orb') - self.assertEqual(stru_['species'][1]['orb_file'], 'Na_gga_6au_100Ry_2s2p1d.orb') + self.assertEqual(a["m"], [1, 1, 1]) + self.assertEqual(a["v"], [0.0, 0.0, 0.0]) + + self.assertEqual(stru_["species"][0]["symbol"], "Cl") + self.assertEqual(stru_["species"][1]["symbol"], "Na") + self.assertEqual(stru_["species"][0]["mass"], ATOM_MASS["Cl"]) + self.assertEqual(stru_["species"][1]["mass"], ATOM_MASS["Na"]) + self.assertEqual(stru_["species"][0]["pp_file"], "Cl.pz-bhs.UPF") + self.assertEqual(stru_["species"][1]["pp_file"], "Na.pz-bhs.UPF") + self.assertEqual(stru_["species"][0]["orb_file"], "Cl_gga_6au_100Ry_2s2p1d.orb") + self.assertEqual(stru_["species"][1]["orb_file"], "Na_gga_6au_100Ry_2s2p1d.orb") def test_kpt_io(self): kpt = { - 'mode': 'point', - 'coordinate': 'Cartesian', - 'nk': 1, - 'kpoints': [(0.0, 0.0, 0.0)], - 'weights': [1] + "mode": "point", + "coordinate": "Cartesian", + "nk": 1, + "kpoints": [(0.0, 0.0, 0.0)], + "weights": [1], } - with tempfile.NamedTemporaryFile(mode='w') as f: + with tempfile.NamedTemporaryFile(mode="w") as f: fn_ = Path(f.name) write_kpt(kpt, fn_.as_posix()) self.assertDictEqual(kpt, read_kpt(fn_.as_posix())) kpt = { - 'mode': 'mp-sampling', - 'nk': (5, 5, 5), - 'kshift': (0, 0, 0), - 'gamma-centered': True, + "mode": "mp-sampling", + "nk": (5, 5, 5), + "kshift": (0, 0, 0), + "gamma-centered": True, } - with tempfile.NamedTemporaryFile(mode='w') as f: + with tempfile.NamedTemporaryFile(mode="w") as f: fn_ = Path(f.name) write_kpt(kpt, fn_.as_posix()) self.assertDictEqual(kpt, read_kpt(fn_.as_posix())) @@ -728,94 +799,115 @@ def test_kpt_io(self): # write_kpt(kpt, fn_.as_posix()) # self.assertDictEqual(kpt, read_kpt(fn_.as_posix())) - @unittest.skip('') + @unittest.skip("") def test_load_pseudo(self): - pseudo_dir = self.testfiles / 'pporb' + pseudo_dir = self.testfiles / "pporb" pseudo_map = load_pseudo(pseudo_dir) - self.assertEqual(pseudo_map['O'], 'O.upf') - self.assertEqual(pseudo_map['Si'], 'Si.upf') - self.assertEqual(pseudo_map['In'], 'In.upf') - self.assertEqual(pseudo_map['As'], 'As.pbe-n-rrkjus_psl.0.2.UPF') - self.assertEqual(pseudo_map['Ga'], 'Ga.pbe-dn-kjpaw_psl.1.0.0.UPF') + self.assertEqual(pseudo_map["O"], "O.upf") + self.assertEqual(pseudo_map["Si"], "Si.upf") + self.assertEqual(pseudo_map["In"], "In.upf") + self.assertEqual(pseudo_map["As"], "As.pbe-n-rrkjus_psl.0.2.UPF") + self.assertEqual(pseudo_map["Ga"], "Ga.pbe-dn-kjpaw_psl.1.0.0.UPF") - @unittest.skip('') + @unittest.skip("") def test_load_orbital(self): - orbital_dir = self.testfiles / 'pporb' + orbital_dir = self.testfiles / "pporb" orbital_map = load_orbital(orbital_dir) - self.assertEqual(orbital_map['O'], 'O_gga_6au_100Ry_2s2p1d.orb') - self.assertEqual(orbital_map['Si'], 'Si_gga_7au_100Ry_2s2p1d.orb') - self.assertEqual(orbital_map['In'], 'In_gga_8au_100Ry_1s1p1d.orb') + self.assertEqual(orbital_map["O"], "O_gga_6au_100Ry_2s2p1d.orb") + self.assertEqual(orbital_map["Si"], "Si_gga_7au_100Ry_2s2p1d.orb") + self.assertEqual(orbital_map["In"], "In_gga_8au_100Ry_1s1p1d.orb") orbital_map = load_orbital(orbital_dir, efficiency=False) - self.assertEqual(orbital_map['O'], 'O_gga_6au_100Ry_2s2p1d.orb') - self.assertEqual(orbital_map['Si'], 'Si_gga_7au_100Ry_2s2p1d.orb') - self.assertEqual(orbital_map['In'], 'In_gga_8au_100Ry_2s2p2d1f.orb') + self.assertEqual(orbital_map["O"], "O_gga_6au_100Ry_2s2p1d.orb") + self.assertEqual(orbital_map["Si"], "Si_gga_7au_100Ry_2s2p1d.orb") + self.assertEqual(orbital_map["In"], "In_gga_8au_100Ry_2s2p2d1f.orb") def test_write_stru_with_magmom(self): # from issue #6516: https://github.com/deepmodeling/abacus-develop/issues/6516 atoms = Atoms( - symbols=['Co', 'Cr', 'Ni', 'Co'], - cell=np.eye(3), - magmoms=[1, 2, 3, 1] + symbols=["Co", "Cr", "Ni", "Co"], cell=np.eye(3), magmoms=[1, 2, 3, 1] ) - with tempfile.NamedTemporaryFile(mode='w') as f: + with tempfile.NamedTemporaryFile(mode="w") as f: write_stru( stru=atoms, outdir=self.testfiles, - pp_file={ # as if we have some pseudopotentials - 'Co': 'Co.upf', 'Cr': 'Cr.upf', 'Ni': 'Ni.upf', 'Co': 'Co.upf', + pp_file={ # as if we have some pseudopotentials + "Co": "Co.upf", + "Cr": "Cr.upf", + "Ni": "Ni.upf", + "Co": "Co.upf", }, - orb_file={ # as if we have some orbitals - 'Co': 'Co.orb', 'Cr': 'Cr.orb', 'Ni': 'Ni.orb', 'Co': 'Co.orb', + orb_file={ # as if we have some orbitals + "Co": "Co.orb", + "Cr": "Cr.orb", + "Ni": "Ni.orb", + "Co": "Co.orb", }, fname=f.name, ) stru = read_stru(f.name) # Co - self.assertEqual(stru['species'][0]['mag_each'], 0.0) - self.assertEqual(stru['species'][0]['atom'][0]['mag'], 1.0) - self.assertEqual(stru['species'][0]['atom'][1]['mag'], 1.0) + self.assertEqual(stru["species"][0]["mag_each"], 0.0) + self.assertEqual(stru["species"][0]["atom"][0]["mag"], 1.0) + self.assertEqual(stru["species"][0]["atom"][1]["mag"], 1.0) # Cr - self.assertEqual(stru['species'][1]['mag_each'], 0.0) - self.assertEqual(stru['species'][1]['atom'][0]['mag'], 2.0) + self.assertEqual(stru["species"][1]["mag_each"], 0.0) + self.assertEqual(stru["species"][1]["atom"][0]["mag"], 2.0) # Ni - self.assertEqual(stru['species'][2]['mag_each'], 0.0) - self.assertEqual(stru['species'][2]['atom'][0]['mag'], 3.0) + self.assertEqual(stru["species"][2]["mag_each"], 0.0) + self.assertEqual(stru["species"][2]["atom"][0]["mag"], 3.0) # then the non-colinear case atoms = Atoms( - symbols=['Co', 'Cr', 'Ni', 'Co'], + symbols=["Co", "Cr", "Ni", "Co"], cell=np.eye(3), - magmoms=np.array([ - [1, 0, 0], - [0, 2, 0], - [0, 0, 3], - [1, 0, 0], - ]) + magmoms=np.array( + [ + [1, 0, 0], + [0, 2, 0], + [0, 0, 3], + [1, 0, 0], + ] + ), ) - with tempfile.NamedTemporaryFile(mode='w') as f: + with tempfile.NamedTemporaryFile(mode="w") as f: write_stru( stru=atoms, outdir=self.testfiles, - pp_file={ # as if we have some pseudopotentials - 'Co': 'Co.upf', 'Cr': 'Cr.upf', 'Ni': 'Ni.upf', 'Co': 'Co.upf', + pp_file={ # as if we have some pseudopotentials + "Co": "Co.upf", + "Cr": "Cr.upf", + "Ni": "Ni.upf", + "Co": "Co.upf", }, - orb_file={ # as if we have some orbitals - 'Co': 'Co.orb', 'Cr': 'Cr.orb', 'Ni': 'Ni.orb', 'Co': 'Co.orb', + orb_file={ # as if we have some orbitals + "Co": "Co.orb", + "Cr": "Cr.orb", + "Ni": "Ni.orb", + "Co": "Co.orb", }, fname=f.name, ) stru = read_stru(f.name) # Co - self.assertEqual(stru['species'][0]['mag_each'], 0.0) - self.assertEqual(stru['species'][0]['atom'][0]['mag'], ('Cartesian', [1.0, 0.0, 0.0])) - self.assertEqual(stru['species'][0]['atom'][1]['mag'], ('Cartesian', [1.0, 0.0, 0.0])) + self.assertEqual(stru["species"][0]["mag_each"], 0.0) + self.assertEqual( + stru["species"][0]["atom"][0]["mag"], ("Cartesian", [1.0, 0.0, 0.0]) + ) + self.assertEqual( + stru["species"][0]["atom"][1]["mag"], ("Cartesian", [1.0, 0.0, 0.0]) + ) # Cr - self.assertEqual(stru['species'][1]['mag_each'], 0.0) - self.assertEqual(stru['species'][1]['atom'][0]['mag'], ('Cartesian', [0.0, 2.0, 0.0])) + self.assertEqual(stru["species"][1]["mag_each"], 0.0) + self.assertEqual( + stru["species"][1]["atom"][0]["mag"], ("Cartesian", [0.0, 2.0, 0.0]) + ) # Ni - self.assertEqual(stru['species'][2]['mag_each'], 0.0) - self.assertEqual(stru['species'][2]['atom'][0]['mag'], ('Cartesian', [0.0, 0.0, 3.0])) + self.assertEqual(stru["species"][2]["mag_each"], 0.0) + self.assertEqual( + stru["species"][2]["atom"][0]["mag"], ("Cartesian", [0.0, 0.0, 3.0]) + ) + -if __name__ == '__main__': - unittest.main() \ No newline at end of file +if __name__ == "__main__": + unittest.main() diff --git a/interfaces/ASE_interface/abacuslite/io/latestio.py b/interfaces/ASE_interface/abacuslite/io/latestio.py index b658c0dc745..7a40c05d957 100644 --- a/interfaces/ASE_interface/abacuslite/io/latestio.py +++ b/interfaces/ASE_interface/abacuslite/io/latestio.py @@ -1,4 +1,5 @@ -'''implements the parser for the latest version of ABACUS''' +"""implements the parser for the latest version of ABACUS""" + import re import shutil import unittest @@ -7,10 +8,7 @@ import numpy as np from ase.atoms import Atoms -from ase.calculators.singlepoint import ( - SinglePointKPoint, - SinglePointDFTCalculator -) +from ase.calculators.singlepoint import SinglePointKPoint, SinglePointDFTCalculator from ase.units import GPa from ase.stress import full_3x3_to_voigt_6_stress @@ -22,140 +20,140 @@ read_traj_from_md_dump, read_magmom_from_running_log, is_invalid_arr, - find_final_info_with_iter_header + find_final_info_with_iter_header, ) -def read_esolver_type_from_running_log(src: str | Path | List[str]) \ - -> str: - ''' + +def read_esolver_type_from_running_log(src: str | Path | List[str]) -> str: + """ read the esolver type from the ABACUS running log file. Parameters ---------- fn : str The path to the ABACUS running log file. - + Returns ------- str The esolver type used in the ABACUS calculation. - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines # search for the line with information like: # "#ENERGY SOLVER# ksdft_lcao" - lines = [ - re.match(r'#ENERGY SOLVER#\s+(\S+)', l) - for l in raw - ] + lines = [re.match(r"#ENERGY SOLVER#\s+(\S+)", l) for l in raw] eslvtyp = [m.group(1) for m in lines if m is not None] - assert len(set(eslvtyp)) == 1, \ - f'Inconsistent esolver type: {set(eslvtyp)}' + assert len(set(eslvtyp)) == 1, f"Inconsistent esolver type: {set(eslvtyp)}" return eslvtyp[0] + def read_band_from_running_log(src: str | Path | List[str]): - '''in the latest branch, the band information is removed from running log. + """in the latest branch, the band information is removed from running log. This function is only for backward compatibility. To get the band information, - please call the "read_band_from_eig_occ" function.''' + please call the "read_band_from_eig_occ" function.""" return None -def read_band_from_eig_occ(src: str | Path | List[str]) \ - -> List[Dict[str, np.ndarray]]: - '''read the OUT.${suffix}/eig_occ.txt - + +def read_band_from_eig_occ(src: str | Path | List[str]) -> List[Dict[str, np.ndarray]]: + """read the OUT.${suffix}/eig_occ.txt + Parameters ---------- src : str or Path or list of str The path to the ABACUS running log file or the return of the readlines() method. - + Returns ------- list of dict A list of dictionaries containing the k-points and band energies. Each dictionary has keys 'k' and 'e', where 'k' is a list of k-point coordinates and 'e' is a numpy array of band energies. - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines - - nframe = len([l for l in raw if l.endswith('# ionic step')]) - ekb_leading_pat = r'spin=(\d)\s+k-point=(\d+)/(\d+)\s+Cartesian=\s*' \ - + r'(-?\d(\.\d+)?(e-\d+)?)\s+' \ - + r'(-?\d(\.\d+)?(e-\d+)?)\s+' \ - + r'(-?\d(\.\d+)?(e-\d+)?)\s+' \ - + r'\(\d+\s+plane wave\)' - # from the ekb leading line, there are nspin, nk information, also the + raw = [l for l in raw if l] # remove empty lines + + nframe = len([l for l in raw if l.endswith("# ionic step")]) + ekb_leading_pat = ( + r"spin=(\d)\s+k-point=(\d+)/(\d+)\s+Cartesian=\s*" + + r"(-?\d(\.\d+)?(e-\d+)?)\s+" + + r"(-?\d(\.\d+)?(e-\d+)?)\s+" + + r"(-?\d(\.\d+)?(e-\d+)?)\s+" + + r"\(\d+\s+plane wave\)" + ) + # from the ekb leading line, there are nspin, nk information, also the # coordinate of kpoints iekb = [i for i, l in enumerate(raw) if re.match(ekb_leading_pat, l)] - assert len(iekb) > 0, f'No k-point found' - + assert len(iekb) > 0, f"No k-point found" + k_raw = [re.match(ekb_leading_pat, raw[i]).groups() for i in iekb] - + # spin ispin = [int(g[0]) for g in k_raw] - assert all(i in [1, 2] for i in ispin) # what about nspin 4? + assert all(i in [1, 2] for i in ispin) # what about nspin 4? nspin = len(set(ispin)) assert nspin in [1, 2] - + # k-points nk = [int(g[2]) for g in k_raw] nk = set(nk) - assert len(nk) == 1, f'Sampling on k-points changed during the calculation: {nk}' + assert len(nk) == 1, f"Sampling on k-points changed during the calculation: {nk}" nk = nk.pop() ik = [int(g[1]) for g in k_raw] - assert all(i-1 in range(nk) for i in ik), f'k-point index out of range: {ik}' + assert all(i - 1 in range(nk) for i in ik), f"k-point index out of range: {ik}" assert len(ik) == nframe * nspin * nk - k = np.array([[float(g[i]) for i in [3, 6, 9]] for g in k_raw]) + k = np.array([[float(g[i]) for i in [3, 6, 9]] for g in k_raw]) assert k.shape == (nframe * nspin * nk, 3) k = k.reshape((nframe, nspin, nk, 3)) - ekbpat = r'\d+\s+' - ekbpat += r'(-?\d+(\.\d+)?(e[+-]\d+)?)\s+' - ekbpat += r'(\d+(\.\d+)?(e[+-]\d+)?)' + ekbpat = r"\d+\s+" + ekbpat += r"(-?\d+(\.\d+)?(e[+-]\d+)?)\s+" + ekbpat += r"(\d+(\.\d+)?(e[+-]\d+)?)" iekb = [i for i, l in enumerate(raw) if re.match(ekbpat, l)] - assert len(iekb) > 0, f'No band energy found' - assert len(iekb) % (nspin*nk) == 0 + assert len(iekb) > 0, f"No band energy found" + assert len(iekb) % (nspin * nk) == 0 nb = len(iekb) // (nframe * nspin * nk) ekb_raw = np.array([list(map(float, raw[i].split()[1:])) for i in iekb]) assert ekb_raw.shape == (nframe * nspin * nk * nb, 2) ekb_raw = ekb_raw.reshape(nframe, nspin, nk, nb, 2) ekb, occ = ekb_raw[:, :, :, :, 0], ekb_raw[:, :, :, :, 1] - return [{'k': ki, 'e': eki, 'occ': occi} - for ki, eki, occi in zip(k, ekb, occ)] + return [{"k": ki, "e": eki, "occ": occi} for ki, eki, occi in zip(k, ekb, occ)] -def read_traj_from_running_log(src: str | Path | List[str]) \ - -> List[Dict[str, np.ndarray|str]]: - ''' - read the trajectory from the ABACUS running log file. + +def read_traj_from_running_log( + src: str | Path | List[str], +) -> List[Dict[str, np.ndarray | str]]: + """ + read the trajectory from the ABACUS running log file. NOTE: in MD runs, the trajectory is not recorded in the running log file. Parameters ---------- fn : str The path to the ABACUS running log file. - + Returns ------- list of dict A list of dictionaries containing the coordinate system, cell, elements and the coordinates of the atoms. Each dictionary has keys 'coordinate', - 'cell', 'cell_unit', 'alat_in_angstrom', 'elem', and 'coords'. + 'cell', 'cell_unit', 'alat_in_angstrom', 'elem', and 'coords'. The values are numpy arrays or strings. - 'coordinate': string, the coordinate system, e.g., 'Cartesian' or 'Direct' - 'cell': numpy array of shape (3, 3) @@ -163,134 +161,159 @@ def read_traj_from_running_log(src: str | Path | List[str]) \ - 'alat_in_angstrom': float, the lattice constant in Angstrom - 'elem': list of strings, the chemical symbols of the elements - 'coords': numpy array of shape (natoms, 3), the coordinates of the atoms - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines # search for the total number of atoms # r'TOTAL ATOM NUMBER = (\d+)' - natoms = [re.search(r'TOTAL ATOM NUMBER\s*=\s*(\d+)', l) for l in raw] + natoms = [re.search(r"TOTAL ATOM NUMBER\s*=\s*(\d+)", l) for l in raw] natoms = [int(n.group(1)) for n in natoms if n] - assert len(set(natoms)) == 1, \ - f'Inconsistent number of atoms: {set(natoms)}' + assert len(set(natoms)) == 1, f"Inconsistent number of atoms: {set(natoms)}" natoms = natoms[0] # search for the coordinate system # r'^([DIRECT|CARTESIAN]) COORDINATES$' - coordinate = [re.match(r'^(DIRECT|CARTESIAN) COORDINATES', l) for l in raw] + coordinate = [re.match(r"^(DIRECT|CARTESIAN) COORDINATES", l) for l in raw] coordinate = [l.group(1).lower().capitalize() for l in coordinate if l] - assert len(set(coordinate)) == 1, \ - f'Inconsistent coordinate system: {set(coordinate)}' + assert ( + len(set(coordinate)) == 1 + ), f"Inconsistent coordinate system: {set(coordinate)}" coordinate = coordinate[0] # search for the cell, but first get the "a0": lattice constant # r'lattice constant (Angstrom) = (-?\d+(\.\d+)?)' - a0 = [re.search(r'lattice constant \(Angstrom\)\s*=\s*(-?\d+(\.\d+)?)', l, - re.IGNORECASE) for l in raw] + a0 = [ + re.search( + r"lattice constant \(Angstrom\)\s*=\s*(-?\d+(\.\d+)?)", l, re.IGNORECASE + ) + for l in raw + ] a0 = [float(n.group(1)) for n in a0 if n] - assert len(set(a0)) == 1, f'Inconsistent lattice constant: {set(a0)}' + assert len(set(a0)) == 1, f"Inconsistent lattice constant: {set(a0)}" a0 = a0[0] # then the cell # r'^Lattice vectors: \(Cartesian coordinate: in unit of a\_0\)$' - icell = [i for i, l in enumerate(raw) - if re.match(r'^Lattice vectors: \(Cartesian coordinate: in unit of a_0\)$', l)] - assert len(icell) > 0, f'No cell found' + icell = [ + i + for i, l in enumerate(raw) + if re.match(r"^Lattice vectors: \(Cartesian coordinate: in unit of a_0\)$", l) + ] + assert len(icell) > 0, f"No cell found" # nframe = len(icell) # will be 1 for cell-invariant MD # assert nframe > 0, f'Invalid trajectory with length {nframe}') - cell_raw = [raw[i+1:i+1+3] for i in icell] - cell = [np.array([list(map(float, l.split())) for l in c]) * a0 - for c in cell_raw] # convert to Angstrom - assert all(c.shape == (3, 3) for c in cell), \ - f'Unexpected shape of cell: {[c.shape for c in cell]}' + cell_raw = [raw[i + 1 : i + 1 + 3] for i in icell] + cell = [ + np.array([list(map(float, l.split())) for l in c]) * a0 for c in cell_raw + ] # convert to Angstrom + assert all( + c.shape == (3, 3) for c in cell + ), f"Unexpected shape of cell: {[c.shape for c in cell]}" # search for the elements and coordinates - coord_leading_pat = r'atom\s+x\s+y\s+z\s+mag' # what about nspin 4? + coord_leading_pat = r"atom\s+x\s+y\s+z\s+mag" # what about nspin 4? icoord = [i for i, l in enumerate(raw) if re.match(coord_leading_pat, l)] nframe = len(icoord) - coord_raw = np.array([l.split() for i in icoord for l in raw[i+1:i+1+natoms]]) + coord_raw = np.array( + [l.split() for i in icoord for l in raw[i + 1 : i + 1 + natoms]] + ) elem = coord_raw[:, 0].astype(str).reshape((nframe, natoms)) coords = coord_raw[:, 1:4].astype(float).reshape((nframe, natoms, 3)) - mag = coord_raw[:, 4].astype(float).reshape((nframe, natoms, )) + mag = ( + coord_raw[:, 4] + .astype(float) + .reshape( + ( + nframe, + natoms, + ) + ) + ) cell = np.array(cell).reshape(-1, 3, 3) if cell.shape[0] == 1: cell = [cell[0] for _ in range(nframe)] - assert len(cell) == nframe, \ - f'Unexpected number of cells: {len(cell)}, ' \ - f'expected {nframe}' - return [{ - 'coordinate': coordinate, - 'cell': c, - 'cell_unit': 'Angstrom', - 'alat_in_angstrom': a0, - 'elem': e, - 'coords': co - } for c, e, co in zip(cell, elem, coords)] - -def read_forces_from_running_log(src: str | Path | List[str]) \ - -> List[np.ndarray]: - ''' + assert len(cell) == nframe, ( + f"Unexpected number of cells: {len(cell)}, " f"expected {nframe}" + ) + return [ + { + "coordinate": coordinate, + "cell": c, + "cell_unit": "Angstrom", + "alat_in_angstrom": a0, + "elem": e, + "coords": co, + } + for c, e, co in zip(cell, elem, coords) + ] + + +def read_forces_from_running_log(src: str | Path | List[str]) -> List[np.ndarray]: + """ read the forces from the ABACUS running log file. Parameters ---------- src : str or Path or list of str The path to the ABACUS running log file or the return of the readlines() method. - + Returns ------- list of numpy array A list of numpy arrays containing the forces on each atom. Each array has shape (natoms, 3). - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines # iteratively search for the forces, which led by the title `#TOTAL-FORCE (eV/Angstrom)#` forces, istart = [], 0 while istart < len(raw): - ith = None # index of the table header + ith = None # index of the table header for i, l in enumerate(raw[istart:]): - if re.match(r'#\s*TOTAL\-FORCE\s*\(eV\s*/Angstrom\)\s*#', l, re.IGNORECASE): + if re.match(r"#\s*TOTAL\-FORCE\s*\(eV\s*/Angstrom\)\s*#", l, re.IGNORECASE): ith = i break - if ith is None: # no forces found + if ith is None: # no forces found break # otherwise # search for the first line that matches the pattern - FORCEPAT_ = r'\s*([A-Z][a-z]?\d+)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)' - itb = None # index of the first line of the table body - for i, l in enumerate(raw[istart+ith+1:]): + FORCEPAT_ = ( + r"\s*([A-Z][a-z]?\d+)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)" + ) + itb = None # index of the first line of the table body + for i, l in enumerate(raw[istart + ith + 1 :]): if re.match(FORCEPAT_, l): itb = i break - if itb is None: # no content found + if itb is None: # no content found break # otherwise - jtb = None # index of the last line of the table body - for j, l in enumerate(raw[istart+ith+1+itb:]): + jtb = None # index of the last line of the table body + for j, l in enumerate(raw[istart + ith + 1 + itb :]): if not re.match(FORCEPAT_, l): jtb = j break - if jtb is None: # no content found + if jtb is None: # no content found break - + # truncate the force table and append - force_raw = raw[istart+ith+1+itb:istart+ith+1+itb+jtb] + force_raw = raw[istart + ith + 1 + itb : istart + ith + 1 + itb + jtb] force = np.array([list(map(float, l.split()[1:])) for l in force_raw]) forces.append(force) @@ -299,59 +322,61 @@ def read_forces_from_running_log(src: str | Path | List[str]) \ return forces -def read_stress_from_running_log(src: str | Path | List[str]) \ - -> List[np.ndarray]: - ''' + +def read_stress_from_running_log(src: str | Path | List[str]) -> List[np.ndarray]: + """ read the stress from the ABACUS running log file. Parameters ---------- src : str or Path or list of str The path to the ABACUS running log file or the return of the readlines() method. - + Returns ------- list of numpy array A list of numpy arrays containing the stress on each atom. Each array has shape (3, 3). - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines # iteratively search for the stress, which led by the title `#TOTAL-STRESS (kbar)#` stresses, istart = [], 0 - + while istart < len(raw): - ith = None # index of the table header + ith = None # index of the table header for i, l in enumerate(raw[istart:]): - if re.match(r'#\s*TOTAL\-STRESS\s*\(kbar\)\s*#', l, re.IGNORECASE): + if re.match(r"#\s*TOTAL\-STRESS\s*\(kbar\)\s*#", l, re.IGNORECASE): ith = i break - if ith is None: # no stress found + if ith is None: # no stress found break # otherwise # search for the first line that matches the pattern - STRESSPAT_ = r'\s*(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)' - itb = None # index of the first line of the table body - for i, l in enumerate(raw[istart+ith+1:]): + STRESSPAT_ = r"\s*(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)" + itb = None # index of the first line of the table body + for i, l in enumerate(raw[istart + ith + 1 :]): if re.match(STRESSPAT_, l): itb = i break - if itb is None: # no content found + if itb is None: # no content found break # otherwise - jtb = 3 # because the stress tensor would be a (3, 3)-matrix - + jtb = 3 # because the stress tensor would be a (3, 3)-matrix + # truncate the stress table and append - stress_raw = raw[istart+ith+1+itb:istart+ith+1+itb+jtb] - stress = np.array([list(map(float, l.split())) for l in stress_raw]).reshape(3, 3) + stress_raw = raw[istart + ith + 1 + itb : istart + ith + 1 + itb + jtb] + stress = np.array([list(map(float, l.split())) for l in stress_raw]).reshape( + 3, 3 + ) # unit: kbar -> GPa stresses.append(-0.1 * stress * GPa) @@ -360,35 +385,40 @@ def read_stress_from_running_log(src: str | Path | List[str]) \ return stresses -def read_iter_header_from_running_log(src: str | Path | List[str]) \ - -> List[Tuple[int, int]]: - ''' + +def read_iter_header_from_running_log( + src: str | Path | List[str], +) -> List[Tuple[int, int]]: + """ read the "iteration header" from the running log, useful for determining which is the final iteration. The "iteration header" is defined as: ``` --> #ION MOVE# 1 #ELEC ITER# 3 ``` - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines - HEADER_PAT = r'-->\s+#ION MOVE#\s+(\d+)\s+#ELEC ITER#\s+(\d+)' + HEADER_PAT = r"-->\s+#ION MOVE#\s+(\d+)\s+#ELEC ITER#\s+(\d+)" res = [re.findall(HEADER_PAT, l) for l in raw] return [(int(pack[0][0]), int(pack[0][1])) for pack in res if pack] -def read_abacus_out(fileobj, - index=slice(None), - results_required=True, - sort_atoms_with: Optional[List[int]] = None) -> Atoms | List[Atoms]: - '''Reads the ABACUS output files. This function would be called by + +def read_abacus_out( + fileobj, + index=slice(None), + results_required=True, + sort_atoms_with: Optional[List[int]] = None, +) -> Atoms | List[Atoms]: + """Reads the ABACUS output files. This function would be called by the AbacusTemplate.read_results() function. The detailed call stack is as follows: get_potential_energy() @@ -420,7 +450,7 @@ def read_abacus_out(fileobj, ------- atoms : Atoms | List[Atoms] The atoms object, whose calculator is the `SinglePointDFTCalculator`. - ''' + """ assert isinstance(fileobj, Path) # it is required that the running log file is passed as the Path object # so that the band structure file ``eig_occ.txt`` can be located as the @@ -428,7 +458,7 @@ def read_abacus_out(fileobj, # invalid and cause the failure with open(fileobj) as f: abacus_lines = f.readlines() - + # read the esolver type eslvtyp = read_esolver_type_from_running_log(abacus_lines) # FIXME: implement read_ksdft_esolver_out instead of read_abacus_out to @@ -437,15 +467,17 @@ def read_abacus_out(fileobj, # read the structure, with the cell, elem, etc. (nframe) # if it is MD run, the trajectories will be in the file MD_dump, instead # of the running log - trajectory = read_traj_from_running_log(abacus_lines) \ - if fileobj.name != 'running_md.log' else \ - read_traj_from_md_dump(fileobj.parent / 'MD_dump') + trajectory = ( + read_traj_from_running_log(abacus_lines) + if fileobj.name != "running_md.log" + else read_traj_from_md_dump(fileobj.parent / "MD_dump") + ) # read the eigenvalues (nframe, nk, nbnd) - elecstate = read_band_from_eig_occ(fileobj.parent / 'eig_occ.txt') - # FIXME: remove thw following line till the eig_occ.txt is not written + elecstate = read_band_from_eig_occ(fileobj.parent / "eig_occ.txt") + # FIXME: remove thw following line till the eig_occ.txt is not written # in the append mode - (fileobj.parent / 'eig_occ.txt').unlink() + (fileobj.parent / "eig_occ.txt").unlink() # read the atomic forces (nframe, nat, 3) forces = read_forces_from_running_log(abacus_lines) @@ -467,191 +499,245 @@ def read_abacus_out(fileobj, # only keep the energies of the final iteration for each ion step energies = find_final_info_with_iter_header( read_energies_from_running_log(abacus_lines)[1], - read_iter_header_from_running_log(abacus_lines) + read_iter_header_from_running_log(abacus_lines), ) - + # read the magmom magmom = read_magmom_from_running_log(abacus_lines) # roughly check the integrity of data from their length consistency - assert len(trajectory) == len(energies), \ - f'Inconsistent length: {len(trajectory)} != {len(energies)}' - assert len(trajectory) == len(elecstate), \ - f'Inconsistent length: {len(trajectory)} != {len(elecstate)}' + assert len(trajectory) == len( + energies + ), f"Inconsistent length: {len(trajectory)} != {len(energies)}" + assert len(trajectory) == len( + elecstate + ), f"Inconsistent length: {len(trajectory)} != {len(elecstate)}" if len(forces) == 0: forces = [None] * len(trajectory) - assert len(trajectory) == len(forces), \ - f'Inconsistent length: {len(trajectory)} != {len(forces)}' + assert len(trajectory) == len( + forces + ), f"Inconsistent length: {len(trajectory)} != {len(forces)}" if len(stress) == 0: stress = [None] * len(trajectory) - assert len(trajectory) == len(stress), \ - f'Inconsistent length: {len(trajectory)} != {len(stress)}' + assert len(trajectory) == len( + stress + ), f"Inconsistent length: {len(trajectory)} != {len(stress)}" if len(magmom) == 0: - magmom = [np.zeros(shape=(len(trajectory[0]['elem'])))] * len(trajectory) + magmom = [np.zeros(shape=(len(trajectory[0]["elem"])))] * len(trajectory) # loop over the frame... images, ind = [], sort_atoms_with for frame, estat, mag, frs, strs, ener in zip( - trajectory, elecstate, magmom, forces, stress, energies): + trajectory, elecstate, magmom, forces, stress, energies + ): # for each frame, a structure can be defined - ind = ind or list(range(len(frame['elem']))) - atoms = Atoms(symbols=np.array(frame['elem'])[ind].tolist(), - positions=frame['coords'][ind], - cell=frame['cell'], - magmoms=mag[ind]) + ind = ind or list(range(len(frame["elem"]))) + atoms = Atoms( + symbols=np.array(frame["elem"])[ind].tolist(), + positions=frame["coords"][ind], + cell=frame["cell"], + magmoms=mag[ind], + ) # from result, a calculator can be assembled # however, sometimes the force and stress is not calculated # in this case, we set them to None - frs = None if is_invalid_arr(frs) else frs[ind] + frs = None if is_invalid_arr(frs) else frs[ind] strs = None if is_invalid_arr(strs) else full_3x3_to_voigt_6_stress(strs) - calc = SinglePointDFTCalculator(atoms=atoms, energy=ener['E_KohnSham'], - free_energy=ener['E_KohnSham'], - forces=frs, stress=strs, - magmoms=mag, efermi=ener['E_Fermi'], - ibzkpts=kvecd, dipole=None) + calc = SinglePointDFTCalculator( + atoms=atoms, + energy=ener["E_KohnSham"], + free_energy=ener["E_KohnSham"], + forces=frs, + stress=strs, + magmoms=mag, + efermi=ener["E_Fermi"], + ibzkpts=kvecd, + dipole=None, + ) # import the eigenvalues and occupations kpoint-by-kpoint calc.kpts = [] - for ispn, (ekb, occ) in enumerate(zip(estat['e'], estat['occ'])): # loop over the spin - calc.kpts += [SinglePointKPoint(weight=wk[ik], - s=ispn, - k=kvecd[ik], - eps_n=ekb[ik,:], - f_n=occ[ik,:]) - for ik in range(len(kvecd))] + for ispn, (ekb, occ) in enumerate( + zip(estat["e"], estat["occ"]) + ): # loop over the spin + calc.kpts += [ + SinglePointKPoint( + weight=wk[ik], s=ispn, k=kvecd[ik], eps_n=ekb[ik, :], f_n=occ[ik, :] + ) + for ik in range(len(kvecd)) + ] # attach the calculator to the atoms atoms.calc = calc images.append(atoms) return images[index] + class TestLatestIO(unittest.TestCase): - ''' + """ test the validities of functions for the I/O of the latest version of ABACUS - ''' + """ + here = Path(__file__).parent - testfiles = here / 'testfiles' + testfiles = here / "testfiles" def test_read_esolver_type_from_running_log(self): self.assertEqual( read_esolver_type_from_running_log( - self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax'), - 'ksdft_lcao' + self.testfiles / "lcao-symm0-nspin2-multik-cellrelax" + ), + "ksdft_lcao", ) self.assertEqual( read_esolver_type_from_running_log( - self.testfiles / 'lcao-symm0-nspin2-multik-relax'), - 'ksdft_lcao' + self.testfiles / "lcao-symm0-nspin2-multik-relax" + ), + "ksdft_lcao", ) self.assertEqual( read_esolver_type_from_running_log( - self.testfiles / 'lcao-symm1-nspin1-multik-scf'), - 'ksdft_lcao' + self.testfiles / "lcao-symm1-nspin1-multik-scf" + ), + "ksdft_lcao", ) self.assertEqual( read_esolver_type_from_running_log( - self.testfiles / 'pw-symm0-nspin4-gamma-md'), - 'ksdft_pw' + self.testfiles / "pw-symm0-nspin4-gamma-md" + ), + "ksdft_pw", ) def test_read_band_from_running_log(self): self.assertIsNone( - read_band_from_running_log(self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax') + read_band_from_running_log( + self.testfiles / "lcao-symm0-nspin2-multik-cellrelax" + ) ) - + def test_read_band_from_eig_occ(self): - fn = self.testfiles / 'nspin4-gamma-eigocc' + fn = self.testfiles / "nspin4-gamma-eigocc" elecstate = read_band_from_eig_occ(fn) # 2 frames, 1 spin channel (nspin 4), 1 kpoint, 35 bands self.assertEqual(len(elecstate), 2) - for es in elecstate: # loop over frames - self.assertIn('k', es) - self.assertEqual(es['k'].shape, (1, 1, 3)) # ispin, ik, 3 - self.assertIn('e', es) - self.assertEqual(es['e'].shape, (1, 1, 35)) # ispin, ik, nbnd - self.assertIn('occ', es) - self.assertEqual(es['occ'].shape, (1, 1, 35)) # ispin, ik, nbnd + for es in elecstate: # loop over frames + self.assertIn("k", es) + self.assertEqual(es["k"].shape, (1, 1, 3)) # ispin, ik, 3 + self.assertIn("e", es) + self.assertEqual(es["e"].shape, (1, 1, 35)) # ispin, ik, nbnd + self.assertIn("occ", es) + self.assertEqual(es["occ"].shape, (1, 1, 35)) # ispin, ik, nbnd def test_read_traj_from_running_log(self): - traj = read_traj_from_running_log(self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax') + traj = read_traj_from_running_log( + self.testfiles / "lcao-symm0-nspin2-multik-cellrelax" + ) self.assertEqual(len(traj), 3) reference = [ - np.array([[4.17203 , 2.086015, 2.086015], - [2.086015, 4.17203 , 2.086015], - [2.086015, 2.086015, 4.17203 ]]), - np.array([[4.17550947, 2.05376104, 2.05376104], - [2.05811246, 4.12078078, 2.09979522], - [2.05811246, 2.09979522, 4.12078078]]), - np.array([[4.17667347, 2.04296382, 2.04296382], - [2.04876712, 4.10361705, 2.10440948], - [2.04876712, 2.10440948, 4.10361705]]) + np.array( + [ + [4.17203, 2.086015, 2.086015], + [2.086015, 4.17203, 2.086015], + [2.086015, 2.086015, 4.17203], + ] + ), + np.array( + [ + [4.17550947, 2.05376104, 2.05376104], + [2.05811246, 4.12078078, 2.09979522], + [2.05811246, 2.09979522, 4.12078078], + ] + ), + np.array( + [ + [4.17667347, 2.04296382, 2.04296382], + [2.04876712, 4.10361705, 2.10440948], + [2.04876712, 2.10440948, 4.10361705], + ] + ), ] - taud = np.array([[0. , 1. , 1. ], - [0.5 , 0.5 , 0.5 ], - [0.25, 0.25, 0.25], - [0.75, 0.75, 0.75]]) + taud = np.array( + [[0.0, 1.0, 1.0], [0.5, 0.5, 0.5], [0.25, 0.25, 0.25], [0.75, 0.75, 0.75]] + ) for t, c in zip(traj, reference): - self.assertEqual(t['coordinate'], 'Direct') - self.assertEqual(t['cell_unit'], 'Angstrom'), - self.assertEqual(t['alat_in_angstrom'], 4.17203) - self.assertTrue(all(e1 == e2 for e1, e2 in zip(t['elem'], np.array(['Ni1', 'Ni2', 'O', 'O'])))) - self.assertTrue(np.allclose(t['cell'], c)) - self.assertTrue(np.allclose(t['coords'] % 1, taud % 1)) + self.assertEqual(t["coordinate"], "Direct") + self.assertEqual(t["cell_unit"], "Angstrom"), + self.assertEqual(t["alat_in_angstrom"], 4.17203) + self.assertTrue( + all( + e1 == e2 + for e1, e2 in zip(t["elem"], np.array(["Ni1", "Ni2", "O", "O"])) + ) + ) + self.assertTrue(np.allclose(t["cell"], c)) + self.assertTrue(np.allclose(t["coords"] % 1, taud % 1)) def test_read_forces_from_running_log(self): - forces = read_forces_from_running_log(self.testfiles / 'lcao-symm0-nspin2-multik-relax') - self.assertEqual(len(forces), 2) # two frames + forces = read_forces_from_running_log( + self.testfiles / "lcao-symm0-nspin2-multik-relax" + ) + self.assertEqual(len(forces), 2) # two frames reference = [ - np.array([ - [-1.2994798821, -0.7502719805, 0.0000000000], - [ 1.2994798821, 0.7502719805, 0.0000000000], - ]), - np.array([ - [-1.6814741322, -0.9708025265, 0.0000000000], - [ 1.6814741322, 0.9708025265, 0.0000000000], - ]), + np.array( + [ + [-1.2994798821, -0.7502719805, 0.0000000000], + [1.2994798821, 0.7502719805, 0.0000000000], + ] + ), + np.array( + [ + [-1.6814741322, -0.9708025265, 0.0000000000], + [1.6814741322, 0.9708025265, 0.0000000000], + ] + ), ] for f, ref in zip(forces, reference): self.assertTrue(np.allclose(f, ref)) def test_read_stress_from_running_log(self): stresses = read_stress_from_running_log( - self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax') - self.assertEqual(len(stresses), 2) # two frames + self.testfiles / "lcao-symm0-nspin2-multik-cellrelax" + ) + self.assertEqual(len(stresses), 2) # two frames reference = [ - np.array([ - [ 28.0257165781, -25.0814687477, -25.0814687477], - [-25.0814687477, -57.2309475134, 52.8147857580], - [-25.0814687477, 52.8147857580, -57.2309475134], - ]), - np.array([ - [ 10.5133147463,-28.8166870580, -28.8166870559], - [-28.8166870580, 0.1640200010, 7.6016822662], - [-28.8166870559, 7.6016822662, 0.1640199977], - ]), + np.array( + [ + [28.0257165781, -25.0814687477, -25.0814687477], + [-25.0814687477, -57.2309475134, 52.8147857580], + [-25.0814687477, 52.8147857580, -57.2309475134], + ] + ), + np.array( + [ + [10.5133147463, -28.8166870580, -28.8166870559], + [-28.8166870580, 0.1640200010, 7.6016822662], + [-28.8166870559, 7.6016822662, 0.1640199977], + ] + ), ] for s, ref in zip(stresses, reference): self.assertTrue(np.allclose(s, -0.1 * GPa * ref)) def test_read_abacus_out_string(self): - fn = self.testfiles / 'pw-symm0-nspin4-gamma-md' + fn = self.testfiles / "pw-symm0-nspin4-gamma-md" # the case that does not give the instance of Path with self.assertRaises(AssertionError): read_abacus_out(str(fn)) def test_read_pw_symm0_nspin4_gamma_md(self): # make files ready - shutil.copy(self.testfiles / 'pw-symm0-nspin4-gamma-md', - self.testfiles / 'running_md.log') - shutil.copy(self.testfiles / 'nspin4-gamma-eigocc', - self.testfiles / 'eig_occ.txt') - shutil.copy(self.testfiles / 'nspin4-gamma-mddump', - self.testfiles / 'MD_dump') - - res = read_abacus_out(self.testfiles / 'running_md.log') + shutil.copy( + self.testfiles / "pw-symm0-nspin4-gamma-md", + self.testfiles / "running_md.log", + ) + shutil.copy( + self.testfiles / "nspin4-gamma-eigocc", self.testfiles / "eig_occ.txt" + ) + shutil.copy(self.testfiles / "nspin4-gamma-mddump", self.testfiles / "MD_dump") + + res = read_abacus_out(self.testfiles / "running_md.log") self.assertIsNotNone(res) - self.assertEqual(len(res), 2) # two frames + self.assertEqual(len(res), 2) # two frames for atoms in res: self.assertIsInstance(atoms, Atoms) @@ -662,16 +748,18 @@ def test_read_pw_symm0_nspin4_gamma_md(self): self.assertIsInstance(k, SinglePointKPoint) # remove the files - (self.testfiles / 'running_md.log').unlink() + (self.testfiles / "running_md.log").unlink() # (self.testfiles / 'eig_occ.txt').unlink() - (self.testfiles / 'MD_dump').unlink() + (self.testfiles / "MD_dump").unlink() def test_read_iter_header_from_running_log(self): header = read_iter_header_from_running_log( - self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax') + self.testfiles / "lcao-symm0-nspin2-multik-cellrelax" + ) self.assertTupleEqual(header[0], (1, 1)) self.assertTupleEqual(header[1], (1, 2)) self.assertTupleEqual(header[2], (2, 1)) -if __name__ == '__main__': - unittest.main() \ No newline at end of file + +if __name__ == "__main__": + unittest.main() diff --git a/interfaces/ASE_interface/abacuslite/io/legacyio.py b/interfaces/ASE_interface/abacuslite/io/legacyio.py index 2fb3640b17c..8ff18fca1eb 100644 --- a/interfaces/ASE_interface/abacuslite/io/legacyio.py +++ b/interfaces/ASE_interface/abacuslite/io/legacyio.py @@ -7,48 +7,54 @@ import numpy as np from ase.atoms import Atoms -from ase.calculators.singlepoint import ( - SinglePointKPoint, - SinglePointDFTCalculator -) +from ase.calculators.singlepoint import SinglePointKPoint, SinglePointDFTCalculator from ase.units import Ry, eV, GPa, bar from ase.stress import full_3x3_to_voigt_6_stress + # from ase.utils import reader -__all__ = ['read_kpoints_from_running_log', - 'read_band_from_running_log', 'read_traj_from_running_log', - 'read_traj_from_md_dump', 'read_forces_from_running_log', - 'read_stress_from_running_log', 'read_energies_from_running_log', - 'read_abacus_out'] +__all__ = [ + "read_kpoints_from_running_log", + "read_band_from_running_log", + "read_traj_from_running_log", + "read_traj_from_md_dump", + "read_forces_from_running_log", + "read_stress_from_running_log", + "read_energies_from_running_log", + "read_abacus_out", +] + + +def parse_kpoints_table( + raw: List[str], +) -> Tuple[np.ndarray, np.ndarray, List[int] | None]: + """parse the lines that are the kpoints table -def parse_kpoints_table(raw: List[str]) \ - -> Tuple[np.ndarray, np.ndarray, List[int] | None]: - '''parse the lines that are the kpoints table - Parameters ---------- raw : list of str The lines of the kpoints table. - + Returns ------- tuple A tuple containing the kpoints coordinates, weights and ibz2bz indexing, or without the indexing. - ''' + """ # the pattern with the ibz2bz indexing - W_PAT_ = r'\s*(\d+)' - W_PAT_ += r'\s+(-?\d\.\d+)\s+(-?\d\.\d+)\s+(-?\d\.\d+)' - W_PAT_ += r'\s+(\d\.\d+)\s+(\d+)' + W_PAT_ = r"\s*(\d+)" + W_PAT_ += r"\s+(-?\d\.\d+)\s+(-?\d\.\d+)\s+(-?\d\.\d+)" + W_PAT_ += r"\s+(\d\.\d+)\s+(\d+)" # the pattern without the ibz2bz indexing - WOPAT_ = r'\s*(\d+)' - WOPAT_ += r'\s+(-?\d\.\d+)\s+(-?\d\.\d+)\s+(-?\d\.\d+)' - WOPAT_ += r'\s+(\d\.\d+)' + WOPAT_ = r"\s*(\d+)" + WOPAT_ += r"\s+(-?\d\.\d+)\s+(-?\d\.\d+)\s+(-?\d\.\d+)" + WOPAT_ += r"\s+(\d\.\d+)" # for each line, must match either the first or the second with_ibz = all(re.match(W_PAT_, l) for l in raw) - assert with_ibz or all(re.match(WOPAT_, l) for l in raw), \ - f'Unexpected format of kpoints table: {raw}' + assert with_ibz or all( + re.match(WOPAT_, l) for l in raw + ), f"Unexpected format of kpoints table: {raw}" if with_ibz: data = [re.match(W_PAT_, l).groups() for l in raw] k = np.array([list(map(float, ki[1:4])) for ki in data]) @@ -61,15 +67,19 @@ def parse_kpoints_table(raw: List[str]) \ w = np.array([float(ki[4]) for ki in data]) return k, w, None -def read_kpoints_from_running_log(src: str | Path | List[str]) \ - -> Tuple[Tuple[np.ndarray, np.ndarray, List[int]], - Tuple[np.ndarray, np.ndarray], - List[Tuple[np.ndarray, np.ndarray]], - List[Tuple[np.ndarray, np.ndarray]], - List[Tuple[np.ndarray, np.ndarray]]]: - ''' + +def read_kpoints_from_running_log( + src: str | Path | List[str], +) -> Tuple[ + Tuple[np.ndarray, np.ndarray, List[int]], + Tuple[np.ndarray, np.ndarray], + List[Tuple[np.ndarray, np.ndarray]], + List[Tuple[np.ndarray, np.ndarray]], + List[Tuple[np.ndarray, np.ndarray]], +]: + """ read the kpoint coordinates and weights from the running log file. Up to now, - the ABACUS version 3.10.1 LTS, the ABACUS will print 4 tables of kpoints at + the ABACUS version 3.10.1 LTS, the ABACUS will print 4 tables of kpoints at first, including the one with the ibz2bz indexing, one of spinless direct coordinates, then two spin cartesian and direct coordinates of kpoints. If the cell would change during the calculation, then after each cell-relax step, @@ -80,32 +90,32 @@ def read_kpoints_from_running_log(src: str | Path | List[str]) \ ---------- fn : str The path to the ABACUS running log file. - + Returns ------- tuple A tuple contains the first table (with ibz2bz indexing), the second table (spinless direct coordinates), the trajectories of the third (spin-direct), fourth (spin-cartesian) and fifth (spin-direct) tables. - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw if l.strip()] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines # the pattern of table header - THPAT_ = r'\s*(IBZ|KPOINTS)' - THPAT_ += r'\s+(DIRECT|CARTESIAN)_X\s+(DIRECT|CARTESIAN)_Y\s+(DIRECT|CARTESIAN)_Z' - THPAT_ += r'\s+WEIGHT(\s+ibz2bz)?' + THPAT_ = r"\s*(IBZ|KPOINTS)" + THPAT_ += r"\s+(DIRECT|CARTESIAN)_X\s+(DIRECT|CARTESIAN)_Y\s+(DIRECT|CARTESIAN)_Z" + THPAT_ += r"\s+WEIGHT(\s+ibz2bz)?" # the pattern of table content, optionally with the ibz2bz data - TBPAT_ = r'\s*\d+' - TBPAT_ += r'\s+(-?\d(\.\d+)?)\s+(-?\d(\.\d+)?)\s+(-?\d(\.\d+)?)' - TBPAT_ += r'\s+(\d(\.\d+)?)(\s+\d+)?' + TBPAT_ = r"\s*\d+" + TBPAT_ += r"\s+(-?\d(\.\d+)?)\s+(-?\d(\.\d+)?)\s+(-?\d(\.\d+)?)" + TBPAT_ += r"\s+(\d(\.\d+)?)(\s+\d+)?" # search for the kpoints table tables, istart = [], 0 @@ -113,81 +123,97 @@ def read_kpoints_from_running_log(src: str | Path | List[str]) \ # search for the table header... ith = None for i, l in enumerate(raw[istart:]): - if re.match(THPAT_, l): # find a table header + if re.match(THPAT_, l): # find a table header ith = i break - if ith is None: # no more table + if ith is None: # no more table break - itb = ith + 1 # we assume there is no more header before the data - assert re.match(TBPAT_, raw[istart+itb]) # really? + itb = ith + 1 # we assume there is no more header before the data + assert re.match(TBPAT_, raw[istart + itb]) # really? # search for the end of the table... jtb = None - for i, l in enumerate(raw[istart+itb:]): - if not re.match(TBPAT_, l): # the next line is not a table content + for i, l in enumerate(raw[istart + itb :]): + if not re.match(TBPAT_, l): # the next line is not a table content jtb = i break - if jtb is None: # no more table + if jtb is None: # no more table break # parse the table - ktab_raw = raw[istart+itb:istart+itb+jtb] + ktab_raw = raw[istart + itb : istart + itb + jtb] tables.append(parse_kpoints_table(ktab_raw)) # update the starting point to search for the next table istart += itb + jtb + 1 - + # sort tables... kibz = tables.pop(0) # get the number of kpoints, then will use in reshaping the kpoints trajectories nk, _ = kibz[0].shape - kspnls = (tables[0][0], tables[0][1]) # spinless direct, drop the None in [2] - kd1traj = [(t[0].reshape(-1, nk, 3), t[1].reshape(-1, nk)) # drop the [2] because it is None - for i, t in enumerate(tables) if i % 3 == 0] - kctraj = [(t[0].reshape(-1, nk, 3), t[1].reshape(-1, nk)) # drop the [2] because it is None - for i, t in enumerate(tables) if i % 3 == 1] - kd2traj = [(t[0].reshape(-1, nk, 3), t[1].reshape(-1, nk)) # drop the [2] because it is None - for i, t in enumerate(tables) if i % 3 == 2] + kspnls = (tables[0][0], tables[0][1]) # spinless direct, drop the None in [2] + kd1traj = [ + ( + t[0].reshape(-1, nk, 3), + t[1].reshape(-1, nk), + ) # drop the [2] because it is None + for i, t in enumerate(tables) + if i % 3 == 0 + ] + kctraj = [ + ( + t[0].reshape(-1, nk, 3), + t[1].reshape(-1, nk), + ) # drop the [2] because it is None + for i, t in enumerate(tables) + if i % 3 == 1 + ] + kd2traj = [ + ( + t[0].reshape(-1, nk, 3), + t[1].reshape(-1, nk), + ) # drop the [2] because it is None + for i, t in enumerate(tables) + if i % 3 == 2 + ] return kibz, kspnls, kd1traj, kctraj, kd2traj -def read_esolver_type_from_running_log(src: str | Path | List[str]) \ - -> str: - ''' + +def read_esolver_type_from_running_log(src: str | Path | List[str]) -> str: + """ read the esolver type from the ABACUS running log file. Parameters ---------- fn : str The path to the ABACUS running log file. - + Returns ------- str The esolver type used in the ABACUS calculation. - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines # search for the line with information like: # "The esolver type has been set to : lj_pot" - lines = [ - re.match(r'The esolver type has been set to : (\S+)', - l) for l in raw - ] + lines = [re.match(r"The esolver type has been set to : (\S+)", l) for l in raw] eslvtyp = [m.group(1) for m in lines if m is not None] - assert len(set(eslvtyp)) == 1, \ - f'Inconsistent esolver type: {set(eslvtyp)}' + assert len(set(eslvtyp)) == 1, f"Inconsistent esolver type: {set(eslvtyp)}" return eslvtyp[0] -def read_band_from_running_log(src: str | Path | List[str]) \ - -> List[Dict[str, np.ndarray]]: - ''' + +def read_band_from_running_log( + src: str | Path | List[str], +) -> List[Dict[str, np.ndarray]]: + """ read the band structure from the ABACUS running log file. This would be helpful for MD case. @@ -195,97 +221,104 @@ def read_band_from_running_log(src: str | Path | List[str]) \ ---------- src : str or Path or list of str The path to the ABACUS running log file or the return of the readlines() method. - + Returns ------- list of dict A list of dictionaries containing the k-points and band energies. Each dictionary has keys 'k' and 'e', where 'k' is a list of k-point coordinates and 'e' is a numpy array of band energies. - ''' + """ masknspin = lambda n: 1 if n in [1, 4] else n if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines - + raw = [l for l in raw if l] # remove empty lines + # search for the number of spin channels, bands and kpoints first # r'nspin\s+=\s+(\d+)' - nspin = [re.search(r'nspin\s+=\s+(\d+)', l) for l in raw] + nspin = [re.search(r"nspin\s+=\s+(\d+)", l) for l in raw] nspin = [int(n.group(1)) for n in nspin if n] - assert len(set(nspin)) == 1, \ - f'Inconsistent number of spins: {set(nspin)}' + assert len(set(nspin)) == 1, f"Inconsistent number of spins: {set(nspin)}" nspin = nspin[0] # r'NBANDS\s+=\s+(\d+)' - nbnd = [re.search(r'NBANDS\s+=\s+(\d+)', l) for l in raw] + nbnd = [re.search(r"NBANDS\s+=\s+(\d+)", l) for l in raw] nbnd = [int(n.group(1)) for n in nbnd if n] - assert len(set(nbnd)) == 1, \ - f'Inconsistent number of bands: {set(nbnd)}' + assert len(set(nbnd)) == 1, f"Inconsistent number of bands: {set(nbnd)}" nbnd = nbnd[0] # r'nkstot\snow\s=\s(\d+)' # (there may be not the nkstot_ibz for symmetry 0 case) # symmetry 1 - nkibz = [re.search(r'nkstot_ibz\s+=\s+(\d+)', l) for l in raw] + nkibz = [re.search(r"nkstot_ibz\s+=\s+(\d+)", l) for l in raw] nkibz = [int(n.group(1)) for n in nkibz if n] # symmetry 0, -1 - nktot = [re.search(r'nkstot\s+=\s+(\d+)', l) for l in raw] + nktot = [re.search(r"nkstot\s+=\s+(\d+)", l) for l in raw] nktot = [int(n.group(1)) for n in nktot if n] nk = nktot if len(nkibz) == 0 else nkibz - assert len(set(nk)) == 1, \ - f'Inconsistent number of k-points: {set(nk)}' + assert len(set(nk)) == 1, f"Inconsistent number of k-points: {set(nk)}" nk = nk[0] # extract the band, first find the leading line # 333/511 kpoint (Cartesian) = 0.13022 0.052050 -6.5974e-10 (190 pws) - ekb_leading_pat = r'\d+/\d+\s+kpoint\s+\(Cartesian\)\s+=\s+' \ - + r'(-?\d(\.\d+)?(e-\d+)?)\s+' \ - + r'(-?\d(\.\d+)?(e-\d+)?)\s+' \ - + r'(-?\d(\.\d+)?(e-\d+)?)\s+' \ - + r'\(\d+\s+pws\)' + ekb_leading_pat = ( + r"\d+/\d+\s+kpoint\s+\(Cartesian\)\s+=\s+" + + r"(-?\d(\.\d+)?(e-\d+)?)\s+" + + r"(-?\d(\.\d+)?(e-\d+)?)\s+" + + r"(-?\d(\.\d+)?(e-\d+)?)\s+" + + r"\(\d+\s+pws\)" + ) iekb = [i for i, l in enumerate(raw) if re.match(ekb_leading_pat, l)] - assert len(iekb) > 0, f'No k-point found' - assert len(iekb) % (masknspin(nspin)*nk) == 0, \ - f'Inconsistent number of k-points: {len(iekb)} vs {nk}' + assert len(iekb) > 0, f"No k-point found" + assert ( + len(iekb) % (masknspin(nspin) * nk) == 0 + ), f"Inconsistent number of k-points: {len(iekb)} vs {nk}" k_raw = [re.match(ekb_leading_pat, raw[i]).groups() for i in iekb] k = np.array([list(map(float, ki[::3])) for ki in k_raw]) - assert k.shape == (len(iekb), 3), \ - f'Unexpected shape of k-points: {k.shape}, expected ({len(iekb)}, 3)' - - nframe = len(iekb) // (masknspin(nspin)*nk) # number of frames, for MD or relax tasks - ekb_raw = [l for i in iekb for l in raw[i+1:i+1+nbnd]] + assert k.shape == ( + len(iekb), + 3, + ), f"Unexpected shape of k-points: {k.shape}, expected ({len(iekb)}, 3)" + + nframe = len(iekb) // ( + masknspin(nspin) * nk + ) # number of frames, for MD or relax tasks + ekb_raw = [l for i in iekb for l in raw[i + 1 : i + 1 + nbnd]] # each line should in the format of # r'\d+\s+(-?\d(\.\d+)?)\s+(\d(\.\d+)?) # Changelog: there are cases that the band energies and occupations are in scientific # notation, e.g., 1.0e-01, 1.0e+00, so the regular expression should be # r'\d+\s+(-?\d+(\.\d+)?(e[+-]\d+)?)\s+(\d+(\.\d+)?(e[+-]\d+)?)' instead - ekbpat = r'\d+\s+' - ekbpat += r'(-?\d+(\.\d+)?(e[+-]\d+)?)\s+' - ekbpat += r'(\d+(\.\d+)?(e[+-]\d+)?)' - assert all(re.match(ekbpat, l) for l in ekb_raw), \ - 'Unexpected format of band energies: \n' + '\n'.join(ekb_raw) + ekbpat = r"\d+\s+" + ekbpat += r"(-?\d+(\.\d+)?(e[+-]\d+)?)\s+" + ekbpat += r"(\d+(\.\d+)?(e[+-]\d+)?)" + assert all( + re.match(ekbpat, l) for l in ekb_raw + ), "Unexpected format of band energies: \n" + "\n".join(ekb_raw) # ekb in the second column, occ in the third column ekb_raw = np.array([list(map(float, l.split())) for l in ekb_raw]) - assert ekb_raw.shape == (nframe * masknspin(nspin) * nk * nbnd, 3), \ - f'Unexpected shape of band energies: {ekb_raw.shape}. ' \ - f'Expected ({nframe * masknspin(nspin) * nk * nbnd}, 3), in which ' \ - f'nframe={nframe}, nspin={nspin}, nk={nk}, nbnd={nbnd}' + assert ekb_raw.shape == (nframe * masknspin(nspin) * nk * nbnd, 3), ( + f"Unexpected shape of band energies: {ekb_raw.shape}. " + f"Expected ({nframe * masknspin(nspin) * nk * nbnd}, 3), in which " + f"nframe={nframe}, nspin={nspin}, nk={nk}, nbnd={nbnd}" + ) ekb = ekb_raw[:, 1].reshape(nframe, masknspin(nspin), nk, nbnd) occ = ekb_raw[:, 2].reshape(nframe, masknspin(nspin), nk, nbnd) # reshape the k-points to (nframe, nspin, nk, 3) k = k.reshape(nframe, masknspin(nspin), nk, 3) - return [{'k': ki, 'e': eki, 'occ': occi} - for ki, eki, occi in zip(k, ekb, occ)] + return [{"k": ki, "e": eki, "occ": occi} for ki, eki, occi in zip(k, ekb, occ)] -def read_traj_from_running_log(src: str | Path | List[str]) \ - -> List[Dict[str, np.ndarray|str]]: - ''' + +def read_traj_from_running_log( + src: str | Path | List[str], +) -> List[Dict[str, np.ndarray | str]]: + """ read the trajectory from the ABACUS running log file. This would be helpful for MD case. @@ -293,13 +326,13 @@ def read_traj_from_running_log(src: str | Path | List[str]) \ ---------- fn : str The path to the ABACUS running log file. - + Returns ------- list of dict A list of dictionaries containing the coordinate system, cell, elements and the coordinates of the atoms. Each dictionary has keys 'coordinate', - 'cell', 'cell_unit', 'alat_in_angstrom', 'elem', and 'coords'. + 'cell', 'cell_unit', 'alat_in_angstrom', 'elem', and 'coords'. The values are numpy arrays or strings. - 'coordinate': string, the coordinate system, e.g., 'Cartesian' or 'Direct' - 'cell': numpy array of shape (3, 3) @@ -307,99 +340,118 @@ def read_traj_from_running_log(src: str | Path | List[str]) \ - 'alat_in_angstrom': float, the lattice constant in Angstrom - 'elem': list of strings, the chemical symbols of the elements - 'coords': numpy array of shape (natoms, 3), the coordinates of the atoms - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines # search for the total number of atoms # r'TOTAL ATOM NUMBER = (\d+)' - natoms = [re.search(r'TOTAL ATOM NUMBER\s*=\s*(\d+)', l) for l in raw] + natoms = [re.search(r"TOTAL ATOM NUMBER\s*=\s*(\d+)", l) for l in raw] natoms = [int(n.group(1)) for n in natoms if n] - assert len(set(natoms)) == 1, \ - f'Inconsistent number of atoms: {set(natoms)}' + assert len(set(natoms)) == 1, f"Inconsistent number of atoms: {set(natoms)}" natoms = natoms[0] # search for the coordinate system # r'^([DIRECT|CARTESIAN]) COORDINATES$' - coordinate = [re.match(r'^(DIRECT|CARTESIAN) COORDINATES', l) for l in raw] + coordinate = [re.match(r"^(DIRECT|CARTESIAN) COORDINATES", l) for l in raw] coordinate = [l.group(1).lower().capitalize() for l in coordinate if l] - assert len(set(coordinate)) == 1, \ - f'Inconsistent coordinate system: {set(coordinate)}' + assert ( + len(set(coordinate)) == 1 + ), f"Inconsistent coordinate system: {set(coordinate)}" coordinate = coordinate[0] # search for the cell, but first get the "a0": lattice constant # r'lattice constant (Angstrom) = (-?\d+(\.\d+)?)' - a0 = [re.search(r'lattice constant \(Angstrom\)\s*=\s*(-?\d+(\.\d+)?)', l, - re.IGNORECASE) for l in raw] + a0 = [ + re.search( + r"lattice constant \(Angstrom\)\s*=\s*(-?\d+(\.\d+)?)", l, re.IGNORECASE + ) + for l in raw + ] a0 = [float(n.group(1)) for n in a0 if n] - assert len(set(a0)) == 1, f'Inconsistent lattice constant: {set(a0)}' + assert len(set(a0)) == 1, f"Inconsistent lattice constant: {set(a0)}" a0 = a0[0] # then the cell # r'^Lattice vectors: \(Cartesian coordinate: in unit of a\_0\)$' - icell = [i for i, l in enumerate(raw) - if re.match(r'^Lattice vectors: \(Cartesian coordinate: in unit of a_0\)$', l)] - assert len(icell) > 0, f'No cell found' + icell = [ + i + for i, l in enumerate(raw) + if re.match(r"^Lattice vectors: \(Cartesian coordinate: in unit of a_0\)$", l) + ] + assert len(icell) > 0, f"No cell found" # nframe = len(icell) # will be 1 for NVT MD # assert nframe > 0, f'Invalid trajectory with length {nframe}') - cell_raw = [raw[i+1:i+1+3] for i in icell] - cell = [np.array([list(map(float, l.split())) for l in c]) * a0 - for c in cell_raw] # convert to Angstrom - assert all(c.shape == (3, 3) for c in cell), \ - f'Unexpected shape of cell: {[c.shape for c in cell]}' - + cell_raw = [raw[i + 1 : i + 1 + 3] for i in icell] + cell = [ + np.array([list(map(float, l.split())) for l in c]) * a0 for c in cell_raw + ] # convert to Angstrom + assert all( + c.shape == (3, 3) for c in cell + ), f"Unexpected shape of cell: {[c.shape for c in cell]}" + # search for the elements and coordinates # r'^tau[c|d]_([A-Z][a-z]?)\d+\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)*' - m_tau = [re.match(r'^tau[c|d]_([A-Z][a-z]?)\d+' - r'\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)', l) - for l in raw] + m_tau = [ + re.match( + r"^tau[c|d]_([A-Z][a-z]?)\d+" + r"\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)", + l, + ) + for l in raw + ] m_tau = [m for m in m_tau if m] - assert len(m_tau) > 0, f'No atoms found' + assert len(m_tau) > 0, f"No atoms found" nframe = len(m_tau) // natoms - assert nframe > 0, f'Invalid trajectory with length {nframe}' + assert nframe > 0, f"Invalid trajectory with length {nframe}" elem = [m.group(1) for m in m_tau] - coords = np.array([[float(m.group(2)), float(m.group(4)), float(m.group(6))] - for m in m_tau]).reshape(-1, natoms, 3) - assert coords.shape == (nframe, natoms, 3), \ - f'Unexpected shape of coordinates: {coords.shape}, ' \ - f'expected ({nframe}, {natoms}, 3)' - assert len(elem) == natoms * nframe, \ - f'Unexpected number of elements: {len(elem)}, ' \ - f'expected {natoms * nframe}' - elem = [elem[i:i+natoms] for i in range(0, len(elem), natoms)] + coords = np.array( + [[float(m.group(2)), float(m.group(4)), float(m.group(6))] for m in m_tau] + ).reshape(-1, natoms, 3) + assert coords.shape == (nframe, natoms, 3), ( + f"Unexpected shape of coordinates: {coords.shape}, " + f"expected ({nframe}, {natoms}, 3)" + ) + assert len(elem) == natoms * nframe, ( + f"Unexpected number of elements: {len(elem)}, " f"expected {natoms * nframe}" + ) + elem = [elem[i : i + natoms] for i in range(0, len(elem), natoms)] # final: for volume-constant run, the cell information will only be printed for once cell = np.array(cell).reshape(-1, 3, 3) if cell.shape[0] == 1: cell = [cell[0] for _ in range(nframe)] - assert len(cell) == nframe, \ - f'Unexpected number of cells: {len(cell)}, ' \ - f'expected {nframe}' - return [{ - 'coordinate': coordinate, - 'cell': c, - 'cell_unit': 'Angstrom', - 'alat_in_angstrom': a0, - 'elem': e, - 'coords': co - } for c, e, co in zip(cell, elem, coords)] - -def read_traj_from_md_dump(src: str | Path | List[str]) \ - -> List[Dict[str, np.ndarray]]: - ''' + assert len(cell) == nframe, ( + f"Unexpected number of cells: {len(cell)}, " f"expected {nframe}" + ) + return [ + { + "coordinate": coordinate, + "cell": c, + "cell_unit": "Angstrom", + "alat_in_angstrom": a0, + "elem": e, + "coords": co, + } + for c, e, co in zip(cell, elem, coords) + ] + + +def read_traj_from_md_dump(src: str | Path | List[str]) -> List[Dict[str, np.ndarray]]: + """ read the trajectory from the ABACUS MD dump file Parameters ---------- fn : str The path to the ABACUS MD dump file. - + Returns ------- list of dict @@ -407,111 +459,122 @@ def read_traj_from_md_dump(src: str | Path | List[str]) \ and the coordinates of the atoms. Each dictionary has keys 'coordinate', 'cell', 'alat_in_angstrom', 'elem', and 'coords'. The values are numpy arrays or strings. - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines # search for the lattice constant # r'LATTICE_CONSTANT:\s+(-?\d+(\.\d+)?) Angstrom' - a0 = [re.search(r'LATTICE_CONSTANT:\s+(-?\d+(\.\d+)?) Angstrom', l) for l in raw] + a0 = [re.search(r"LATTICE_CONSTANT:\s+(-?\d+(\.\d+)?) Angstrom", l) for l in raw] a0 = [float(n.group(1)) for n in a0 if n] - assert len(set(a0)) == 1, \ - f'Inconsistent lattice constant: {set(a0)}' + assert len(set(a0)) == 1, f"Inconsistent lattice constant: {set(a0)}" a0 = a0[0] # search for the cell # r'^LATTICE_VECTORS$' - icell = [i for i, l in enumerate(raw) if re.match(r'^LATTICE_VECTORS$', l)] - assert len(icell) > 0, f'No cell found in file' - cell_raw = [raw[i+1:i+1+3] for i in icell] - cell = [np.array([list(map(float, l.split())) for l in c]) - for c in cell_raw] - assert all(c.shape == (3, 3) for c in cell), \ - f'Unexpected shape of cell: {[c.shape for c in cell]}' + icell = [i for i, l in enumerate(raw) if re.match(r"^LATTICE_VECTORS$", l)] + assert len(icell) > 0, f"No cell found in file" + cell_raw = [raw[i + 1 : i + 1 + 3] for i in icell] + cell = [np.array([list(map(float, l.split())) for l in c]) for c in cell_raw] + assert all( + c.shape == (3, 3) for c in cell + ), f"Unexpected shape of cell: {[c.shape for c in cell]}" nframe = len(cell) # search for the elements and coordinates # r'^\d+\s+([A-Z][a-z]?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)*' - m_tau = [re.match(r'^\d+\s+([A-Z][a-z]?)\s+' - r'(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)', l) - for l in raw] + m_tau = [ + re.match( + r"^\d+\s+([A-Z][a-z]?)\s+" + r"(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)", + l, + ) + for l in raw + ] m_tau = [m for m in m_tau if m] - assert len(m_tau) > 0, f'No atoms found' + assert len(m_tau) > 0, f"No atoms found" natoms = len(m_tau) // nframe - assert natoms > 0, f'Invalid trajectory with length {nframe}.' + assert natoms > 0, f"Invalid trajectory with length {nframe}." elem = [m.group(1) for m in m_tau] - coords = np.array([[float(m.group(2)), float(m.group(4)), float(m.group(6))] - for m in m_tau]).reshape(nframe, natoms, 3) - assert coords.shape == (nframe, natoms, 3), \ - f'Unexpected shape of coordinates: {coords.shape}, ' \ - f'expected ({nframe}, {natoms}, 3)' - assert len(elem) == natoms * nframe, \ - f'Unexpected number of elements: {len(elem)}, ' \ - f'expected {natoms * nframe}' - elem = [elem[i:i+natoms] for i in range(0, len(elem), natoms)] - assert len(elem) == nframe, \ - f'Unexpected number of elements: {len(elem)}, ' \ - f'expected {nframe}' - - return [{ - 'coordinate': 'Cartesian', - 'cell': c, - 'alat_in_angstrom': a0, - 'elem': e, - 'coords': co - } for c, e, co in zip(cell, elem, coords)] - -def read_forces_from_running_log(src: str | Path | List[str]) \ - -> List[np.ndarray]: - '''''' + coords = np.array( + [[float(m.group(2)), float(m.group(4)), float(m.group(6))] for m in m_tau] + ).reshape(nframe, natoms, 3) + assert coords.shape == (nframe, natoms, 3), ( + f"Unexpected shape of coordinates: {coords.shape}, " + f"expected ({nframe}, {natoms}, 3)" + ) + assert len(elem) == natoms * nframe, ( + f"Unexpected number of elements: {len(elem)}, " f"expected {natoms * nframe}" + ) + elem = [elem[i : i + natoms] for i in range(0, len(elem), natoms)] + assert len(elem) == nframe, ( + f"Unexpected number of elements: {len(elem)}, " f"expected {nframe}" + ) + + return [ + { + "coordinate": "Cartesian", + "cell": c, + "alat_in_angstrom": a0, + "elem": e, + "coords": co, + } + for c, e, co in zip(cell, elem, coords) + ] + + +def read_forces_from_running_log(src: str | Path | List[str]) -> List[np.ndarray]: + """""" if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines # iteratively search for the forces, which led by the title `TOTAL-FORCE` forces, istart = [], 0 - + while istart < len(raw): - ith = None # index of the table header + ith = None # index of the table header for i, l in enumerate(raw[istart:]): - if re.match(r'\s*TOTAL\-FORCE\s*\(eV\s*/Angstrom\)', l, re.IGNORECASE): + if re.match(r"\s*TOTAL\-FORCE\s*\(eV\s*/Angstrom\)", l, re.IGNORECASE): ith = i break - if ith is None: # no forces found + if ith is None: # no forces found break # otherwise # search for the first line that matches the pattern - FORCEPAT_ = r'\s*([A-Z][a-z]?\d+)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)' - itb = None # index of the first line of the table body - for i, l in enumerate(raw[istart+ith+1:]): + FORCEPAT_ = ( + r"\s*([A-Z][a-z]?\d+)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)" + ) + itb = None # index of the first line of the table body + for i, l in enumerate(raw[istart + ith + 1 :]): if re.match(FORCEPAT_, l): itb = i break - if itb is None: # no content found + if itb is None: # no content found break # otherwise - jtb = None # index of the last line of the table body - for j, l in enumerate(raw[istart+ith+1+itb:]): + jtb = None # index of the last line of the table body + for j, l in enumerate(raw[istart + ith + 1 + itb :]): if not re.match(FORCEPAT_, l): jtb = j break - if jtb is None: # no content found + if jtb is None: # no content found break - + # truncate the force table and append - force_raw = raw[istart+ith+1+itb:istart+ith+1+itb+jtb] + force_raw = raw[istart + ith + 1 + itb : istart + ith + 1 + itb + jtb] force = np.array([list(map(float, l.split()[1:])) for l in force_raw]) forces.append(force) @@ -520,46 +583,48 @@ def read_forces_from_running_log(src: str | Path | List[str]) \ return forces -def read_stress_from_running_log(src: str | Path | List[str]) \ - -> List[np.ndarray]: - '''''' + +def read_stress_from_running_log(src: str | Path | List[str]) -> List[np.ndarray]: + """""" if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines # iteratively search for the stress, which led by the title `TOTAL-STRESS` stresses, istart = [], 0 - + while istart < len(raw): - ith = None # index of the table header + ith = None # index of the table header for i, l in enumerate(raw[istart:]): - if re.match(r'\s*TOTAL\-STRESS\s*\(KBAR\)', l, re.IGNORECASE): + if re.match(r"\s*TOTAL\-STRESS\s*\(KBAR\)", l, re.IGNORECASE): ith = i break - if ith is None: # no stress found + if ith is None: # no stress found break # otherwise # search for the first line that matches the pattern - STRESSPAT_ = r'\s*(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)' - itb = None # index of the first line of the table body - for i, l in enumerate(raw[istart+ith+1:]): + STRESSPAT_ = r"\s*(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)" + itb = None # index of the first line of the table body + for i, l in enumerate(raw[istart + ith + 1 :]): if re.match(STRESSPAT_, l): itb = i break - if itb is None: # no content found + if itb is None: # no content found break # otherwise - jtb = 3 # because the stress tensor would be a (3, 3)-matrix - + jtb = 3 # because the stress tensor would be a (3, 3)-matrix + # truncate the stress table and append - stress_raw = raw[istart+ith+1+itb:istart+ith+1+itb+jtb] - stress = np.array([list(map(float, l.split())) for l in stress_raw]).reshape(3, 3) + stress_raw = raw[istart + ith + 1 + itb : istart + ith + 1 + itb + jtb] + stress = np.array([list(map(float, l.split())) for l in stress_raw]).reshape( + 3, 3 + ) # unit: kbar -> GPa stresses.append(-0.1 * stress * GPa) @@ -568,50 +633,52 @@ def read_stress_from_running_log(src: str | Path | List[str]) \ return stresses -def read_energies_from_running_log(src: str | Path | List[str]) \ - -> List[Dict[str, float]]: - '''''' + +def read_energies_from_running_log( + src: str | Path | List[str], +) -> List[Dict[str, float]]: + """""" if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines energies_ry, energies_ev, istart = [], [], 0 - + while istart < len(raw): - ith = None # index of the table header + ith = None # index of the table header for i, l in enumerate(raw[istart:]): - if re.match(r'\s*ENERGY\s+Rydberg\s+eV', l, re.IGNORECASE): + if re.match(r"\s*ENERGY\s+Rydberg\s+eV", l, re.IGNORECASE): ith = i break - if ith is None: # no energies found + if ith is None: # no energies found break # otherwise # search for the first line that matches the pattern - ENERGYPAT_ = r'\s*E_(\S+)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)' - itb = None # index of the first line of the table body - for i, l in enumerate(raw[istart+ith+1:]): + ENERGYPAT_ = r"\s*E_(\S+)\s+(-?\d+(\.\d+)?)\s+(-?\d+(\.\d+)?)" + itb = None # index of the first line of the table body + for i, l in enumerate(raw[istart + ith + 1 :]): if re.match(ENERGYPAT_, l): itb = i break - if itb is None: # no content found + if itb is None: # no content found break # otherwise jtb = None - for j, l in enumerate(raw[istart+ith+1+itb:]): + for j, l in enumerate(raw[istart + ith + 1 + itb :]): if not re.match(ENERGYPAT_, l): jtb = j break - if jtb is None: # no content found + if jtb is None: # no content found break - + # truncate the energy table and append - tb_raw = raw[istart+ith+1+itb:istart+ith+1+itb+jtb] + tb_raw = raw[istart + ith + 1 + itb : istart + ith + 1 + itb + jtb] # first item is the name of the energy component # the second and third items are the ry and ev values name, e_ry, e_ev = zip(*[l.split() for l in tb_raw]) @@ -623,9 +690,9 @@ def read_energies_from_running_log(src: str | Path | List[str]) \ return energies_ry, energies_ev -def read_magmom_from_running_log(src: str | Path | List[str]) \ - -> List[np.ndarray]: - ''' + +def read_magmom_from_running_log(src: str | Path | List[str]) -> List[np.ndarray]: + """ Read the magnetic momentum from ABACUS running log. Note: this function returns the list of np.ndarray which has dimension of (nat, 3), where nat is the number of atoms, and 3 stands for @@ -647,68 +714,74 @@ def read_magmom_from_running_log(src: str | Path | List[str]) \ ------- magmom : List[np.ndarray] The trajectories of the magnetic moment of each atom. - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines - + raw = [l for l in raw if l] # remove empty lines + magmom, istart = [], 0 while istart < len(raw): - ith = None # index of the table header + ith = None # index of the table header for i, l in enumerate(raw[istart:]): - if re.match(r'\s*Total\sMagnetism\s\(uB\)(\s+x\s+y\s+z)?\s*$', l, - re.IGNORECASE): + if re.match( + r"\s*Total\sMagnetism\s\(uB\)(\s+x\s+y\s+z)?\s*$", l, re.IGNORECASE + ): ith = i break - if ith is None: # no magmom found + if ith is None: # no magmom found break # otherwise # search for the first line that matches the pattern - MAGMOMPAT_ = r'\s*([A-Z][a-z]?\d+)' - MAGMOMPAT_ += r'\s+([-+]?\d+\.\d+)' - MAGMOMPAT_ += r'(\s+([-+]?\d+\.\d+)\s+([-+]?\d+\.\d+))?\s*' - itb = None # index of the first line of the table body - for i, l in enumerate(raw[istart+ith+1:]): + MAGMOMPAT_ = r"\s*([A-Z][a-z]?\d+)" + MAGMOMPAT_ += r"\s+([-+]?\d+\.\d+)" + MAGMOMPAT_ += r"(\s+([-+]?\d+\.\d+)\s+([-+]?\d+\.\d+))?\s*" + itb = None # index of the first line of the table body + for i, l in enumerate(raw[istart + ith + 1 :]): if re.match(MAGMOMPAT_, l): itb = i break - if itb is None: # no content found + if itb is None: # no content found break # otherwise jtb = None - for j, l in enumerate(raw[istart+ith+1+itb:]): + for j, l in enumerate(raw[istart + ith + 1 + itb :]): if not re.match(MAGMOMPAT_, l): jtb = j break - if jtb is None: # no content found + if jtb is None: # no content found break - + # truncate the magmom table and append - tb_raw = raw[istart+ith+1+itb:istart+ith+1+itb+jtb] + tb_raw = raw[istart + ith + 1 + itb : istart + ith + 1 + itb + jtb] # first item is the name of the magmom component # the second to fourth items are the x, y, z components res = list(zip(*[l.split() for l in tb_raw]))[1:] - assert len(res) in [1, 3] # colinear or non-colinear case - if len(res) == 1: # colinear case + assert len(res) in [1, 3] # colinear or non-colinear case + if len(res) == 1: # colinear case magmom.append(np.array([list(map(float, res[-1]))]).flatten()) - else: # non-colinear case + else: # non-colinear case mx, my, mz = res - magmom.append(np.array([list(map(float, (mx, my, mz))) - for mx, my, mz in zip(mx, my, mz)])) + magmom.append( + np.array( + [list(map(float, (mx, my, mz))) for mx, my, mz in zip(mx, my, mz)] + ) + ) # update the istart istart += ith + itb + jtb + 1 return magmom -def read_iter_header_from_running_log(src: str | Path | List[str]) \ - -> List[Tuple[int, int]]: - ''' + +def read_iter_header_from_running_log( + src: str | Path | List[str], +) -> List[Tuple[int, int]]: + """ read the "iteration header" from the running log, useful for determining which is the final iteration. The "iteration header" is defined as: ``` @@ -718,42 +791,42 @@ def read_iter_header_from_running_log(src: str | Path | List[str]) \ ``` PW ALGORITHM --------------- ION=2 ELEC=1 ----------------------- ``` - ''' + """ if isinstance(src, (str, Path)): with open(src) as f: raw = f.readlines() - else: # assume the src is the return of the readlines() + else: # assume the src is the return of the readlines() raw = src # with open(fn) as f: # raw = f.readlines() raw = [l.strip() for l in raw] - raw = [l for l in raw if l] # remove empty lines + raw = [l for l in raw if l] # remove empty lines - HEADER_PAT = r'(LCAO|PW)\s+ALGORITHM\s+-+\s+ION=\s+([0-9]+)\s+ELEC=\s+([0-9]+)' + HEADER_PAT = r"(LCAO|PW)\s+ALGORITHM\s+-+\s+ION=\s+([0-9]+)\s+ELEC=\s+([0-9]+)" res = [re.findall(HEADER_PAT, l) for l in raw] return [(int(pack[0][1]), int(pack[0][2])) for pack in res if pack] + def find_final_info_with_iter_header( - info: List[Any], - headers: List[Tuple[int, int]] - ) -> List[Any]: - '''find the energies of the final iteration - + info: List[Any], headers: List[Tuple[int, int]] +) -> List[Any]: + """find the energies of the final iteration + Parameters ---------- info: List[Dict[str, float]] - The information that is printed after each iteration. + The information that is printed after each iteration. headers: List[Tuple[int, int]] The "iteration header" returned from the function `read_iter_header_from_running_log` - + Returns ------- List[Any] The information of the final iteration. - ''' - headers = np.array(headers) # because indices should start from 0 + """ + headers = np.array(headers) # because indices should start from 0 assert headers.ndim == 2 assert headers.shape[1] == 2 @@ -763,8 +836,9 @@ def find_final_info_with_iter_header( return [info[i] for i in ielec] + def is_invalid_arr(arr) -> bool: - '''Check if the array is invalid, including the cases of None, + """Check if the array is invalid, including the cases of None, empty array, and array with NaN values. Parameters @@ -776,7 +850,7 @@ def is_invalid_arr(arr) -> bool: ------- is_invalid : bool Whether the array is invalid. - ''' + """ if arr is None: return True if isinstance(arr, list): @@ -789,12 +863,15 @@ def is_invalid_arr(arr) -> bool: return True return False + # @reader -def read_abacus_out(fileobj, - index=slice(None), - results_required=True, - sort_atoms_with: Optional[List[int]] = None) -> Atoms | List[Atoms]: - '''Reads the ABACUS output files. This function would be called by +def read_abacus_out( + fileobj, + index=slice(None), + results_required=True, + sort_atoms_with: Optional[List[int]] = None, +) -> Atoms | List[Atoms]: + """Reads the ABACUS output files. This function would be called by the AbacusTemplate.read_results() function. The detailed call stack is as follows: get_potential_energy() @@ -825,17 +902,17 @@ def read_abacus_out(fileobj, ------- atoms : Atoms | List[Atoms] The atoms object, whose calculator is the `SinglePointDFTCalculator`. - ''' + """ if isinstance(fileobj, (str, Path)): with open(fileobj) as f: abacus_lines = f.readlines() - else: # from the `with open(fn) as fileobj:` context + else: # from the `with open(fn) as fileobj:` context assert isinstance(fileobj, TextIOWrapper) abacus_lines = fileobj.readlines() - + # read the esolver type eslvtyp = read_esolver_type_from_running_log(abacus_lines) - + # read the structure, with the cell, elem, etc. (nframe) trajectory = read_traj_from_running_log(abacus_lines) # read the eigenvalues (nframe, nk, nbnd) @@ -857,220 +934,259 @@ def read_abacus_out(fileobj, # only keep the energies of the final iteration for each ion step energies = find_final_info_with_iter_header( read_energies_from_running_log(abacus_lines)[1], - read_iter_header_from_running_log(abacus_lines) + read_iter_header_from_running_log(abacus_lines), ) - + # read the magmom magmom = read_magmom_from_running_log(abacus_lines) # roughly check the integrity of data from their length consistency - assert len(trajectory) == len(energies), \ - f'Inconsistent length: {len(trajectory)} != {len(energies)}' - assert len(trajectory) == len(elecstate), \ - f'Inconsistent length: {len(trajectory)} != {len(elecstate)}' + assert len(trajectory) == len( + energies + ), f"Inconsistent length: {len(trajectory)} != {len(energies)}" + assert len(trajectory) == len( + elecstate + ), f"Inconsistent length: {len(trajectory)} != {len(elecstate)}" if len(forces) == 0: forces = [None] * len(trajectory) - assert len(trajectory) == len(forces), \ - f'Inconsistent length: {len(trajectory)} != {len(forces)}' + assert len(trajectory) == len( + forces + ), f"Inconsistent length: {len(trajectory)} != {len(forces)}" if len(stress) == 0: stress = [None] * len(trajectory) - assert len(trajectory) == len(stress), \ - f'Inconsistent length: {len(trajectory)} != {len(stress)}' + assert len(trajectory) == len( + stress + ), f"Inconsistent length: {len(trajectory)} != {len(stress)}" if len(magmom) == 0: - magmom = [np.zeros(shape=(len(trajectory[0]['elem'])))] * len(trajectory) + magmom = [np.zeros(shape=(len(trajectory[0]["elem"])))] * len(trajectory) # loop over the frame... images, ind = [], sort_atoms_with for frame, estat, mag, frs, strs, ener in zip( - trajectory, elecstate, magmom, forces, stress, energies): + trajectory, elecstate, magmom, forces, stress, energies + ): # for each frame, a structure can be defined - ind = ind or list(range(len(frame['elem']))) - atoms = Atoms(symbols=np.array(frame['elem'])[ind].tolist(), - positions=frame['coords'][ind], - cell=frame['cell'], - magmoms=mag[ind]) - + ind = ind or list(range(len(frame["elem"]))) + atoms = Atoms( + symbols=np.array(frame["elem"])[ind].tolist(), + positions=frame["coords"][ind], + cell=frame["cell"], + magmoms=mag[ind], + ) + # from result, a calculator can be assembled # however, sometimes the force and stress is not calculated # in this case, we set them to None - frs = None if is_invalid_arr(frs) else frs[ind] + frs = None if is_invalid_arr(frs) else frs[ind] strs = None if is_invalid_arr(strs) else full_3x3_to_voigt_6_stress(strs) - calc = SinglePointDFTCalculator(atoms=atoms, energy=ener['E_KohnSham'], - free_energy=ener['E_KohnSham'], - forces=frs, stress=strs, - magmoms=mag, efermi=ener['E_Fermi'], - ibzkpts=kvecd, dipole=None) + calc = SinglePointDFTCalculator( + atoms=atoms, + energy=ener["E_KohnSham"], + free_energy=ener["E_KohnSham"], + forces=frs, + stress=strs, + magmoms=mag, + efermi=ener["E_Fermi"], + ibzkpts=kvecd, + dipole=None, + ) # import the eigenvalues and occupations kpoint-by-kpoint calc.kpts = [] - for ispn, (ekb, occ) in enumerate(zip(estat['e'], estat['occ'])): # loop over the spin - calc.kpts += [SinglePointKPoint(weight=wk[ik], - s=ispn, - k=kvecd[ik], - eps_n=ekb[ik,:], - f_n=occ[ik,:]) - for ik in range(len(kvecd))] + for ispn, (ekb, occ) in enumerate( + zip(estat["e"], estat["occ"]) + ): # loop over the spin + calc.kpts += [ + SinglePointKPoint( + weight=wk[ik], s=ispn, k=kvecd[ik], eps_n=ekb[ik, :], f_n=occ[ik, :] + ) + for ik in range(len(kvecd)) + ] # attach the calculator to the atoms atoms.calc = calc images.append(atoms) return images[index] + class TestLegacyIO(unittest.TestCase): here = Path(__file__).parent - testfiles = here / 'testfiles' + testfiles = here / "testfiles" def test_read_band_from_running_log(self): # nspin1 - fn = self.testfiles / 'lcao-symm1-nspin1-multik-scf_' + fn = self.testfiles / "lcao-symm1-nspin1-multik-scf_" data = read_band_from_running_log(fn) self.assertIsInstance(data, list) self.assertGreater(len(data), 0) - self.assertTrue(all('k' in d and 'e' in d and 'occ' in d for d in data)) - nspin, nk, nband = data[0]['e'].shape + self.assertTrue(all("k" in d and "e" in d and "occ" in d for d in data)) + nspin, nk, nband = data[0]["e"].shape self.assertEqual(nspin, 1) self.assertEqual(nband, 24) self.assertEqual(nk, 2) - for d in data: # for each frame - self.assertTrue(d['k'].shape == (nspin, nk, 3)) - self.assertTrue(d['e'].shape == (nspin, nk, nband)) - self.assertTrue(d['occ'].shape == (nspin, nk, nband)) + for d in data: # for each frame + self.assertTrue(d["k"].shape == (nspin, nk, 3)) + self.assertTrue(d["e"].shape == (nspin, nk, nband)) + self.assertTrue(d["occ"].shape == (nspin, nk, nband)) # nspin2 - fn = self.testfiles / 'lcao-symm0-nspin2-multik-relax_' + fn = self.testfiles / "lcao-symm0-nspin2-multik-relax_" data = read_band_from_running_log(fn) self.assertIsInstance(data, list) self.assertGreater(len(data), 0) - self.assertTrue(all('k' in d and 'e' in d and 'occ' in d for d in data)) - nspin, nk, nband = data[0]['e'].shape + self.assertTrue(all("k" in d and "e" in d and "occ" in d for d in data)) + nspin, nk, nband = data[0]["e"].shape self.assertEqual(nspin, 2) self.assertEqual(nband, 24) self.assertEqual(nk, 2) - for d in data: # for each frame - self.assertTrue(d['k'].shape == (nspin, nk, 3)) - self.assertTrue(d['e'].shape == (nspin, nk, nband)) - self.assertTrue(d['occ'].shape == (nspin, nk, nband)) - + for d in data: # for each frame + self.assertTrue(d["k"].shape == (nspin, nk, 3)) + self.assertTrue(d["e"].shape == (nspin, nk, nband)) + self.assertTrue(d["occ"].shape == (nspin, nk, nband)) + # nspin 2, cell-relax (multi-frames) - fn = self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax_' + fn = self.testfiles / "lcao-symm0-nspin2-multik-cellrelax_" data = read_band_from_running_log(fn) self.assertIsInstance(data, list) - self.assertEqual(len(data), 2) # two frames - self.assertTrue(all('k' in d and 'e' in d and 'occ' in d for d in data)) - nspin, nk, nband = data[0]['e'].shape + self.assertEqual(len(data), 2) # two frames + self.assertTrue(all("k" in d and "e" in d and "occ" in d for d in data)) + nspin, nk, nband = data[0]["e"].shape self.assertEqual(nspin, 2) self.assertEqual(nband, 40) self.assertEqual(nk, 2) - for d in data: # for each frame - self.assertTrue(d['k'].shape == (nspin, nk, 3)) - self.assertTrue(d['e'].shape == (nspin, nk, nband)) - self.assertTrue(d['occ'].shape == (nspin, nk, nband)) + for d in data: # for each frame + self.assertTrue(d["k"].shape == (nspin, nk, 3)) + self.assertTrue(d["e"].shape == (nspin, nk, nband)) + self.assertTrue(d["occ"].shape == (nspin, nk, nband)) # nspin 2, MD (multi-frames) - fn = self.testfiles / 'pw-symm0-nspin4-gamma-md_' + fn = self.testfiles / "pw-symm0-nspin4-gamma-md_" data = read_band_from_running_log(fn) self.assertIsInstance(data, list) self.assertEqual(len(data), 3) - self.assertTrue(all('k' in d and 'e' in d and 'occ' in d for d in data)) - nspin, nk, nband = data[0]['e'].shape + self.assertTrue(all("k" in d and "e" in d and "occ" in d for d in data)) + nspin, nk, nband = data[0]["e"].shape self.assertEqual(nspin, 1) self.assertEqual(nband, 35) self.assertEqual(nk, 1) - for d in data: # for each frame - self.assertTrue(d['k'].shape == (nspin, nk, 3)) - self.assertTrue(d['e'].shape == (nspin, nk, nband)) - self.assertTrue(d['occ'].shape == (nspin, nk, nband)) + for d in data: # for each frame + self.assertTrue(d["k"].shape == (nspin, nk, 3)) + self.assertTrue(d["e"].shape == (nspin, nk, nband)) + self.assertTrue(d["occ"].shape == (nspin, nk, nband)) def test_read_traj_from_running_log(self): - fn = self.testfiles / 'lcao-symm1-nspin1-multik-scf_' + fn = self.testfiles / "lcao-symm1-nspin1-multik-scf_" data = read_traj_from_running_log(fn) self.assertIsInstance(data, list) - self.assertEqual(len(data), 1) # it is scf run, only one frame - self.assertTrue(all('coordinate' in d and 'cell' in d and - 'elem' in d and 'coords' in d for d in data)) + self.assertEqual(len(data), 1) # it is scf run, only one frame + self.assertTrue( + all( + "coordinate" in d and "cell" in d and "elem" in d and "coords" in d + for d in data + ) + ) for d in data: - self.assertIn(d['coordinate'], ['Cartesian', 'Direct']) - self.assertEqual(d['cell'].shape, (3, 3)) - self.assertIsInstance(d['elem'], list) - self.assertEqual(len(d['elem']), 2) + self.assertIn(d["coordinate"], ["Cartesian", "Direct"]) + self.assertEqual(d["cell"].shape, (3, 3)) + self.assertIsInstance(d["elem"], list) + self.assertEqual(len(d["elem"]), 2) # relax - fn = self.testfiles / 'lcao-symm0-nspin2-multik-relax_' + fn = self.testfiles / "lcao-symm0-nspin2-multik-relax_" data = read_traj_from_running_log(fn) self.assertIsInstance(data, list) - self.assertEqual(len(data), 1) + self.assertEqual(len(data), 1) # relax task will only print the coordinate at the first run # but band structure will be printed for multiple times... - self.assertTrue(all('coordinate' in d and 'cell' in d and - 'elem' in d and 'coords' in d for d in data)) + self.assertTrue( + all( + "coordinate" in d and "cell" in d and "elem" in d and "coords" in d + for d in data + ) + ) for d in data: - self.assertIn(d['coordinate'], ['Cartesian', 'Direct']) - self.assertEqual(d['cell'].shape, (3, 3)) - self.assertIsInstance(d['elem'], list) - self.assertEqual(len(d['elem']), 2) - self.assertEqual(d['coords'].shape, (2, 3)) + self.assertIn(d["coordinate"], ["Cartesian", "Direct"]) + self.assertEqual(d["cell"].shape, (3, 3)) + self.assertIsInstance(d["elem"], list) + self.assertEqual(len(d["elem"]), 2) + self.assertEqual(d["coords"].shape, (2, 3)) # cell-relax - fn = self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax_' + fn = self.testfiles / "lcao-symm0-nspin2-multik-cellrelax_" data = read_traj_from_running_log(fn) self.assertIsInstance(data, list) - self.assertEqual(len(data), 3) # print each time - self.assertTrue(all('coordinate' in d and 'cell' in d and - 'elem' in d and 'coords' in d for d in data)) + self.assertEqual(len(data), 3) # print each time + self.assertTrue( + all( + "coordinate" in d and "cell" in d and "elem" in d and "coords" in d + for d in data + ) + ) for d in data: - self.assertIn(d['coordinate'], ['Cartesian', 'Direct']) - self.assertEqual(d['cell'].shape, (3, 3)) - self.assertIsInstance(d['elem'], list) - self.assertEqual(len(d['elem']), 4) - self.assertEqual(d['coords'].shape, (4, 3)) + self.assertIn(d["coordinate"], ["Cartesian", "Direct"]) + self.assertEqual(d["cell"].shape, (3, 3)) + self.assertIsInstance(d["elem"], list) + self.assertEqual(len(d["elem"]), 4) + self.assertEqual(d["coords"].shape, (4, 3)) def test_read_traj_from_md_dump(self): - fn = self.testfiles / 'nspin4-gamma-mddump' + fn = self.testfiles / "nspin4-gamma-mddump" data = read_traj_from_md_dump(fn) self.assertIsInstance(data, list) self.assertEqual(len(data), 2) - self.assertTrue(all('coordinate' in d and 'cell' in d and - 'alat_in_angstrom' in d and 'elem' in d and - 'coords' in d for d in data)) + self.assertTrue( + all( + "coordinate" in d + and "cell" in d + and "alat_in_angstrom" in d + and "elem" in d + and "coords" in d + for d in data + ) + ) for d in data: - self.assertEqual(d['coordinate'], 'Cartesian') - self.assertEqual(d['cell'].shape, (3, 3)) - self.assertEqual(d['alat_in_angstrom'], 0.529177000000) - self.assertIsInstance(d['elem'], list) - self.assertEqual(len(d['elem']), 2) - self.assertEqual(d['coords'].shape, (2, 3)) + self.assertEqual(d["coordinate"], "Cartesian") + self.assertEqual(d["cell"].shape, (3, 3)) + self.assertEqual(d["alat_in_angstrom"], 0.529177000000) + self.assertIsInstance(d["elem"], list) + self.assertEqual(len(d["elem"]), 2) + self.assertEqual(d["coords"].shape, (2, 3)) def test_read_forces_from_running_log(self): - fn = self.testfiles / 'pw-symm0-nspin4-gamma-md_' + fn = self.testfiles / "pw-symm0-nspin4-gamma-md_" forces = read_forces_from_running_log(fn) - self.assertEqual(len(forces), 3) # 3 frames - self.assertTrue(all(f.shape == (2, 3) for f in forces)) # 2 atoms, 3 components + self.assertEqual(len(forces), 3) # 3 frames + self.assertTrue(all(f.shape == (2, 3) for f in forces)) # 2 atoms, 3 components def test_read_stress_from_running_log(self): - fn = self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax_' + fn = self.testfiles / "lcao-symm0-nspin2-multik-cellrelax_" stress = read_stress_from_running_log(fn) self.assertEqual(len(stress), 2) - self.assertTrue(all(s.shape == (3, 3) for s in stress)) # 3x3 matrix - - reference = np.array([ - [ 28.0257165780, -25.0814687477, -25.0814687478], - [-25.0814687477, -57.2309475134, 52.8147857580], - [-25.0814687478, 52.8147857580, -57.2309475133], - [ 7.3061116295, -27.6053387696, -27.6053387674], - [-27.6053387696, 0.8540980637, 7.6367729837], - [-27.6053387674, 7.6367729837, 0.8540980603], - ]).reshape(-1, 3, 3) + self.assertTrue(all(s.shape == (3, 3) for s in stress)) # 3x3 matrix + + reference = np.array( + [ + [28.0257165780, -25.0814687477, -25.0814687478], + [-25.0814687477, -57.2309475134, 52.8147857580], + [-25.0814687478, 52.8147857580, -57.2309475133], + [7.3061116295, -27.6053387696, -27.6053387674], + [-27.6053387696, 0.8540980637, 7.6367729837], + [-27.6053387674, 7.6367729837, 0.8540980603], + ] + ).reshape(-1, 3, 3) for s, sref in zip(stress, reference): self.assertTrue(np.allclose(s, -0.1 * GPa * sref)) def test_read_energies_from_running_log(self): - fn = self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax_' + fn = self.testfiles / "lcao-symm0-nspin2-multik-cellrelax_" energies_ry, energies_ev = read_energies_from_running_log(fn) self.assertIsInstance(energies_ry, list) self.assertIsInstance(energies_ev, list) self.assertEqual(len(energies_ry), 3) self.assertEqual(len(energies_ev), 3) - self.assertTrue(all(isinstance(e, dict) for e in energies_ry)) # dict of energies + self.assertTrue( + all(isinstance(e, dict) for e in energies_ry) + ) # dict of energies self.assertTrue(all(isinstance(e, dict) for e in energies_ev)) for e_ev, e_ry in zip(energies_ev, energies_ry): # take energies of one SCF step, there are still many energy terms @@ -1080,13 +1196,13 @@ def test_read_energies_from_running_log(self): self.assertAlmostEqual(ei_ev, e_ry[k] * Ry / eV, delta=1e-2) def test_read_kpoints_from_running_log(self): - fn = self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax_' + fn = self.testfiles / "lcao-symm0-nspin2-multik-cellrelax_" kpoints = read_kpoints_from_running_log(fn) self.assertIsInstance(kpoints, tuple) self.assertEqual(len(kpoints), 5) # thus we unpack kibz, kdspnls, kd1traj, kctraj, kd2traj = kpoints - + # kibz self.assertIsInstance(kibz, tuple) self.assertEqual(len(kibz), 3) @@ -1113,7 +1229,7 @@ def test_read_kpoints_from_running_log(self): # kd1traj self.assertIsInstance(kd1traj, list) - self.assertEqual(len(kd1traj), 2) # 2 cell-relax steps + self.assertEqual(len(kd1traj), 2) # 2 cell-relax steps for i, kd1 in enumerate(kd1traj): # because the i=0 corresponds to the spinless case, # it has 29 instead of 58 kpoints like the others @@ -1133,7 +1249,7 @@ def test_read_kpoints_from_running_log(self): # kctraj and kd2traj for ktraj in [kctraj, kd2traj]: self.assertIsInstance(ktraj, list) - self.assertEqual(len(ktraj), 2) # 2 cell-relax steps + self.assertEqual(len(ktraj), 2) # 2 cell-relax steps for i, k in enumerate(ktraj): self.assertIsInstance(k, tuple) self.assertEqual(len(k), 2) @@ -1146,45 +1262,47 @@ def test_read_kpoints_from_running_log(self): self.assertAlmostEqual(wk.sum(), 2.0, delta=1e-3) def test_read_magmom_from_running_log(self): - fn = self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax_' + fn = self.testfiles / "lcao-symm0-nspin2-multik-cellrelax_" magmoms = read_magmom_from_running_log(fn) self.assertIsInstance(magmoms, list) - self.assertEqual(len(magmoms), 2) # 2 cell-relax steps + self.assertEqual(len(magmoms), 2) # 2 cell-relax steps for i, magmom in enumerate(magmoms): self.assertIsInstance(magmom, np.ndarray) self.assertEqual(magmom.shape, (4,)) - self.assertAlmostEqual(magmom.sum(), 0.0, delta=1e-3) # AFM + self.assertAlmostEqual(magmom.sum(), 0.0, delta=1e-3) # AFM # non-colinear case - fn = self.testfiles / 'pw-symm0-nspin4-gamma-md_' + fn = self.testfiles / "pw-symm0-nspin4-gamma-md_" magmoms = read_magmom_from_running_log(fn) self.assertIsInstance(magmoms, list) self.assertEqual(len(magmoms), 2) for magmom in magmoms: self.assertTrue( - np.allclose(magmom, - np.array([[0. , 0. , 3.62032142], - [0. , 0. , 3.62032142]]))) + np.allclose( + magmom, np.array([[0.0, 0.0, 3.62032142], [0.0, 0.0, 3.62032142]]) + ) + ) def test_read_iter_header_from_running_log(self): - fn = self.testfiles / 'lcao-symm0-nspin2-multik-cellrelax_' + fn = self.testfiles / "lcao-symm0-nspin2-multik-cellrelax_" header = read_iter_header_from_running_log(fn) - self.assertEqual(header[0], (1,1)) - self.assertEqual(header[1], (1,2)) - self.assertEqual(header[2], (2,1)) - fn = self.testfiles / 'pw-symm0-nspin4-gamma-md_' + self.assertEqual(header[0], (1, 1)) + self.assertEqual(header[1], (1, 2)) + self.assertEqual(header[2], (2, 1)) + fn = self.testfiles / "pw-symm0-nspin4-gamma-md_" header = read_iter_header_from_running_log(fn) - self.assertEqual(header[0], (1,1)) - self.assertEqual(header[1], (1,2)) - self.assertEqual(header[2], (1,3)) - self.assertEqual(header[3], (3,2)) - self.assertEqual(header[4], (3,3)) + self.assertEqual(header[0], (1, 1)) + self.assertEqual(header[1], (1, 2)) + self.assertEqual(header[2], (1, 3)) + self.assertEqual(header[3], (3, 2)) + self.assertEqual(header[4], (3, 3)) def test_find_final_info_with_iter_header(self): info = [1, 2, 3, 4, 5, 6] - header = [[1,1], [1,2], [2,1], [3,1], [3,2], [3,3]] + header = [[1, 1], [1, 2], [2, 1], [3, 1], [3, 2], [3, 3]] final_info = find_final_info_with_iter_header(info, header) self.assertListEqual(final_info, [info[1], info[2], info[5]]) -if __name__ == '__main__': + +if __name__ == "__main__": unittest.main() diff --git a/interfaces/ASE_interface/abacuslite/io/testfiles/input-script b/interfaces/ASE_interface/abacuslite/io/testfiles/input-script index 1ecbd7e13a3..7f79189676a 100644 --- a/interfaces/ASE_interface/abacuslite/io/testfiles/input-script +++ b/interfaces/ASE_interface/abacuslite/io/testfiles/input-script @@ -1,32 +1,32 @@ INPUT_PARAMETERS #Parameters (1.General) -suffix autotest +suffix autotest calculation scf device gpu gamma_only 1 # GPU acceleration currently only support gamma_only set to 1. ### Abacus will generate/overwrite a KPT file when gamma_only is set to 1. -ks_solver cusolver # if not set, the default ks_solver is cusolver, +ks_solver cusolver # if not set, the default ks_solver is cusolver, # you can also choose genelpa or scalapack_gvx. -#nbands 8 -symmetry 1 +#nbands 8 +symmetry 1 #Parameters (2.Iteration) -ecutwfc 100 ###Energy cutoff needs to be tested to ensure your calculation is reliable.[1] -scf_thr 1e-6 -scf_nmax 100 +ecutwfc 100 ###Energy cutoff needs to be tested to ensure your calculation is reliable.[1] +scf_thr 1e-6 +scf_nmax 100 cal_force 1 cal_stress 1 #Parameters (3.Basis) -basis_type lcao +basis_type lcao #Parameters (4.Smearing) -smearing_method gauss -smearing_sigma 0.002 +smearing_method gauss +smearing_sigma 0.002 #Parameters (5.Mixing) -mixing_type broyden -mixing_beta 0.3 +mixing_type broyden +mixing_beta 0.3 ### [1] Energy cutoff determines the quality of numerical quadratures in your calculations. diff --git a/interfaces/ASE_interface/abacuslite/io/testfiles/pw-symm0-nspin4-gamma-md_ b/interfaces/ASE_interface/abacuslite/io/testfiles/pw-symm0-nspin4-gamma-md_ index 45143f8269c..9ce4e82d7d6 100644 --- a/interfaces/ASE_interface/abacuslite/io/testfiles/pw-symm0-nspin4-gamma-md_ +++ b/interfaces/ASE_interface/abacuslite/io/testfiles/pw-symm0-nspin4-gamma-md_ @@ -56,7 +56,7 @@ K-POINTS DIRECT COORDINATES PW ALGORITHM --------------- ION= 1 ELEC= 1-------------------------------- -total magnetism (Bohr mag/cell) 0 0 1.43092 +total magnetism (Bohr mag/cell) 0 0 1.43092 absolute magnetism (Bohr mag/cell) = 1.46002 Density error is 0.425536171685 @@ -71,7 +71,7 @@ total magnetism (Bohr mag/cell) 0 0 1.43092 PW ALGORITHM --------------- ION= 1 ELEC= 2-------------------------------- -total magnetism (Bohr mag/cell) 0 0 1.29536921409 +total magnetism (Bohr mag/cell) 0 0 1.29536921409 absolute magnetism (Bohr mag/cell) = 1.47327692817 Density error is 0.147809332734 @@ -86,7 +86,7 @@ total magnetism (Bohr mag/cell) 0 0 1.29536921409 PW ALGORITHM --------------- ION= 1 ELEC= 3-------------------------------- -total magnetism (Bohr mag/cell) 0 0 1.90445147148 +total magnetism (Bohr mag/cell) 0 0 1.90445147148 absolute magnetism (Bohr mag/cell) = 1.92389538407 Density error is 0.044016528552 @@ -192,7 +192,7 @@ total magnetism (Bohr mag/cell) 0 0 1.90445147148 hsover_error=0.180000 > DRHO=0.0154165 Origin diag ethr = 0.0100000 New diag ethr = 8.56474e-05 -total magnetism (Bohr mag/cell) 0.00000 0.00000 1.92056 +total magnetism (Bohr mag/cell) 0.00000 0.00000 1.92056 absolute magnetism (Bohr mag/cell) = 1.92336 Density error is 0.0450726236251 @@ -282,7 +282,7 @@ total magnetism (Bohr mag/cell) 0.00000 0.00000 1.92056 PW ALGORITHM --------------- ION=3 ELEC=1 -------------------------------- -total magnetism (Bohr mag/cell) 0.00000 0.00000 1.95640 +total magnetism (Bohr mag/cell) 0.00000 0.00000 1.95640 absolute magnetism (Bohr mag/cell) = 1.95962 Density error is 0.477550291489 @@ -297,7 +297,7 @@ total magnetism (Bohr mag/cell) 0.00000 0.00000 1.95640 PW ALGORITHM --------------- ION= 3 ELEC= 2-------------------------------- -total magnetism (Bohr mag/cell) 0.00000000000 0.00000000000 1.98933318075 +total magnetism (Bohr mag/cell) 0.00000000000 0.00000000000 1.98933318075 absolute magnetism (Bohr mag/cell) = 2.03111991516 Density error is 0.175985640789 @@ -312,7 +312,7 @@ total magnetism (Bohr mag/cell) 0.00000000000 0.00000000000 1.98933318075 PW ALGORITHM --------------- ION= 3 ELEC= 3-------------------------------- -total magnetism (Bohr mag/cell) 0.00000000000 0.00000000000 1.97493083463 +total magnetism (Bohr mag/cell) 0.00000000000 0.00000000000 1.97493083463 absolute magnetism (Bohr mag/cell) = 2.02445029910 Density error is 0.0131512819145 diff --git a/interfaces/ASE_interface/abacuslite/utils/ksampling.py b/interfaces/ASE_interface/abacuslite/utils/ksampling.py index 328973e9558..c9bbc92eb6f 100644 --- a/interfaces/ASE_interface/abacuslite/utils/ksampling.py +++ b/interfaces/ASE_interface/abacuslite/utils/ksampling.py @@ -1,4 +1,5 @@ -'''this module provides some useful tools for k-sampling''' +"""this module provides some useful tools for k-sampling""" + import seekpath import unittest from typing import Optional, Tuple, List, Dict @@ -6,10 +7,11 @@ import numpy as np from ase.atoms import Atoms -def convert_kspacing_to_kpts(cell: np.ndarray, - kspacing: float | Tuple[float, float, float])\ - -> Tuple[int, int, int]: - ''' + +def convert_kspacing_to_kpts( + cell: np.ndarray, kspacing: float | Tuple[float, float, float] +) -> Tuple[int, int, int]: + """ convert the kspacing to kpts, according to the given cell in Angstrom. This function would be helpful for those calculators that only support kpts, but not kspacing. A negative value in kspacing would yield nk=1 @@ -22,62 +24,81 @@ def convert_kspacing_to_kpts(cell: np.ndarray, kspacing : float or tuple of float The kspacing in Angstrom. If a tuple of float is given, it would be interpreted as the kspacing in each direction. - + Returns ------- tuple of int The kpts in each direction. - ''' + """ # get reciprocal cell vectors... - bvec = 2*np.pi * np.linalg.solve(cell.T, np.eye(3)) + bvec = 2 * np.pi * np.linalg.solve(cell.T, np.eye(3)) bnorm = np.linalg.norm(bvec, axis=1).tolist() - kspacing = (kspacing, kspacing, kspacing) if isinstance(kspacing, float) else kspacing + kspacing = ( + (kspacing, kspacing, kspacing) if isinstance(kspacing, float) else kspacing + ) assert len(kspacing) == 3 nk = [int(norm / kspac) if kspac > 0 else 1 for kspac, norm in zip(kspacing, bnorm)] - return tuple(map(lambda x: max(1, x+1), nk)) + return tuple(map(lambda x: max(1, x + 1), nk)) -def get_kpath(atoms: Atoms, n_interpl: int = 10) -> Tuple[np.ndarray, np.ndarray, List[str]]: - '''''' + +def get_kpath( + atoms: Atoms, n_interpl: int = 10 +) -> Tuple[np.ndarray, np.ndarray, List[str]]: + """""" from seekpath import get_path as _corefunc_seekpath + seeked = _corefunc_seekpath( - structure=(atoms.get_cell().tolist(), - atoms.get_scaled_positions(), - atoms.get_atomic_numbers())) - + structure=( + atoms.get_cell().tolist(), + atoms.get_scaled_positions(), + atoms.get_atomic_numbers(), + ) + ) + # get the most useful informaiton - k = np.array(list(seeked['point_coords'].values())) + k = np.array(list(seeked["point_coords"].values())) assert k.ndim == 2 nk, dim = k.shape assert dim == 3 # interpolate... - kvec = np.vstack([np.linspace(k[i, :], k[i + 1, :], - num=n_interpl+int(i == nk - 2), - endpoint=bool(i == nk - 2)) - for i in range(nk - 1)]) - + kvec = np.vstack( + [ + np.linspace( + k[i, :], + k[i + 1, :], + num=n_interpl + int(i == nk - 2), + endpoint=bool(i == nk - 2), + ) + for i in range(nk - 1) + ] + ) + # for easy-drawing kdist = np.linalg.norm(kvec[1:] - kvec[:-1], axis=1) kdist = np.cumsum(kdist) kdist = np.hstack([[0], kdist]) - kname = list(seeked['point_coords'].keys()) - kname = [[kn] + [''] * (n_interpl-1) for kn in kname[:-1]] + [[kname[-1]]] + kname = list(seeked["point_coords"].keys()) + kname = [[kn] + [""] * (n_interpl - 1) for kn in kname[:-1]] + [[kname[-1]]] kname = [n for kn in kname for n in kn] # finally, we assert the consistency of the data - assert len(kvec) == len(kdist) == len(kname), f'{len(kvec)}, {len(kdist)}, {len(kname)}' + assert ( + len(kvec) == len(kdist) == len(kname) + ), f"{len(kvec)}, {len(kdist)}, {len(kname)}" return kvec, kdist, kname -def interpolate_kpath(knodes: np.ndarray, - knames: List[str], - n_interpl: int | List[int] = 10) -> Tuple[np.ndarray, np.ndarray, List[str]]: - ''' + +def interpolate_kpath( + knodes: np.ndarray, knames: List[str], n_interpl: int | List[int] = 10 +) -> Tuple[np.ndarray, np.ndarray, List[str]]: + """ interpolate between the given k-points (nodes, as they are nodes along the path). The number of interpolated points is given by `n_interpl`, in which the last number will be ignored. - ''' + """ if isinstance(n_interpl, int): n_interpl = [n_interpl] * (len(knodes) - 1) + [1] assert isinstance(knodes, np.ndarray) @@ -87,31 +108,43 @@ def interpolate_kpath(knodes: np.ndarray, assert dim == 3 assert len(n_interpl) == len(knames) == nk - kvec = np.vstack([np.linspace(knodes[i, :], knodes[i + 1, :], - num=n_interpl[i]+int(i == nk - 2), - endpoint=bool(i == nk - 2)) - for i in range(nk - 1)]) - + kvec = np.vstack( + [ + np.linspace( + knodes[i, :], + knodes[i + 1, :], + num=n_interpl[i] + int(i == nk - 2), + endpoint=bool(i == nk - 2), + ) + for i in range(nk - 1) + ] + ) + # for easy-drawing kdist = np.linalg.norm(kvec[1:] - kvec[:-1], axis=1) kdist = np.cumsum(kdist) kdist = np.hstack([[0], kdist]) # padding the knames to have the same length as kvec - kname = [[kn] + [''] * (n_interpl[i]-1) for i, kn in enumerate(knames[:-1])] + [[knames[-1]]] + kname = [[kn] + [""] * (n_interpl[i] - 1) for i, kn in enumerate(knames[:-1])] + [ + [knames[-1]] + ] kname = [n for kn in kname for n in kn] # finally, we assert the consistency of the data - assert len(kvec) == len(kdist) == len(kname), f'{len(kvec)}, {len(kdist)}, {len(kname)}' + assert ( + len(kvec) == len(kdist) == len(kname) + ), f"{len(kvec)}, {len(kdist)}, {len(kname)}" return kvec, kdist, kname + def merge_ksgm(segments) -> Tuple[List[str], List[bool]]: - ''' + """ SeeKpath generates the path of kpoints in the format of list of 2-element tuples. This is good but not quite compatible with some DFT softwares like ABACUS. This function will return a list of special kpoint labels accompanied with a boolean list that helps distinguish the breakpoint of path. - + Parameters ---------- segments : List[Tuple[str, str]] @@ -125,22 +158,22 @@ def merge_ksgm(segments) -> Tuple[List[str], List[bool]]: Tuple[List[str], List[bool]] The first element is the list of special kpoint labels. The second element is the boolean list that helps distinguish the breakpoint of path. - ''' + """ klabels, is_brkpt = [segments[0][0]], [False] for i, (start, end) in enumerate(segments): if start != klabels[-1]: is_brkpt[-1] = True klabels.append(start) is_brkpt.append(False) - + klabels.append(end) is_brkpt.append(i == len(segments) - 1) - + return klabels, is_brkpt -def make_kstring(klabels: List[str], - is_brkpt: List[bool]) -> str: - ''' + +def make_kstring(klabels: List[str], is_brkpt: List[bool]) -> str: + """ Make the kpoint path in the str. For path in which there are break point, will use the comma to distinguish @@ -155,19 +188,19 @@ def make_kstring(klabels: List[str], ------- str The kstring that ABACUS uses to represent the kpath. - ''' - out = '' + """ + out = "" for lbl, brkpt in zip(klabels, is_brkpt): out += lbl if brkpt: - out += ',' - return out[:-1] # remove the last comma - -def make_klines(kpts, - is_brkpt, - n_interpl, - klabels) -> List[Dict[str, np.ndarray | str | int]]: - ''' + out += "," + return out[:-1] # remove the last comma + + +def make_klines( + kpts, is_brkpt, n_interpl, klabels +) -> List[Dict[str, np.ndarray | str | int]]: + """ gather the information and output the list of dicts that organizes the information easy for exporting the ABAUCS KLINES file. Each dictionary contains the keys `coord`, `label`, `n`, where `coord` is the coordinate @@ -191,70 +224,93 @@ def make_klines(kpts, List[Dict[str, np.ndarray | str | int]] The list of dictionaries that organizes the information easy for exporting the ABAUCS KLINES file. - ''' + """ + def fspawnk(c: np.ndarray, n: int, label: str) -> Dict[str, np.ndarray | str | int]: - return {'coord': c, 'label': label, 'n': n} - - return [fspawnk(c, 1 if is_brkpt[i] else n_interpl, klbl) - for i, (c, klbl) in enumerate(zip(kpts, klabels))] + return {"coord": c, "label": label, "n": n} + + return [ + fspawnk(c, 1 if is_brkpt[i] else n_interpl, klbl) + for i, (c, klbl) in enumerate(zip(kpts, klabels)) + ] + def kpathgen(atoms: Atoms) -> Tuple[str, Dict[str, List[float]]]: - ''' + """ Generate the k-path by default SeeK-Path flavor in the format compatible with ase bandpath module - ''' + """ kpathseen = seekpath.get_path( - structure=(np.array(atoms.get_cell()), - atoms.get_scaled_positions(), - atoms.get_atomic_numbers()), - with_time_reversal=True + structure=( + np.array(atoms.get_cell()), + atoms.get_scaled_positions(), + atoms.get_atomic_numbers(), + ), + with_time_reversal=True, ) # convert the kpoint path to the format that is acceptable by ASE - kpathstr, is_brkpt = merge_ksgm(kpathseen['path']) - fklblfilter = lambda lbl: lbl if lbl != 'GAMMA' else 'G' + kpathstr, is_brkpt = merge_ksgm(kpathseen["path"]) + fklblfilter = lambda lbl: lbl if lbl != "GAMMA" else "G" kpathstr = make_kstring([fklblfilter(lbl) for lbl in kpathstr], is_brkpt) - kpathstr = ''.join([k if k != 'GAMMA' else 'G' for k in kpathstr]) + kpathstr = "".join([k if k != "GAMMA" else "G" for k in kpathstr]) # seekpath use 'GAMMA' as the gamma point symbol, while the ASE use 'G' - kspecial = {k: v for k, v in kpathseen['point_coords'].items() if k != 'GAMMA'} - kspecial['G'] = [0.0, 0.0, 0.0] + kspecial = {k: v for k, v in kpathseen["point_coords"].items() if k != "GAMMA"} + kspecial["G"] = [0.0, 0.0, 0.0] return kpathstr, kspecial + # the following are for quick test on the silicon case -SILICON_KNODES = np.array([[0.0000000000, 0.0000000000, 0.0000000000], - [0.5000000000, 0.0000000000, 0.5000000000], - [0.6250000000, 0.2500000000, 0.6250000000], - [0.3750000000, 0.3750000000, 0.7500000000], - [0.0000000000, 0.0000000000, 0.0000000000], - [0.5000000000, 0.5000000000, 0.5000000000], - [0.5000000000, 0.2500000000, 0.7500000000], - [0.5000000000, 0.0000000000, 0.5000000000]]) +SILICON_KNODES = np.array( + [ + [0.0000000000, 0.0000000000, 0.0000000000], + [0.5000000000, 0.0000000000, 0.5000000000], + [0.6250000000, 0.2500000000, 0.6250000000], + [0.3750000000, 0.3750000000, 0.7500000000], + [0.0000000000, 0.0000000000, 0.0000000000], + [0.5000000000, 0.5000000000, 0.5000000000], + [0.5000000000, 0.2500000000, 0.7500000000], + [0.5000000000, 0.0000000000, 0.5000000000], + ] +) SILICON_KNAMES = ["G", "X", "X/U", "K", "G", "L", "W", "X"] -SILICON_NINTPL = [50, 50, 1, 50, 50, 50, 50, 1] # from the DeePTB example :) +SILICON_NINTPL = [50, 50, 1, 50, 50, 50, 50, 1] # from the DeePTB example :) + class TestKsampling(unittest.TestCase): - + def test_convert_kspacing(self): # test-reference: ABACUS 3.8.4 implementation from ase.geometry import cellpar_to_cell cell = cellpar_to_cell([4.22798145, 4.22798145, 4.22798145, 60, 60, 60]) - kpts = convert_kspacing_to_kpts(cell, 0.03*1.889725989) + kpts = convert_kspacing_to_kpts(cell, 0.03 * 1.889725989) # kspacing 0.03 Bohr-1, multiply 1.889725989 to convert to Angstrom-1 self.assertEqual(kpts, (33, 33, 33)) def test_merge_ksgm(self): - klables, is_brkpt = merge_ksgm([('GAMMA', 'X'), ('X', 'U'), ('K', 'GAMMA'), - ('GAMMA', 'L'), ('L', 'W'), ('W', 'X')]) - self.assertEqual(klables, ['GAMMA', 'X', 'U', 'K','GAMMA', 'L', 'W', 'X']) - self.assertEqual(is_brkpt, [False, False, True, False, False, False, False, True]) + klables, is_brkpt = merge_ksgm( + [ + ("GAMMA", "X"), + ("X", "U"), + ("K", "GAMMA"), + ("GAMMA", "L"), + ("L", "W"), + ("W", "X"), + ] + ) + self.assertEqual(klables, ["GAMMA", "X", "U", "K", "GAMMA", "L", "W", "X"]) + self.assertEqual( + is_brkpt, [False, False, True, False, False, False, False, True] + ) def test_make_kstring(self): - fklblfilter = lambda lbl: lbl if lbl != 'GAMMA' else 'G' - klabels = ['GAMMA', 'X', 'U', 'K','GAMMA', 'L', 'W', 'X'] + fklblfilter = lambda lbl: lbl if lbl != "GAMMA" else "G" + klabels = ["GAMMA", "X", "U", "K", "GAMMA", "L", "W", "X"] klabels = [fklblfilter(lbl) for lbl in klabels] - is_brkpt = [False, False, True, False, False, False, False, True] - self.assertEqual(make_kstring(klabels, is_brkpt), 'GXU,KGLWX') + is_brkpt = [False, False, True, False, False, False, False, True] + self.assertEqual(make_kstring(klabels, is_brkpt), "GXU,KGLWX") + -if __name__ == '__main__': - unittest.main() \ No newline at end of file +if __name__ == "__main__": + unittest.main() diff --git a/interfaces/ASE_interface/examples/bandstructure.py b/interfaces/ASE_interface/examples/bandstructure.py index 626638e21e9..5315b40a6ed 100644 --- a/interfaces/ASE_interface/examples/bandstructure.py +++ b/interfaces/ASE_interface/examples/bandstructure.py @@ -1,5 +1,5 @@ -''' -This example shows how to run a SCF calculation with ABACUS +""" +This example shows how to run a SCF calculation with ABACUS of Si diamond structure. To run this example, please install the SeeK-path package: @@ -8,13 +8,15 @@ ``` . The SeeK-path package recommands you cite by the way posted here: https://seekpath.materialscloud.io/ -''' +""" + import shutil -from pathlib import Path # a more Pythonic alternative to the os.path +from pathlib import Path # a more Pythonic alternative to the os.path + here = Path(__file__).parent # to the directory where the pseudopotential and orbital files are stored # In your case you change to the appropriate one -pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' +pporb = here.parent.parent.parent / "tests" / "PP_ORB" from ase.build import bulk from abacuslite import Abacus, AbacusProfile @@ -23,60 +25,58 @@ # AbacusProfile: the interface connecting the Abacus calculator instance # with the file system and the enviroment aprof = AbacusProfile( - command='mpirun -np 4 abacus', + command="mpirun -np 4 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, ) # Abacus: the calculator instance -jobdir = here / 'bandstructure' +jobdir = here / "bandstructure" abacus = Abacus( profile=aprof, directory=str(jobdir), - pseudopotentials={'Si': 'Si_ONCV_PBE-1.0.upf'}, - basissets={'Si': 'Si_gga_8au_100Ry_2s2p1d.orb'}, + pseudopotentials={"Si": "Si_ONCV_PBE-1.0.upf"}, + basissets={"Si": "Si_gga_8au_100Ry_2s2p1d.orb"}, inp={ - 'calculation': 'scf', - 'nspin': 1, - 'basis_type': 'lcao', - 'ks_solver': 'genelpa', - 'ecutwfc': 100, - 'symmetry': 1, - 'kspacing': 0.1 - } + "calculation": "scf", + "nspin": 1, + "basis_type": "lcao", + "ks_solver": "genelpa", + "ecutwfc": 100, + "symmetry": 1, + "kspacing": 0.1, + }, ) -# get the structure, can also from the +# get the structure, can also from the # ``` # from ase.io import read # atoms = read(...) # ``` -atoms = bulk('Si', 'diamond', a=5.43) +atoms = bulk("Si", "diamond", a=5.43) # bind the atoms with the abacus atoms.calc = abacus # perform the SCF calculation to get the converged wavefunction -print('SCF calculation get energy:', atoms.get_potential_energy()) +print("SCF calculation get energy:", atoms.get_potential_energy()) kpathstr, kspecial = kpathgen(atoms) # instantiate the bandpath -bandpath = atoms.cell.bandpath(path=kpathstr, - npoints=50, - special_points=kspecial) +bandpath = atoms.cell.bandpath(path=kpathstr, npoints=50, special_points=kspecial) # derive the band structure calculator from SCF calculator bscalc = atoms.calc.fixed_density(bandpath) atoms.calc = bscalc -_ = atoms.get_potential_energy() # NSCF calculation will be performed +_ = atoms.get_potential_energy() # NSCF calculation will be performed bs = bscalc.band_structure() -bs.write('bandstructure.json') +bs.write("bandstructure.json") # you can use the ase-cli to plot the JSON file later by: # ``` # ase band-structure bandstructure.json -r -10 15 # ``` -bs.plot(emin=-10, emax=15, filename='bandstructure.png') +bs.plot(emin=-10, emax=15, filename="bandstructure.png") -shutil.rmtree(jobdir) \ No newline at end of file +shutil.rmtree(jobdir) diff --git a/interfaces/ASE_interface/examples/cellrelax.py b/interfaces/ASE_interface/examples/cellrelax.py index a6b5cc06c5f..2c65756faac 100644 --- a/interfaces/ASE_interface/examples/cellrelax.py +++ b/interfaces/ASE_interface/examples/cellrelax.py @@ -1,13 +1,15 @@ -''' -This example shows how to perform a cell-ion joint relaxation with ABACUS +""" +This example shows how to perform a cell-ion joint relaxation with ABACUS of Si diamond structure. -''' +""" + import shutil -from pathlib import Path # a more Pythonic alternative to the os.path +from pathlib import Path # a more Pythonic alternative to the os.path + here = Path(__file__).parent # to the directory where the pseudopotential and orbital files are stored # In your case you change to the appropriate one -pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' +pporb = here.parent.parent.parent / "tests" / "PP_ORB" from ase.build import bulk from ase.filters import FrechetCellFilter @@ -17,51 +19,51 @@ # AbacusProfile: the interface connecting the Abacus calculator instance # with the file system and the enviroment aprof = AbacusProfile( - command='mpirun -np 4 abacus', + command="mpirun -np 4 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, ) # Abacus: the calculator instance -jobdir = here / 'scf' +jobdir = here / "scf" abacus = Abacus( profile=aprof, directory=str(jobdir), - pseudopotentials={'Si': 'Si_ONCV_PBE-1.0.upf'}, - basissets={'Si': 'Si_gga_8au_100Ry_2s2p1d.orb'}, + pseudopotentials={"Si": "Si_ONCV_PBE-1.0.upf"}, + basissets={"Si": "Si_gga_8au_100Ry_2s2p1d.orb"}, inp={ - 'calculation': 'scf', - 'nspin': 1, - 'basis_type': 'lcao', - 'ks_solver': 'genelpa', - 'ecutwfc': 100, - 'symmetry': 1, - 'kspacing': 0.1, - 'cal_force': 1, # let ABACUS calculate the forces - 'cal_stress': 1 # let ABACUS calculate the stress - } + "calculation": "scf", + "nspin": 1, + "basis_type": "lcao", + "ks_solver": "genelpa", + "ecutwfc": 100, + "symmetry": 1, + "kspacing": 0.1, + "cal_force": 1, # let ABACUS calculate the forces + "cal_stress": 1, # let ABACUS calculate the stress + }, ) -# get the structure, can also from the +# get the structure, can also from the # ``` # from ase.io import read # atoms = read(...) # ``` -atoms = bulk('Si', 'diamond', a=5.43) +atoms = bulk("Si", "diamond", a=5.43) # bind the atoms with the abacus atoms.calc = abacus # print the energy before relaxation -print(f'Before: {atoms.get_potential_energy()}') -print(f'Cell: {atoms.get_cell()}') +print(f"Before: {atoms.get_potential_energy()}") +print(f"Cell: {atoms.get_cell()}") # perform the relaxation calculation -dyn = BFGS(FrechetCellFilter(atoms), logfile='-') +dyn = BFGS(FrechetCellFilter(atoms), logfile="-") # or a fixed alpha, beta, gamma relaxation, if you needed # dyn = BFGS(FrechetCellFilter( -# atoms, +# atoms, # mask=[True, True, True, False, False, False] # ), logfile='-') # the first three mask elements are for the strain, @@ -69,8 +71,8 @@ dyn.run(fmax=0.05) # print the energy after relaxation -print(f'After: {atoms.get_potential_energy()}') -print(f'Cell: {atoms.get_cell()}') +print(f"After: {atoms.get_potential_energy()}") +print(f"Cell: {atoms.get_cell()}") # remove the temporary job directory (including all files inside) shutil.rmtree(jobdir) diff --git a/interfaces/ASE_interface/examples/constraintmd.py b/interfaces/ASE_interface/examples/constraintmd.py index b28a781490c..75dc42bbfb8 100644 --- a/interfaces/ASE_interface/examples/constraintmd.py +++ b/interfaces/ASE_interface/examples/constraintmd.py @@ -1,10 +1,11 @@ import shutil import tempfile -from pathlib import Path # a more Pythonic alternative to the os.path +from pathlib import Path # a more Pythonic alternative to the os.path + here = Path(__file__).parent # to the directory where the pseudopotential and orbital files are stored # In your case you change to the appropriate one -pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' +pporb = here.parent.parent.parent / "tests" / "PP_ORB" import numpy as np import matplotlib.pyplot as plt @@ -16,39 +17,39 @@ from abacuslite import AbacusProfile, Abacus aprof = AbacusProfile( - command='mpirun -np 16 abacus', + command="mpirun -np 16 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, ) -jobdir = here / 'constraintmd' +jobdir = here / "constraintmd" abacus = Abacus( profile=aprof, directory=str(jobdir), pseudopotentials={ - 'C': 'C_ONCV_PBE-1.0.upf', - 'H': 'H_ONCV_PBE-1.0.upf', - 'F': 'F_ONCV_PBE-1.0.upf', + "C": "C_ONCV_PBE-1.0.upf", + "H": "H_ONCV_PBE-1.0.upf", + "F": "F_ONCV_PBE-1.0.upf", }, basissets={ - 'C': 'C_gga_8au_100Ry_2s2p1d.orb', - 'H': 'H_gga_8au_100Ry_2s1p.orb', - 'F': 'F_gga_7au_100Ry_2s2p1d.orb', + "C": "C_gga_8au_100Ry_2s2p1d.orb", + "H": "H_gga_8au_100Ry_2s1p.orb", + "F": "F_gga_7au_100Ry_2s2p1d.orb", }, inp={ - 'calculation': 'scf', - 'nspin': 2, - 'basis_type': 'lcao', - 'ks_solver': 'genelpa', - 'ecutwfc': 40, - 'scf_thr': 1e-6, - 'symmetry': 1, - 'gamma_only': True, - 'init_chg': 'auto' # small trick, use the previous charge density - } + "calculation": "scf", + "nspin": 2, + "basis_type": "lcao", + "ks_solver": "genelpa", + "ecutwfc": 40, + "scf_thr": 1e-6, + "symmetry": 1, + "gamma_only": True, + "init_chg": "auto", # small trick, use the previous charge density + }, ) -mol = ''' 6 +mol = """ 6 CH4-F C -0.00000000 -0.00000000 -1.50074532 H 0.00000000 -1.01539888 -1.16330635 @@ -56,13 +57,13 @@ H 0.87936122 0.50769944 -1.16330635 H -0.00000000 -0.00000000 -2.57055225 F 0.00000000 -0.00000000 0.88279136 -''' -with tempfile.NamedTemporaryFile(mode='w', suffix='.xyz') as f: +""" +with tempfile.NamedTemporaryFile(mode="w", suffix=".xyz") as f: f.write(mol) f.flush() atoms = read(f.name) -atoms.center(vacuum=5.0) # to reduce the computational cost +atoms.center(vacuum=5.0) # to reduce the computational cost # view(atoms) # constraint the No.1, 5, 6 atoms' X and Y coordiantes so that @@ -73,29 +74,31 @@ MaxwellBoltzmannDistribution(atoms, temperature_K=300) atoms.calc = abacus -dyn = Langevin(atoms, - timestep=1.0 * fs, - temperature_K=300, - friction=0.004, - logfile='-', - trajectory='constraintmd.traj') +dyn = Langevin( + atoms, + timestep=1.0 * fs, + temperature_K=300, + friction=0.004, + logfile="-", + trajectory="constraintmd.traj", +) dyn.run(5) # let's see if the X, Y coordinates of No.1, 5, and 6 atoms are really # fixed -with Trajectory('constraintmd.traj') as traj: +with Trajectory("constraintmd.traj") as traj: traj = np.array([atoms.get_positions() for atoms in traj]) # transpose from (nframe, natom, 3) to (natom, nframe, 3) traj = traj.transpose(1, 0, 2) # plot the trajectory of No.1, 5, and 6 atoms -plt.plot(traj[0, :, 2], label='C') -plt.plot(traj[4, :, 2], label='H') -plt.plot(traj[5, :, 2], label='F') -plt.xlabel('Step') -plt.ylabel('Z (Å)') +plt.plot(traj[0, :, 2], label="C") +plt.plot(traj[4, :, 2], label="H") +plt.plot(traj[5, :, 2], label="F") +plt.xlabel("Step") +plt.ylabel("Z (Å)") plt.legend() plt.show() -shutil.rmtree(jobdir) \ No newline at end of file +shutil.rmtree(jobdir) diff --git a/interfaces/ASE_interface/examples/dos.py b/interfaces/ASE_interface/examples/dos.py index 39a5f12fa84..5c405911ee5 100644 --- a/interfaces/ASE_interface/examples/dos.py +++ b/interfaces/ASE_interface/examples/dos.py @@ -1,13 +1,15 @@ -''' -This example shows how to run a SCF calculation with ABACUS +""" +This example shows how to run a SCF calculation with ABACUS of Si diamond structure. -''' +""" + import shutil -from pathlib import Path # a more Pythonic alternative to the os.path +from pathlib import Path # a more Pythonic alternative to the os.path + here = Path(__file__).parent # to the directory where the pseudopotential and orbital files are stored # In your case you change to the appropriate one -pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' +pporb = here.parent.parent.parent / "tests" / "PP_ORB" import matplotlib.pyplot as plt from ase.build import bulk @@ -15,35 +17,35 @@ from abacuslite import Abacus, AbacusProfile aprof = AbacusProfile( - command='mpirun -np 4 abacus', + command="mpirun -np 4 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, ) -jobdir = here / 'scf' +jobdir = here / "scf" abacus = Abacus( profile=aprof, directory=str(jobdir), - pseudopotentials={'Si': 'Si_ONCV_PBE-1.0.upf'}, - basissets={'Si': 'Si_gga_8au_100Ry_2s2p1d.orb'}, + pseudopotentials={"Si": "Si_ONCV_PBE-1.0.upf"}, + basissets={"Si": "Si_gga_8au_100Ry_2s2p1d.orb"}, inp={ - 'calculation': 'scf', - 'nspin': 1, - 'basis_type': 'lcao', - 'ks_solver': 'genelpa', - 'ecutwfc': 100, - 'symmetry': 1, - 'kspacing': 0.1 - } + "calculation": "scf", + "nspin": 1, + "basis_type": "lcao", + "ks_solver": "genelpa", + "ecutwfc": 100, + "symmetry": 1, + "kspacing": 0.1, + }, ) -# get the structure, can also from the +# get the structure, can also from the # ``` # from ase.io import read # atoms = read(...) # ``` -atoms = bulk('Si', 'diamond', a=5.43) +atoms = bulk("Si", "diamond", a=5.43) # bind the atoms with the abacus atoms.calc = abacus @@ -55,10 +57,10 @@ e, dos = doscalc.get_energies(), doscalc.get_dos() plt.plot(e, dos) -plt.xlim(-5, 5) -plt.xlabel('E - E_f (eV)') -plt.ylabel('DOS') -plt.title('DOS of Si Diamond') +plt.xlim(-5, 5) +plt.xlabel("E - E_f (eV)") +plt.ylabel("DOS") +plt.title("DOS of Si Diamond") plt.show() # remove the temporary job directory (including all files inside) diff --git a/interfaces/ASE_interface/examples/md.py b/interfaces/ASE_interface/examples/md.py index 2fc2bbefbb8..b74891ef540 100644 --- a/interfaces/ASE_interface/examples/md.py +++ b/interfaces/ASE_interface/examples/md.py @@ -1,15 +1,17 @@ -'''this example recap the example of MD in abacus example -directory, but there the CSVR thermostat is used instead +"""this example recap the example of MD in abacus example +directory, but there the CSVR thermostat is used instead of those implemented in ABACUS. In ASE, the CSVR thermostat is named as the Bussi -''' +""" + import shutil -from pathlib import Path # a more Pythonic alternative to the os.path +from pathlib import Path # a more Pythonic alternative to the os.path + here = Path(__file__).parent # to the directory where the pseudopotential and orbital files are stored # In your case you change to the appropriate one -pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' +pporb = here.parent.parent.parent / "tests" / "PP_ORB" import numpy as np from ase.atoms import Atoms @@ -29,44 +31,41 @@ [0.75000000, 0.25000000, 0.75000000], [0.75000000, 0.75000000, 0.25000000], ] -atoms = Atoms(symbols=['Si' for _ in range(8)], - scaled_positions=taud, - cell=cell, - pbc=True) +atoms = Atoms( + symbols=["Si" for _ in range(8)], scaled_positions=taud, cell=cell, pbc=True +) aprof = AbacusProfile( - command='mpirun -np 4 abacus', + command="mpirun -np 4 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, ) -jobdir = here / 'md' +jobdir = here / "md" abacus = Abacus( profile=aprof, directory=str(jobdir), - pseudopotentials={'Si': 'Si_ONCV_PBE-1.0.upf'}, - basissets={'Si': 'Si_gga_8au_100Ry_2s2p1d.orb'}, + pseudopotentials={"Si": "Si_ONCV_PBE-1.0.upf"}, + basissets={"Si": "Si_gga_8au_100Ry_2s2p1d.orb"}, inp={ - 'calculation': 'scf', # still use SCF here because the MD is driven by ASE - 'nspin': 1, - 'basis_type': 'lcao', - 'ks_solver': 'genelpa', - 'ecutwfc': 100, - 'symmetry': 1, - 'kspacing': 0.25 # highly unconverged, just for demo - } + "calculation": "scf", # still use SCF here because the MD is driven by ASE + "nspin": 1, + "basis_type": "lcao", + "ks_solver": "genelpa", + "ecutwfc": 100, + "symmetry": 1, + "kspacing": 0.25, # highly unconverged, just for demo + }, ) atoms.calc = abacus # initialize the velocities, necessary for CSVR MaxwellBoltzmannDistribution(atoms, temperature_K=300) -dyn = Bussi(atoms, - timestep=1*fs, - temperature_K=300, - taut=10*fs, - logfile='-') # let's see the trajectory +dyn = Bussi( + atoms, timestep=1 * fs, temperature_K=300, taut=10 * fs, logfile="-" +) # let's see the trajectory dyn.run(2) shutil.rmtree(jobdir) diff --git a/interfaces/ASE_interface/examples/metadynamics.py b/interfaces/ASE_interface/examples/metadynamics.py index 5595d131436..d697aa4b44f 100644 --- a/interfaces/ASE_interface/examples/metadynamics.py +++ b/interfaces/ASE_interface/examples/metadynamics.py @@ -1,4 +1,4 @@ -''' +""" To run the metadynamics, you need to configure the plumed correctly: conda install -c conda-forge plumed=2.8.2=mpi_openmpi_hb0545ae_0 @@ -7,7 +7,7 @@ You may be also interested in a newer version of plumed, a possible solution is to search `plumed` at conda website: https://anaconda.org/channels/conda-forge/packages/plumed/files -in which, up to 2026/02/25, the latest version is +in which, up to 2026/02/25, the latest version is ``` linux-64/plumed-2.9.2-mpi_openmpi_h02da92d_0.conda, ``` @@ -18,31 +18,32 @@ is nompi-labelled, may cause segmentation fault error during the MTD run. In this example, we will run a metadynamics simulation to explore the -substitution reaction, during which the famous Walden inversion +substitution reaction, during which the famous Walden inversion (https://en.wikipedia.org/wiki/Walden_inversion) happens: ``` CH4 + F -> CH3F + H ``` -. Because the F is a radical, we set nspin 2 throughout the simulation. +. Because the F is a radical, we set nspin 2 throughout the simulation. The structure is like H H \ / H - C F· | H -, thus the best Collective Variable (CV) is the difference between the +, thus the best Collective Variable (CV) is the difference between the H-C bond length and the C-F bond length. CSVR thermostat is used to maintain the temperature during the simulation. -''' +""" import shutil import tempfile -from pathlib import Path # a more Pythonic alternative to the os.path +from pathlib import Path # a more Pythonic alternative to the os.path + here = Path(__file__).parent # to the directory where the pseudopotential and orbital files are stored # In your case you change to the appropriate one -pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' +pporb = here.parent.parent.parent / "tests" / "PP_ORB" from ase.io import read from ase.md import Bussi @@ -52,45 +53,46 @@ kJ as _kJ, mol as _mol, ) + _ps = 1000 * fs from ase.constraints import FixCartesian from ase.calculators.plumed import Plumed from abacuslite import AbacusProfile, Abacus aprof = AbacusProfile( - command='mpirun -np 16 abacus', + command="mpirun -np 16 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, ) -jobdir = here / 'constraintmd' +jobdir = here / "constraintmd" abacus = Abacus( profile=aprof, directory=str(jobdir), pseudopotentials={ - 'C': 'C_ONCV_PBE-1.0.upf', - 'H': 'H_ONCV_PBE-1.0.upf', - 'F': 'F_ONCV_PBE-1.0.upf', + "C": "C_ONCV_PBE-1.0.upf", + "H": "H_ONCV_PBE-1.0.upf", + "F": "F_ONCV_PBE-1.0.upf", }, basissets={ - 'C': 'C_gga_8au_100Ry_2s2p1d.orb', - 'H': 'H_gga_8au_100Ry_2s1p.orb', - 'F': 'F_gga_7au_100Ry_2s2p1d.orb', + "C": "C_gga_8au_100Ry_2s2p1d.orb", + "H": "H_gga_8au_100Ry_2s1p.orb", + "F": "F_gga_7au_100Ry_2s2p1d.orb", }, inp={ - 'calculation': 'scf', - 'nspin': 2, - 'basis_type': 'lcao', - 'ks_solver': 'genelpa', - 'ecutwfc': 40, - 'scf_thr': 1e-6, - 'symmetry': 1, - 'gamma_only': True, - 'init_chg': 'auto' # small trick, use the previous charge density - } + "calculation": "scf", + "nspin": 2, + "basis_type": "lcao", + "ks_solver": "genelpa", + "ecutwfc": 40, + "scf_thr": 1e-6, + "symmetry": 1, + "gamma_only": True, + "init_chg": "auto", # small trick, use the previous charge density + }, ) -ch4f = ''' 6 +ch4f = """ 6 ABACUS ASE Plugin Metadynamics example structure C -0.00000000 -0.00000000 -1.50074532 F 0.00000000 -0.00000000 0.88279136 @@ -98,49 +100,49 @@ H -0.87936122 0.50769944 -1.16330635 H 0.87936122 0.50769944 -1.16330635 H -0.00000000 -0.00000000 -2.57055225 -''' -with tempfile.NamedTemporaryFile(mode='w', suffix='.xyz') as f: +""" +with tempfile.NamedTemporaryFile(mode="w", suffix=".xyz") as f: f.write(ch4f) f.flush() atoms = read(f.name) -atoms.center(vacuum=5.0) # to reduce the computational cost +atoms.center(vacuum=5.0) # to reduce the computational cost # constraint the No.5, 6 atoms' X and Y coordiantes so that # they can only move along the z-axis, also fix the atom C's # all components -atoms.set_constraint([FixCartesian(a=[4, 5], mask=(True, True, False)), - FixCartesian(a=[0])]) +atoms.set_constraint( + [FixCartesian(a=[4, 5], mask=(True, True, False)), FixCartesian(a=[0])] +) MaxwellBoltzmannDistribution(atoms, temperature_K=300) -setup = [# define the unit within the PLUMED runtime - f'UNITS LENGTH=A TIME={1/_ps} ENERGY={_mol/_kJ}', - # define the two bond lengths - 'd1: DISTANCE ATOMS=1,5', - 'd2: DISTANCE ATOMS=1,6', - # define the CV as the difference between the two bond lengths - 'c1: MATHEVAL ARG=d1,d2 VAR=a,b FUNC=a-b PERIODIC=NO', - # add walls to confine the position of H and F atoms - # such that the C-H bond will have length between 0.5 and 2.0, - # and the C-F bond will have length between 1.0 and 3.0 - 'lwall: LOWER_WALLS ARG=d1,d2 AT=0.5,1.0 KAPPA=150.0,150.0 EXP=2,2', - 'uwall: UPPER_WALLS ARG=d1,d2 AT=2.0,3.0 KAPPA=150.0,150.0 EXP=2,2', - # setup the metadynamics simulation - 'metad: METAD ARG=c1 PACE=5 HEIGHT=0.2 SIGMA=0.05 FILE=HILLS TEMP=300', - 'PRINT STRIDE=1 ARG=d1,d2,c1 FILE=COLVAR'] - -atoms.calc = Plumed(calc=abacus, - input=setup, - timestep=1.0 * fs, - atoms=atoms, - kT=0.1) - -dyn = Bussi(atoms, - timestep=1.0 * fs, - temperature_K=300, - taut=10.0 * fs, - trajectory='metadynamics.traj', - logfile='-') +setup = [ # define the unit within the PLUMED runtime + f"UNITS LENGTH=A TIME={1/_ps} ENERGY={_mol/_kJ}", + # define the two bond lengths + "d1: DISTANCE ATOMS=1,5", + "d2: DISTANCE ATOMS=1,6", + # define the CV as the difference between the two bond lengths + "c1: MATHEVAL ARG=d1,d2 VAR=a,b FUNC=a-b PERIODIC=NO", + # add walls to confine the position of H and F atoms + # such that the C-H bond will have length between 0.5 and 2.0, + # and the C-F bond will have length between 1.0 and 3.0 + "lwall: LOWER_WALLS ARG=d1,d2 AT=0.5,1.0 KAPPA=150.0,150.0 EXP=2,2", + "uwall: UPPER_WALLS ARG=d1,d2 AT=2.0,3.0 KAPPA=150.0,150.0 EXP=2,2", + # setup the metadynamics simulation + "metad: METAD ARG=c1 PACE=5 HEIGHT=0.2 SIGMA=0.05 FILE=HILLS TEMP=300", + "PRINT STRIDE=1 ARG=d1,d2,c1 FILE=COLVAR", +] + +atoms.calc = Plumed(calc=abacus, input=setup, timestep=1.0 * fs, atoms=atoms, kT=0.1) + +dyn = Bussi( + atoms, + timestep=1.0 * fs, + temperature_K=300, + taut=10.0 * fs, + trajectory="metadynamics.traj", + logfile="-", +) dyn.run(20) shutil.rmtree(jobdir) diff --git a/interfaces/ASE_interface/examples/neb.py b/interfaces/ASE_interface/examples/neb.py index 1118fcadc19..201327bca1a 100644 --- a/interfaces/ASE_interface/examples/neb.py +++ b/interfaces/ASE_interface/examples/neb.py @@ -1,10 +1,12 @@ -''' +""" PbTiO3 ferroelectric inversion energy barrier Learn how to use the NEB module in ASE, please refer to the online manual at: https://ase-lib.org/examples_generated/tutorials/neb_idpp.html -''' +""" + from pathlib import Path + here = Path(__file__).parent import numpy as np @@ -15,97 +17,105 @@ import matplotlib.pyplot as plt from abacuslite import Abacus, AbacusProfile -pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' +pporb = here.parent.parent.parent / "tests" / "PP_ORB" -elem = ['Ti', 'Pb', 'O', 'O', 'O'] -taud = np.array([ - [0.5, 0.5, 0.5948316037314115], - [0.0, 0.0, 0.1235879499999999], - [0.0, 0.5, 0.5094847864489368], - [0.5, 0.0, 0.5094847864489368], - [0.5, 0.5, 0.0088672395150394], -]) -cell = np.array([ - [3.8795519, 0.0000000, 0.00000000], - [0.0000000, 3.8795519, 0.00000000], - [0.0000000, 0.0000000, 4.28588762], -]) +elem = ["Ti", "Pb", "O", "O", "O"] +taud = np.array( + [ + [0.5, 0.5, 0.5948316037314115], + [0.0, 0.0, 0.1235879499999999], + [0.0, 0.5, 0.5094847864489368], + [0.5, 0.0, 0.5094847864489368], + [0.5, 0.5, 0.0088672395150394], + ] +) +cell = np.array( + [ + [3.8795519, 0.0000000, 0.00000000], + [0.0000000, 3.8795519, 0.00000000], + [0.0000000, 0.0000000, 4.28588762], + ] +) # we have relaxed with the parameters above :) up = Atoms(elem, cell=cell, scaled_positions=taud) # get the polarisation inversed by inversing the Ti atoms -taud = np.array([ - [0.5, 0.5, 0.6508136593687969], - [0.0, 0.0, 0.1235879499999999], - [0.0, 0.5, 0.7348401327639794], - [0.5, 0.0, 0.7348401327639794], - [0.5, 0.5, 0.2364165087650052], -]) +taud = np.array( + [ + [0.5, 0.5, 0.6508136593687969], + [0.0, 0.0, 0.1235879499999999], + [0.0, 0.5, 0.7348401327639794], + [0.5, 0.0, 0.7348401327639794], + [0.5, 0.5, 0.2364165087650052], + ] +) dw = Atoms(elem, cell=cell, scaled_positions=taud) aprof = AbacusProfile( - command='mpirun -np 8 abacus_2p', + command="mpirun -np 8 abacus_2p", pseudo_dir=pporb, orbital_dir=pporb, - omp_num_threads=1 + omp_num_threads=1, ) pseudopotentials = { - 'Ti': 'Ti_ONCV_PBE-1.0.upf', - 'Pb': 'Pb_ONCV_PBE-1.0.upf', - 'O' : 'O_ONCV_PBE-1.0.upf', + "Ti": "Ti_ONCV_PBE-1.0.upf", + "Pb": "Pb_ONCV_PBE-1.0.upf", + "O": "O_ONCV_PBE-1.0.upf", } basissets = { - 'Ti': 'Ti_gga_8au_100Ry_4s2p2d1f.orb', - 'Pb': 'Pb_gga_7au_100Ry_2s2p2d1f.orb', - 'O' : 'O_gga_7au_100Ry_2s2p1d.orb', + "Ti": "Ti_gga_8au_100Ry_4s2p2d1f.orb", + "Pb": "Pb_gga_7au_100Ry_2s2p2d1f.orb", + "O": "O_gga_7au_100Ry_2s2p1d.orb", } inp = { - 'profile': aprof, - 'pseudopotentials': pseudopotentials, - 'basissets': basissets, - 'inp': { - 'basis_type': 'lcao', - 'symmetry': 1, - 'kspacing': 0.25, # Oops! - 'init_chg': 'auto', - 'cal_force': 1, - } + "profile": aprof, + "pseudopotentials": pseudopotentials, + "basissets": basissets, + "inp": { + "basis_type": "lcao", + "symmetry": 1, + "kspacing": 0.25, # Oops! + "init_chg": "auto", + "cal_force": 1, + }, } -n_replica = 7 # the ini and fin images included. 7 is acceptable for production +n_replica = 7 # the ini and fin images included. 7 is acceptable for production replica = [] for irep in range(n_replica): image = up.copy() if irep <= (n_replica // 2) else dw.copy() # attach the calculator to each image, so that we can run the optimization - image.calc = Abacus(**inp, directory=here / f'neb-{irep}') + image.calc = Abacus(**inp, directory=here / f"neb-{irep}") replica.append(image) -neb = NEB(replica, - k=0.05, # too high value is hard to converge - climb=False, # use True in production run, though CI-NEB is harder to converge - parallel=True) -neb.interpolate('idpp') +neb = NEB( + replica, + k=0.05, # too high value is hard to converge + climb=False, # use True in production run, though CI-NEB is harder to converge + parallel=True, +) +neb.interpolate("idpp") -qn = FIRE(neb, trajectory=here / 'neb.traj') +qn = FIRE(neb, trajectory=here / "neb.traj") qn.run(fmax=0.05) energies = [] # get the energy profile along the reaction path -with Trajectory(here / 'neb.traj') as traj: - replica = traj[-7:] # the last NEB frames +with Trajectory(here / "neb.traj") as traj: + replica = traj[-7:] # the last NEB frames for i, rep in enumerate(replica): - rep: Atoms # type hint + rep: Atoms # type hint # the energies of the initial and the final state # are not calculated, here we calculate them - rep.calc = Abacus(**inp, directory=here / f'neb-{i}') + rep.calc = Abacus(**inp, directory=here / f"neb-{i}") energies.append(rep.get_potential_energy()) energies = np.array(energies) # plot the energy profile -plt.plot(energies - energies[0], 'o-') -plt.xlabel('NEB image index') -plt.ylabel('Total energies (eV)') -plt.title('Energy profile along the reaction path') -plt.savefig(here / 'energy_profile.png', dpi=300) +plt.plot(energies - energies[0], "o-") +plt.xlabel("NEB image index") +plt.ylabel("Total energies (eV)") +plt.title("Energy profile along the reaction path") +plt.savefig(here / "energy_profile.png", dpi=300) plt.close() diff --git a/interfaces/ASE_interface/examples/relax.py b/interfaces/ASE_interface/examples/relax.py index ac769055a40..d57acc0a160 100644 --- a/interfaces/ASE_interface/examples/relax.py +++ b/interfaces/ASE_interface/examples/relax.py @@ -1,13 +1,15 @@ -''' -This example shows how to perform a ion relaxation with ABACUS +""" +This example shows how to perform a ion relaxation with ABACUS of Si diamond structure. -''' +""" + import shutil -from pathlib import Path # a more Pythonic alternative to the os.path +from pathlib import Path # a more Pythonic alternative to the os.path + here = Path(__file__).parent # to the directory where the pseudopotential and orbital files are stored # In your case you change to the appropriate one -pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' +pporb = here.parent.parent.parent / "tests" / "PP_ORB" from ase.build import bulk from ase.optimize import BFGS @@ -16,37 +18,37 @@ # AbacusProfile: the interface connecting the Abacus calculator instance # with the file system and the enviroment aprof = AbacusProfile( - command='mpirun -np 8 abacus', + command="mpirun -np 8 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, ) # Abacus: the calculator instance -jobdir = here / 'relax' +jobdir = here / "relax" abacus = Abacus( profile=aprof, directory=str(jobdir), - pseudopotentials={'Si': 'Si_ONCV_PBE-1.0.upf'}, - basissets={'Si': 'Si_gga_8au_100Ry_2s2p1d.orb'}, + pseudopotentials={"Si": "Si_ONCV_PBE-1.0.upf"}, + basissets={"Si": "Si_gga_8au_100Ry_2s2p1d.orb"}, inp={ - 'calculation': 'scf', - 'nspin': 1, - 'basis_type': 'lcao', - 'ks_solver': 'genelpa', - 'ecutwfc': 100, - 'symmetry': 1, - 'kspacing': 0.1, - 'cal_force': 1 # let ABACUS calculate the forces - } + "calculation": "scf", + "nspin": 1, + "basis_type": "lcao", + "ks_solver": "genelpa", + "ecutwfc": 100, + "symmetry": 1, + "kspacing": 0.1, + "cal_force": 1, # let ABACUS calculate the forces + }, ) -# get the structure, can also from the +# get the structure, can also from the # ``` # from ase.io import read # atoms = read(...) # ``` -atoms = bulk('Si', 'diamond', a=5.43) +atoms = bulk("Si", "diamond", a=5.43) # displacement the atoms a little bit atoms.rattle(stdev=0.1) @@ -54,14 +56,14 @@ atoms.calc = abacus # print the energy before relaxation -print(f'Before: {atoms.get_potential_energy()}') +print(f"Before: {atoms.get_potential_energy()}") # perform the relaxation calculation -dyn = BFGS(atoms, logfile='-') # let's print to screen, observe the trajectory +dyn = BFGS(atoms, logfile="-") # let's print to screen, observe the trajectory dyn.run(fmax=0.05) # print the energy after relaxation -print(f'After: {atoms.get_potential_energy()}') +print(f"After: {atoms.get_potential_energy()}") # remove the temporary job directory (including all files inside) shutil.rmtree(jobdir) diff --git a/interfaces/ASE_interface/examples/scf.py b/interfaces/ASE_interface/examples/scf.py index 9e3fdc4f228..7ae355b0e4f 100644 --- a/interfaces/ASE_interface/examples/scf.py +++ b/interfaces/ASE_interface/examples/scf.py @@ -1,13 +1,15 @@ -''' -This example shows how to run a SCF calculation with ABACUS +""" +This example shows how to run a SCF calculation with ABACUS of Si diamond structure. -''' +""" + import shutil -from pathlib import Path # a more Pythonic alternative to the os.path +from pathlib import Path # a more Pythonic alternative to the os.path + here = Path(__file__).parent # to the directory where the pseudopotential and orbital files are stored # In your case you change to the appropriate one -pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' +pporb = here.parent.parent.parent / "tests" / "PP_ORB" from ase.build import bulk from abacuslite import Abacus, AbacusProfile @@ -15,36 +17,36 @@ # AbacusProfile: the interface connecting the Abacus calculator instance # with the file system and the enviroment aprof = AbacusProfile( - command='mpirun -np 4 abacus', + command="mpirun -np 4 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, ) # Abacus: the calculator instance -jobdir = here / 'scf' +jobdir = here / "scf" abacus = Abacus( profile=aprof, directory=str(jobdir), - pseudopotentials={'Si': 'Si_ONCV_PBE-1.0.upf'}, - basissets={'Si': 'Si_gga_8au_100Ry_2s2p1d.orb'}, + pseudopotentials={"Si": "Si_ONCV_PBE-1.0.upf"}, + basissets={"Si": "Si_gga_8au_100Ry_2s2p1d.orb"}, inp={ - 'calculation': 'scf', - 'nspin': 1, - 'basis_type': 'lcao', - 'ks_solver': 'genelpa', - 'ecutwfc': 100, - 'symmetry': 1, - 'kspacing': 0.1 - } + "calculation": "scf", + "nspin": 1, + "basis_type": "lcao", + "ks_solver": "genelpa", + "ecutwfc": 100, + "symmetry": 1, + "kspacing": 0.1, + }, ) -# get the structure, can also from the +# get the structure, can also from the # ``` # from ase.io import read # atoms = read(...) # ``` -atoms = bulk('Si', 'diamond', a=5.43) +atoms = bulk("Si", "diamond", a=5.43) # bind the atoms with the abacus atoms.calc = abacus diff --git a/interfaces/ASE_interface/examples/soc.py b/interfaces/ASE_interface/examples/soc.py index cdbbd04d6e4..82f9b8506e3 100644 --- a/interfaces/ASE_interface/examples/soc.py +++ b/interfaces/ASE_interface/examples/soc.py @@ -1,63 +1,68 @@ -'''this example shows how to perform the noncolinear -spin-orbit coupling calculation''' +"""this example shows how to perform the noncolinear +spin-orbit coupling calculation""" + import shutil from pathlib import Path + here = Path(__file__).parent -pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' +pporb = here.parent.parent.parent / "tests" / "PP_ORB" import numpy as np from ase.atoms import Atoms from abacuslite import Abacus, AbacusProfile -'''SPECIAL: ase does not support the noncolinear spin yet +"""SPECIAL: ase does not support the noncolinear spin yet till 2026/3/24, see ase/outputs.py:L154-155, in which the magmom cannot be set as the vector, so we release the -datatype of magmom and magmoms by ourself''' +datatype of magmom and magmoms by ourself""" from ase.outputs import _defineprop, all_outputs -del all_outputs['magmom'] -del all_outputs['magmoms'] -_defineprop('magmom', float, shape=3) # re-define the magmom can be set as the vector -_defineprop('magmoms', float, shape=('natoms', 3)) -fe = Atoms(symbols=['Fe'] * 2, - scaled_positions=[[0., 0., 0.], [0.5, 0.5, 0.5]], - magmoms=np.array([[0, 0, 1], [0, 0, 1]]), - cell=np.eye(3) * 5.2, - pbc=True) +del all_outputs["magmom"] +del all_outputs["magmoms"] +_defineprop("magmom", float, shape=3) # re-define the magmom can be set as the vector +_defineprop("magmoms", float, shape=("natoms", 3)) + +fe = Atoms( + symbols=["Fe"] * 2, + scaled_positions=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], + magmoms=np.array([[0, 0, 1], [0, 0, 1]]), + cell=np.eye(3) * 5.2, + pbc=True, +) aprof = AbacusProfile( - command='mpirun -np 2 abacus', - pseudo_dir=pporb, - orbital_dir=pporb, - omp_num_threads=1 + command="mpirun -np 2 abacus", + pseudo_dir=pporb, + orbital_dir=pporb, + omp_num_threads=1, ) -jobdir = here / 'soc' +jobdir = here / "soc" abacus = Abacus( profile=aprof, directory=jobdir, - pseudopotentials={'Fe': 'Fe.upf'}, - basissets={'Fe': 'Fe_gga_6au_100Ry_4s2p2d1f.orb'}, + pseudopotentials={"Fe": "Fe.upf"}, + basissets={"Fe": "Fe_gga_6au_100Ry_4s2p2d1f.orb"}, inp={ - 'basis_type': 'lcao', - 'nspin': 4, - 'lspinorb': True, - 'noncolin': True, - 'out_mul': True, - 'scf_nmax': 10 # not serious setting! + "basis_type": "lcao", + "nspin": 4, + "lspinorb": True, + "noncolin": True, + "out_mul": True, + "scf_nmax": 10, # not serious setting! }, kpts={ - 'mode': 'mp-sampling', - 'gamma-centered': True, - 'nk': (2, 2, 2), - 'kshift': (0, 0, 0) - } + "mode": "mp-sampling", + "gamma-centered": True, + "nk": (2, 2, 2), + "kshift": (0, 0, 0), + }, ) fe.calc = abacus -print(f'Fe (non-colinear): {fe.get_potential_energy()} eV') -for ife, m in enumerate(fe.calc.results['magmoms']): +print(f"Fe (non-colinear): {fe.get_potential_energy()} eV") +for ife, m in enumerate(fe.calc.results["magmoms"]): print(f'Fe{ife}: ({",".join([f"{mi:10.6f}" for mi in m])}) uB') -shutil.rmtree(jobdir) \ No newline at end of file +shutil.rmtree(jobdir) diff --git a/interfaces/ASE_interface/tests/band.py b/interfaces/ASE_interface/tests/band.py index 78b80922111..837415b8d81 100644 --- a/interfaces/ASE_interface/tests/band.py +++ b/interfaces/ASE_interface/tests/band.py @@ -1,28 +1,30 @@ import unittest import tempfile from pathlib import Path + here = Path(__file__).parent from ase.build import bulk from abacuslite.io.generalio import load_pseudo, load_orbital from abacuslite import AbacusProfile, Abacus from abacuslite.utils.ksampling import kpathgen + class TestSCFFollowedNSCF(unittest.TestCase): def setUp(self): - '''if SeeK-path is not installed, skip the test''' + """if SeeK-path is not installed, skip the test""" try: import seekpath except ImportError: - self.skipTest('seekpath is not installed') + self.skipTest("seekpath is not installed") return super().setUp() def test(self): - pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' + pporb = here.parent.parent.parent / "tests" / "PP_ORB" - silicon = bulk('Si', 'diamond', a=5.43) + silicon = bulk("Si", "diamond", a=5.43) aprof = AbacusProfile( - command='mpirun -np 2 abacus', + command="mpirun -np 2 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, @@ -35,10 +37,10 @@ def test(self): pseudopotentials=load_pseudo(pporb), basissets=load_orbital(pporb, efficiency=True), inp={ - 'basis_type': 'lcao', - 'scf_thr': 1e-3, # fast for test, wrong for production, - 'kspacing': 0.25 - } + "basis_type": "lcao", + "scf_thr": 1e-3, # fast for test, wrong for production, + "kspacing": 0.25, + }, ) silicon.calc = abacus @@ -47,15 +49,16 @@ def test(self): # ============================================================= # kpath, kspecial = kpathgen(silicon) - bandpath = silicon.cell.bandpath(path=kpath, - npoints=5, - special_points=kspecial) + bandpath = silicon.cell.bandpath( + path=kpath, npoints=5, special_points=kspecial + ) bscalc = silicon.calc.fixed_density(bandpath) silicon.calc = bscalc _ = silicon.get_potential_energy() - bscalc.band_structure().write(Path(tmpdir) / 'bandstructure.json') - self.assertTrue((Path(tmpdir) / 'bandstructure.json').exists()) + bscalc.band_structure().write(Path(tmpdir) / "bandstructure.json") + self.assertTrue((Path(tmpdir) / "bandstructure.json").exists()) + -if __name__ == '__main__': - unittest.main() \ No newline at end of file +if __name__ == "__main__": + unittest.main() diff --git a/interfaces/ASE_interface/tests/magnetic.py b/interfaces/ASE_interface/tests/magnetic.py index 3fbacbdc998..1fdaab40b2e 100644 --- a/interfaces/ASE_interface/tests/magnetic.py +++ b/interfaces/ASE_interface/tests/magnetic.py @@ -1,129 +1,142 @@ -''' +""" test if ABACUS can perform the calculation on the anti-ferromagnetic and ferromagnetic phases calculation on the BCC Fe -''' +""" + import unittest import tempfile import numpy as np from pathlib import Path + here = Path(__file__).parent from ase.atoms import Atoms from abacuslite import AbacusProfile, Abacus + class TestMagneticSCF(unittest.TestCase): def setUp(self): - pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' + pporb = here.parent.parent.parent / "tests" / "PP_ORB" self.aprof = AbacusProfile( - command='mpirun -np 2 abacus', + command="mpirun -np 2 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, ) def test_antiferromagnetic(self): - fe = Atoms(symbols=['Fe'] * 2, - scaled_positions=[[0., 0., 0.], [0.5, 0.5, 0.5]], - magmoms=[-1, 1], - cell=np.eye(3) * 5.2, - pbc=True) + fe = Atoms( + symbols=["Fe"] * 2, + scaled_positions=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], + magmoms=[-1, 1], + cell=np.eye(3) * 5.2, + pbc=True, + ) with tempfile.TemporaryDirectory() as tmpdir: abacus = Abacus( profile=self.aprof, directory=tmpdir, - pseudopotentials={'Fe': 'Fe_ONCV_PBE-1.0.upf'}, - basissets={'Fe': 'Fe_gga_6au_100Ry_4s2p2d1f.orb'}, + pseudopotentials={"Fe": "Fe_ONCV_PBE-1.0.upf"}, + basissets={"Fe": "Fe_gga_6au_100Ry_4s2p2d1f.orb"}, inp={ - 'basis_type': 'lcao', - 'gamma_only': True, - 'scf_thr': 1e-3, # fast for test, wrong for production - 'nspin': 2, - 'out_mul': True - } + "basis_type": "lcao", + "gamma_only": True, + "scf_thr": 1e-3, # fast for test, wrong for production + "nspin": 2, + "out_mul": True, + }, ) fe.calc = abacus - print(f'Fe (AFM): {fe.get_potential_energy()} eV') - for ife, m in enumerate(fe.calc.results['magmoms']): - print(f'Fe{ife}: {m:10.6f} uB') + print(f"Fe (AFM): {fe.get_potential_energy()} eV") + for ife, m in enumerate(fe.calc.results["magmoms"]): + print(f"Fe{ife}: {m:10.6f} uB") self.assertGreater(abs(m), 1e-3) - self.assertTrue(np.allclose(np.sum(fe.calc.results['magmoms']), 0.0, atol=1e-6)) + self.assertTrue( + np.allclose(np.sum(fe.calc.results["magmoms"]), 0.0, atol=1e-6) + ) def test_ferromagnetic(self): - fe = Atoms(symbols=['Fe'] * 2, - scaled_positions=[[0., 0., 0.], [0.5, 0.5, 0.5]], - magmoms=[1, 1], - cell=np.eye(3) * 5.2, - pbc=True) + fe = Atoms( + symbols=["Fe"] * 2, + scaled_positions=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], + magmoms=[1, 1], + cell=np.eye(3) * 5.2, + pbc=True, + ) with tempfile.TemporaryDirectory() as tmpdir: abacus = Abacus( profile=self.aprof, directory=tmpdir, - pseudopotentials={'Fe': 'Fe_ONCV_PBE-1.0.upf'}, - basissets={'Fe': 'Fe_gga_6au_100Ry_4s2p2d1f.orb'}, + pseudopotentials={"Fe": "Fe_ONCV_PBE-1.0.upf"}, + basissets={"Fe": "Fe_gga_6au_100Ry_4s2p2d1f.orb"}, inp={ - 'basis_type': 'lcao', - 'gamma_only': True, - 'scf_thr': 1e-3, # fast for test, wrong for production - 'nspin': 2, - 'out_mul': True - } + "basis_type": "lcao", + "gamma_only": True, + "scf_thr": 1e-3, # fast for test, wrong for production + "nspin": 2, + "out_mul": True, + }, ) fe.calc = abacus - print(f'Fe (FM): {fe.get_potential_energy()} eV') - for ife, m in enumerate(fe.calc.results['magmoms']): - print(f'Fe{ife}: {m:10.6f} uB') + print(f"Fe (FM): {fe.get_potential_energy()} eV") + for ife, m in enumerate(fe.calc.results["magmoms"]): + print(f"Fe{ife}: {m:10.6f} uB") self.assertGreater(abs(m), 1e-3) - self.assertGreater(abs(np.sum(fe.calc.results['magmoms'])), 0.0) + self.assertGreater(abs(np.sum(fe.calc.results["magmoms"])), 0.0) # @unittest.skip('see ase/outputs.py:L154-155, the magmom cannot be set as the vector, so ' # 'we skip this test for now') def test_noncolinear(self): from ase.outputs import _defineprop, all_outputs + # refresh the definition of magmom and magmoms - del all_outputs['magmom'] - del all_outputs['magmoms'] - _defineprop('magmom', float, shape=3) - _defineprop('magmoms', float, shape=('natoms', 3)) + del all_outputs["magmom"] + del all_outputs["magmoms"] + _defineprop("magmom", float, shape=3) + _defineprop("magmoms", float, shape=("natoms", 3)) - fe = Atoms(symbols=['Fe'] * 2, - scaled_positions=[[0., 0., 0.], [0.5, 0.5, 0.5]], - magmoms=np.array([[1, 0, 0], [0, 1, 0]]), - cell=np.eye(3) * 5.2, - pbc=True) + fe = Atoms( + symbols=["Fe"] * 2, + scaled_positions=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], + magmoms=np.array([[1, 0, 0], [0, 1, 0]]), + cell=np.eye(3) * 5.2, + pbc=True, + ) with tempfile.TemporaryDirectory() as tmpdir: abacus = Abacus( profile=self.aprof, directory=tmpdir, - pseudopotentials={'Fe': 'Fe.upf'}, - basissets={'Fe': 'Fe_gga_6au_100Ry_4s2p2d1f.orb'}, + pseudopotentials={"Fe": "Fe.upf"}, + basissets={"Fe": "Fe_gga_6au_100Ry_4s2p2d1f.orb"}, inp={ - 'basis_type': 'lcao', - 'scf_thr': 1e-2, # fast for test, wrong for production - 'nspin': 4, - 'lspinorb': True, - 'noncolin': True, - 'out_mul': True, - 'scf_nmax': 1 + "basis_type": "lcao", + "scf_thr": 1e-2, # fast for test, wrong for production + "nspin": 4, + "lspinorb": True, + "noncolin": True, + "out_mul": True, + "scf_nmax": 1, }, kpts={ - 'mode': 'mp-sampling', - 'gamma-centered': True, - 'nk': (2, 2, 2), - 'kshift': (0, 0, 0) - } + "mode": "mp-sampling", + "gamma-centered": True, + "nk": (2, 2, 2), + "kshift": (0, 0, 0), + }, ) fe.calc = abacus - print(f'Fe (non-colinear): {fe.get_potential_energy()} eV') - for ife, m in enumerate(fe.calc.results['magmoms']): + print(f"Fe (non-colinear): {fe.get_potential_energy()} eV") + for ife, m in enumerate(fe.calc.results["magmoms"]): print(f'Fe{ife}: ({",".join([f"{mi:10.6f}" for mi in m])}) uB') self.assertGreater(np.linalg.norm(m), 1e-3) -if __name__ == '__main__': - unittest.main() \ No newline at end of file + +if __name__ == "__main__": + unittest.main() diff --git a/interfaces/ASE_interface/tests/md.py b/interfaces/ASE_interface/tests/md.py index 2b771eb3df3..633292c11cb 100644 --- a/interfaces/ASE_interface/tests/md.py +++ b/interfaces/ASE_interface/tests/md.py @@ -1,6 +1,7 @@ import unittest import tempfile from pathlib import Path + here = Path(__file__).parent from ase.build import bulk from ase.units import fs @@ -9,14 +10,15 @@ from abacuslite.io.generalio import load_pseudo, load_orbital from abacuslite import AbacusProfile, Abacus + class TestLangevinMolecularDynamics(unittest.TestCase): def test(self): - pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' + pporb = here.parent.parent.parent / "tests" / "PP_ORB" - silicon = bulk('Si', 'diamond', a=5.43) + silicon = bulk("Si", "diamond", a=5.43) aprof = AbacusProfile( - command='mpirun -np 2 abacus', + command="mpirun -np 2 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, @@ -29,22 +31,20 @@ def test(self): pseudopotentials=load_pseudo(pporb), basissets=load_orbital(pporb, efficiency=True), inp={ - 'basis_type': 'lcao', - 'gamma_only': True, - 'scf_thr': 1e-3, # fast for test, wrong for production, - 'cal_force': True, - 'cal_stress': True, - 'init_chg': 'auto' - } + "basis_type": "lcao", + "gamma_only": True, + "scf_thr": 1e-3, # fast for test, wrong for production, + "cal_force": True, + "cal_stress": True, + "init_chg": "auto", + }, ) silicon.calc = abacus MaxwellBoltzmannDistribution(silicon, temperature_K=300) - dyn = Langevin(silicon, - timestep=1.0 * fs, - temperature_K=300, - friction=0.01) + dyn = Langevin(silicon, timestep=1.0 * fs, temperature_K=300, friction=0.01) dyn.run(2) -if __name__ == '__main__': - unittest.main() \ No newline at end of file + +if __name__ == "__main__": + unittest.main() diff --git a/interfaces/ASE_interface/tests/relax.py b/interfaces/ASE_interface/tests/relax.py index dc8e9e9fd70..8c0e7b7489d 100644 --- a/interfaces/ASE_interface/tests/relax.py +++ b/interfaces/ASE_interface/tests/relax.py @@ -1,20 +1,22 @@ import unittest import tempfile from pathlib import Path + here = Path(__file__).parent from ase.build import bulk from ase.optimize import BFGS from abacuslite.io.generalio import load_pseudo, load_orbital from abacuslite import AbacusProfile, Abacus + class TestIonicRelaxationWithStress(unittest.TestCase): def test(self): - pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' + pporb = here.parent.parent.parent / "tests" / "PP_ORB" - silicon = bulk('Si', 'diamond', a=5.43) + silicon = bulk("Si", "diamond", a=5.43) aprof = AbacusProfile( - command='mpirun -np 2 abacus', + command="mpirun -np 2 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, @@ -27,12 +29,12 @@ def test(self): pseudopotentials=load_pseudo(pporb), basissets=load_orbital(pporb, efficiency=True), inp={ - 'basis_type': 'lcao', - 'gamma_only': True, - 'scf_thr': 1e-3, # fast for test, wrong for production, - 'cal_force': True, - 'cal_stress': True - } + "basis_type": "lcao", + "gamma_only": True, + "scf_thr": 1e-3, # fast for test, wrong for production, + "cal_force": True, + "cal_stress": True, + }, ) silicon.calc = abacus @@ -40,8 +42,9 @@ def test(self): opt = BFGS(silicon) opt.run(fmax=0.05, steps=1) self.assertLessEqual(silicon.get_potential_energy(), e) - self.assertIsNotNone(silicon.calc.results['forces']) - self.assertIsNotNone(silicon.calc.results['stress']) + self.assertIsNotNone(silicon.calc.results["forces"]) + self.assertIsNotNone(silicon.calc.results["stress"]) + -if __name__ == '__main__': - unittest.main() \ No newline at end of file +if __name__ == "__main__": + unittest.main() diff --git a/interfaces/ASE_interface/tests/scf.py b/interfaces/ASE_interface/tests/scf.py index 4d792e8eab2..48c61981e53 100644 --- a/interfaces/ASE_interface/tests/scf.py +++ b/interfaces/ASE_interface/tests/scf.py @@ -1,19 +1,21 @@ import unittest import tempfile from pathlib import Path + here = Path(__file__).parent from ase.build import bulk from abacuslite.io.generalio import load_pseudo, load_orbital from abacuslite import AbacusProfile, Abacus + class TestSCF(unittest.TestCase): def test(self): - pporb = here.parent.parent.parent / 'tests' / 'PP_ORB' + pporb = here.parent.parent.parent / "tests" / "PP_ORB" - silicon = bulk('Si', 'diamond', a=5.43) + silicon = bulk("Si", "diamond", a=5.43) aprof = AbacusProfile( - command='mpirun -np 2 abacus', + command="mpirun -np 2 abacus", pseudo_dir=pporb, orbital_dir=pporb, omp_num_threads=1, @@ -26,14 +28,15 @@ def test(self): pseudopotentials=load_pseudo(pporb), basissets=load_orbital(pporb, efficiency=True), inp={ - 'basis_type': 'lcao', - 'gamma_only': True, - 'scf_thr': 1e-3, # fast for test, wrong for production - } + "basis_type": "lcao", + "gamma_only": True, + "scf_thr": 1e-3, # fast for test, wrong for production + }, ) silicon.calc = abacus - print('Silicon :', silicon.get_potential_energy()) + print("Silicon :", silicon.get_potential_energy()) + -if __name__ == '__main__': - unittest.main() \ No newline at end of file +if __name__ == "__main__": + unittest.main() diff --git a/interfaces/DPGEN_interface/README.md b/interfaces/DPGEN_interface/README.md index 6a1a4d107fc..7c6abfa7c0f 100644 --- a/interfaces/DPGEN_interface/README.md +++ b/interfaces/DPGEN_interface/README.md @@ -1,10 +1,12 @@ # DPGEN Interface -This directory contains the interface between ABACUS and DPGEN (Deep Potential GENerator), an open-source tool for generating deep learning potentials for molecular dynamics simulations. +This directory contains the interface between ABACUS and DPGEN (Deep Potential GENerator), an +open-source tool for generating deep learning potentials for molecular dynamics simulations. ## What is DPGEN? -DPGEN is an open-source tool that automates the generation of deep learning potentials (DPLs) for molecular dynamics simulations. It is designed to: +DPGEN is an open-source tool that automates the generation of deep learning potentials (DPLs) for +molecular dynamics simulations. It is designed to: - Generate training data through ab initio calculations - Train deep learning models for potential energy surfaces @@ -12,6 +14,7 @@ DPGEN is an open-source tool that automates the generation of deep learning pote - Provide a framework for high-throughput materials simulations DPGEN is particularly useful for: + - Accelerating molecular dynamics simulations - Studying large systems that are computationally expensive with ab initio methods - Simulating long-time dynamics @@ -19,7 +22,9 @@ DPGEN is particularly useful for: ## ABACUS-DPGEN Interface -The ABACUS-DPGEN interface allows ABACUS to be used as the ab initio calculator for DPGEN. This enables DPGEN to generate training data using ABACUS's various basis sets (plane wave and LCAO) and functional choices. +The ABACUS-DPGEN interface allows ABACUS to be used as the ab initio calculator for DPGEN. This +enables DPGEN to generate training data using ABACUS's various basis sets (plane wave and LCAO) and +functional choices. ### Key Features of the Interface @@ -30,9 +35,11 @@ The ABACUS-DPGEN interface allows ABACUS to be used as the ab initio calculator ## Examples -This directory contains two examples demonstrating different use cases of the ABACUS-DPGEN interface: +This directory contains two examples demonstrating different use cases of the ABACUS-DPGEN +interface: ### 1. autotest + - **Purpose**: Demonstrates automated testing of the ABACUS-DPGEN interface - **Input Files**: - DPGEN input files @@ -40,6 +47,7 @@ This directory contains two examples demonstrating different use cases of the AB - Scripts for running the calculation ### 2. init_and_run + - **Purpose**: Demonstrates the complete workflow of initializing and running DPGEN with ABACUS - **Input Files**: - DPGEN input files @@ -50,30 +58,35 @@ This directory contains two examples demonstrating different use cases of the AB ### Prerequisites -1. **Install DPGEN**: Follow the installation instructions on the [DPGEN GitHub repository](https://github.com/deepmodeling/dpgen) -2. **Set up ABACUS**: Ensure ABACUS is compiled and accessible in your PATH -3. **Prepare input files**: Create ABACUS input files and DPGEN input files +1. **Install DPGEN**: Follow the installation instructions on the + [DPGEN GitHub repository](https://github.com/deepmodeling/dpgen) +1. **Set up ABACUS**: Ensure ABACUS is compiled and accessible in your PATH +1. **Prepare input files**: Create ABACUS input files and DPGEN input files ### Basic Workflow 1. **Prepare DPGEN input files**: + - Create `input.json` file with calculation parameters - Define the structure and configuration space - Set up the ABACUS calculator settings -2. **Run DPGEN**: +1. **Run DPGEN**: + - DPGEN will automatically generate initial configurations - It will run ABACUS calculations to generate training data - It will train deep learning models based on the data - It will validate and test the trained models -3. **Use the trained model**: +1. **Use the trained model**: + - The trained deep learning potential can be used for molecular dynamics simulations - It can be integrated with molecular dynamics packages like LAMMPS ### Important Notes -- The quality of the deep learning potential depends on the quality and diversity of the training data +- The quality of the deep learning potential depends on the quality and diversity of the training + data - Ensure that the ABACUS calculations are properly converged - Convergence tests should be performed for basis set, k-point sampling, and other parameters @@ -81,10 +94,12 @@ This directory contains two examples demonstrating different use cases of the AB - **ABACUS calculations failing**: Check that ABACUS is properly installed and accessible - **DPGEN cannot read ABACUS output**: Ensure that ABACUS is generating the necessary output files -- **Training not converging**: Consider increasing the amount of training data or adjusting the model parameters +- **Training not converging**: Consider increasing the amount of training data or adjusting the + model parameters ## References -- **DPGEN GitHub repository**: [https://github.com/deepmodeling/dpgen](https://github.com/deepmodeling/dpgen) +- **DPGEN GitHub repository**: + [https://github.com/deepmodeling/dpgen](https://github.com/deepmodeling/dpgen) - **DPGEN paper**: L. Zhang et al., *npj Comput. Mater.* **6**, 1 (2020) - **ABACUS documentation**: Refer to the ABACUS user manual for more details on input parameters diff --git a/interfaces/DPGEN_interface/autotest/INPUT.rlx b/interfaces/DPGEN_interface/autotest/INPUT.rlx index 742042fdf42..fdded79c7a9 100644 --- a/interfaces/DPGEN_interface/autotest/INPUT.rlx +++ b/interfaces/DPGEN_interface/autotest/INPUT.rlx @@ -1,7 +1,7 @@ INPUT_PARAMETERS # Created by Atomic Simulation Enviroment calculation cell-relax -relax_nmax 100 +relax_nmax 100 stress_thr 0.01 force_thr_ev 0.001 relax_method cg diff --git a/interfaces/DPGEN_interface/autotest/machine.json b/interfaces/DPGEN_interface/autotest/machine.json index 0d9c75af15a..30bf24d46cd 100644 --- a/interfaces/DPGEN_interface/autotest/machine.json +++ b/interfaces/DPGEN_interface/autotest/machine.json @@ -101,7 +101,7 @@ "queue_name": "CPU", "group_size": 2, "local_root":"./", - "source_list": ["/opt/intel/oneapi/setvars.sh"] + "source_list": ["/opt/intel/oneapi/setvars.sh"] } } ] diff --git a/interfaces/DPGEN_interface/autotest/property.json b/interfaces/DPGEN_interface/autotest/property.json index c90a77619e0..e3dc2fd93f6 100644 --- a/interfaces/DPGEN_interface/autotest/property.json +++ b/interfaces/DPGEN_interface/autotest/property.json @@ -5,7 +5,7 @@ "incar": "./INPUT", "potcar_prefix":"./", "potcars": {"Al": "Al.PD04.PBE.UPF"}, - "orb_files": {"Al":"Al_gga_10au_100Ry_3s3p2d.orb"} + "orb_files": {"Al":"Al_gga_10au_100Ry_3s3p2d.orb"} }, "_relaxation": { "cal_type": "relaxation", @@ -16,7 +16,7 @@ "properties": [ { "type": "eos", - "vol_start": 0.85, + "vol_start": 0.85, "vol_end": 1.15, "vol_step": 0.01, "cal_setting": { @@ -27,25 +27,25 @@ "type": "abacus", "incar": "./INPUT", "potcar_prefix":"./", - "orb_files": {"Al":"Al_gga_10au_100Ry_3s3p2d.orb"}, + "orb_files": {"Al":"Al_gga_10au_100Ry_3s3p2d.orb"}, "potcars": {"Al": "Al.PD04.PBE.UPF"} } } }, - { + { "type": "elastic", - "skip": false, + "skip": false, "norm_deform": 1e-2, "shear_deform": 1e-2 }, { "type": "vacancy", "skip": false, - "supercell": [2, 2, 2] + "supercell": [2, 2, 2] }, { "type": "surface", "skip": true, - "min_slab_size": 15, + "min_slab_size": 15, "min_vacuum_size":11, "pert_xz": 0.01, "max_miller": 3, diff --git a/interfaces/DPGEN_interface/init_and_run/INPUT.md b/interfaces/DPGEN_interface/init_and_run/INPUT.md index 4114899b341..cc084d738c0 100644 --- a/interfaces/DPGEN_interface/init_and_run/INPUT.md +++ b/interfaces/DPGEN_interface/init_and_run/INPUT.md @@ -1,29 +1,11 @@ -INPUT_PARAMETERS -#Parameters (1.General) -suffix ABACUS -calculation md -symmetry 1 -pseudo_dir ./ +INPUT_PARAMETERS #Parameters (1.General) suffix ABACUS calculation md symmetry 1 pseudo_dir ./ -#Parameters (2.Iteration) -ecutwfc 40 -scf_thr 1e-6 -scf_nmax 100 +#Parameters (2.Iteration) ecutwfc 40 scf_thr 1e-6 scf_nmax 100 +#Parameters (3.Basis) basis_type pw -#Parameters (3.Basis) -basis_type pw +#Parameters (4.Smearing) smearing_method gauss smearing_sigma 0.002 -#Parameters (4.Smearing) -smearing_method gauss -smearing_sigma 0.002 +#Parameters (5.Mixing) mixing_type broyden mixing_beta 0.7 -#Parameters (5.Mixing) -mixing_type broyden -mixing_beta 0.7 - -cal_stress 1 -md_nstep 3 -md_tfirst 10 -md_tfreq 0.1 -out_stru 1 +cal_stress 1 md_nstep 3 md_tfirst 10 md_tfreq 0.1 out_stru 1 diff --git a/interfaces/DPGEN_interface/init_and_run/init.json b/interfaces/DPGEN_interface/init_and_run/init.json index 0842e802fe3..547a5063f3c 100644 --- a/interfaces/DPGEN_interface/init_and_run/init.json +++ b/interfaces/DPGEN_interface/init_and_run/init.json @@ -1,23 +1,23 @@ { "init_fp_style": "ABACUS", "stages": [1,2,3,4], - "cell_type": "fcc", - "super_cell": [2, 1, 1], - "elements": ["Al"], - "from_poscar": true, - "from_poscar_path": "./Al.STRU", - "potcars": ["Al_ONCV_PBE-1.0.upf"], - "relax_incar": "INPUT", - "relax_kpt": "KPT", - "md_incar" : "INPUT.md", - "md_kpt" : "KPT", - "skip_relax": false, - "scale": [1.00], - "pert_numb": 10, - "md_nstep" : 10, - "pert_box": 0.01, - "pert_atom": 0.01, - "deepgen_templ": "../generator/template/", - "coll_ndata": 10, - "_comment": "that's all" + "cell_type": "fcc", + "super_cell": [2, 1, 1], + "elements": ["Al"], + "from_poscar": true, + "from_poscar_path": "./Al.STRU", + "potcars": ["Al_ONCV_PBE-1.0.upf"], + "relax_incar": "INPUT", + "relax_kpt": "KPT", + "md_incar" : "INPUT.md", + "md_kpt" : "KPT", + "skip_relax": false, + "scale": [1.00], + "pert_numb": 10, + "md_nstep" : 10, + "pert_box": 0.01, + "pert_atom": 0.01, + "deepgen_templ": "../generator/template/", + "coll_ndata": 10, + "_comment": "that's all" } diff --git a/interfaces/DPGEN_interface/init_and_run/machine.json b/interfaces/DPGEN_interface/init_and_run/machine.json index 0d9c75af15a..30bf24d46cd 100644 --- a/interfaces/DPGEN_interface/init_and_run/machine.json +++ b/interfaces/DPGEN_interface/init_and_run/machine.json @@ -101,7 +101,7 @@ "queue_name": "CPU", "group_size": 2, "local_root":"./", - "source_list": ["/opt/intel/oneapi/setvars.sh"] + "source_list": ["/opt/intel/oneapi/setvars.sh"] } } ] diff --git a/interfaces/HefeiNAMD_interface/README.md b/interfaces/HefeiNAMD_interface/README.md index 01026923ad5..71fef40a362 100644 --- a/interfaces/HefeiNAMD_interface/README.md +++ b/interfaces/HefeiNAMD_interface/README.md @@ -1,21 +1,34 @@ # Hefei-NAMD Interface -This directory contains the interface between ABACUS and Hefei-NAMD, an open-source, ab initio non-adiabatic molecular dynamics (NAMD) package designed for simulating ultrafast excited-state carrier dynamics in condensed-matter systems. +This directory contains the interface between ABACUS and Hefei-NAMD, an open-source, ab initio +non-adiabatic molecular dynamics (NAMD) package designed for simulating ultrafast excited-state +carrier dynamics in condensed-matter systems. ## What is Hefei-NAMD? -Hefei-NAMD is an open-source, ab initio non-adiabatic molecular dynamics (NAMD) package designed for simulating ultrafast excited-state carrier dynamics in condensed-matter systems (e.g., semiconductors, 2D materials, oxides, and interfaces) across real/momentum space, energy, and time domains. Developed primarily by Prof. Qijing Zheng (University of Science and Technology of China, USTC) and collaborators, it is hosted publicly on GitHub: [github.com/QijingZheng/Hefei-NAMD](https://github.com/QijingZheng/Hefei-NAMD). +Hefei-NAMD is an open-source, ab initio non-adiabatic molecular dynamics (NAMD) package designed for +simulating ultrafast excited-state carrier dynamics in condensed-matter systems (e.g., +semiconductors, 2D materials, oxides, and interfaces) across real/momentum space, energy, and time +domains. Developed primarily by Prof. Qijing Zheng (University of Science and Technology of China, +USTC) and collaborators, it is hosted publicly on GitHub: +[github.com/QijingZheng/Hefei-NAMD](https://github.com/QijingZheng/Hefei-NAMD). ### Core Methodology -- **Theoretical foundation**: Combines time-dependent density-functional theory (TDDFT) with the fewest-switches surface hopping (FSSH) algorithm and decoherence-induced surface hopping (DISH) to treat electron–phonon coupling and non-adiabatic transitions between electronic states. -- **Key quantities**: Computes non-adiabatic coupling (NAC) matrices and electron–phonon coupling (EPC) from first-principles wavefunctions. -- **Implementation**: Mainly written in Fortran (≈80%) with Python pre/post-processing tools; minimal external dependencies, easy to compile via make. +- **Theoretical foundation**: Combines time-dependent density-functional theory (TDDFT) with the + fewest-switches surface hopping (FSSH) algorithm and decoherence-induced surface hopping (DISH) to + treat electron–phonon coupling and non-adiabatic transitions between electronic states. +- **Key quantities**: Computes non-adiabatic coupling (NAC) matrices and electron–phonon coupling + (EPC) from first-principles wavefunctions. +- **Implementation**: Mainly written in Fortran (≈80%) with Python pre/post-processing tools; + minimal external dependencies, easy to compile via make. ### Key Features -- **Interfaces to major DFT codes**: Works natively with VASP and ABACUS (via abacus-namd scripts) to read MD trajectories, wavefunctions, and band structures. -- **Real- and momentum-space dynamics**: Supports carrier relaxation, recombination, hot-carrier transport, and exciton dynamics. +- **Interfaces to major DFT codes**: Works natively with VASP and ABACUS (via abacus-namd scripts) + to read MD trajectories, wavefunctions, and band structures. +- **Real- and momentum-space dynamics**: Supports carrier relaxation, recombination, hot-carrier + transport, and exciton dynamics. - **Advanced capabilities**: - Spin–orbit coupling (SOC) (via NAMDwithSOC extension). - Light–matter interaction (NAMD-LMI) for photoexcitation and stimulated emission. @@ -25,40 +38,48 @@ Hefei-NAMD is an open-source, ab initio non-adiabatic molecular dynamics (NAMD) ### Workflow 1. **Geometry optimization** → ab initio MD → trajectory snapshots. -2. **DFT single-points (SCF)** → wavefunction output. -3. **NAMD simulation** → analysis of carrier lifetime, relaxation pathways, etc. +1. **DFT single-points (SCF)** → wavefunction output. +1. **NAMD simulation** → analysis of carrier lifetime, relaxation pathways, etc. ### Applications -- **Carrier relaxation/recombination**: e.g., in TiO₂, perovskites, 2D van der Waals heterostructures. +- **Carrier relaxation/recombination**: e.g., in TiO₂, perovskites, 2D van der Waals + heterostructures. - **Hot-carrier dynamics and transport** in photovoltaics and photocatalysts. - **Exciton dissociation and charge transfer** at interfaces. - **Ultrafast spectroscopy** (transient absorption, photoluminescence) interpretation. ### Availability & Use -- **Open-source**: Free under academic license; source code, manual, tutorials, and examples are fully public. -- **Citation**: Users are requested to cite core publications (e.g., Zheng et al., WIREs Comput. Mol. Sci., 2021). +- **Open-source**: Free under academic license; source code, manual, tutorials, and examples are + fully public. +- **Citation**: Users are requested to cite core publications (e.g., Zheng et al., WIREs Comput. + Mol. Sci., 2021). -In short, Hefei-NAMD is a widely used, community-driven tool for first-principles excited-state dynamics in materials science, valued for its efficiency, flexibility, and compatibility with standard DFT workflows. +In short, Hefei-NAMD is a widely used, community-driven tool for first-principles excited-state +dynamics in materials science, valued for its efficiency, flexibility, and compatibility with +standard DFT workflows. ## ABACUS-Hefei-NAMD Interface -The ABACUS-Hefei-NAMD interface allows ABACUS to generate the necessary files for Hefei-NAMD calculations, including overlap matrices, wavefunctions, and Hamiltonian matrices. +The ABACUS-Hefei-NAMD interface allows ABACUS to generate the necessary files for Hefei-NAMD +calculations, including overlap matrices, wavefunctions, and Hamiltonian matrices. ### Key Parameters for ABACUS-Hefei-NAMD Interface: - `cal_syns`: Set to 1 to calculate asynchronous overlap matrix -- `dmax`: Maximum displacement of all atoms in one step (in bohr) for calculating asynchronous overlap matrix +- `dmax`: Maximum displacement of all atoms in one step (in bohr) for calculating asynchronous + overlap matrix - `out_wfc_lcao`: Set to 1 to output wavefunction files - `out_mat_hs`: Set to 1 to output Hamiltonian and overlap matrix files ### Examples -The `example01` directory contains a simple example demonstrating how to set up an ABACUS calculation that generates the necessary files for Hefei-NAMD. +The `example01` directory contains a simple example demonstrating how to set up an ABACUS +calculation that generates the necessary files for Hefei-NAMD. ### How to Use the Interface 1. Set up an ABACUS calculation with the appropriate parameters for Hefei-NAMD (see examples) -2. Run ABACUS to generate the necessary output files -3. Use the generated files as input for Hefei-NAMD calculations +1. Run ABACUS to generate the necessary output files +1. Use the generated files as input for Hefei-NAMD calculations diff --git a/interfaces/Phonopy_interface/README.md b/interfaces/Phonopy_interface/README.md index bf8c1f455ea..ef8fe20e8c9 100644 --- a/interfaces/Phonopy_interface/README.md +++ b/interfaces/Phonopy_interface/README.md @@ -1,10 +1,13 @@ # Phonopy Interface -This directory contains the interface between ABACUS and Phonopy, an open-source software for phonon calculations. Phonopy is widely used for calculating phonon dispersion relations, phonon density of states, and thermodynamic properties of materials. +This directory contains the interface between ABACUS and Phonopy, an open-source software for phonon +calculations. Phonopy is widely used for calculating phonon dispersion relations, phonon density of +states, and thermodynamic properties of materials. ## What is Phonopy? -Phonopy is an open-source software package for phonon calculations at harmonic and quasi-harmonic levels. It is designed to: +Phonopy is an open-source software package for phonon calculations at harmonic and quasi-harmonic +levels. It is designed to: - Calculate phonon dispersion relations - Compute phonon density of states (DOS) @@ -13,14 +16,17 @@ Phonopy is an open-source software package for phonon calculations at harmonic a - Support various first-principles calculation codes through interfaces Phonopy works by: + 1. Generating supercells with atomic displacements -2. Running force calculations for these displaced supercells -3. Fitting a force constant matrix from the calculated forces -4. Calculating phonon properties based on the force constants +1. Running force calculations for these displaced supercells +1. Fitting a force constant matrix from the calculated forces +1. Calculating phonon properties based on the force constants ## ABACUS-Phonopy Interface -The ABACUS-Phonopy interface allows ABACUS to be used as the force calculator for Phonopy. This enables users to perform phonon calculations using ABACUS's various basis sets (plane wave and LCAO) and functional choices. +The ABACUS-Phonopy interface allows ABACUS to be used as the force calculator for Phonopy. This +enables users to perform phonon calculations using ABACUS's various basis sets (plane wave and LCAO) +and functional choices. ### Key Features of the Interface @@ -31,7 +37,8 @@ The ABACUS-Phonopy interface allows ABACUS to be used as the force calculator fo ## Example -The `example01` directory contains a simple example demonstrating how to use the ABACUS-Phonopy interface to calculate phonons for aluminum (Al). +The `example01` directory contains a simple example demonstrating how to use the ABACUS-Phonopy +interface to calculate phonons for aluminum (Al). ### Example Files @@ -48,20 +55,24 @@ The `example01` directory contains a simple example demonstrating how to use the ### Prerequisites -1. **Install Phonopy**: Follow the installation instructions on the [Phonopy website](https://phonopy.github.io/phonopy/) -2. **Set up ABACUS**: Ensure ABACUS is compiled and accessible in your PATH -3. **Prepare input files**: Create INPUT, KPT, and STRU files for your system +1. **Install Phonopy**: Follow the installation instructions on the + [Phonopy website](https://phonopy.github.io/phonopy/) +1. **Set up ABACUS**: Ensure ABACUS is compiled and accessible in your PATH +1. **Prepare input files**: Create INPUT, KPT, and STRU files for your system ### Usage Notes -- For detailed instructions on using Phonopy with ABACUS, please refer to the [Phonopy documentation](https://phonopy.github.io/phonopy/) +- For detailed instructions on using Phonopy with ABACUS, please refer to the + [Phonopy documentation](https://phonopy.github.io/phonopy/) - The interface requires ABACUS to generate FORCE_ABACUS files in the OUT.ABACUS directory - Phonopy will use these force files to calculate phonon properties ## Troubleshooting -- **Force files not found**: Ensure ABACUS is generating FORCE_ABACUS files in the OUT.ABACUS directory -- **Phonopy cannot read ABACUS output**: Check that ABACUS is compiled with the necessary output options +- **Force files not found**: Ensure ABACUS is generating FORCE_ABACUS files in the OUT.ABACUS + directory +- **Phonopy cannot read ABACUS output**: Check that ABACUS is compiled with the necessary output + options - **Memory issues**: For large supercells, increase the memory allocation for ABACUS - **Convergence issues**: Ensure the SCF calculation is converged for each displaced supercell @@ -76,4 +87,5 @@ The `example01` directory contains a simple example demonstrating how to use the - The ABACUS-Phonopy interface is continuously being improved - For large systems, consider using parallel calculations to speed up the force calculations - Always check the convergence of your results with respect to supercell size and k-point sampling -- The example provided is for demonstration purposes; adjust parameters according to your specific system +- The example provided is for demonstration purposes; adjust parameters according to your specific + system diff --git a/interfaces/Phonopy_interface/example01/STRU-001 b/interfaces/Phonopy_interface/example01/STRU-001 index 82c6d126bb6..9dd0bd1426d 100644 --- a/interfaces/Phonopy_interface/example01/STRU-001 +++ b/interfaces/Phonopy_interface/example01/STRU-001 @@ -1,5 +1,5 @@ ATOMIC_SPECIES -Al 26.9815386 Al.PD04.PBE.UPF +Al 26.9815386 Al.PD04.PBE.UPF NUMERICAL_ORBITAL Al_gga_10au_100Ry_3s3p2d.orb diff --git a/interfaces/ShengBTE_interface/01_pw/2nd/au2si.py b/interfaces/ShengBTE_interface/01_pw/2nd/au2si.py index 0068de50b9f..7d8c0c1920d 100644 --- a/interfaces/ShengBTE_interface/01_pw/2nd/au2si.py +++ b/interfaces/ShengBTE_interface/01_pw/2nd/au2si.py @@ -1,14 +1,14 @@ Bohr2Ang = 0.529177208 -with open('FORCE_CONSTANTS', 'r') as f1: +with open("FORCE_CONSTANTS", "r") as f1: fc = f1.readlines() -with open('FORCE_CONSTANTS_2ND', 'w') as f2: +with open("FORCE_CONSTANTS_2ND", "w") as f2: for idx, ii in enumerate(fc): char = ii.split() if len(char) == 3: for idy, jj in enumerate(char): char[idy] = str(float(jj) / Bohr2Ang) - bloks = ' ' + bloks = " " fc[idx] = bloks.join(char) - fc[idx] = fc[idx] + '\n' + fc[idx] = fc[idx] + "\n" f2.write(fc[idx]) diff --git a/interfaces/ShengBTE_interface/01_pw/3rd/aba2vasp.py b/interfaces/ShengBTE_interface/01_pw/3rd/aba2vasp.py index 3a8e1b72f16..f97fe1593ad 100644 --- a/interfaces/ShengBTE_interface/01_pw/3rd/aba2vasp.py +++ b/interfaces/ShengBTE_interface/01_pw/3rd/aba2vasp.py @@ -2,41 +2,50 @@ import dpdata import glob -def prettyXml(element, indent, newline, level = 0): - if element: - if element.text == None or element.text.isspace(): - element.text = newline + indent * (level + 1) - else: - element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * (level + 1) - temp = list(element) - for subelement in temp: - if temp.index(subelement) < (len(temp) - 1): - subelement.tail = newline + indent * (level + 1) - else: - subelement.tail = newline + indent * level - prettyXml(subelement, indent, newline, level = level + 1) + +def prettyXml(element, indent, newline, level=0): + if element: + if element.text == None or element.text.isspace(): + element.text = newline + indent * (level + 1) + else: + element.text = ( + newline + + indent * (level + 1) + + element.text.strip() + + newline + + indent * (level + 1) + ) + temp = list(element) + for subelement in temp: + if temp.index(subelement) < (len(temp) - 1): + subelement.tail = newline + indent * (level + 1) + else: + subelement.tail = newline + indent * level + prettyXml(subelement, indent, newline, level=level + 1) + def generate_xml(force, suffix): - ''' + """ force : natom*3 eV/Angstrom - ''' - root = ET.Element('modeling') - head = ET.SubElement(root, 'calculation') - title = ET.SubElement(head, 'varray') - title.set('name',"forces") + """ + root = ET.Element("modeling") + head = ET.SubElement(root, "calculation") + title = ET.SubElement(head, "varray") + title.set("name", "forces") for ii in force: - body = ET.SubElement(title, 'v') - body.text = str(ii[0]) + ' ' + str(ii[1]) + ' ' + str(ii[2]) + body = ET.SubElement(title, "v") + body.text = str(ii[0]) + " " + str(ii[1]) + " " + str(ii[2]) tree = ET.ElementTree(root) - prettyXml(root, '\t', '\n') + prettyXml(root, "\t", "\n") + + name_xml = suffix + "/vasprun.xml" + tree.write(name_xml, encoding="utf-8") - name_xml = suffix + '/vasprun.xml' - tree.write(name_xml, encoding = 'utf-8') -if __name__ == '__main__': - log = glob.glob('SCF-*') +if __name__ == "__main__": + log = glob.glob("SCF-*") for ii in log: - out = dpdata.LabeledSystem(ii, fmt='abacus/scf') + out = dpdata.LabeledSystem(ii, fmt="abacus/scf") print(ii) - generate_xml(out["forces"].reshape(-1,3), ii) \ No newline at end of file + generate_xml(out["forces"].reshape(-1, 3), ii) diff --git a/interfaces/ShengBTE_interface/01_pw/3rd/pos2stru.py b/interfaces/ShengBTE_interface/01_pw/3rd/pos2stru.py index 6ecc2a1150c..203cfefd71a 100644 --- a/interfaces/ShengBTE_interface/01_pw/3rd/pos2stru.py +++ b/interfaces/ShengBTE_interface/01_pw/3rd/pos2stru.py @@ -2,18 +2,17 @@ from ase.io import read, write from pathlib import Path -pos = glob.glob('3RD.POSCAR.*') +pos = glob.glob("3RD.POSCAR.*") for ii in pos: - idx = ii.split('.')[-1] + idx = ii.split(".")[-1] print(ii, idx) - cs_dir = './' + cs_dir = "./" cs_vasp = Path(cs_dir, ii) - cs_atoms = read(cs_vasp, format='vasp') - stru = 'STRU_' + str(idx) + cs_atoms = read(cs_vasp, format="vasp") + stru = "STRU_" + str(idx) print(stru) cs_stru = Path(cs_dir, stru) - pp = {'Si':'Si_ONCV_PBE-1.2.upf'} - write(cs_stru, cs_atoms, format='abacus', pp=pp) + pp = {"Si": "Si_ONCV_PBE-1.2.upf"} + write(cs_stru, cs_atoms, format="abacus", pp=pp) # basis = {'Si':'Si_gga_7au_100Ry_2s2p1d.orb'} # write(cs_stru, cs_atoms, format='abacus', pp=pp, basis=basis) - \ No newline at end of file diff --git a/interfaces/ShengBTE_interface/02_lcao/2nd/au2si.py b/interfaces/ShengBTE_interface/02_lcao/2nd/au2si.py index 0068de50b9f..7d8c0c1920d 100644 --- a/interfaces/ShengBTE_interface/02_lcao/2nd/au2si.py +++ b/interfaces/ShengBTE_interface/02_lcao/2nd/au2si.py @@ -1,14 +1,14 @@ Bohr2Ang = 0.529177208 -with open('FORCE_CONSTANTS', 'r') as f1: +with open("FORCE_CONSTANTS", "r") as f1: fc = f1.readlines() -with open('FORCE_CONSTANTS_2ND', 'w') as f2: +with open("FORCE_CONSTANTS_2ND", "w") as f2: for idx, ii in enumerate(fc): char = ii.split() if len(char) == 3: for idy, jj in enumerate(char): char[idy] = str(float(jj) / Bohr2Ang) - bloks = ' ' + bloks = " " fc[idx] = bloks.join(char) - fc[idx] = fc[idx] + '\n' + fc[idx] = fc[idx] + "\n" f2.write(fc[idx]) diff --git a/interfaces/ShengBTE_interface/02_lcao/3rd/aba2vasp.py b/interfaces/ShengBTE_interface/02_lcao/3rd/aba2vasp.py index 3a8e1b72f16..f97fe1593ad 100644 --- a/interfaces/ShengBTE_interface/02_lcao/3rd/aba2vasp.py +++ b/interfaces/ShengBTE_interface/02_lcao/3rd/aba2vasp.py @@ -2,41 +2,50 @@ import dpdata import glob -def prettyXml(element, indent, newline, level = 0): - if element: - if element.text == None or element.text.isspace(): - element.text = newline + indent * (level + 1) - else: - element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * (level + 1) - temp = list(element) - for subelement in temp: - if temp.index(subelement) < (len(temp) - 1): - subelement.tail = newline + indent * (level + 1) - else: - subelement.tail = newline + indent * level - prettyXml(subelement, indent, newline, level = level + 1) + +def prettyXml(element, indent, newline, level=0): + if element: + if element.text == None or element.text.isspace(): + element.text = newline + indent * (level + 1) + else: + element.text = ( + newline + + indent * (level + 1) + + element.text.strip() + + newline + + indent * (level + 1) + ) + temp = list(element) + for subelement in temp: + if temp.index(subelement) < (len(temp) - 1): + subelement.tail = newline + indent * (level + 1) + else: + subelement.tail = newline + indent * level + prettyXml(subelement, indent, newline, level=level + 1) + def generate_xml(force, suffix): - ''' + """ force : natom*3 eV/Angstrom - ''' - root = ET.Element('modeling') - head = ET.SubElement(root, 'calculation') - title = ET.SubElement(head, 'varray') - title.set('name',"forces") + """ + root = ET.Element("modeling") + head = ET.SubElement(root, "calculation") + title = ET.SubElement(head, "varray") + title.set("name", "forces") for ii in force: - body = ET.SubElement(title, 'v') - body.text = str(ii[0]) + ' ' + str(ii[1]) + ' ' + str(ii[2]) + body = ET.SubElement(title, "v") + body.text = str(ii[0]) + " " + str(ii[1]) + " " + str(ii[2]) tree = ET.ElementTree(root) - prettyXml(root, '\t', '\n') + prettyXml(root, "\t", "\n") + + name_xml = suffix + "/vasprun.xml" + tree.write(name_xml, encoding="utf-8") - name_xml = suffix + '/vasprun.xml' - tree.write(name_xml, encoding = 'utf-8') -if __name__ == '__main__': - log = glob.glob('SCF-*') +if __name__ == "__main__": + log = glob.glob("SCF-*") for ii in log: - out = dpdata.LabeledSystem(ii, fmt='abacus/scf') + out = dpdata.LabeledSystem(ii, fmt="abacus/scf") print(ii) - generate_xml(out["forces"].reshape(-1,3), ii) \ No newline at end of file + generate_xml(out["forces"].reshape(-1, 3), ii) diff --git a/interfaces/ShengBTE_interface/02_lcao/3rd/pos2stru.py b/interfaces/ShengBTE_interface/02_lcao/3rd/pos2stru.py index 527d44cfbb8..6fbdad42eca 100644 --- a/interfaces/ShengBTE_interface/02_lcao/3rd/pos2stru.py +++ b/interfaces/ShengBTE_interface/02_lcao/3rd/pos2stru.py @@ -2,18 +2,17 @@ from ase.io import read, write from pathlib import Path -pos = glob.glob('3RD.POSCAR.*') +pos = glob.glob("3RD.POSCAR.*") for ii in pos: - idx = ii.split('.')[-1] + idx = ii.split(".")[-1] print(ii, idx) - cs_dir = './' + cs_dir = "./" cs_vasp = Path(cs_dir, ii) - cs_atoms = read(cs_vasp, format='vasp') - stru = 'STRU_' + str(idx) + cs_atoms = read(cs_vasp, format="vasp") + stru = "STRU_" + str(idx) print(stru) cs_stru = Path(cs_dir, stru) - pp = {'Si':'Si_ONCV_PBE-1.0.upf'} + pp = {"Si": "Si_ONCV_PBE-1.0.upf"} # write(cs_stru, cs_atoms, format='abacus', pp=pp) - basis = {'Si':'Si_gga_7au_100Ry_2s2p1d.orb'} - write(cs_stru, cs_atoms, format='abacus', pp=pp, basis=basis) - \ No newline at end of file + basis = {"Si": "Si_gga_7au_100Ry_2s2p1d.orb"} + write(cs_stru, cs_atoms, format="abacus", pp=pp, basis=basis) diff --git a/interfaces/ShengBTE_interface/README.md b/interfaces/ShengBTE_interface/README.md index 4f2a1cb5194..41318e4b688 100644 --- a/interfaces/ShengBTE_interface/README.md +++ b/interfaces/ShengBTE_interface/README.md @@ -1,10 +1,12 @@ # ShengBTE Interface -This directory contains the interface between ABACUS and ShengBTE, an open-source code for calculating lattice thermal conductivity using the Boltzmann Transport Equation (BTE). +This directory contains the interface between ABACUS and ShengBTE, an open-source code for +calculating lattice thermal conductivity using the Boltzmann Transport Equation (BTE). ## What is ShengBTE? -ShengBTE is an open-source code that calculates lattice thermal conductivity from first principles using the Boltzmann Transport Equation (BTE). It is designed to: +ShengBTE is an open-source code that calculates lattice thermal conductivity from first principles +using the Boltzmann Transport Equation (BTE). It is designed to: - Calculate lattice thermal conductivity - Compute phonon dispersion relations @@ -13,6 +15,7 @@ ShengBTE is an open-source code that calculates lattice thermal conductivity fro - Support various first-principles calculation codes through interfaces ShengBTE is particularly useful for: + - Studying thermal transport in materials - Designing materials with specific thermal properties - Understanding phonon scattering mechanisms @@ -36,9 +39,11 @@ The ABACUS-ShengBTE interface allows ABACUS to generate the necessary files for ## Examples -This directory contains two examples demonstrating different use cases of the ABACUS-ShengBTE interface: +This directory contains two examples demonstrating different use cases of the ABACUS-ShengBTE +interface: ### 1. 01_pw + - **System**: Silicon (Si) - **Basis**: Plane wave (PW) - **Purpose**: Demonstrates ShengBTE calculation using plane wave basis set @@ -48,6 +53,7 @@ This directory contains two examples demonstrating different use cases of the AB - Scripts for running the calculation ### 2. 02_lcao + - **System**: Silicon (Si) - **Basis**: LCAO (Linear Combination of Atomic Orbitals) - **Purpose**: Demonstrates ShengBTE calculation using LCAO basis set @@ -60,23 +66,27 @@ This directory contains two examples demonstrating different use cases of the AB ### Prerequisites -1. **Install ShengBTE**: Follow the installation instructions on the [ShengBTE website](https://shengbte.org/) -2. **Set up ABACUS**: Ensure ABACUS is compiled with ShengBTE support -3. **Prepare input files**: Create ABACUS input files and ShengBTE input files +1. **Install ShengBTE**: Follow the installation instructions on the + [ShengBTE website](https://shengbte.org/) +1. **Set up ABACUS**: Ensure ABACUS is compiled with ShengBTE support +1. **Prepare input files**: Create ABACUS input files and ShengBTE input files ### Basic Workflow 1. **Run ABACUS calculations to generate force constants**: + - Calculate second-order force constants - Calculate third-order force constants - This will generate files containing the force constant information -2. **Prepare ShengBTE input files**: +1. **Prepare ShengBTE input files**: + - Create `control.f90` file with calculation parameters - Create `structure.f90` file with crystal structure information - Create `BTE.out` file with initial conditions -3. **Run ShengBTE**: +1. **Run ShengBTE**: + - Use the force constants from ABACUS as input - This will calculate the lattice thermal conductivity @@ -89,7 +99,8 @@ This directory contains two examples demonstrating different use cases of the AB ## Troubleshooting - **Force constants not found**: Ensure ABACUS is generating the necessary force constant files -- **ShengBTE cannot read ABACUS output**: Check that the force constant files are in the correct format +- **ShengBTE cannot read ABACUS output**: Check that the force constant files are in the correct + format - **Convergence issues**: Ensure the force constant calculations are properly converged ## References diff --git a/interfaces/Wannier90_interface/README.md b/interfaces/Wannier90_interface/README.md index ff2ba9e71ae..e69ab7431ed 100644 --- a/interfaces/Wannier90_interface/README.md +++ b/interfaces/Wannier90_interface/README.md @@ -1,9 +1,13 @@ # A Brief Introduction to ABACUS Wannier90 Interface -This package provides a user-friendly Python interface: abacusw90 to bridge **ABACUS** (Atomic-scale Simulation Package) with **Wannier90**. It automates the workflow of generating Maximally Localized Wannier Functions (MLWFs) and tight-binding models from ABACUS calculations. + +This package provides a user-friendly Python interface: abacusw90 to bridge **ABACUS** (Atomic-scale +Simulation Package) with **Wannier90**. It automates the workflow of generating Maximally Localized +Wannier Functions (MLWFs) and tight-binding models from ABACUS calculations. ## What is Wannier90? -Wannier90 is an open-source code that calculates maximally localized Wannier functions (MLWFs) from first-principles calculations. It is designed to: +Wannier90 is an open-source code that calculates maximally localized Wannier functions (MLWFs) from +first-principles calculations. It is designed to: - Generate maximally localized Wannier functions - Calculate band structures and density of states @@ -12,6 +16,7 @@ Wannier90 is an open-source code that calculates maximally localized Wannier fun - Support various first-principles calculation codes through interfaces Wannier functions are particularly useful for: + - Electronic structure calculations - Transport properties - Spectroscopy calculations @@ -26,17 +31,22 @@ The abacusw90 package allows ABACUS to generate the necessary files for Wannier9 - `UNK*` files: Bloch wavefunctions ## Key features + - **Various Basis Sets**: Support for both plane wave (PW) and LCAO basis sets. -- **Automated Workflow**: Handles the core coupling pipeline (Steps 3-5 of the standard tutorial workflow). +- **Automated Workflow**: Handles the core coupling pipeline (Steps 3-5 of the standard tutorial + workflow). - **Input Generation**: Automatically generates `wannier90.win`, `INPUT`, `KPT`, and `STRU` files. -- **Method Support**: Supports the recommended `wannier_method = 2` for efficient overlap matrix calculation. +- **Method Support**: Supports the recommended `wannier_method = 2` for efficient overlap matrix + calculation. - **Spin-Orbit Coupling**: Full support for SOC calculations (`nspin=4`, `lspinorb=1`). ## Examples -This directory contains three examples demonstrating different use cases of the ABACUS-Wannier90 interface: +This directory contains three examples demonstrating different use cases of the ABACUS-Wannier90 +interface: ### 1. 01_lcao + - **System**: Diamond (C) - **Basis**: LCAO (Linear Combination of Atomic Orbitals) - **Purpose**: Demonstrates Wannier90 calculation using LCAO basis set @@ -50,36 +60,47 @@ This directory contains three examples demonstrating different use cases of the - `diamond.nnkp`: Wannier90 preprocessing file ### 2. 02_pw + - **System**: Diamond (C) - **Basis**: Plane wave (PW) - **Purpose**: Demonstrates Wannier90 calculation using plane wave basis set - **Input Files**: Similar to 01_lcao, but configured for plane wave basis ### 3. 03_lcao_in_pw + - **System**: Diamond (C) - **Basis**: LCAO in plane wave mode - **Purpose**: Demonstrates Wannier90 calculation using LCAO basis set in plane wave mode - **Input Files**: Similar to 01_lcao, but configured for LCAO in plane wave mode # How to Use abacusw90 + ## Installation + ```bash pip install . # Or for development pip install -e . ``` + ## Workflow Scope -This interface automates the technical coupling steps between ABACUS and Wannier90. In the context of the standard tutorial workflow, it covers the following stages: -| Step | Description | Responsibility | -| :--- | :--- | :--- | -| **Automated** | **Step 1**: ABACUS SCF Calculation | **Interface Step 0** | -| **Prerequisite** | **Step 2**: Determine Energy Windows | User provides `dis_win` parameters | -| **Automated** | **Step 3**: Generate `wannier90.win` & Run `-pp` | **Interface Step 1** | -| **Automated** | **Step 4**: ABACUS NSCF (Interface Mode) | **Interface Step 2 & 3** | -| **Automated** | **Step 5**: Wannier90 Minimization | **Interface Step 4** | -| **Post-process** | **Step 6**: WannierTools Analysis | User (Downstream tool) | + +This interface automates the technical coupling steps between ABACUS and Wannier90. In the context +of the standard tutorial workflow, it covers the following stages: + +| Step | Description | Responsibility | +| :--------------- | :----------------------------------------------- | :--------------------------------- | +| **Automated** | **Step 1**: ABACUS SCF Calculation | **Interface Step 0** | +| **Prerequisite** | **Step 2**: Determine Energy Windows | User provides `dis_win` parameters | +| **Automated** | **Step 3**: Generate `wannier90.win` & Run `-pp` | **Interface Step 1** | +| **Automated** | **Step 4**: ABACUS NSCF (Interface Mode) | **Interface Step 2 & 3** | +| **Automated** | **Step 5**: Wannier90 Minimization | **Interface Step 4** | +| **Post-process** | **Step 6**: WannierTools Analysis | User (Downstream tool) | + ## Quick Start + Here is an example of generating Wannier functions for Bi2Se3: + ```python from abacusw90 import ABACUSWannier90 # 1. Initialize @@ -115,13 +136,19 @@ job.run() ``` ## Detailed Workflow Steps + The `run()` method executes the following automated sequence: -1. **Generate Inputs & Preprocess**: Write `wannier90.win` and execute `wannier90 -pp` to generate `.nnkp`. -2. **Prepare ABACUS**: Parse `.nnkp` to generate ABACUS `KPT`, `INPUT`, and `STRU` files. Copy SCF charge densities. -3. **Run ABACUS Interface**: Execute ABACUS in NSCF mode with `towannier90=1`. This generates `mmn`, `amn`, `eig` files. -4. **Run Wannier90**: Execute `wannier90.x` to compute MLWFs and output `wannier90_hr.dat`. + +1. **Generate Inputs & Preprocess**: Write `wannier90.win` and execute `wannier90 -pp` to generate + `.nnkp`. +1. **Prepare ABACUS**: Parse `.nnkp` to generate ABACUS `KPT`, `INPUT`, and `STRU` files. Copy SCF + charge densities. +1. **Run ABACUS Interface**: Execute ABACUS in NSCF mode with `towannier90=1`. This generates `mmn`, + `amn`, `eig` files. +1. **Run Wannier90**: Execute `wannier90.x` to compute MLWFs and output `wannier90_hr.dat`. ## Requirements + - **ABACUS**: v3.0 or higher (with Wannier90 interface support). - **Wannier90**: v3.0 or higher. - **Python**: 3.8+ @@ -129,13 +156,17 @@ The `run()` method executes the following automated sequence: # Important Notes - The k-point grid in the ABACUS NSCF calculation must match the one in the Wannier90 input file -- Set `wvfn_formatted = .true.` in the Wannier90 input file to ensure compatibility with ABACUS output -- For LCAO calculations, ensure that the orbital basis set is appropriate for the Wannier functions you want to generate +- Set `wvfn_formatted = .true.` in the Wannier90 input file to ensure compatibility with ABACUS + output +- For LCAO calculations, ensure that the orbital basis set is appropriate for the Wannier functions + you want to generate # Troubleshooting -- **Files not found**: Ensure ABACUS is generating `*.amn`, `*.mmn`, and `UNK*` files in the OUT.* directory -- **Wannier90 cannot read ABACUS output**: Check that `wvfn_formatted = .true.` is set in the Wannier90 input file +- **Files not found**: Ensure ABACUS is generating `*.amn`, `*.mmn`, and `UNK*` files in the OUT.\* + directory +- **Wannier90 cannot read ABACUS output**: Check that `wvfn_formatted = .true.` is set in the + Wannier90 input file - **Convergence issues**: Ensure the SCF and NSCF calculations are properly converged # References diff --git a/interfaces/Wannier90_interface/abacusw90/README.md b/interfaces/Wannier90_interface/abacusw90/README.md index ff2ba9e71ae..e69ab7431ed 100644 --- a/interfaces/Wannier90_interface/abacusw90/README.md +++ b/interfaces/Wannier90_interface/abacusw90/README.md @@ -1,9 +1,13 @@ # A Brief Introduction to ABACUS Wannier90 Interface -This package provides a user-friendly Python interface: abacusw90 to bridge **ABACUS** (Atomic-scale Simulation Package) with **Wannier90**. It automates the workflow of generating Maximally Localized Wannier Functions (MLWFs) and tight-binding models from ABACUS calculations. + +This package provides a user-friendly Python interface: abacusw90 to bridge **ABACUS** (Atomic-scale +Simulation Package) with **Wannier90**. It automates the workflow of generating Maximally Localized +Wannier Functions (MLWFs) and tight-binding models from ABACUS calculations. ## What is Wannier90? -Wannier90 is an open-source code that calculates maximally localized Wannier functions (MLWFs) from first-principles calculations. It is designed to: +Wannier90 is an open-source code that calculates maximally localized Wannier functions (MLWFs) from +first-principles calculations. It is designed to: - Generate maximally localized Wannier functions - Calculate band structures and density of states @@ -12,6 +16,7 @@ Wannier90 is an open-source code that calculates maximally localized Wannier fun - Support various first-principles calculation codes through interfaces Wannier functions are particularly useful for: + - Electronic structure calculations - Transport properties - Spectroscopy calculations @@ -26,17 +31,22 @@ The abacusw90 package allows ABACUS to generate the necessary files for Wannier9 - `UNK*` files: Bloch wavefunctions ## Key features + - **Various Basis Sets**: Support for both plane wave (PW) and LCAO basis sets. -- **Automated Workflow**: Handles the core coupling pipeline (Steps 3-5 of the standard tutorial workflow). +- **Automated Workflow**: Handles the core coupling pipeline (Steps 3-5 of the standard tutorial + workflow). - **Input Generation**: Automatically generates `wannier90.win`, `INPUT`, `KPT`, and `STRU` files. -- **Method Support**: Supports the recommended `wannier_method = 2` for efficient overlap matrix calculation. +- **Method Support**: Supports the recommended `wannier_method = 2` for efficient overlap matrix + calculation. - **Spin-Orbit Coupling**: Full support for SOC calculations (`nspin=4`, `lspinorb=1`). ## Examples -This directory contains three examples demonstrating different use cases of the ABACUS-Wannier90 interface: +This directory contains three examples demonstrating different use cases of the ABACUS-Wannier90 +interface: ### 1. 01_lcao + - **System**: Diamond (C) - **Basis**: LCAO (Linear Combination of Atomic Orbitals) - **Purpose**: Demonstrates Wannier90 calculation using LCAO basis set @@ -50,36 +60,47 @@ This directory contains three examples demonstrating different use cases of the - `diamond.nnkp`: Wannier90 preprocessing file ### 2. 02_pw + - **System**: Diamond (C) - **Basis**: Plane wave (PW) - **Purpose**: Demonstrates Wannier90 calculation using plane wave basis set - **Input Files**: Similar to 01_lcao, but configured for plane wave basis ### 3. 03_lcao_in_pw + - **System**: Diamond (C) - **Basis**: LCAO in plane wave mode - **Purpose**: Demonstrates Wannier90 calculation using LCAO basis set in plane wave mode - **Input Files**: Similar to 01_lcao, but configured for LCAO in plane wave mode # How to Use abacusw90 + ## Installation + ```bash pip install . # Or for development pip install -e . ``` + ## Workflow Scope -This interface automates the technical coupling steps between ABACUS and Wannier90. In the context of the standard tutorial workflow, it covers the following stages: -| Step | Description | Responsibility | -| :--- | :--- | :--- | -| **Automated** | **Step 1**: ABACUS SCF Calculation | **Interface Step 0** | -| **Prerequisite** | **Step 2**: Determine Energy Windows | User provides `dis_win` parameters | -| **Automated** | **Step 3**: Generate `wannier90.win` & Run `-pp` | **Interface Step 1** | -| **Automated** | **Step 4**: ABACUS NSCF (Interface Mode) | **Interface Step 2 & 3** | -| **Automated** | **Step 5**: Wannier90 Minimization | **Interface Step 4** | -| **Post-process** | **Step 6**: WannierTools Analysis | User (Downstream tool) | + +This interface automates the technical coupling steps between ABACUS and Wannier90. In the context +of the standard tutorial workflow, it covers the following stages: + +| Step | Description | Responsibility | +| :--------------- | :----------------------------------------------- | :--------------------------------- | +| **Automated** | **Step 1**: ABACUS SCF Calculation | **Interface Step 0** | +| **Prerequisite** | **Step 2**: Determine Energy Windows | User provides `dis_win` parameters | +| **Automated** | **Step 3**: Generate `wannier90.win` & Run `-pp` | **Interface Step 1** | +| **Automated** | **Step 4**: ABACUS NSCF (Interface Mode) | **Interface Step 2 & 3** | +| **Automated** | **Step 5**: Wannier90 Minimization | **Interface Step 4** | +| **Post-process** | **Step 6**: WannierTools Analysis | User (Downstream tool) | + ## Quick Start + Here is an example of generating Wannier functions for Bi2Se3: + ```python from abacusw90 import ABACUSWannier90 # 1. Initialize @@ -115,13 +136,19 @@ job.run() ``` ## Detailed Workflow Steps + The `run()` method executes the following automated sequence: -1. **Generate Inputs & Preprocess**: Write `wannier90.win` and execute `wannier90 -pp` to generate `.nnkp`. -2. **Prepare ABACUS**: Parse `.nnkp` to generate ABACUS `KPT`, `INPUT`, and `STRU` files. Copy SCF charge densities. -3. **Run ABACUS Interface**: Execute ABACUS in NSCF mode with `towannier90=1`. This generates `mmn`, `amn`, `eig` files. -4. **Run Wannier90**: Execute `wannier90.x` to compute MLWFs and output `wannier90_hr.dat`. + +1. **Generate Inputs & Preprocess**: Write `wannier90.win` and execute `wannier90 -pp` to generate + `.nnkp`. +1. **Prepare ABACUS**: Parse `.nnkp` to generate ABACUS `KPT`, `INPUT`, and `STRU` files. Copy SCF + charge densities. +1. **Run ABACUS Interface**: Execute ABACUS in NSCF mode with `towannier90=1`. This generates `mmn`, + `amn`, `eig` files. +1. **Run Wannier90**: Execute `wannier90.x` to compute MLWFs and output `wannier90_hr.dat`. ## Requirements + - **ABACUS**: v3.0 or higher (with Wannier90 interface support). - **Wannier90**: v3.0 or higher. - **Python**: 3.8+ @@ -129,13 +156,17 @@ The `run()` method executes the following automated sequence: # Important Notes - The k-point grid in the ABACUS NSCF calculation must match the one in the Wannier90 input file -- Set `wvfn_formatted = .true.` in the Wannier90 input file to ensure compatibility with ABACUS output -- For LCAO calculations, ensure that the orbital basis set is appropriate for the Wannier functions you want to generate +- Set `wvfn_formatted = .true.` in the Wannier90 input file to ensure compatibility with ABACUS + output +- For LCAO calculations, ensure that the orbital basis set is appropriate for the Wannier functions + you want to generate # Troubleshooting -- **Files not found**: Ensure ABACUS is generating `*.amn`, `*.mmn`, and `UNK*` files in the OUT.* directory -- **Wannier90 cannot read ABACUS output**: Check that `wvfn_formatted = .true.` is set in the Wannier90 input file +- **Files not found**: Ensure ABACUS is generating `*.amn`, `*.mmn`, and `UNK*` files in the OUT.\* + directory +- **Wannier90 cannot read ABACUS output**: Check that `wvfn_formatted = .true.` is set in the + Wannier90 input file - **Convergence issues**: Ensure the SCF and NSCF calculations are properly converged # References diff --git a/interfaces/Wannier90_interface/abacusw90/interface.py b/interfaces/Wannier90_interface/abacusw90/interface.py index 2c4e793c08e..9ddfba0633b 100644 --- a/interfaces/Wannier90_interface/abacusw90/interface.py +++ b/interfaces/Wannier90_interface/abacusw90/interface.py @@ -30,9 +30,7 @@ class ABACUSWannier90: # Internal objects _wannier_input: Optional[io_utils.Wannier90Input] = field(default=None, init=False) _abacus_input: Optional[io_utils.AbacusInput] = field(default=None, init=False) - _scf_input: Optional[io_utils.AbacusInput] = field( - default=None, init=False - ) + _scf_input: Optional[io_utils.AbacusInput] = field(default=None, init=False) def __post_init__(self): self.work_dir = Path(self.work_dir) diff --git a/interfaces/Wannier90_interface/examples/01_lcao/STRU b/interfaces/Wannier90_interface/examples/01_lcao/STRU index 96bfb06a13f..7003761779b 100644 --- a/interfaces/Wannier90_interface/examples/01_lcao/STRU +++ b/interfaces/Wannier90_interface/examples/01_lcao/STRU @@ -14,7 +14,7 @@ LATTICE_VECTORS ATOMIC_POSITIONS Direct -C +C 0.0 2 0.875 0.875 0.875 0 0 0 diff --git a/interfaces/Wannier90_interface/examples/02_pw/STRU b/interfaces/Wannier90_interface/examples/02_pw/STRU index 01e5b354ab5..7aea1630a52 100644 --- a/interfaces/Wannier90_interface/examples/02_pw/STRU +++ b/interfaces/Wannier90_interface/examples/02_pw/STRU @@ -11,7 +11,7 @@ LATTICE_VECTORS ATOMIC_POSITIONS Direct -C +C 0.0 2 0.875 0.875 0.875 0 0 0 diff --git a/interfaces/Wannier90_interface/examples/03_lcao_in_pw/STRU b/interfaces/Wannier90_interface/examples/03_lcao_in_pw/STRU index 96bfb06a13f..7003761779b 100644 --- a/interfaces/Wannier90_interface/examples/03_lcao_in_pw/STRU +++ b/interfaces/Wannier90_interface/examples/03_lcao_in_pw/STRU @@ -14,7 +14,7 @@ LATTICE_VECTORS ATOMIC_POSITIONS Direct -C +C 0.0 2 0.875 0.875 0.875 0 0 0 diff --git a/interfaces/Wannier90_interface/examples_python/example_advanced.py b/interfaces/Wannier90_interface/examples_python/example_advanced.py index 0855a7fb01f..f4afbd3adce 100644 --- a/interfaces/Wannier90_interface/examples_python/example_advanced.py +++ b/interfaces/Wannier90_interface/examples_python/example_advanced.py @@ -65,8 +65,14 @@ def main(): # ---------------------------------------------------------- # 3. Dependency files # ---------------------------------------------------------- - job.pp_orbitals = {"Bi": "../../../tests/PP_ORB/Bi_pbe_fr.upf", "Se": "../../../tests/PP_ORB/Se_pbe_fr.upf"} - job.orbital_files = ["../../../tests/PP_ORB/Bi_gga_10au_100Ry_2s2p2d.orb", "../../../tests/PP_ORB/Se_gga_10au_100Ry_2s2p2d.orb"] + job.pp_orbitals = { + "Bi": "../../../tests/PP_ORB/Bi_pbe_fr.upf", + "Se": "../../../tests/PP_ORB/Se_pbe_fr.upf", + } + job.orbital_files = [ + "../../../tests/PP_ORB/Bi_gga_10au_100Ry_2s2p2d.orb", + "../../../tests/PP_ORB/Se_gga_10au_100Ry_2s2p2d.orb", + ] # ---------------------------------------------------------- # 4. Advanced Parameter Configuration diff --git a/interfaces/Wannier90_interface/examples_python/example_basic.py b/interfaces/Wannier90_interface/examples_python/example_basic.py index 0943f623a3e..66686f35324 100644 --- a/interfaces/Wannier90_interface/examples_python/example_basic.py +++ b/interfaces/Wannier90_interface/examples_python/example_basic.py @@ -65,8 +65,14 @@ def main(): # ---------------------------------------------------------- # 3. Dependency files # ---------------------------------------------------------- - job.pp_orbitals = {"Bi": "../../../tests/PP_ORB/Bi_pbe_fr.upf", "Se": "../../../tests/PP_ORB/Se_pbe_fr.upf"} - job.orbital_files = ["../../../tests/PP_ORB/Bi_gga_10au_100Ry_2s2p2d.orb", "../../../tests/PP_ORB/Se_gga_10au_100Ry_2s2p2d.orb"] + job.pp_orbitals = { + "Bi": "../../../tests/PP_ORB/Bi_pbe_fr.upf", + "Se": "../../../tests/PP_ORB/Se_pbe_fr.upf", + } + job.orbital_files = [ + "../../../tests/PP_ORB/Bi_gga_10au_100Ry_2s2p2d.orb", + "../../../tests/PP_ORB/Se_gga_10au_100Ry_2s2p2d.orb", + ] # ---------------------------------------------------------- # 4. Wannier90 Parameters @@ -156,7 +162,9 @@ def main(): print(f"\n[FILE ERROR] {e}") print(" [1] wannier90.x in PATH? → which wannier90.x") print(" [2] abacus in PATH? → which abacus") - print(" [3] PP / orbital files? → ls ../../../tests/PP_ORB/Bi*.upf ../../../tests/PP_ORB/Bi*.orb") + print( + " [3] PP / orbital files? → ls ../../../tests/PP_ORB/Bi*.upf ../../../tests/PP_ORB/Bi*.orb" + ) except RuntimeError as e: print(f"\n[RUNTIME ERROR] {e}") except ValueError as e: diff --git a/interfaces/Wannier90_interface/examples_python/example_pw.py b/interfaces/Wannier90_interface/examples_python/example_pw.py index ff70d2e86eb..0fb644a70c1 100644 --- a/interfaces/Wannier90_interface/examples_python/example_pw.py +++ b/interfaces/Wannier90_interface/examples_python/example_pw.py @@ -63,7 +63,10 @@ def main(): # ---------------------------------------------------------- # 3. Dependency files (PW only needs pseudopotentials) # ---------------------------------------------------------- - job.pp_orbitals = {"Bi": "../../../tests/PP_ORB/Bi_pbe_fr.upf", "Se": "../../../tests/PP_ORB/Se_pbe_fr.upf"} + job.pp_orbitals = { + "Bi": "../../../tests/PP_ORB/Bi_pbe_fr.upf", + "Se": "../../../tests/PP_ORB/Se_pbe_fr.upf", + } # ← PW基组不需要轨道文件,不设置 orbital_files # ---------------------------------------------------------- @@ -152,4 +155,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/tools/README.md b/tools/README.md index a3ce30b1139..c15908a9177 100644 --- a/tools/README.md +++ b/tools/README.md @@ -1,6 +1,6 @@ SIAB: codes to generate numerical atomic orbitals. -molden: generate molden style file for Multiwfn analysis. +molden: generate molden style file for Multiwfn analysis. plot-tools: band structure, dos and pdos, dipole and adsorption. @@ -22,4 +22,4 @@ opt_orb_pytorch_dpsi: related to generating NAO basis set. qo: generate quasiatomic orbital (qo). -selective_dynamics: used to do selective dynamics with ABACUS + Phonopy. \ No newline at end of file +selective_dynamics: used to do selective dynamics with ABACUS + Phonopy. diff --git a/tools/SIAB/Generate_Orbital_AllInOne.sh b/tools/SIAB/Generate_Orbital_AllInOne.sh index 95d323c43d4..35ecc9401aa 100755 --- a/tools/SIAB/Generate_Orbital_AllInOne.sh +++ b/tools/SIAB/Generate_Orbital_AllInOne.sh @@ -308,11 +308,11 @@ echo " -------------------------------------------------------> $element" # (1.2) make the dir, the name is 'name' if ( test -d $name ) -then - echo " The dir exist: $name" +then + echo " The dir exist: $name" else - echo " Make dir: $name" - mkdir $name + echo " Make dir: $name" + mkdir $name fi # (1.3) enter the name dir @@ -322,10 +322,10 @@ cd $name count_r=1 while [ $count_r -le $rcut_number ] do - ### (1.4.1) - #rcut=`echo "$info_r" | awk '{print $'$count_r'}' ` + ### (1.4.1) + #rcut=`echo "$info_r" | awk '{print $'$count_r'}' ` rcut=${info_r[count_r-1]} - echo " |run cicle: rcut=$rcut" + echo " |run cicle: rcut=$rcut" @@ -337,7 +337,7 @@ do echo " |skip cicle: iSTRU=$iSTRU" continue; fi - echo " |run cicle: iSTRU=$iSTRU" + echo " |run cicle: iSTRU=$iSTRU" @@ -495,17 +495,17 @@ do - #### (1.4.2) enter the forth big cicle : Bond Length. - count=1 - while [ $count -le ${BL_number[iSTRU]} ] - do + #### (1.4.2) enter the forth big cicle : Bond Length. + count=1 + while [ $count -le ${BL_number[iSTRU]} ] + do - # (1.4.2.0) calculate the Bond Length for iSTRU - BL=`echo "${BLSTRU[iSTRU]}" | awk '{print $'$count'}' ` + # (1.4.2.0) calculate the Bond Length for iSTRU + BL=`echo "${BLSTRU[iSTRU]}" | awk '{print $'$count'}' ` dis1=$(echo "scale=5;$BL * 0.86603 "|bc) dis2=$(echo "scale=5;$BL * 0.5 "|bc) - dis3=$(echo "scale=5;$BL * 0.81649 "|bc) - dis4=$(echo "scale=5;$BL * 0.28867 "|bc) + dis3=$(echo "scale=5;$BL * 0.81649 "|bc) + dis4=$(echo "scale=5;$BL * 0.28867 "|bc) echo " |run cicle: BL=$BL" if [ "${ListSTRU[iSTRU]}" == "dimer" ]; then @@ -710,7 +710,7 @@ cat >> INPUT << EOF 1 //number of k points -1 // number of pools +1 // number of pools @@ -946,12 +946,12 @@ done "Ecut": { "$element": $ecut }, - "lr": $lr_value, + "lr": $lr_value, "cal_T": true, "cal_smooth": true }, - "weight": - { + "weight": + { "stru": [ EOF @@ -1015,8 +1015,8 @@ fi }, "V_info": { - "same_band": true, - "init_from_file": true + "same_band": true, + "init_from_file": true } } EOF @@ -1162,7 +1162,7 @@ fi "Ecut": { "$element": $ecut }, - "lr": $lr_value, + "lr": $lr_value, "cal_T": false, "cal_smooth": true }, diff --git a/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/exx.py b/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/exx.py index f37b55a81a3..f22a56645d7 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/exx.py +++ b/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/exx.py @@ -5,70 +5,72 @@ import utils import read_stru + def cal(): - pathlib.Path(utils.folder_exx).mkdir(parents=True,exist_ok=False) - - os.system(f"cp INPUT {utils.folder_exx}/") - os.system(f"cp KPT {utils.folder_exx}/") - - with open(f"{utils.folder_exx}/INPUT","w") as file: - input_dict = read_stru.get_input_dict() - input_dict["pseudo_dir"] = os.path.abspath(input_dict.get("pseudo_dir",r"./")) - read_stru.print_input(file,input_dict) - - with open("STRU","r") as file: - strus = re.compile("LATTICE_CONSTANT").split(file.read()) - with open(f"{utils.folder_exx}/STRU","w") as file: - Ts = read_stru.get_T() - file.write("ATOMIC_SPECIES\n") - pseudo_path = read_stru.get_pseudo_path() - for T in Ts: - file.write(f"{T} 12 {pseudo_path[T]}\n") - file.write("\nNUMERICAL_ORBITAL\n") - lcao_path = read_stru.get_lcao_path() - for T in Ts: - file.write(f"{lcao_path[T]}\n") - file.write("\nABFS_ORBITAL\n") - for T in read_stru.get_T(): - file.write(f"../{utils.folder_opt}/orb_{T}.dat\n") - file.write("\nLATTICE_CONSTANT") - file.write(strus[1]) - - info = utils.read_info() - if utils.sub=="qsub": - with open(f"{utils.folder_exx}/sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/bash - #PBS -q gold5120 - #PBS -l nodes=1:ppn=28 - #PBS -l walltime=24:00:00 - #PBS -o job.log - #PBS -e job.err - ulimit -s unlimited - cd $PBS_O_WORKDIR - EXEC={info["ABACUS"]} - mpirun -n 1 -env OMP_NUM_THREADS=28 $EXEC - """)) - elif utils.sub=="bsub": - with open(f"{utils.folder_exx}/sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/sh - #BSUB -q renxg - #BSUB -o job.log -e job.err - #BSUB -n 6 - mpirun -n 1 -env OMP_NUM_THREADS=6 {info['ABACUS']} - """)) + pathlib.Path(utils.folder_exx).mkdir(parents=True, exist_ok=False) + + os.system(f"cp INPUT {utils.folder_exx}/") + os.system(f"cp KPT {utils.folder_exx}/") + + with open(f"{utils.folder_exx}/INPUT", "w") as file: + input_dict = read_stru.get_input_dict() + input_dict["pseudo_dir"] = os.path.abspath(input_dict.get("pseudo_dir", r"./")) + read_stru.print_input(file, input_dict) + + with open("STRU", "r") as file: + strus = re.compile("LATTICE_CONSTANT").split(file.read()) + with open(f"{utils.folder_exx}/STRU", "w") as file: + Ts = read_stru.get_T() + file.write("ATOMIC_SPECIES\n") + pseudo_path = read_stru.get_pseudo_path() + for T in Ts: + file.write(f"{T} 12 {pseudo_path[T]}\n") + file.write("\nNUMERICAL_ORBITAL\n") + lcao_path = read_stru.get_lcao_path() + for T in Ts: + file.write(f"{lcao_path[T]}\n") + file.write("\nABFS_ORBITAL\n") + for T in read_stru.get_T(): + file.write(f"../{utils.folder_opt}/orb_{T}.dat\n") + file.write("\nLATTICE_CONSTANT") + file.write(strus[1]) + + info = utils.read_info() + if utils.sub == "qsub": + with open(f"{utils.folder_exx}/sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #PBS -q gold5120 + #PBS -l nodes=1:ppn=28 + #PBS -l walltime=24:00:00 + #PBS -o job.log + #PBS -e job.err + ulimit -s unlimited + cd $PBS_O_WORKDIR + EXEC={info["ABACUS"]} + mpirun -n 1 -env OMP_NUM_THREADS=28 $EXEC + """)) + elif utils.sub == "bsub": + with open(f"{utils.folder_exx}/sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/sh + #BSUB -q renxg + #BSUB -o job.log -e job.err + #BSUB -n 6 + mpirun -n 1 -env OMP_NUM_THREADS=6 {info['ABACUS']} + """)) + + os.chdir(utils.folder_exx) + if utils.sub == "qsub": + os.system("qsub sub.sh") + elif utils.sub == "bsub": + os.system(f"bsub < sub.sh") + elif utils.sub == "tianhe2": + os.system(f'yhrun -N 1 -n 1 -c 24 -t 1440 {info["ABACUS"]} >Log.txt 2>&1 &') + else: + raise ValueError("utils.sub") + os.chdir("../") + - os.chdir(utils.folder_exx) - if utils.sub=="qsub": - os.system("qsub sub.sh") - elif utils.sub=="bsub": - os.system(f"bsub < sub.sh") - elif utils.sub=="tianhe2": - os.system(f'yhrun -N 1 -n 1 -c 24 -t 1440 {info["ABACUS"]} >Log.txt 2>&1 &') - else: - raise ValueError("utils.sub") - os.chdir("../") - -if __name__=="__main__": - cal() \ No newline at end of file +if __name__ == "__main__": + cal() diff --git a/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/opt_orb.py b/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/opt_orb.py index 3a86ed9fce0..f31167ffdf8 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/opt_orb.py +++ b/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/opt_orb.py @@ -6,96 +6,106 @@ import read_stru import utils + def cp_matrix(folders_matrix): - pathlib.Path(utils.folder_opt+"/"+utils.folder_opt_matrix).mkdir(parents=True,exist_ok=False) - folders_same_atom = set() - for folder_matrix in folders_matrix: - T1,T2 = folder_matrix.split("_")[0].split("-") - dis = float(folder_matrix.split("_")[1]) - if dis: - if T1==T2: - matrix_file = "matrix_0_0_0_1" - else: - matrix_file = "matrix_0_0_1_0" - else: - matrix_file = "matrix_0_0_0_0" - os.system(f"cp {folder_matrix}/{matrix_file} {utils.folder_opt}/{utils.folder_opt_matrix}/{folder_matrix}") - + pathlib.Path(utils.folder_opt + "/" + utils.folder_opt_matrix).mkdir( + parents=True, exist_ok=False + ) + folders_same_atom = set() + for folder_matrix in folders_matrix: + T1, T2 = folder_matrix.split("_")[0].split("-") + dis = float(folder_matrix.split("_")[1]) + if dis: + if T1 == T2: + matrix_file = "matrix_0_0_0_1" + else: + matrix_file = "matrix_0_0_1_0" + else: + matrix_file = "matrix_0_0_0_0" + os.system( + f"cp {folder_matrix}/{matrix_file} {utils.folder_opt}/{utils.folder_opt_matrix}/{folder_matrix}" + ) + + def add_nbands(folders_matrix): - for folder_matrix in folders_matrix: - with open(f"{utils.folder_opt}/{utils.folder_opt_matrix}/{folder_matrix}","r") as file: - nband = int(re.compile(r"(\d+)\s+nbands").search(file.read()).group(1)) - folders_matrix[folder_matrix] = (folders_matrix[folder_matrix], nband) + for folder_matrix in folders_matrix: + with open( + f"{utils.folder_opt}/{utils.folder_opt_matrix}/{folder_matrix}", "r" + ) as file: + nband = int(re.compile(r"(\d+)\s+nbands").search(file.read()).group(1)) + folders_matrix[folder_matrix] = (folders_matrix[folder_matrix], nband) + def set_input(folders_matrix): - Ts = read_stru.get_T() - input_dict = read_stru.get_input_dict() - Ecut = float(input_dict["ecutwfc"]) - info = utils.read_info() - input = { - "file_list": [f"{utils.folder_opt_matrix}/"+folder_matrix for folder_matrix in folders_matrix], - "info": - { - "Nt_all": Ts, - "Nu": {T:info["Nu"] for T in Ts}, - "Nb_true": [nbands for weight,nbands in folders_matrix.values()], - "weight": [weight for weight,nbands in folders_matrix.values()], - "Rcut": read_stru.get_Rcut(), - "dr": {T:utils.dr for T in Ts}, - "Ecut": {T:Ecut for T in Ts}, - "lr": utils.lr - }, - "C_init_info":{ "init_from_file": False }, - "V_info": - { - "init_from_file": True, - "same_band": False - } - } - return json.dumps(input,indent=4) - + Ts = read_stru.get_T() + input_dict = read_stru.get_input_dict() + Ecut = float(input_dict["ecutwfc"]) + info = utils.read_info() + input = { + "file_list": [ + f"{utils.folder_opt_matrix}/" + folder_matrix + for folder_matrix in folders_matrix + ], + "info": { + "Nt_all": Ts, + "Nu": {T: info["Nu"] for T in Ts}, + "Nb_true": [nbands for weight, nbands in folders_matrix.values()], + "weight": [weight for weight, nbands in folders_matrix.values()], + "Rcut": read_stru.get_Rcut(), + "dr": {T: utils.dr for T in Ts}, + "Ecut": {T: Ecut for T in Ts}, + "lr": utils.lr, + }, + "C_init_info": {"init_from_file": False}, + "V_info": {"init_from_file": True, "same_band": False}, + } + return json.dumps(input, indent=4) + + def cal(input): - info = utils.read_info() - with open(f"{utils.folder_opt}/input.json","w") as file: - file.write(input) - if utils.sub=="qsub": - with open(f"{utils.folder_opt}/sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/bash - #PBS -q batch - #PBS -l nodes=1:ppn=1 - #PBS -l walltime=2:00:00 - #PBS -o job.log - #PBS -e job.err - ulimit -s unlimited - cd $PBS_O_WORKDIR - export OMP_NUM_THREADS=1 - EXEC={info["opt_orb"]} - python3 -u $EXEC - """)) - elif utils.sub=="tianhe2": - with open(f"{utils.folder_opt}/sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/bash - EXEC={info["opt_orb"]} - python3 -u $EXEC >Log.txt - """)) - os.chdir(utils.folder_opt) - if utils.sub=="qsub": - os.system("qsub sub.sh") - elif utils.sub=="tianhe2": - os.system("yhbatch -N 1 sub.sh") -# os.system(f'python3 -u {info["opt_orb"]}') - os.chdir("../") - + info = utils.read_info() + with open(f"{utils.folder_opt}/input.json", "w") as file: + file.write(input) + if utils.sub == "qsub": + with open(f"{utils.folder_opt}/sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #PBS -q batch + #PBS -l nodes=1:ppn=1 + #PBS -l walltime=2:00:00 + #PBS -o job.log + #PBS -e job.err + ulimit -s unlimited + cd $PBS_O_WORKDIR + export OMP_NUM_THREADS=1 + EXEC={info["opt_orb"]} + python3 -u $EXEC + """)) + elif utils.sub == "tianhe2": + with open(f"{utils.folder_opt}/sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/bash + EXEC={info["opt_orb"]} + python3 -u $EXEC >Log.txt + """)) + os.chdir(utils.folder_opt) + if utils.sub == "qsub": + os.system("qsub sub.sh") + elif utils.sub == "tianhe2": + os.system("yhbatch -N 1 sub.sh") + # os.system(f'python3 -u {info["opt_orb"]}') + os.chdir("../") + + def all(): - pathlib.Path(utils.folder_opt).mkdir(parents=True,exist_ok=False) - with open("folders","r") as file: - folders_matrix = json.loads(file.read()) - cp_matrix(folders_matrix.keys()) - add_nbands(folders_matrix) - input = set_input(folders_matrix) - cal(input) - -if __name__=="__main__": - all() \ No newline at end of file + pathlib.Path(utils.folder_opt).mkdir(parents=True, exist_ok=False) + with open("folders", "r") as file: + folders_matrix = json.loads(file.read()) + cp_matrix(folders_matrix.keys()) + add_nbands(folders_matrix) + input = set_input(folders_matrix) + cal(input) + + +if __name__ == "__main__": + all() diff --git a/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/read_stru.py b/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/read_stru.py index 2038e998677..9f5bccf97d5 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/read_stru.py +++ b/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/read_stru.py @@ -10,224 +10,251 @@ import json import utils + def skip_notes(line): - line = re.compile(r"#.*").sub("",line) - line = re.compile(r"//.*").sub("",line) - line = line.strip() - return line + line = re.compile(r"#.*").sub("", line) + line = re.compile(r"//.*").sub("", line) + line = line.strip() + return line + @functools.lru_cache(maxsize=None) def get_input_dict(): - input_dict = dict() - with open("INPUT","r") as file: - for line in file: - line = skip_notes(line) - if not line or line=="INPUT_PARAMETERS": - continue - label, value = re.compile(r"\s+").split( line, maxsplit=1 ) - input_dict[label] = value - return input_dict - -def print_input(file,input_dict): - print("INPUT_PARAMETERS",file=file) - max_len = max([len(label) for label in input_dict]) - for label,value in input_dict.items(): - print( label, " "*(max_len-len(label)+4), value, file=file) - - + input_dict = dict() + with open("INPUT", "r") as file: + for line in file: + line = skip_notes(line) + if not line or line == "INPUT_PARAMETERS": + continue + label, value = re.compile(r"\s+").split(line, maxsplit=1) + input_dict[label] = value + return input_dict + + +def print_input(file, input_dict): + print("INPUT_PARAMETERS", file=file) + max_len = max([len(label) for label in input_dict]) + for label, value in input_dict.items(): + print(label, " " * (max_len - len(label) + 4), value, file=file) + + """ @functools.lru_cache(maxsize=None) def search_in_input(label): - with open("INPUT","r") as file: - regex = label+"\s+(\d+)" - value = re.compile(regex).search(file.read()).group(1) - return value + with open("INPUT","r") as file: + regex = label+"\s+(\d+)" + value = re.compile(regex).search(file.read()).group(1) + return value """ + @functools.lru_cache(maxsize=None) def get_k(): - with open("KPT","r") as file: - utils.search_sentence(file,"Gamma") - return list(map(int,skip_notes(file.readline()).split()[:3])) + with open("KPT", "r") as file: + utils.search_sentence(file, "Gamma") + return list(map(int, skip_notes(file.readline()).split()[:3])) + @functools.lru_cache(maxsize=None) def get_T(): - ntype = int(get_input_dict()["ntype"]) - T = [] - with open("STRU","r") as file: - utils.search_sentence(file,"ATOMIC_SPECIES") - for it in range(ntype): - line = skip_notes(file.readline()) - T.append(line.split()[0]) - return T + ntype = int(get_input_dict()["ntype"]) + T = [] + with open("STRU", "r") as file: + utils.search_sentence(file, "ATOMIC_SPECIES") + for it in range(ntype): + line = skip_notes(file.readline()) + T.append(line.split()[0]) + return T + @functools.lru_cache(maxsize=None) def get_Rcut(): - Ts = get_T() - lcao_path = get_lcao_path() - Rcut = dict() - for T in Ts: - with open(lcao_path[T],"r") as file: - for line in file: - line = skip_notes(line) - if line.startswith("Radius Cutoff(a.u.)"): - Rcut[T] = float(line.split()[-1]) - break - return Rcut + Ts = get_T() + lcao_path = get_lcao_path() + Rcut = dict() + for T in Ts: + with open(lcao_path[T], "r") as file: + for line in file: + line = skip_notes(line) + if line.startswith("Radius Cutoff(a.u.)"): + Rcut[T] = float(line.split()[-1]) + break + return Rcut + @functools.lru_cache(maxsize=None) def get_pseudo_path(): - Ts = get_T() - path = dict() - with open("STRU","r") as file: - utils.search_sentence(file,"ATOMIC_SPECIES") - for T in Ts: - path[T] = skip_notes(file.readline()).split()[-1] - return path - + Ts = get_T() + path = dict() + with open("STRU", "r") as file: + utils.search_sentence(file, "ATOMIC_SPECIES") + for T in Ts: + path[T] = skip_notes(file.readline()).split()[-1] + return path + + @functools.lru_cache(maxsize=None) def get_lcao_path(): - Ts = get_T() - path = dict() - with open("STRU","r") as file: - utils.search_sentence(file,"NUMERICAL_ORBITAL") - for T in Ts: - path[T] = os.path.abspath(skip_notes(file.readline())) - return path - + Ts = get_T() + path = dict() + with open("STRU", "r") as file: + utils.search_sentence(file, "NUMERICAL_ORBITAL") + for T in Ts: + path[T] = os.path.abspath(skip_notes(file.readline())) + return path + + @functools.lru_cache(maxsize=None) def get_lattice(): - with open("STRU","r") as file: - utils.search_sentence(file,"LATTICE_CONSTANT") - lat0 = float(skip_notes(file.readline()).split()[0]) - with open("STRU","r") as file: - utils.search_sentence(file,"LATTICE_VECTORS") - lat_vec = [] - for i in range(3): - lat_vec.append(list(map(float,skip_notes(file.readline()).split()))) - lat_vec = np.array(lat_vec) - with open("STRU","r") as file: - utils.search_sentence(file,"ATOMIC_POSITIONS") - position = skip_notes(file.readline()) - return lat0, lat_vec, position - + with open("STRU", "r") as file: + utils.search_sentence(file, "LATTICE_CONSTANT") + lat0 = float(skip_notes(file.readline()).split()[0]) + with open("STRU", "r") as file: + utils.search_sentence(file, "LATTICE_VECTORS") + lat_vec = [] + for i in range(3): + lat_vec.append(list(map(float, skip_notes(file.readline()).split()))) + lat_vec = np.array(lat_vec) + with open("STRU", "r") as file: + utils.search_sentence(file, "ATOMIC_POSITIONS") + position = skip_notes(file.readline()) + return lat0, lat_vec, position + + @functools.lru_cache(maxsize=None) def get_lcao(): - lcao = collections.defaultdict(list) - lcao_path = get_lcao_path() - for T in lcao_path: - with open(lcao_path[T],"r") as file: - for line in file: - line = skip_notes(line) - if line.startswith("Number of"): - lcao[T].append(int(line.split()[-1])) - return dict(lcao) - + lcao = collections.defaultdict(list) + lcao_path = get_lcao_path() + for T in lcao_path: + with open(lcao_path[T], "r") as file: + for line in file: + line = skip_notes(line) + if line.startswith("Number of"): + lcao[T].append(int(line.split()[-1])) + return dict(lcao) + + @functools.lru_cache(maxsize=None) def get_nw(): - nw = dict() - lcao = get_lcao() - for T in lcao: - nw[T] = functools.reduce(operator.add,((2*l+1)*n for l,n in enumerate(lcao[T]))) - return nw + nw = dict() + lcao = get_lcao() + for T in lcao: + nw[T] = functools.reduce( + operator.add, ((2 * l + 1) * n for l, n in enumerate(lcao[T])) + ) + return nw + # R[T] = [..., [xi,yi,zi], ...] def get_R(): - Ts = get_T() - R = dict() - with open("STRU","r") as file: - for T in Ts: - utils.search_sentence(file,T) - utils.ignore_lines(file,1) - na = int(skip_notes(file.readline()).split()[0]) - R_tmp = [] - for i in range(na): - R_tmp.append(list(map(float,skip_notes(file.readline()).split()[:3]))) - R[T] = np.array(R_tmp) - return R + Ts = get_T() + R = dict() + with open("STRU", "r") as file: + for T in Ts: + utils.search_sentence(file, T) + utils.ignore_lines(file, 1) + na = int(skip_notes(file.readline()).split()[0]) + R_tmp = [] + for i in range(na): + R_tmp.append(list(map(float, skip_notes(file.readline()).split()[:3]))) + R[T] = np.array(R_tmp) + return R + def change_R(R): - lat0, lat_vec, position = get_lattice() - if position == "Direct": - for T in R: - R[T] = np.dot(R[T],lat_vec) - elif position == "Cartesian_angstrom": - for T in R: - R[T] /= 0.529166 - for T in R: - R[T] *= lat0 - - nx,ny,nz = get_k() - lat_vec *= lat0 - for T in R: - R_new = [] - for ix in range(nx): - for iy in range(ny): - for iz in range(nz): - R_new.append( R[T] + np.dot(np.array([ix,iy,iz]), lat_vec) ) - R[T] = np.concatenate(R_new) - - return R + lat0, lat_vec, position = get_lattice() + if position == "Direct": + for T in R: + R[T] = np.dot(R[T], lat_vec) + elif position == "Cartesian_angstrom": + for T in R: + R[T] /= 0.529166 + for T in R: + R[T] *= lat0 + + nx, ny, nz = get_k() + lat_vec *= lat0 + for T in R: + R_new = [] + for ix in range(nx): + for iy in range(ny): + for iz in range(nz): + R_new.append(R[T] + np.dot(np.array([ix, iy, iz]), lat_vec)) + R[T] = np.concatenate(R_new) + + return R + # dis[T1,T2] = {..., i_dis:num, ...} def cal_dis(R): - dis = dict() - for T1,T2 in itertools.combinations_with_replacement(R,2): - dis_TT = collections.defaultdict(int) - for ia1,ia2 in itertools.product(R[T1],R[T2]): - i_dis = np.linalg.norm(ia1-ia2) - dis_TT[i_dis] += 1 - dis[T1,T2] = dict(dis_TT) - return dis - -def round_dis(dis,precision): - dis_round = dict() - for T1,T2 in dis: - dis_TT = collections.defaultdict(int) - for i_dis,num in dis[T1,T2].items(): - i_dis = float(decimal.Decimal(i_dis).quantize(decimal.Decimal(str(precision)), rounding=decimal.ROUND_HALF_UP)) # test - dis_TT[i_dis] += num - dis_round[T1,T2] = dict(dis_TT) - return dis_round + dis = dict() + for T1, T2 in itertools.combinations_with_replacement(R, 2): + dis_TT = collections.defaultdict(int) + for ia1, ia2 in itertools.product(R[T1], R[T2]): + i_dis = np.linalg.norm(ia1 - ia2) + dis_TT[i_dis] += 1 + dis[T1, T2] = dict(dis_TT) + return dis + + +def round_dis(dis, precision): + dis_round = dict() + for T1, T2 in dis: + dis_TT = collections.defaultdict(int) + for i_dis, num in dis[T1, T2].items(): + i_dis = float( + decimal.Decimal(i_dis).quantize( + decimal.Decimal(str(precision)), rounding=decimal.ROUND_HALF_UP + ) + ) # test + dis_TT[i_dis] += num + dis_round[T1, T2] = dict(dis_TT) + return dis_round + def cut_dis(dis): - Rcut = get_Rcut() - for T1,T2 in dis: - Rcut_sum = Rcut[T1]+Rcut[T2] - dis[T1,T2] = { i_dis:num for i_dis,num in dis[T1,T2].items() if i_disRcut_sum): - norm = np.linalg.norm(delta) - if norm>0 and normRcut_sum): + norm = np.linalg.norm(delta) + if norm>0 and normLog.txt') - os.chdir("../") - -# dis_opt[T1,T2] = [..., dis, ...] + +def cal_ABACUS(T1, T2, i_dis): + folder = pathlib.Path(utils.folder_name(T1, T2, i_dis)).resolve() + folder.mkdir(parents=True, exist_ok=False) + + with open(folder / "INPUT", "w") as file: + info = utils.read_info() + input_dict = read_stru.get_input_dict() + input_dict["ntype"] = 1 if T1 == T2 else 2 + input_dict["exx_hybrid_type"] = "opt_orb" + input_dict["nbands"] = ( + read_stru.get_nw()[T1] + if abs(i_dis) < 1e-10 + else read_stru.get_nw()[T1] + read_stru.get_nw()[T2] + ) + input_dict["nspin"] = 1 + input_dict["gamma_only"] = 1 + input_dict["pseudo_dir"] = os.path.abspath(input_dict.get("pseudo_dir", r"./")) + input_dict["exx_opt_orb_lmax"] = len(info["Nu"]) - 1 + read_stru.print_input(file, input_dict) + + with open(folder / "STRU", "w") as file: + Ts = (T1,) if T1 == T2 else (T1, T2) + file.write("ATOMIC_SPECIES\n") + pseudo_path = read_stru.get_pseudo_path() + for T in Ts: + file.write(f"{T} 1 {pseudo_path[T]}\n") + file.write("\nNUMERICAL_ORBITAL\n") + lcao_path = read_stru.get_lcao_path() + for T in Ts: + file.write(f"{lcao_path[T]}\n") + file.write(textwrap.dedent(f""" + LATTICE_CONSTANT + 1\n + LATTICE_VECTORS + 30 0 0 + 0 30 0 + 0 0 30\n + ATOMIC_POSITIONS + Cartesian + """)) + if T1 == T2: + if abs(i_dis) < 1e-10: + file.write(textwrap.dedent(f""" + {T1} + 0 + 1 + 0 0 0 0 0 0 + """)) + else: + file.write(textwrap.dedent(f""" + {T1} + 0 + 2 + 0 0 0 0 0 0 + {i_dis} 0 0 0 0 0 + """)) + else: + file.write(textwrap.dedent(f""" + {T1} + 0 + 1 + 0 0 0 0 0 0\n + {T2} + 0 + 1 + {i_dis} 0 0 0 0 0 + """)) + + with open(folder / "KPT", "w") as file: + file.write(textwrap.dedent(f"""\ + K_POINTS + 0 + Gamma + 1 1 1 0 0 0 + """)) + + info = utils.read_info() + if utils.sub == "qsub": + with open(folder / "sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #PBS -q gold5120 + #PBS -l nodes=1:ppn=1 + #PBS -l walltime=1:00:00 + #PBS -o job.log + #PBS -e job.err + ulimit -s unlimited + cd $PBS_O_WORKDIR + EXEC={info["ABACUS"]} + mpirun -n 1 -env OMP_NUM_THREADS=1 $EXEC + """)) + elif utils.sub == "bsub": + with open(folder / "sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/sh + #BSUB -q renxg + #BSUB -o job.log -e job.err + #BSUB -n 1 + EXEC={info["ABACUS"]} + mpirun -n 1 -env OMP_NUM_THREADS=1 $EXEC + """)) + + os.chdir(folder) + if utils.sub == "qsub": + os.system("qsub sub.sh") + elif utils.sub == "bsub": + os.system("bsub < sub.sh") + elif utils.sub == "tianh2": + os.system(f'yhrun -n 1 -c 1 {info["ABACUS"]} >Log.txt') + os.chdir("../") + + +# dis_opt[T1,T2] = [..., dis, ...] def get_dis_opt(dis): - opt_mode = "kmeans" - dis_opt = dict() - info = utils.read_info() - for T1,T2 in dis: - dis_tmp = read_stru.delete_zero(dis[T1,T2]) - if len(dis_tmp)<=info["dimer_num"]: - dis_opt[T1,T2] = list(dis_tmp.keys()) - else: - if opt_mode=="linspace": - dis_opt[T1,T2] = np.linspace( min(dis_tmp), max(dis_tmp), info["dimer_num"] ) - elif opt_mode=="kmeans": - kmeans = KMeans(n_clusters=info["dimer_num"]) - label = kmeans.fit_predict( - np.array(list(dis_tmp.keys())).reshape(-1,1), - sample_weight = [num/i_dis**2 for i_dis,num in dis_tmp.items()]) - dis_opt[T1,T2] = list(kmeans.cluster_centers_.reshape(-1)) - pprint.pprint(dict(zip(dis_tmp.keys(),label))) - if T1==T2: - dis_opt[T1,T2].append(0.0) - return dis_opt - + opt_mode = "kmeans" + dis_opt = dict() + info = utils.read_info() + for T1, T2 in dis: + dis_tmp = read_stru.delete_zero(dis[T1, T2]) + if len(dis_tmp) <= info["dimer_num"]: + dis_opt[T1, T2] = list(dis_tmp.keys()) + else: + if opt_mode == "linspace": + dis_opt[T1, T2] = np.linspace( + min(dis_tmp), max(dis_tmp), info["dimer_num"] + ) + elif opt_mode == "kmeans": + kmeans = KMeans(n_clusters=info["dimer_num"]) + label = kmeans.fit_predict( + np.array(list(dis_tmp.keys())).reshape(-1, 1), + sample_weight=[num / i_dis**2 for i_dis, num in dis_tmp.items()], + ) + dis_opt[T1, T2] = list(kmeans.cluster_centers_.reshape(-1)) + pprint.pprint(dict(zip(dis_tmp.keys(), label))) + if T1 == T2: + dis_opt[T1, T2].append(0.0) + return dis_opt + + # dis_weight[T1,T2] = {..., i_dis_opt:weight, ...} -def cal_dis_weight(dis_opt,dis_all): - def weight_func(x,D): - return (2/D**3)*x**3 + (-3/D**2)*x**2 + 1 - dis_weight = collections.defaultdict(dict) - for T1,T2 in dis_opt: - dis_opt_TT = sorted(dis_opt[T1,T2]) - for index,i_dis_opt in enumerate(dis_opt_TT): - i_weight = 0 - i_dis_low = dis_opt_TT[index-1] if index>0 else -np.infty - i_dis_up = dis_opt_TT[index+1] if index 0 else -np.infty + i_dis_up = ( + dis_opt_TT[index + 1] if index < len(dis_opt_TT) - 1 else np.infty + ) + for i_dis, num in dis_all[T1, T2].items(): + if i_dis_low < i_dis < i_dis_opt: + i_weight += ( + weight_func(i_dis_opt - i_dis, i_dis_opt - i_dis_low) * num + ) + elif i_dis == i_dis_opt: + i_weight += num + elif i_dis_opt < i_dis < i_dis_up: + i_weight += ( + weight_func(i_dis_opt - i_dis, i_dis_opt - i_dis_up) * num + ) + dis_weight[T1, T2][i_dis_opt] = i_weight + return dis_weight + + def cal(): - dis = read_stru.cut_dis(read_stru.cal_dis(read_stru.change_R(read_stru.get_R()))) - dis_decimal = read_stru.round_dis(dis,1E-6) - pprint.pprint(dis_decimal) - dis_opt = get_dis_opt(dis_decimal) - for T1,T2 in dis_opt: - for i_dis in dis_opt[T1,T2]: - cal_ABACUS(T1,T2,i_dis) - dis_weight = cal_dis_weight(dis_opt,dis) - read_stru.print_folders(dis_weight) - -if __name__=="__main__": - cal() \ No newline at end of file + dis = read_stru.cut_dis(read_stru.cal_dis(read_stru.change_R(read_stru.get_R()))) + dis_decimal = read_stru.round_dis(dis, 1e-6) + pprint.pprint(dis_decimal) + dis_opt = get_dis_opt(dis_decimal) + for T1, T2 in dis_opt: + for i_dis in dis_opt[T1, T2]: + cal_ABACUS(T1, T2, i_dis) + dis_weight = cal_dis_weight(dis_opt, dis) + read_stru.print_folders(dis_weight) + + +if __name__ == "__main__": + cal() diff --git a/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/utils.py b/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/utils.py index 8e676b6a460..83af732b34e 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/utils.py +++ b/tools/SIAB/PyTorchGradient/example_opt_abfs_bash/utils.py @@ -1,42 +1,50 @@ import json import functools + @functools.lru_cache(maxsize=None) def read_info(flag=True): - """ - { - "ABACUS":"dir/ABACUS/ABACUS.mpi.1.0.0", - "opt_orb":"dir/opt_orb/main.py", - "Nu":[7,10,8,3,1], - "dimer_num":5 - } - """ - with open("info","r") as file: - return json.loads(file.read()) - -def ignore_lines(file,n): - for i in range(n): - file.readline() - -def search_sentence(file,sentence): - sentence = sentence.strip() - for line in file: - if line.strip() == sentence: - break - + """ + { + "ABACUS":"dir/ABACUS/ABACUS.mpi.1.0.0", + "opt_orb":"dir/opt_orb/main.py", + "Nu":[7,10,8,3,1], + "dimer_num":5 + } + """ + with open("info", "r") as file: + return json.loads(file.read()) + + +def ignore_lines(file, n): + for i in range(n): + file.readline() + + +def search_sentence(file, sentence): + sentence = sentence.strip() + for line in file: + if line.strip() == sentence: + break + + def floatlist_str(l): - return "-".join(list(map(str,l))) + return "-".join(list(map(str, l))) + sub = "qsub" -dr = 0.01 -lr = 0.01 +dr = 0.01 +lr = 0.01 + + +def folder_name(T1, T2, i_dis): + return f"{T1}-{T2}_{i_dis}" + -def folder_name(T1,T2,i_dis): - return f"{T1}-{T2}_{i_dis}" try: - info = read_info(False) - folder_opt = "opt_orb_"+floatlist_str(info["Nu"]) - folder_exx = "exx_"+floatlist_str(info["Nu"]) - folder_opt_matrix = "matrix" + info = read_info(False) + folder_opt = "opt_orb_" + floatlist_str(info["Nu"]) + folder_exx = "exx_" + floatlist_str(info["Nu"]) + folder_opt_matrix = "matrix" except FileNotFoundError: - print("info FileNotFoundError") \ No newline at end of file + print("info FileNotFoundError") diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/dis.py b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/dis.py index ed071177f2b..916efb57b86 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/dis.py +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/dis.py @@ -1,104 +1,104 @@ dis = { - "H": [ 0.6, 0.75, 0.9, 1.2, 1.5 ], - "He": [ 1.25, 1.75, 2.4, 3.25 ], - "Li": [ 1.5, 2.1, 2.5, 2.8, 3.2, 3.5, 4.2 ], - "Be": [ 1.75, 2, 2.375, 3, 4 ], - "B": [ 1.25, 1.625, 2.5, 3.5 ], - "C": [ 1, 1.25, 1.5, 2, 3 ], - "N": [ 1, 1.1, 1.5, 2, 3 ], - "O": [ 1, 1.208, 1.5, 2, 3 ], - "F": [ 1.2, 1.418, 1.75, 2.25, 3.25 ], - "Ne": [ 1.5, 1.75, 2.25, 2.625, 3, 3.5 ], - "Na": [ 2.05, 2.4, 2.8, 3.1, 3.3, 3.8, 4.3 ], - "Mg": [ 2.125, 2.375, 2.875, 3.375, 4.5 ], - "Al": [ 2, 2.5, 3, 3.75, 4.5 ], - "Si": [ 1.75, 2, 2.25, 2.75, 3.75 ], - "P": [ 1.625, 1.875, 2.5, 3.25, 4 ], - "S": [ 1.6, 1.9, 2.5, 3.25, 4 ], - "Cl": [ 1.65, 2, 2.5, 3.25, 4 ], - "Ar": [ 2.25, 2.625, 3, 3.375, 4 ], - "K": [ 1.8, 2.6, 3.4, 3.8, 4, 4.4, 4.8 ], - "Ca": [ 2.5, 3, 3.5, 4, 5 ], - "Sc": [ 1.75, 2.15, 2.75, 3.5, 4.5 ], - "Ti": [ 1.6, 1.85, 2.5, 3.25, 4.25 ], - "V": [ 1.45, 1.65, 2.25, 3, 4 ], - "Cr": [ 1.375, 1.55, 2, 2.75, 3.75 ], - "Mn": [ 1.4, 1.6, 2.1, 2.75, 3.75 ], - "Fe": [ 1.45, 1.725, 2.25, 3, 4 ], - "Co": [ 1.8, 2, 2.5, 3.5 ], - "Ni": [ 1.65, 2, 2.5, 3, 4 ], - "Cu": [ 1.8, 2.2, 3, 4 ], - "Zn": [ 2, 2.3, 2.85, 3.5, 4.25 ], - "Ga": [ 1.85, 2.1, 2.45, 3, 4 ], - "Ge": [ 1.8, 2, 2.35, 3, 4 ], - "As": [ 1.75, 2.1, 2.5, 3, 4 ], - "Se": [ 1.85, 2.15, 2.5, 3, 4 ], - "Br": [ 1.9, 2.25, 2.75, 3.25, 4 ], - "Kr": [ 2.4, 3, 3.675, 4.25, 5 ], - "Rb": [ 2.45, 3, 4, 5 ], - "Sr": [ 2.75, 3.5, 4.4, 5 ], - "Y": [ 2.125, 2.5, 2.875, 3.25, 4, 5 ], - "Zr": [ 1.9, 2.25, 3, 4 ], - "Nb": [ 1.75, 2.05, 2.4, 3, 4 ], - "Mo": [ 1.675, 1.9, 2.375, 3, 4 ], - "Tc": [ 1.7, 1.915, 2.375, 3, 4 ], - "Ru": [ 1.725, 1.925, 2.375, 3, 4 ], - "Rh": [ 1.8, 2.1, 2.5, 3, 4 ], - "Pd": [ 2, 2.275, 2.75, 3.75 ], - "Ag": [ 2.1, 2.45, 3, 4 ], - "Cd": [ 2.15, 2.5, 3.1, 4, 5 ], - "In": [ 2.15, 2.5, 3, 3.75, 4.75 ], - "Sn": [ 2.1, 2.4, 3.75, 3.5, 4.5 ], - "Sb": [ 2.1, 2.5, 3, 3.5, 4.5 ], - "Te": [ 2.15, 2.55, 3.1, 3.6, 4.5 ], - "I": [ 2.22, 2.65, 3.25, 4.25 ], - "Xe": [ 3, 3.5, 4.06, 4.5, 5.25 ], - "Cs": [ 2.7, 3.5, 4.5, 5.5 ], - "Ba": [ 2.65, 3, 3.5, 4.4, 5.5 ], - "La": [ 2.2, 2.6, 3.25, 4, 5 ], - "Ce": [ 2, 2.375, 2.875, 3.5, 4.5 ], - "Pr": [ 1.9, 2.25, 2.75, 3.5, 4.5 ], - "Nd": [ 1.8, 2.125, 2.625, 3.375, 4.5 ], - "Pm": [ 1.775, 2.05, 2.5, 3.25, 4.25 ], - "Sm": [ 1.775, 2.05, 2.5, 3.25, 4.25 ], - "Eu": [ 1.775, 2.075, 2.5, 3.25, 4.25 ], - "Gd": [ 1.8, 2.11, 2.625, 3.375, 4.1, 5 ], - "Tb": [ 1.825, 2.16, 2.625, 3.375, 4.1, 5 ], - "Dy": [ 1.85, 2.24, 2.625, 3.375, 4.1, 5 ], - "Ho": [ 1.93, 2.375, 3, 4.1, 5 ], - "Er": [ 2.025, 2.5, 3.125, 4.1, 5 ], - "Tm": [ 2.2, 2.625, 3.25, 4.1, 5 ], - "Yb": [ 2.5, 3, 3.5, 4.1, 5 ], - "Lu": [ 2.2, 2.5, 3.04, 4, 5 ], - "Hf": [ 1.975, 2.49, 3.25, 4.5 ], - "Ta": [ 1.85, 2.12, 2.625, 3.25, 4.5 ], - "W": [ 1.775, 1.99, 2.5, 3.25, 4.5 ], - "Re": [ 1.775, 2.01, 2.5, 3.25, 4.25 ], - "Os": [ 1.8, 2.04, 2.5, 3.25, 4.5 ], - "Ir": [ 1.85, 2.125, 2.5, 3.25, 4.25 ], - "Pt": [ 2, 2.275, 2.75, 3.75 ], - "Au": [ 2.1, 2.45, 3, 4 ], - "Hg": [ 2.225, 2.5, 3.04, 4, 5 ], - "Tl": [ 2.21, 2.6, 3.11, 3.75, 4.75 ], - "Pb": [ 2.225, 2.5, 2.88, 3.625, 4.5 ], - "Bi": [ 2.225, 2.61, 3.125, 3.75, 4.75 ], - "Po": [ 2.3, 2.72, 3.25, 3.875, 4.75 ], - "At": [ 2.375, 2.83, 3.5, 4.5 ], - "Rn": [ 2.8, 3.5, 4.17, 4.75, 5.5 ], - "Fr": [ 2.85, 3.5, 4.43, 5.5 ], - "Ra": [ 3.15, 3.5, 4.25, 5.12, 6 ], - "Ac": [ 2.48, 3.1, 3.72, 4.25, 5 ], - "Th": [ 2.25, 2.65, 3.25, 4, 5 ], - "Pa": [ 2.04, 2.3, 3, 3.75, 4.75 ], - "U": [ 1.89, 2.09, 2.75, 3.5, 4.5 ], - "Np": [ 1.84, 2.05, 2.625, 3.375, 4.5 ], - "Pu": [ 1.81, 2.02, 2.5, 3.25, 4.25 ], - "Am": [ 1.81, 2.03, 2.5, 3.25, 4.25 ], - "Cm": [ 1.83, 2.07, 2.5, 3.25, 4.25 ], - "Bk": [ 1.86, 2.12, 2.5, 3, 4 ], - "Cf": [ 1.89, 2.19, 2.625, 3.125, 4 ], - "Es": [ 1.93, 2.29, 2.625, 3.125, 4 ], - "Fm": [ 1.98, 2.375, 2.75, 3.25, 4.25 ], - "Md": [ 2.08, 2.5, 3, 3.43, 4.25 ], - "No": [ 2.6, 3.125, 3.75, 4.27, 5 ] -} \ No newline at end of file + "H": [0.6, 0.75, 0.9, 1.2, 1.5], + "He": [1.25, 1.75, 2.4, 3.25], + "Li": [1.5, 2.1, 2.5, 2.8, 3.2, 3.5, 4.2], + "Be": [1.75, 2, 2.375, 3, 4], + "B": [1.25, 1.625, 2.5, 3.5], + "C": [1, 1.25, 1.5, 2, 3], + "N": [1, 1.1, 1.5, 2, 3], + "O": [1, 1.208, 1.5, 2, 3], + "F": [1.2, 1.418, 1.75, 2.25, 3.25], + "Ne": [1.5, 1.75, 2.25, 2.625, 3, 3.5], + "Na": [2.05, 2.4, 2.8, 3.1, 3.3, 3.8, 4.3], + "Mg": [2.125, 2.375, 2.875, 3.375, 4.5], + "Al": [2, 2.5, 3, 3.75, 4.5], + "Si": [1.75, 2, 2.25, 2.75, 3.75], + "P": [1.625, 1.875, 2.5, 3.25, 4], + "S": [1.6, 1.9, 2.5, 3.25, 4], + "Cl": [1.65, 2, 2.5, 3.25, 4], + "Ar": [2.25, 2.625, 3, 3.375, 4], + "K": [1.8, 2.6, 3.4, 3.8, 4, 4.4, 4.8], + "Ca": [2.5, 3, 3.5, 4, 5], + "Sc": [1.75, 2.15, 2.75, 3.5, 4.5], + "Ti": [1.6, 1.85, 2.5, 3.25, 4.25], + "V": [1.45, 1.65, 2.25, 3, 4], + "Cr": [1.375, 1.55, 2, 2.75, 3.75], + "Mn": [1.4, 1.6, 2.1, 2.75, 3.75], + "Fe": [1.45, 1.725, 2.25, 3, 4], + "Co": [1.8, 2, 2.5, 3.5], + "Ni": [1.65, 2, 2.5, 3, 4], + "Cu": [1.8, 2.2, 3, 4], + "Zn": [2, 2.3, 2.85, 3.5, 4.25], + "Ga": [1.85, 2.1, 2.45, 3, 4], + "Ge": [1.8, 2, 2.35, 3, 4], + "As": [1.75, 2.1, 2.5, 3, 4], + "Se": [1.85, 2.15, 2.5, 3, 4], + "Br": [1.9, 2.25, 2.75, 3.25, 4], + "Kr": [2.4, 3, 3.675, 4.25, 5], + "Rb": [2.45, 3, 4, 5], + "Sr": [2.75, 3.5, 4.4, 5], + "Y": [2.125, 2.5, 2.875, 3.25, 4, 5], + "Zr": [1.9, 2.25, 3, 4], + "Nb": [1.75, 2.05, 2.4, 3, 4], + "Mo": [1.675, 1.9, 2.375, 3, 4], + "Tc": [1.7, 1.915, 2.375, 3, 4], + "Ru": [1.725, 1.925, 2.375, 3, 4], + "Rh": [1.8, 2.1, 2.5, 3, 4], + "Pd": [2, 2.275, 2.75, 3.75], + "Ag": [2.1, 2.45, 3, 4], + "Cd": [2.15, 2.5, 3.1, 4, 5], + "In": [2.15, 2.5, 3, 3.75, 4.75], + "Sn": [2.1, 2.4, 3.75, 3.5, 4.5], + "Sb": [2.1, 2.5, 3, 3.5, 4.5], + "Te": [2.15, 2.55, 3.1, 3.6, 4.5], + "I": [2.22, 2.65, 3.25, 4.25], + "Xe": [3, 3.5, 4.06, 4.5, 5.25], + "Cs": [2.7, 3.5, 4.5, 5.5], + "Ba": [2.65, 3, 3.5, 4.4, 5.5], + "La": [2.2, 2.6, 3.25, 4, 5], + "Ce": [2, 2.375, 2.875, 3.5, 4.5], + "Pr": [1.9, 2.25, 2.75, 3.5, 4.5], + "Nd": [1.8, 2.125, 2.625, 3.375, 4.5], + "Pm": [1.775, 2.05, 2.5, 3.25, 4.25], + "Sm": [1.775, 2.05, 2.5, 3.25, 4.25], + "Eu": [1.775, 2.075, 2.5, 3.25, 4.25], + "Gd": [1.8, 2.11, 2.625, 3.375, 4.1, 5], + "Tb": [1.825, 2.16, 2.625, 3.375, 4.1, 5], + "Dy": [1.85, 2.24, 2.625, 3.375, 4.1, 5], + "Ho": [1.93, 2.375, 3, 4.1, 5], + "Er": [2.025, 2.5, 3.125, 4.1, 5], + "Tm": [2.2, 2.625, 3.25, 4.1, 5], + "Yb": [2.5, 3, 3.5, 4.1, 5], + "Lu": [2.2, 2.5, 3.04, 4, 5], + "Hf": [1.975, 2.49, 3.25, 4.5], + "Ta": [1.85, 2.12, 2.625, 3.25, 4.5], + "W": [1.775, 1.99, 2.5, 3.25, 4.5], + "Re": [1.775, 2.01, 2.5, 3.25, 4.25], + "Os": [1.8, 2.04, 2.5, 3.25, 4.5], + "Ir": [1.85, 2.125, 2.5, 3.25, 4.25], + "Pt": [2, 2.275, 2.75, 3.75], + "Au": [2.1, 2.45, 3, 4], + "Hg": [2.225, 2.5, 3.04, 4, 5], + "Tl": [2.21, 2.6, 3.11, 3.75, 4.75], + "Pb": [2.225, 2.5, 2.88, 3.625, 4.5], + "Bi": [2.225, 2.61, 3.125, 3.75, 4.75], + "Po": [2.3, 2.72, 3.25, 3.875, 4.75], + "At": [2.375, 2.83, 3.5, 4.5], + "Rn": [2.8, 3.5, 4.17, 4.75, 5.5], + "Fr": [2.85, 3.5, 4.43, 5.5], + "Ra": [3.15, 3.5, 4.25, 5.12, 6], + "Ac": [2.48, 3.1, 3.72, 4.25, 5], + "Th": [2.25, 2.65, 3.25, 4, 5], + "Pa": [2.04, 2.3, 3, 3.75, 4.75], + "U": [1.89, 2.09, 2.75, 3.5, 4.5], + "Np": [1.84, 2.05, 2.625, 3.375, 4.5], + "Pu": [1.81, 2.02, 2.5, 3.25, 4.25], + "Am": [1.81, 2.03, 2.5, 3.25, 4.25], + "Cm": [1.83, 2.07, 2.5, 3.25, 4.25], + "Bk": [1.86, 2.12, 2.5, 3, 4], + "Cf": [1.89, 2.19, 2.625, 3.125, 4], + "Es": [1.93, 2.29, 2.625, 3.125, 4], + "Fm": [1.98, 2.375, 2.75, 3.25, 4.25], + "Md": [2.08, 2.5, 3, 3.43, 4.25], + "No": [2.6, 3.125, 3.75, 4.27, 5], +} diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/generate_orbital_mixstru.sh b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/generate_orbital_mixstru.sh index a810997e5ed..0a5207ca6d7 100755 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/generate_orbital_mixstru.sh +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/generate_orbital_mixstru.sh @@ -247,11 +247,11 @@ echo " -------------------------------------------------------> $element" # (1.2) make the dir, the name is 'name' if ( test -d $name ) -then - echo " The dir exist: $name" +then + echo " The dir exist: $name" else - echo " Make dir: $name" - mkdir $name + echo " Make dir: $name" + mkdir $name fi # (1.3) enter the name dir @@ -261,9 +261,9 @@ cd $name count_r=1 while [ $count_r -le $rcut_number ] do - # (1.4.1) - rcut=`echo "$info_r" | awk '{print $'$count_r'}' ` - echo " |run cicle: rcut=$rcut" + # (1.4.1) + rcut=`echo "$info_r" | awk '{print $'$count_r'}' ` + echo " |run cicle: rcut=$rcut" # (1.x.x)enter the third big cicle: each iSTRU @@ -273,19 +273,19 @@ do echo " |skip cicle: iSTRU=$iSTRU" continue; fi - echo " |run cicle: iSTRU=$iSTRU" + echo " |run cicle: iSTRU=$iSTRU" - # (1.4.2) enter the forth big cicle : each Bond Length. - count=1 - while [ $count -le ${BL_number[iSTRU]} ] - do + # (1.4.2) enter the forth big cicle : each Bond Length. + count=1 + while [ $count -le ${BL_number[iSTRU]} ] + do - # (1.4.2.0) calculate the Bond Length for iSTRU - BL=`echo "${info[iSTRU]}" | awk '{print $'$count'}' ` + # (1.4.2.0) calculate the Bond Length for iSTRU + BL=`echo "${info[iSTRU]}" | awk '{print $'$count'}' ` dis1=$(echo "scale=5;$BL * 0.86603 "|bc) dis2=$(echo "scale=5;$BL * 0.5 "|bc) - dis3=$(echo "scale=5;$BL * 0.81649 "|bc) - dis4=$(echo "scale=5;$BL * 0.28867 "|bc) + dis3=$(echo "scale=5;$BL * 0.81649 "|bc) + dis4=$(echo "scale=5;$BL * 0.28867 "|bc) echo " |run cicle: BL=$BL" @@ -510,7 +510,7 @@ nspin 1 lmaxmax $maxL symmetry 0 -nbands ${nbands[iSTRU]} +nbands ${nbands[iSTRU]} ecutwfc $ecut scf_thr 1.0e-7 // about iteration @@ -522,7 +522,7 @@ smearing_sigma $smearing_sigma mixing_type pulay // about charge mixing mixing_beta 0.4 mixing_ndim 8 -printe 1 +printe 1 EOF let count++ @@ -682,7 +682,7 @@ cat >> INPUT << EOF 1 //number of k points -1 // number of pools +1 // number of pools diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/info.json b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/info.json index 493b4c1b783..a79ce1fe11e 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/info.json +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/info.json @@ -1,20 +1,20 @@ { - "exe": - { - "exe_pw": "/home/nic/wszhang/eclipse_project/abacus-NewGit/ABACUS.1.0.0/bin/20160621ABACUS.mpi.1.0.0", - "exe_orbital": "/home/nic/wszhang/eclipse_project/abacus-NewGit/ABACUS.1.0.0/tools/opt_orb_pytorch/main.py", - "qsub": [1,8] - }, - "input": - { - "element": "Si", - "ref_bands": 4.0, - "nbands": 8.0, - "ecut": 100, - "rcut": 6, - "pseudo_dir": "/home/nic/wszhang/eclipse_project/delta_dft/CIF_POT/SG15_ONCV_PBE-1.0/", - "pseudo": "Si_ONCV_PBE-1.0.upf", - "smearing_sigma": 0.01 - }, - "orbital": [2,2,1] + "exe": + { + "exe_pw": "/home/nic/wszhang/eclipse_project/abacus-NewGit/ABACUS.1.0.0/bin/20160621ABACUS.mpi.1.0.0", + "exe_orbital": "/home/nic/wszhang/eclipse_project/abacus-NewGit/ABACUS.1.0.0/tools/opt_orb_pytorch/main.py", + "qsub": [1,8] + }, + "input": + { + "element": "Si", + "ref_bands": 4.0, + "nbands": 8.0, + "ecut": 100, + "rcut": 6, + "pseudo_dir": "/home/nic/wszhang/eclipse_project/delta_dft/CIF_POT/SG15_ONCV_PBE-1.0/", + "pseudo": "Si_ONCV_PBE-1.0.upf", + "smearing_sigma": 0.01 + }, + "orbital": [2,2,1] } diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/info_linpz.json b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/info_linpz.json index d7671d2dc86..511c2714784 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/info_linpz.json +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/info_linpz.json @@ -1,21 +1,21 @@ { - "exe": - { - "exe_pw": "/home/linpz/ABACUS/ABACUS.1.0.1_2016-12-19/bin/ABACUS.mpi.1.0.0", - "exe_orbital": "/home/linpz/ABACUS/ABACUS_RI_git/tools/opt_orb_pytorch/main.py", - "qsub": [1,8], + "exe": + { + "exe_pw": "/home/linpz/ABACUS/ABACUS.1.0.1_2016-12-19/bin/ABACUS.mpi.1.0.0", + "exe_orbital": "/home/linpz/ABACUS/ABACUS_RI_git/tools/opt_orb_pytorch/main.py", + "qsub": [1,8], "_comment": "comment for qsub: [np,nthread] ", - }, - "input": - { - "element": "N", - "ref_bands": 5, - "nbands": 8, - "ecut": 50, - "rcut": 6, - "pseudo_dir": "../", - "pseudo": "N_ONCV_PBE-1.0.upf", - "smearing_sigma": 0.01 - }, - "orbital": [2,2,1] + }, + "input": + { + "element": "N", + "ref_bands": 5, + "nbands": 8, + "ecut": 50, + "rcut": 6, + "pseudo_dir": "../", + "pseudo": "N_ONCV_PBE-1.0.upf", + "smearing_sigma": 0.01 + }, + "orbital": [2,2,1] } diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb.py b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb.py index 9bc8691b5cb..5361e6f02e0 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb.py +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb.py @@ -6,36 +6,39 @@ from dis import dis import utils + def cal_pw(): - info = read_info("info.json") - for distance in dis[info["input"]["element"]]: - folder = f'{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}' - pathlib.Path(folder).mkdir(parents=True,exist_ok=False) - os.chdir(folder) - print_file_pw(info,distance) - if utils.sub=="qsub": - os.system("qsub sub.sh") - elif utils.sub=="bsub": - os.system("bsub < sub.sh") - else: - raise KeyError("utils.sub = ",utils.sub) - os.chdir("../") - + info = read_info("info.json") + for distance in dis[info["input"]["element"]]: + folder = f'{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}' + pathlib.Path(folder).mkdir(parents=True, exist_ok=False) + os.chdir(folder) + print_file_pw(info, distance) + if utils.sub == "qsub": + os.system("qsub sub.sh") + elif utils.sub == "bsub": + os.system("bsub < sub.sh") + else: + raise KeyError("utils.sub = ", utils.sub) + os.chdir("../") + + def cal_opt(): - info = read_info("info.json") - pathlib.Path("opt_orb").mkdir(parents=True,exist_ok=False) - os.chdir("opt_orb") - print_file_opt(info,dis) - if utils.sub=="qsub": - os.system("qsub sub.sh") - elif utils.sub=="bsub": - os.system("bsub < sub.sh") - else: - raise KeyError("utils.sub = ",utils.sub) - os.chdir("../") - -if __name__=="__main__": - if sys.argv[1]=='1': - cal_pw() - elif sys.argv[1]=='2': - cal_opt() \ No newline at end of file + info = read_info("info.json") + pathlib.Path("opt_orb").mkdir(parents=True, exist_ok=False) + os.chdir("opt_orb") + print_file_opt(info, dis) + if utils.sub == "qsub": + os.system("qsub sub.sh") + elif utils.sub == "bsub": + os.system("bsub < sub.sh") + else: + raise KeyError("utils.sub = ", utils.sub) + os.chdir("../") + + +if __name__ == "__main__": + if sys.argv[1] == "1": + cal_pw() + elif sys.argv[1] == "2": + cal_opt() diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/C.dat b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/C.dat index 42bf77fb797..2a7c958d902 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/C.dat +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/C.dat @@ -1,108 +1,108 @@ - Total number of radial orbitals. - Type L Zeta-Orbital - 1 0 1 - -0.19199676811695 - -0.42662301659584 - -0.00396813778207 - 0.20699395239353 - 0.34481701254845 - 0.17653037607670 - 0.16215451061726 - 0.02640141732991 - 0.03819778189063 - -0.01881365850568 - 0.00475356727839 - -0.00619863439351 - -0.00136023212690 - 0.00962408073246 - -0.00935681536794 - 0.01730877906084 - -0.02055048942566 - 0.02749578095973 - -0.05699118971825 - Type L Zeta-Orbital - 1 0 2 - 0.30962923169136 - -0.16427905857563 - 0.08350813388824 - 0.06277896463871 - 0.31105494499207 - 0.02079799026251 - 0.17415840923786 - -0.06041001901031 - 0.09245581179857 - -0.07529501616955 - 0.06037591025233 - -0.05913654714823 - 0.04711834713817 - -0.04198740422726 - 0.03929244354367 - -0.03382994607091 - 0.03340724855661 - -0.03432041406631 - 0.05123715847731 - Type L Zeta-Orbital - 1 1 1 - 0.25186207890511 - -0.20918227732182 - -0.08370970934629 - -0.15929590165615 - 0.08962316811085 - -0.08605520427227 - 0.09530898928642 - -0.07312455028296 - 0.07764542102814 - -0.07303284853697 - 0.06055606529117 - -0.05832349136472 - 0.05315782502294 - -0.04757346212864 - 0.04572277888656 - -0.04357923939824 - 0.04375959560275 - -0.04557648673654 - 0.14015159010887 - Type L Zeta-Orbital - 1 1 2 - 0.14663653075695 - -0.45157122612000 - -0.24329291284084 - -0.23687231540680 - 0.08860915154219 - -0.09253106266260 - 0.10457736253738 - -0.07112644612789 - 0.07671085745096 - -0.06851065903902 - 0.04920373484492 - -0.04355899244547 - 0.03515684232116 - -0.02379258535802 - 0.01789759658277 - -0.01059364248067 - 0.00445373868570 - 0.00087588251336 - -0.07497041672468 - Type L Zeta-Orbital - 1 2 1 - -0.03181628510356 - -0.06655264645815 - -0.05716326087713 - -0.03969582915306 - -0.02385406382382 - -0.02287989854813 - -0.01499674562365 - -0.01447977125645 - -0.00762272952124 - -0.00876726862043 - -0.00291843665764 - -0.00510095292702 - 0.00015748980513 - -0.00368582759984 - 0.00161157804541 - -0.00293236947618 - 0.00256342999637 - -0.00244636344723 - 0.01787436939776 + Total number of radial orbitals. + Type L Zeta-Orbital + 1 0 1 + -0.19199676811695 + -0.42662301659584 + -0.00396813778207 + 0.20699395239353 + 0.34481701254845 + 0.17653037607670 + 0.16215451061726 + 0.02640141732991 + 0.03819778189063 + -0.01881365850568 + 0.00475356727839 + -0.00619863439351 + -0.00136023212690 + 0.00962408073246 + -0.00935681536794 + 0.01730877906084 + -0.02055048942566 + 0.02749578095973 + -0.05699118971825 + Type L Zeta-Orbital + 1 0 2 + 0.30962923169136 + -0.16427905857563 + 0.08350813388824 + 0.06277896463871 + 0.31105494499207 + 0.02079799026251 + 0.17415840923786 + -0.06041001901031 + 0.09245581179857 + -0.07529501616955 + 0.06037591025233 + -0.05913654714823 + 0.04711834713817 + -0.04198740422726 + 0.03929244354367 + -0.03382994607091 + 0.03340724855661 + -0.03432041406631 + 0.05123715847731 + Type L Zeta-Orbital + 1 1 1 + 0.25186207890511 + -0.20918227732182 + -0.08370970934629 + -0.15929590165615 + 0.08962316811085 + -0.08605520427227 + 0.09530898928642 + -0.07312455028296 + 0.07764542102814 + -0.07303284853697 + 0.06055606529117 + -0.05832349136472 + 0.05315782502294 + -0.04757346212864 + 0.04572277888656 + -0.04357923939824 + 0.04375959560275 + -0.04557648673654 + 0.14015159010887 + Type L Zeta-Orbital + 1 1 2 + 0.14663653075695 + -0.45157122612000 + -0.24329291284084 + -0.23687231540680 + 0.08860915154219 + -0.09253106266260 + 0.10457736253738 + -0.07112644612789 + 0.07671085745096 + -0.06851065903902 + 0.04920373484492 + -0.04355899244547 + 0.03515684232116 + -0.02379258535802 + 0.01789759658277 + -0.01059364248067 + 0.00445373868570 + 0.00087588251336 + -0.07497041672468 + Type L Zeta-Orbital + 1 2 1 + -0.03181628510356 + -0.06655264645815 + -0.05716326087713 + -0.03969582915306 + -0.02385406382382 + -0.02287989854813 + -0.01499674562365 + -0.01447977125645 + -0.00762272952124 + -0.00876726862043 + -0.00291843665764 + -0.00510095292702 + 0.00015748980513 + -0.00368582759984 + 0.00161157804541 + -0.00293236947618 + 0.00256342999637 + -0.00244636344723 + 0.01787436939776 diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/ORBITAL_RESULTS.txt b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/ORBITAL_RESULTS.txt index ed99c220500..55c60ceb8b9 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/ORBITAL_RESULTS.txt +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/ORBITAL_RESULTS.txt @@ -1,108 +1,108 @@ - 5 Total number of radial orbitals. - Type L Zeta-Orbital - 1 0 1 - -0.37029626965523 - -0.32845607399940 - -0.05236993357539 - 0.16915917396545 - 0.16208435595036 - 0.16317158937454 - 0.06008159369230 - 0.06111942231655 - -0.01554259378463 - 0.02477064356208 - -0.03000785224140 - 0.02776389382780 - -0.02820792980492 - 0.03330243378878 - -0.03134765848517 - 0.03595250099897 - -0.03872996568680 - 0.04586529359221 - -0.08364135026932 - Type L Zeta-Orbital - 1 0 2 - 0.44759389758110 - 0.05423882603645 - 0.09421791136265 - -0.04740507528186 - 0.15205667912960 - -0.06914632022381 - 0.11768817901611 - -0.08118863403797 - 0.09447790682316 - -0.08625630289316 - 0.07484791427851 - -0.07580946385860 - 0.06302624940872 - -0.05698876082897 - 0.05341921746731 - -0.04328351095319 - 0.04037299007177 - -0.03715490549803 - 0.04147742688656 - Type L Zeta-Orbital - 1 1 1 - -0.03850352764130 - 0.78923970460892 - 0.45826691389084 - 0.35484749078751 - -0.10603722929955 - 0.11701935529709 - -0.13467907905579 - 0.08430394530296 - -0.09366131573915 - 0.07933947443962 - -0.05581488460302 - 0.04933071136475 - -0.03924917057157 - 0.02653631381691 - -0.02039544284344 - 0.01263934932649 - -0.00650039361790 - 0.00118041725364 - 0.06417543441057 - Type L Zeta-Orbital - 1 1 2 - 0.16830199956894 - -0.28665229678154 - -0.14189192652702 - -0.17033232748508 - 0.08038503676653 - -0.07949967682362 - 0.08882774412632 - -0.06532122939825 - 0.07081296294928 - -0.06477906554937 - 0.05393818393350 - -0.05239685997367 - 0.04906428605318 - -0.04467587545514 - 0.04411740228534 - -0.04331725090742 - 0.04480121657252 - -0.04789821431041 - 0.16592700779438 - Type L Zeta-Orbital - 1 2 1 - -0.26238062977791 - -0.54614186286926 - -0.46579909324646 - -0.32306829094887 - -0.19440701603889 - -0.18322914838791 - -0.12065424025059 - -0.11036488413811 - -0.05986255407333 - -0.06028308346868 - -0.02166043967009 - -0.02877865545452 - -0.00323722697794 - -0.01622269488871 - 0.00376422237605 - -0.00851553026587 - 0.00649465387687 - -0.00904022529721 - 0.00542650418356 + 5 Total number of radial orbitals. + Type L Zeta-Orbital + 1 0 1 + -0.37029626965523 + -0.32845607399940 + -0.05236993357539 + 0.16915917396545 + 0.16208435595036 + 0.16317158937454 + 0.06008159369230 + 0.06111942231655 + -0.01554259378463 + 0.02477064356208 + -0.03000785224140 + 0.02776389382780 + -0.02820792980492 + 0.03330243378878 + -0.03134765848517 + 0.03595250099897 + -0.03872996568680 + 0.04586529359221 + -0.08364135026932 + Type L Zeta-Orbital + 1 0 2 + 0.44759389758110 + 0.05423882603645 + 0.09421791136265 + -0.04740507528186 + 0.15205667912960 + -0.06914632022381 + 0.11768817901611 + -0.08118863403797 + 0.09447790682316 + -0.08625630289316 + 0.07484791427851 + -0.07580946385860 + 0.06302624940872 + -0.05698876082897 + 0.05341921746731 + -0.04328351095319 + 0.04037299007177 + -0.03715490549803 + 0.04147742688656 + Type L Zeta-Orbital + 1 1 1 + -0.03850352764130 + 0.78923970460892 + 0.45826691389084 + 0.35484749078751 + -0.10603722929955 + 0.11701935529709 + -0.13467907905579 + 0.08430394530296 + -0.09366131573915 + 0.07933947443962 + -0.05581488460302 + 0.04933071136475 + -0.03924917057157 + 0.02653631381691 + -0.02039544284344 + 0.01263934932649 + -0.00650039361790 + 0.00118041725364 + 0.06417543441057 + Type L Zeta-Orbital + 1 1 2 + 0.16830199956894 + -0.28665229678154 + -0.14189192652702 + -0.17033232748508 + 0.08038503676653 + -0.07949967682362 + 0.08882774412632 + -0.06532122939825 + 0.07081296294928 + -0.06477906554937 + 0.05393818393350 + -0.05239685997367 + 0.04906428605318 + -0.04467587545514 + 0.04411740228534 + -0.04331725090742 + 0.04480121657252 + -0.04789821431041 + 0.16592700779438 + Type L Zeta-Orbital + 1 2 1 + -0.26238062977791 + -0.54614186286926 + -0.46579909324646 + -0.32306829094887 + -0.19440701603889 + -0.18322914838791 + -0.12065424025059 + -0.11036488413811 + -0.05986255407333 + -0.06028308346868 + -0.02166043967009 + -0.02877865545452 + -0.00323722697794 + -0.01622269488871 + 0.00376422237605 + -0.00851553026587 + 0.00649465387687 + -0.00904022529721 + 0.00542650418356 diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/input.json b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/input.json index bcdce6134cd..f767e10d4b9 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/input.json +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/input.json @@ -40,7 +40,7 @@ "Ecut": { "Si": 100 }, - "lr": 0.01 + "lr": 0.01 }, "C_init_info": { "init_from_file": false diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/running_stdout.log b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/running_stdout.log index 17399cb3a66..e4a3234d54d 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/running_stdout.log +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/opt_orb/running_stdout.log @@ -24,19 +24,19 @@ Si 3 3 read QI: 4 0 read SI: 4 0 read VI: 4 0 -Nt_all ['Si'] -Nu {'Si': [2, 2, 1]} -Nb_true [4.0, 4.0, 4.0, 4.0, 4.0] -weight [1.0, 1.0, 1.0, 1.0, 1.0] -Rcut {'Si': 6} -dr {'Si': 0.01} -Ecut {'Si': 100} -lr 0.01 -Nl {'Si': 3} -Nst 5 -Nt [['Si'], ['Si'], ['Si'], ['Si'], ['Si']] -Na [{'Si': 2}, {'Si': 2}, {'Si': 2}, {'Si': 2}, {'Si': 2}] -Nb [8, 8, 8, 8, 8] -Ne {'Si': 19} +Nt_all ['Si'] +Nu {'Si': [2, 2, 1]} +Nb_true [4.0, 4.0, 4.0, 4.0, 4.0] +weight [1.0, 1.0, 1.0, 1.0, 1.0] +Rcut {'Si': 6} +dr {'Si': 0.01} +Ecut {'Si': 100} +lr 0.01 +Nl {'Si': 3} +Nst 5 +Nt [['Si'], ['Si'], ['Si'], ['Si'], ['Si']] +Na [{'Si': 2}, {'Si': 2}, {'Si': 2}, {'Si': 2}, {'Si': 2}] +Nb [8, 8, 8, 8, 8] +Ne {'Si': 19} See "Spillage.dat" for running status -Time: 370.14801597595215 +Time: 370.14801597595215 diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/print_file.py b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/print_file.py index cdf317ffc00..c3c8653b3b1 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/print_file.py +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/print_file.py @@ -2,185 +2,175 @@ import utils import textwrap -def print_file_pw(info,dis): - - with open("INPUT","w") as file: - file.write(textwrap.dedent(f"""\ - INPUT_PARAMETERS - pseudo_dir {info["input"]["pseudo_dir"]} - calculation scf - ntype 1 - nspin 1 - lmaxmax {len(info["orbital"])-1} - - symmetry 0 - nbands {info["input"]["nbands"]} - - ecutwfc {info["input"]["ecut"]} - scf_thr 2.0e-8 // about iteration - scf_nmax 1000 - - smearing_method gauss - smearing_sigma {info["input"]["smearing_sigma"]} - - mixing_type pulay // about charge mixing - mixing_beta 0.4 - mixing_ndim 8 - printe 1 - """)) - - - - with open("INPUTw","w") as file: - file.write(textwrap.dedent(f"""\ - WANNIER_PARAMETERS - rcut 10 - out_spillage 2 - """)) - - - - with open("INPUTs","w") as file: - file.write(textwrap.dedent(f"""\ - INPUT_ORBITAL_INFORMATION - - 1 // smooth or not - 0.1 // smearing_sigma - {info["input"]["ecut"]} // energy cutoff for spherical bessel functions(Ry) - {info["input"]["rcut"]} // cutoff of wavefunctions(a.u.) - 1.0e-12 // tolerence - - """)) - - - - with open("STRU","w") as file: - file.write("ATOMIC_SPECIES\n") - file.write(f'{info["input"]["element"]} 1 {info["input"]["pseudo"]}\n') - file.write(textwrap.dedent(f"""\ - LATTICE_CONSTANT - {utils.lat0}\n - LATTICE_VECTORS - 1 0 0 - 0 1 0 - 0 0 1\n - ATOMIC_POSITIONS - Cartesian_angstrom - """)) - if info["input"]["element"] in ["Na","Li","K","Ca"]: - file.write(textwrap.dedent(f"""\ - {info["input"]["element"]} - 0.0 - 3 - 0 0 0 0 0 0 - 0 0 {dis} 0 0 0 - 0 {dis*0.86603} {dis*0.5} 0 0 0 - """)) - else: - file.write(textwrap.dedent(f"""\ - {info["input"]["element"]} - 0.0 - 2 - 0 0 0 0 0 0 - 0 0 {dis} 0 0 0 - """)) - - - - with open("KPT","w") as file: - file.write(textwrap.dedent(f"""\ - K_POINTS - 0 - Gamma - 1 1 1 0 0 0 - """)) - - - - if utils.sub=="qsub": - with open("sub.sh","w") as file: - core = info["exe"]["qsub"][0]*info["exe"]["qsub"][1] - file.write(textwrap.dedent(f"""\ - #!/bin/bash - #PBS -q gold5120 - #PBS -l nodes={info["exe"]["qsub"][0]}:ppn={info["exe"]["qsub"][1]} - #PBS -l walltime=1:00:00 - #PBS -o job.log - #PBS -e job.err - ulimit -s unlimited - cd $PBS_O_WORKDIR - EXEC={info["exe"]["exe_pw"]} - mpirun -n {core} -env OMP_NUM_THREADS=1 $EXEC - """)) - elif utils.sub=="bsub": - with open("sub.sh","w") as file: - core = info["exe"]["qsub"][0]*info["exe"]["qsub"][1] - file.write(textwrap.dedent(f"""\ - #!/bin/sh - #BSUB -q renxg - #BSUB -o job.log -e job.err - #BSUB -n {core} - EXEC={info["exe"]["exe_pw"]} - mpirun -n {core} -env OMP_NUM_THREADS=1 $EXEC - """)) - else: - raise KeyError("utils.sub = ",utils.sub) - - - - - -def print_file_opt(info,dis): - - with open("input.json","w") as file: - input = { - "file_list": [ f'../{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}/test.{utils.lat0}.dat' for distance in dis[info["input"]["element"]] ], - "info": { - "Nt_all": [info["input"]["element"]], - "Nu": {info["input"]["element"] : info["orbital"]}, - "Nb_true": info["input"]["ref_bands"] if isinstance(info["input"]["ref_bands"],list) else [info["input"]["ref_bands"]] * len(dis[info["input"]["element"]]), - "weight": [1] * len(dis[info["input"]["element"]]), - "Rcut": {info["input"]["element"] : info["input"]["rcut"]}, - "dr": {info["input"]["element"] : utils.dr}, - "Ecut": {info["input"]["element"] : info["input"]["ecut"]}, - "lr": utils.lr - }, - "C_init_info": { - "init_from_file": False - }, - "V_info": { - "same_band": True, - "init_from_file": False - } - } - file.write(json.dumps(input,indent=4)) - - - if utils.sub=="qsub": - with open("sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/bash - #PBS -q gold5120 - #PBS -l nodes=1:ppn=1 - #PBS -l walltime=1:00:00 - #PBS -o job.log - #PBS -e job.err - ulimit -s unlimited - cd $PBS_O_WORKDIR - export OMP_NUM_THREADS=1 - EXEC={info["exe"]["exe_orbital"]} - python3 $EXEC - """)) - elif utils.sub=="bsub": - with open("sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/sh - #BSUB -q renxg - #BSUB -o job.log -e job.err - #BSUB -n 1 - export OMP_NUM_THREADS=1 - EXEC={info["exe"]["exe_orbital"]} - python3 $EXEC - """)) - else: - raise KeyError("utils.sub = ",utils.sub) \ No newline at end of file + +def print_file_pw(info, dis): + + with open("INPUT", "w") as file: + file.write(textwrap.dedent(f"""\ + INPUT_PARAMETERS + pseudo_dir {info["input"]["pseudo_dir"]} + calculation scf + ntype 1 + nspin 1 + lmaxmax {len(info["orbital"])-1} + + symmetry 0 + nbands {info["input"]["nbands"]} + + ecutwfc {info["input"]["ecut"]} + scf_thr 2.0e-8 // about iteration + scf_nmax 1000 + + smearing_method gauss + smearing_sigma {info["input"]["smearing_sigma"]} + + mixing_type pulay // about charge mixing + mixing_beta 0.4 + mixing_ndim 8 + printe 1 + """)) + + with open("INPUTw", "w") as file: + file.write(textwrap.dedent(f"""\ + WANNIER_PARAMETERS + rcut 10 + out_spillage 2 + """)) + + with open("INPUTs", "w") as file: + file.write(textwrap.dedent(f"""\ + INPUT_ORBITAL_INFORMATION + + 1 // smooth or not + 0.1 // smearing_sigma + {info["input"]["ecut"]} // energy cutoff for spherical bessel functions(Ry) + {info["input"]["rcut"]} // cutoff of wavefunctions(a.u.) + 1.0e-12 // tolerence + + """)) + + with open("STRU", "w") as file: + file.write("ATOMIC_SPECIES\n") + file.write(f'{info["input"]["element"]} 1 {info["input"]["pseudo"]}\n') + file.write(textwrap.dedent(f"""\ + LATTICE_CONSTANT + {utils.lat0}\n + LATTICE_VECTORS + 1 0 0 + 0 1 0 + 0 0 1\n + ATOMIC_POSITIONS + Cartesian_angstrom + """)) + if info["input"]["element"] in ["Na", "Li", "K", "Ca"]: + file.write(textwrap.dedent(f"""\ + {info["input"]["element"]} + 0.0 + 3 + 0 0 0 0 0 0 + 0 0 {dis} 0 0 0 + 0 {dis*0.86603} {dis*0.5} 0 0 0 + """)) + else: + file.write(textwrap.dedent(f"""\ + {info["input"]["element"]} + 0.0 + 2 + 0 0 0 0 0 0 + 0 0 {dis} 0 0 0 + """)) + + with open("KPT", "w") as file: + file.write(textwrap.dedent(f"""\ + K_POINTS + 0 + Gamma + 1 1 1 0 0 0 + """)) + + if utils.sub == "qsub": + with open("sub.sh", "w") as file: + core = info["exe"]["qsub"][0] * info["exe"]["qsub"][1] + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #PBS -q gold5120 + #PBS -l nodes={info["exe"]["qsub"][0]}:ppn={info["exe"]["qsub"][1]} + #PBS -l walltime=1:00:00 + #PBS -o job.log + #PBS -e job.err + ulimit -s unlimited + cd $PBS_O_WORKDIR + EXEC={info["exe"]["exe_pw"]} + mpirun -n {core} -env OMP_NUM_THREADS=1 $EXEC + """)) + elif utils.sub == "bsub": + with open("sub.sh", "w") as file: + core = info["exe"]["qsub"][0] * info["exe"]["qsub"][1] + file.write(textwrap.dedent(f"""\ + #!/bin/sh + #BSUB -q renxg + #BSUB -o job.log -e job.err + #BSUB -n {core} + EXEC={info["exe"]["exe_pw"]} + mpirun -n {core} -env OMP_NUM_THREADS=1 $EXEC + """)) + else: + raise KeyError("utils.sub = ", utils.sub) + + +def print_file_opt(info, dis): + + with open("input.json", "w") as file: + input = { + "file_list": [ + f'../{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}/test.{utils.lat0}.dat' + for distance in dis[info["input"]["element"]] + ], + "info": { + "Nt_all": [info["input"]["element"]], + "Nu": {info["input"]["element"]: info["orbital"]}, + "Nb_true": ( + info["input"]["ref_bands"] + if isinstance(info["input"]["ref_bands"], list) + else [info["input"]["ref_bands"]] + * len(dis[info["input"]["element"]]) + ), + "weight": [1] * len(dis[info["input"]["element"]]), + "Rcut": {info["input"]["element"]: info["input"]["rcut"]}, + "dr": {info["input"]["element"]: utils.dr}, + "Ecut": {info["input"]["element"]: info["input"]["ecut"]}, + "lr": utils.lr, + }, + "C_init_info": {"init_from_file": False}, + "V_info": {"same_band": True, "init_from_file": False}, + } + file.write(json.dumps(input, indent=4)) + + if utils.sub == "qsub": + with open("sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #PBS -q gold5120 + #PBS -l nodes=1:ppn=1 + #PBS -l walltime=1:00:00 + #PBS -o job.log + #PBS -e job.err + ulimit -s unlimited + cd $PBS_O_WORKDIR + export OMP_NUM_THREADS=1 + EXEC={info["exe"]["exe_orbital"]} + python3 $EXEC + """)) + elif utils.sub == "bsub": + with open("sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/sh + #BSUB -q renxg + #BSUB -o job.log -e job.err + #BSUB -n 1 + export OMP_NUM_THREADS=1 + EXEC={info["exe"]["exe_orbital"]} + python3 $EXEC + """)) + else: + raise KeyError("utils.sub = ", utils.sub) diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/read_info.py b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/read_info.py index 2f28f9f6043..e8062d9a77b 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/read_info.py +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/read_info.py @@ -1,34 +1,35 @@ import json import os + def read_info(file_name): - with open(file_name,"r") as file: - info = file.read() - info = json.loads(info) - info["input"]["pseudo_dir"] = os.path.abspath(info["input"].get("pseudo_dir","./")) - info["exe"]["qsub"] = info["exe"].get("qsub",[1,1]) - return info + with open(file_name, "r") as file: + info = file.read() + info = json.loads(info) + info["input"]["pseudo_dir"] = os.path.abspath(info["input"].get("pseudo_dir", "./")) + info["exe"]["qsub"] = info["exe"].get("qsub", [1, 1]) + return info + """ info.json { - "exe": - { - "exe_pw": "/home/linpz/ABACUS/ABACUS.1.0.1_2016-12-19/bin/ABACUS.mpi.1.0.0", - "exe_orbital": "/home/linpz/ABACUS/ABACUS_RI_git/tools/opt_orb_pytorch/main.py", - "qsub": [1,8] - }, - "input": - { - "element": "N", - "ref_bands": 5, or [5,5,5,5,5], - "nbands": 8, - "ecut": 50, - "rcut": 6, - "pseudo_dir": "../", - "pseudo": "N_ONCV_PBE-1.0.upf", - "smearing_sigma": 0.01 - }, - "orbital": [2,2,1] + "exe": + { + "exe_pw": "/home/linpz/ABACUS/ABACUS.1.0.1_2016-12-19/bin/ABACUS.mpi.1.0.0", + "exe_orbital": "/home/linpz/ABACUS/ABACUS_RI_git/tools/opt_orb_pytorch/main.py", + "qsub": [1,8] + }, + "input": + { + "element": "N", + "ref_bands": 5, or [5,5,5,5,5], + "nbands": 8, + "ecut": 50, + "rcut": 6, + "pseudo_dir": "../", + "pseudo": "N_ONCV_PBE-1.0.upf", + "smearing_sigma": 0.01 + }, + "orbital": [2,2,1] } """ - diff --git a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/utils.py b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/utils.py index d085415fb26..c540be2a244 100644 --- a/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/utils.py +++ b/tools/SIAB/PyTorchGradient/example_opt_lcao_bash/utils.py @@ -1,4 +1,4 @@ lat0 = 20 -dr = 0.01 -lr = 1 -sub = "qsub" \ No newline at end of file +dr = 0.01 +lr = 1 +sub = "qsub" diff --git a/tools/SIAB/PyTorchGradient/source/IO/func_C.py b/tools/SIAB/PyTorchGradient/source/IO/func_C.py index 6d5ebc31ebb..4c1e3fd614f 100644 --- a/tools/SIAB/PyTorchGradient/source/IO/func_C.py +++ b/tools/SIAB/PyTorchGradient/source/IO/func_C.py @@ -4,95 +4,100 @@ # C means Coefficient + def random_C_init(info): - """ C[it][il][ie,iu] """ - C = dict() - for it in info.Nt_all: - C[it] = ND_list(info.Nl[it]) - for il in range(info.Nl[it]): - C[it][il] = torch.tensor(np.random.uniform(-1,1, (info.Ne[it], info.Nu[it][il])), dtype=torch.float32, requires_grad=True) - return C - - - -def read_C_init(file_name,info): - """ C[it][il][ie,iu] """ - C = random_C_init(info) + """C[it][il][ie,iu]""" + C = dict() + for it in info.Nt_all: + C[it] = ND_list(info.Nl[it]) + for il in range(info.Nl[it]): + C[it][il] = torch.tensor( + np.random.uniform(-1, 1, (info.Ne[it], info.Nu[it][il])), + dtype=torch.float32, + requires_grad=True, + ) + return C + + +def read_C_init(file_name, info): + """C[it][il][ie,iu]""" + C = random_C_init(info) + + with open(file_name, "r") as file: + + for line in file: + if line.strip() == "": + line = None + break + ignore_line(file, 1) + + while True: + line = file.readline().strip() + if line.startswith("Type"): + it, il, iu = list(map(int, file.readline().split())) + it = info.Nt_all[it - 1] + iu -= 1 + line = file.readline().split() + for ie in range(info.Ne[it]): + if not line: + line = file.readline().split() + C[it][il].data[ie, iu] = float(line.pop(0)) + elif line.startswith(""): + break + else: + raise IOError("unknown line in read_C_init " + file_name + "\n" + line) + return C + + +def copy_C(C, info): + C_copy = dict() + for it in info.Nt_all: + C_copy[it] = ND_list(info.Nl[it]) + for il in range(info.Nl[it]): + C_copy[it][il] = C[it][il].clone() + return C_copy + - with open(file_name,"r") as file: - - for line in file: - if line.strip() == "": - line=None - break - ignore_line(file,1) - - while True: - line = file.readline().strip() - if line.startswith("Type"): - it,il,iu = list(map(int,file.readline().split())); - it=info.Nt_all[it-1]; iu-=1 - line = file.readline().split() - for ie in range(info.Ne[it]): - if not line: line = file.readline().split() - C[it][il].data[ie,iu] = float(line.pop(0)) - elif line.startswith(""): - break; - else: - raise IOError("unknown line in read_C_init "+file_name+"\n"+line) - return C +def write_C(file_name, info, C, Spillage): + with open(file_name, "w") as file: + print("", file=file) + nTotal = 0 + for it, C_t in C.items(): + for il, C_tl in enumerate(C_t): + for iu in range(C_tl.size()[1]): + nTotal += 1 + # nTotal = sum(info["Nu"][it]) + # + print("\t %s Total number of radial orbitals." % nTotal, file=file) + for it, C_t in C.items(): + for il, C_tl in enumerate(C_t): + for iu in range(C_tl.size()[1]): + print("\tType\tL\tZeta-Orbital", file=file) + print( + f"\t {info.Nt_all.index(it)+1} \t{il}\t {iu+1}", file=file + ) + for ie in range(C_tl.size()[0]): + print("\t", "%18.14f" % C_tl[ie, iu].item(), file=file) + print("", file=file) + print("", file=file) + print("Left spillage = %.10e" % Spillage.item(), file=file) + print("", file=file) - - -def copy_C(C,info): - C_copy = dict() - for it in info.Nt_all: - C_copy[it] = ND_list(info.Nl[it]) - for il in range(info.Nl[it]): - C_copy[it][il] = C[it][il].clone() - return C_copy - - - -def write_C(file_name,info,C,Spillage): - with open(file_name,"w") as file: - print("", file=file) - nTotal = 0 - for it,C_t in C.items(): - for il,C_tl in enumerate(C_t): - for iu in range(C_tl.size()[1]): - nTotal += 1 - #nTotal = sum(info["Nu"][it]) - # - print("\t %s Total number of radial orbitals."%nTotal , file=file) - for it,C_t in C.items(): - for il,C_tl in enumerate(C_t): - for iu in range(C_tl.size()[1]): - print("\tType\tL\tZeta-Orbital", file=file) - print(f"\t {info.Nt_all.index(it)+1} \t{il}\t {iu+1}", file=file) - for ie in range(C_tl.size()[0]): - print("\t", '%18.14f'%C_tl[ie,iu].item(), file=file) - print("", file=file) - print("", file=file) - print("Left spillage = %.10e"%Spillage.item(), file=file) - print("", file=file) - - -#def init_C(info): -# """ C[it][il][ie,iu] """ -# C = ND_list(max(info.Nt)) -# for it in range(len(C)): -# C[it] = ND_list(info.Nl[it]) -# for il in range(info.Nl[it]): -# C[it][il] = torch.autograd.Variable( torch.Tensor( info.Ne, info.Nu[it][il] ), requires_grad = True ) -# -# with open("C_init.dat","r") as file: -# line = [] -# for it in range(len(C)): -# for il in range(info.Nl[it]): -# for i_n in range(info.Nu[it][il]): -# for ie in range(info.Ne[it]): -# if not line: line=file.readline().split() -# C[it][il].data[ie,i_n] = float(line.pop(0)) -# return C +# def init_C(info): +# """ C[it][il][ie,iu] """ +# C = ND_list(max(info.Nt)) +# for it in range(len(C)): +# C[it] = ND_list(info.Nl[it]) +# for il in range(info.Nl[it]): +# C[it][il] = torch.autograd.Variable( torch.Tensor( info.Ne, info.Nu[it][il] ), requires_grad = True ) +# +# with open("C_init.dat","r") as file: +# line = [] +# for it in range(len(C)): +# for il in range(info.Nl[it]): +# for i_n in range(info.Nu[it][il]): +# for ie in range(info.Ne[it]): +# if not line: line=file.readline().split() +# C[it][il].data[ie,i_n] = float(line.pop(0)) +# return C diff --git a/tools/SIAB/PyTorchGradient/source/IO/print_QSV.py b/tools/SIAB/PyTorchGradient/source/IO/print_QSV.py index 1b0f88c59ef..ca8527ed293 100644 --- a/tools/SIAB/PyTorchGradient/source/IO/print_QSV.py +++ b/tools/SIAB/PyTorchGradient/source/IO/print_QSV.py @@ -1,29 +1,30 @@ -def print_V(V,file_name): - """ V[ist][ib] """ - with open(file_name,"w") as file: - for V_s in V: - for V_sb in V_s: - print(1-V_sb.item(),end="\t",file=file) - print(file=file) - -def print_S(S,file_name): - """ S[ist][it1,it2][il1][il2][ia1*im1*in1,ia2*im2*in2] """ - with open(file_name,"w") as file: - for ist,S_s in enumerate(S): - for (it1,it2),S_tt in S_s.items(): - for il1,S_ttl in enumerate(S_tt): - for il2,S_ttll in enumerate(S_ttl): - print(ist,it1,it2,il1,il2,file=file) - print(S_ttll.real.numpy(),file=file) - print(S_ttll.imag.numpy(),"\n",file=file) - -def print_Q(Q,file_name): - """ Q[ist][it][il][ib,ia*im*iu] """ - with open(file_name,"w") as file: - for ist,Q_s in enumerate(Q): - for it,Q_st in Q_s.items(): - for il,Q_stl in enumerate(Q_st): - print(ist,it,il,file=file) - print(Q_stl.real.numpy(),file=file) - print(Q_stl.imag.numpy(),"\n",file=file) - \ No newline at end of file +def print_V(V, file_name): + """V[ist][ib]""" + with open(file_name, "w") as file: + for V_s in V: + for V_sb in V_s: + print(1 - V_sb.item(), end="\t", file=file) + print(file=file) + + +def print_S(S, file_name): + """S[ist][it1,it2][il1][il2][ia1*im1*in1,ia2*im2*in2]""" + with open(file_name, "w") as file: + for ist, S_s in enumerate(S): + for (it1, it2), S_tt in S_s.items(): + for il1, S_ttl in enumerate(S_tt): + for il2, S_ttll in enumerate(S_ttl): + print(ist, it1, it2, il1, il2, file=file) + print(S_ttll.real.numpy(), file=file) + print(S_ttll.imag.numpy(), "\n", file=file) + + +def print_Q(Q, file_name): + """Q[ist][it][il][ib,ia*im*iu]""" + with open(file_name, "w") as file: + for ist, Q_s in enumerate(Q): + for it, Q_st in Q_s.items(): + for il, Q_stl in enumerate(Q_st): + print(ist, it, il, file=file) + print(Q_stl.real.numpy(), file=file) + print(Q_stl.imag.numpy(), "\n", file=file) diff --git a/tools/SIAB/PyTorchGradient/source/IO/print_orbital.py b/tools/SIAB/PyTorchGradient/source/IO/print_orbital.py index b0deb0b451f..bdc7db2f65a 100644 --- a/tools/SIAB/PyTorchGradient/source/IO/print_orbital.py +++ b/tools/SIAB/PyTorchGradient/source/IO/print_orbital.py @@ -1,69 +1,142 @@ -periodtable = { 'H': 1, 'He': 2, 'Li': 3, 'Be': 4, 'B': 5, 'C': 6, 'N': 7, - 'O': 8, 'F': 9, 'Ne': 10, 'Na': 11, 'Mg': 12, 'Al': 13, - 'Si': 14, 'P': 15, 'S': 16, 'Cl': 17, 'Ar': 18, 'K': 19, - 'Ca': 20, 'Sc': 21, 'Ti': 22, 'V': 23, 'Cr': 24, 'Mn': 25, - 'Fe': 26, 'Co': 27, 'Ni': 28, 'Cu': 29, 'Zn': 30, 'Ga': 31, - 'Ge': 32, 'As': 33, 'Se': 34, 'Br': 35, 'Kr': 36, 'Rb': 37, - 'Sr': 38, 'Y': 39, 'Zr': 40, 'Nb': 41, 'Mo': 42, 'Tc': 43, - 'Ru': 44, 'Rh': 45, 'Pd': 46, 'Ag': 47, 'Cd': 48, 'In': 49, - 'Sn': 50, 'Sb': 51, 'Te': 52, 'I': 53, 'Xe': 54, 'Cs': 55, - 'Ba': 56, #'La': 57, 'Ce': 58, 'Pr': 59, 'Nd': 60, 'Pm': 61, - ## 'Sm': 62, 'Eu': 63, 'Gd': 64, 'Tb': 65, 'Dy': 66, 'Ho': 67, - ## 'Er': 68, 'Tm': 69, 'Yb': 70, - ## 'Lu': 71, - 'Hf': 72, 'Ta': 73, - 'W': 74, 'Re': 75, 'Os': 76, 'Ir': 77, 'Pt': 78, 'Au': 79, - 'Hg': 80, 'Tl': 81, 'Pb': 82, 'Bi': 83, - ## 'Po': 84, #'At': 85, - ## 'Rn': 86, #'Fr': 87, 'Ra': 88, 'Ac': 89, 'Th': 90, 'Pa': 91, - ## 'U': 92, 'Np': 93, 'Pu': 94, 'Am': 95, 'Cm': 96, 'Bk': 97, - ## 'Cf': 98, 'Es': 99, 'Fm': 100, 'Md': 101, 'No': 102, 'Lr': 103, - ## 'Rf': 104, 'Db': 105, 'Sg': 106, 'Bh': 107, 'Hs': 108, - ## 'Mt': 109, 'Ds': 110, 'Rg': 111, 'Cn': 112, 'Uut': 113, - ## 'Fl': 114, 'Uup': 115, 'Lv': 116, 'Uus': 117, 'Uuo': 118 - } +periodtable = { + "H": 1, + "He": 2, + "Li": 3, + "Be": 4, + "B": 5, + "C": 6, + "N": 7, + "O": 8, + "F": 9, + "Ne": 10, + "Na": 11, + "Mg": 12, + "Al": 13, + "Si": 14, + "P": 15, + "S": 16, + "Cl": 17, + "Ar": 18, + "K": 19, + "Ca": 20, + "Sc": 21, + "Ti": 22, + "V": 23, + "Cr": 24, + "Mn": 25, + "Fe": 26, + "Co": 27, + "Ni": 28, + "Cu": 29, + "Zn": 30, + "Ga": 31, + "Ge": 32, + "As": 33, + "Se": 34, + "Br": 35, + "Kr": 36, + "Rb": 37, + "Sr": 38, + "Y": 39, + "Zr": 40, + "Nb": 41, + "Mo": 42, + "Tc": 43, + "Ru": 44, + "Rh": 45, + "Pd": 46, + "Ag": 47, + "Cd": 48, + "In": 49, + "Sn": 50, + "Sb": 51, + "Te": 52, + "I": 53, + "Xe": 54, + "Cs": 55, + "Ba": 56, #'La': 57, 'Ce': 58, 'Pr': 59, 'Nd': 60, 'Pm': 61, + ## 'Sm': 62, 'Eu': 63, 'Gd': 64, 'Tb': 65, 'Dy': 66, 'Ho': 67, + ## 'Er': 68, 'Tm': 69, 'Yb': 70, + ## 'Lu': 71, + "Hf": 72, + "Ta": 73, + "W": 74, + "Re": 75, + "Os": 76, + "Ir": 77, + "Pt": 78, + "Au": 79, + "Hg": 80, + "Tl": 81, + "Pb": 82, + "Bi": 83, + ## 'Po': 84, #'At': 85, + ## 'Rn': 86, #'Fr': 87, 'Ra': 88, 'Ac': 89, 'Th': 90, 'Pa': 91, + ## 'U': 92, 'Np': 93, 'Pu': 94, 'Am': 95, 'Cm': 96, 'Bk': 97, + ## 'Cf': 98, 'Es': 99, 'Fm': 100, 'Md': 101, 'No': 102, 'Lr': 103, + ## 'Rf': 104, 'Db': 105, 'Sg': 106, 'Bh': 107, 'Hs': 108, + ## 'Mt': 109, 'Ds': 110, 'Rg': 111, 'Cn': 112, 'Uut': 113, + ## 'Fl': 114, 'Uup': 115, 'Lv': 116, 'Uus': 117, 'Uuo': 118 +} -def print_orbital(orb,info): - """ orb[it][il][iu][r] """ - for it,orb_t in orb.items(): - with open("ORBITAL_{0}U.dat".format( periodtable[it] ),"w") as file: - print_orbital_head(file,info,it) - for il,orb_tl in enumerate(orb_t): - for iu,orb_tlu in enumerate(orb_tl): - print(""" Type L N""",file=file) - print(""" 0 {0} {1}""".format(il,iu),file=file) - for ir,orb_tlur in enumerate(orb_tlu): - print( '%.14e'%orb_tlur, end=" ",file=file) - if ir%4==3: print(file=file) - print(file=file) - - -def plot_orbital(orb,Rcut,dr): - for it,orb_t in orb.items(): - #with open("orb_{0}_plot.dat".format(it),"w") as file: - with open("ORBITAL_PLOTU.dat", "w") as file: - Nr = int(Rcut[it]/dr[it])+1 - for ir in range(Nr): - print( '%10.6f'%(ir*dr[it]) ,end=" ",file=file) - for il,orb_tl in enumerate(orb_t): - for orb_tlu in orb_tl: - print( '%18.14f'%orb_tlu[ir], end=" ",file=file) - print(file=file) - - -def print_orbital_head(file,info,it): - print( "---------------------------------------------------------------------------", file=file ) - print( "Element {0}".format(it), file=file ) - print( "Energy Cutoff(Ry) {0}".format(info.Ecut[it]), file=file ) - print( "Radius Cutoff(a.u.) {0}".format(info.Rcut[it]), file=file ) - print( "Lmax {0}".format(info.Nl[it]-1), file=file ) - l_name = ["S","P","D"]+list(map(chr,range(ord('F'),ord('Z')+1))) - for il,iu in enumerate(info.Nu[it]): - print( "Number of {0}orbital--> {1}".format(l_name[il],iu), file=file ) - print( "---------------------------------------------------------------------------", file=file ) - print( "SUMMARY END", file=file ) - print( file=file ) - print( "Mesh {0}".format(int(info.Rcut[it]/info.dr[it])+1), file=file ) - print( "dr {0}".format(info.dr[it]), file=file ) - +def print_orbital(orb, info): + """orb[it][il][iu][r]""" + for it, orb_t in orb.items(): + with open("ORBITAL_{0}U.dat".format(periodtable[it]), "w") as file: + print_orbital_head(file, info, it) + for il, orb_tl in enumerate(orb_t): + for iu, orb_tlu in enumerate(orb_tl): + print( + """ Type L N""", + file=file, + ) + print( + """ 0 {0} {1}""".format( + il, iu + ), + file=file, + ) + for ir, orb_tlur in enumerate(orb_tlu): + print("%.14e" % orb_tlur, end=" ", file=file) + if ir % 4 == 3: + print(file=file) + print(file=file) + + +def plot_orbital(orb, Rcut, dr): + for it, orb_t in orb.items(): + # with open("orb_{0}_plot.dat".format(it),"w") as file: + with open("ORBITAL_PLOTU.dat", "w") as file: + Nr = int(Rcut[it] / dr[it]) + 1 + for ir in range(Nr): + print("%10.6f" % (ir * dr[it]), end=" ", file=file) + for il, orb_tl in enumerate(orb_t): + for orb_tlu in orb_tl: + print("%18.14f" % orb_tlu[ir], end=" ", file=file) + print(file=file) + + +def print_orbital_head(file, info, it): + print( + "---------------------------------------------------------------------------", + file=file, + ) + print("Element {0}".format(it), file=file) + print("Energy Cutoff(Ry) {0}".format(info.Ecut[it]), file=file) + print("Radius Cutoff(a.u.) {0}".format(info.Rcut[it]), file=file) + print("Lmax {0}".format(info.Nl[it] - 1), file=file) + l_name = ["S", "P", "D"] + list(map(chr, range(ord("F"), ord("Z") + 1))) + for il, iu in enumerate(info.Nu[it]): + print("Number of {0}orbital--> {1}".format(l_name[il], iu), file=file) + print( + "---------------------------------------------------------------------------", + file=file, + ) + print("SUMMARY END", file=file) + print(file=file) + print( + "Mesh {0}".format(int(info.Rcut[it] / info.dr[it]) + 1), + file=file, + ) + print("dr {0}".format(info.dr[it]), file=file) diff --git a/tools/SIAB/PyTorchGradient/source/IO/read_QSV.py b/tools/SIAB/PyTorchGradient/source/IO/read_QSV.py index 09c034080ff..a20ae8cce05 100644 --- a/tools/SIAB/PyTorchGradient/source/IO/read_QSV.py +++ b/tools/SIAB/PyTorchGradient/source/IO/read_QSV.py @@ -6,159 +6,208 @@ import time -def read_file(info,file_list,V_info): - """ QI[ist][it][il][ib*ia*im,ie] """ - """ SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] """ - """ VI[ist][ib] """ - import copy - info_true = copy.deepcopy(info) - info_true.Nst = len(file_list) - info_true.Nt = ND_list(info_true.Nst,element="list()") - info_true.Na = ND_list(info_true.Nst,element="dict()") - info_true.Nb = ND_list(info_true.Nst) - info_true.Nk = ND_list(info_true.Nst) - info_true.Ne = dict() - info_true.weight = ND_list(info_true.Nst,element="list()") - QI=[]; SI=[]; VI=[] - - for ist_true,file_name in enumerate(file_list): - print(" "+file_name, flush=True ) - with open(file_name,"r") as file: - - ignore_line(file,4) - Nt_tmp = int(file.readline().split()[0]) - for it in range(Nt_tmp): - t_tmp = file.readline().split()[0] - assert t_tmp in info.Nt_all - info_true.Nt[ist_true].append( t_tmp ) - info_true.Na[ist_true][t_tmp] = int(file.readline().split()[0]) - ignore_line( file, info_true.Na[ist_true][t_tmp] ) - ignore_line(file,6) - Nl_ist = int(file.readline().split()[0])+1 - for it,Nl_C in info.Nl.items(): - print(" "+it,Nl_ist,Nl_C, flush=True ) - assert Nl_ist>=Nl_C - info_true.Nl[it] = Nl_ist - info_true.Nk[ist_true] = int(file.readline().split()[0]) - info_true.Nb[ist_true] = int(file.readline().split()[0]) - ignore_line(file,1) - Ne_tmp = list(map(int,file.readline().split()[:Nt_tmp])) - for it,Ne in zip(info_true.Nt[ist_true],Ne_tmp): - assert info_true.Ne.setdefault(it,Ne)==Ne - ignore_line(file,1) - for ik in range(info_true.Nk[ist_true]): - info_true.weight[ist_true].append(float(file.readline().split()[-1])) - ignore_line(file,3) - - line = None - for ik in range(info_true.Nk[ist_true]): - print(" read QI:",ist_true,ik, flush=True ) - qi,line = read_QI(info_true,ist_true,file,line) - QI.append( qi ) - ignore_line(file,3) - for ik in range(info_true.Nk[ist_true]): - print(" read SI:",ist_true,ik, flush=True ) - si,line = read_SI(info_true,ist_true,file,line) - SI.append( si ) - if V_info["init_from_file"]: - ignore_line(file,3) - for ik in range(info_true.Nk[ist_true]): - print(" read VI:",ist_true,ik, flush=True ) - vi,line = read_VI(info_true,V_info,ist_true,file,line) - VI.append( vi ) - - info.Nst = sum(info_true.Nk,0) - import itertools - repeat_Nk = lambda x: list( itertools.chain.from_iterable( map( lambda x:itertools.repeat(*x), zip(x,info_true.Nk) ) ) ) - info.Nt = repeat_Nk(info_true.Nt) - info.Na = repeat_Nk(info_true.Na) - info.Nb = repeat_Nk(info_true.Nb) - info.Nb_true = repeat_Nk(info.Nb_true) - info.Ne = info_true.Ne - info.weight = list(itertools.chain.from_iterable([np.array(wk)*ws for wk,ws in zip(info_true.weight,info.weight)])) # info_true.weight[ist][ik] * info.weight[ist] - - return QI,SI,VI - - - - -def read_QI(info,ist,file,line=None): - """ QI[it][il][ib*ia*im,ie] """ - QI = dict() - for it in info.Nt[ist]: - QI[it] = ND_list(info.Nl[it]) - for il in range(info.Nl[it]): - QI[it][il] = torch_complex.ComplexTensor( - np.empty((info.Nb[ist],info.Na[ist][it],info.Nm(il),info.Ne[it]),dtype=np.float32), - np.empty((info.Nb[ist],info.Na[ist][it],info.Nm(il),info.Ne[it]),dtype=np.float32) ) - for ib in range(info.Nb[ist]): - for it in info.Nt[ist]: - for ia in range(info.Na[ist][it]): - for il in range(info.Nl[it]): - for im in range(info.Nm(il)): - for ie in range(info.Ne[it]): - if not line: line = file.readline().split() - QI[it][il].real[ib,ia,im,ie] = float(line.pop(0)) - if not line: line = file.readline().split() - QI[it][il].imag[ib,ia,im,ie] = float(line.pop(0)) - for it in info.Nt[ist]: - for il in range(info.Nl[it]): - QI[it][il] = torch_complex.ComplexTensor( - torch.from_numpy(QI[it][il].real).view(-1,info.Ne[it]), - torch.from_numpy(QI[it][il].imag).view(-1,info.Ne[it])) - return QI,line - - - -def read_SI(info,ist,file,line=None): - """ SI[it1,it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] """ - SI = dict() - for it1,it2 in itertools.product( info.Nt[ist], info.Nt[ist] ): - SI[it1,it2] = ND_list(info.Nl[it1],info.Nl[it2]) - for il1,il2 in itertools.product( range(info.Nl[it1]), range(info.Nl[it2]) ): - SI[it1,it2][il1][il2] = torch_complex.ComplexTensor( - np.empty((info.Na[ist][it1],info.Nm(il1),info.Ne[it1],info.Na[ist][it2],info.Nm(il2),info.Ne[it2]),dtype=np.float32), - np.empty((info.Na[ist][it1],info.Nm(il1),info.Ne[it1],info.Na[ist][it2],info.Nm(il2),info.Ne[it2]),dtype=np.float32) ) - for it1 in info.Nt[ist]: - for ia1 in range(info.Na[ist][it1]): - for il1 in range(info.Nl[it1]): - for im1 in range(info.Nm(il1)): - for it2 in info.Nt[ist]: - for ia2 in range(info.Na[ist][it2]): - for il2 in range(info.Nl[it2]): - for im2 in range(info.Nm(il2)): - for ie1 in range(info.Ne[it1]): - for ie2 in range(info.Ne[it2]): - if not line: line = file.readline().split() - SI[it1,it2][il1][il2].real[ia1,im1,ie1,ia2,im2,ie2] = float(line.pop(0)) - if not line: line = file.readline().split() - SI[it1,it2][il1][il2].imag[ia1,im1,ie1,ia2,im2,ie2] = float(line.pop(0)) - for it1,it2 in itertools.product( info.Nt[ist], info.Nt[ist] ): - for il1,il2 in itertools.product( range(info.Nl[it1]), range(info.Nl[it2]) ): - SI[it1,it2][il1][il2] = torch_complex.ComplexTensor( - torch.from_numpy(SI[it1,it2][il1][il2].real), - torch.from_numpy(SI[it1,it2][il1][il2].imag)) - return SI,line - - - -def read_VI(info,V_info,ist,file,line=None): - if V_info["same_band"]: - """ VI[ib] """ - if V_info["init_from_file"]: - VI = np.empty(info.Nb[ist],dtype=np.float32) - for ib in range(info.Nb[ist]): - if not line: line = file.readline().split() - VI.data[ib] = float(line.pop(0)) - else: - VI = np.ones(info.Nb[ist],dtype=np.float32) - else: - """ VI[ib1,ib2] """ - if V_info["init_from_file"]: - VI = np.empty((info.Nb[ist],info.Nb[ist]),dtype=np.float32) - for ib1,ib2 in itertools.product( range(info.Nb[ist]), range(info.Nb[ist]) ): - if not line: line = file.readline().split() - VI[ib1,ib2] = float(line.pop(0)) - else: - VI = np.eye(info.Nb[ist],info.Nb[ist],dtype=np.float32) - return torch.from_numpy(VI),line + +def read_file(info, file_list, V_info): + """QI[ist][it][il][ib*ia*im,ie]""" + """ SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] """ + """ VI[ist][ib] """ + import copy + + info_true = copy.deepcopy(info) + info_true.Nst = len(file_list) + info_true.Nt = ND_list(info_true.Nst, element="list()") + info_true.Na = ND_list(info_true.Nst, element="dict()") + info_true.Nb = ND_list(info_true.Nst) + info_true.Nk = ND_list(info_true.Nst) + info_true.Ne = dict() + info_true.weight = ND_list(info_true.Nst, element="list()") + QI = [] + SI = [] + VI = [] + + for ist_true, file_name in enumerate(file_list): + print(" " + file_name, flush=True) + with open(file_name, "r") as file: + + ignore_line(file, 4) + Nt_tmp = int(file.readline().split()[0]) + for it in range(Nt_tmp): + t_tmp = file.readline().split()[0] + assert t_tmp in info.Nt_all + info_true.Nt[ist_true].append(t_tmp) + info_true.Na[ist_true][t_tmp] = int(file.readline().split()[0]) + ignore_line(file, info_true.Na[ist_true][t_tmp]) + ignore_line(file, 6) + Nl_ist = int(file.readline().split()[0]) + 1 + for it, Nl_C in info.Nl.items(): + print(" " + it, Nl_ist, Nl_C, flush=True) + assert Nl_ist >= Nl_C + info_true.Nl[it] = Nl_ist + info_true.Nk[ist_true] = int(file.readline().split()[0]) + info_true.Nb[ist_true] = int(file.readline().split()[0]) + ignore_line(file, 1) + Ne_tmp = list(map(int, file.readline().split()[:Nt_tmp])) + for it, Ne in zip(info_true.Nt[ist_true], Ne_tmp): + assert info_true.Ne.setdefault(it, Ne) == Ne + ignore_line(file, 1) + for ik in range(info_true.Nk[ist_true]): + info_true.weight[ist_true].append(float(file.readline().split()[-1])) + ignore_line(file, 3) + + line = None + for ik in range(info_true.Nk[ist_true]): + print(" read QI:", ist_true, ik, flush=True) + qi, line = read_QI(info_true, ist_true, file, line) + QI.append(qi) + ignore_line(file, 3) + for ik in range(info_true.Nk[ist_true]): + print(" read SI:", ist_true, ik, flush=True) + si, line = read_SI(info_true, ist_true, file, line) + SI.append(si) + if V_info["init_from_file"]: + ignore_line(file, 3) + for ik in range(info_true.Nk[ist_true]): + print(" read VI:", ist_true, ik, flush=True) + vi, line = read_VI(info_true, V_info, ist_true, file, line) + VI.append(vi) + + info.Nst = sum(info_true.Nk, 0) + import itertools + + repeat_Nk = lambda x: list( + itertools.chain.from_iterable( + map(lambda x: itertools.repeat(*x), zip(x, info_true.Nk)) + ) + ) + info.Nt = repeat_Nk(info_true.Nt) + info.Na = repeat_Nk(info_true.Na) + info.Nb = repeat_Nk(info_true.Nb) + info.Nb_true = repeat_Nk(info.Nb_true) + info.Ne = info_true.Ne + info.weight = list( + itertools.chain.from_iterable( + [np.array(wk) * ws for wk, ws in zip(info_true.weight, info.weight)] + ) + ) # info_true.weight[ist][ik] * info.weight[ist] + + return QI, SI, VI + + +def read_QI(info, ist, file, line=None): + """QI[it][il][ib*ia*im,ie]""" + QI = dict() + for it in info.Nt[ist]: + QI[it] = ND_list(info.Nl[it]) + for il in range(info.Nl[it]): + QI[it][il] = torch_complex.ComplexTensor( + np.empty( + (info.Nb[ist], info.Na[ist][it], info.Nm(il), info.Ne[it]), + dtype=np.float32, + ), + np.empty( + (info.Nb[ist], info.Na[ist][it], info.Nm(il), info.Ne[it]), + dtype=np.float32, + ), + ) + for ib in range(info.Nb[ist]): + for it in info.Nt[ist]: + for ia in range(info.Na[ist][it]): + for il in range(info.Nl[it]): + for im in range(info.Nm(il)): + for ie in range(info.Ne[it]): + if not line: + line = file.readline().split() + QI[it][il].real[ib, ia, im, ie] = float(line.pop(0)) + if not line: + line = file.readline().split() + QI[it][il].imag[ib, ia, im, ie] = float(line.pop(0)) + for it in info.Nt[ist]: + for il in range(info.Nl[it]): + QI[it][il] = torch_complex.ComplexTensor( + torch.from_numpy(QI[it][il].real).view(-1, info.Ne[it]), + torch.from_numpy(QI[it][il].imag).view(-1, info.Ne[it]), + ) + return QI, line + + +def read_SI(info, ist, file, line=None): + """SI[it1,it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2]""" + SI = dict() + for it1, it2 in itertools.product(info.Nt[ist], info.Nt[ist]): + SI[it1, it2] = ND_list(info.Nl[it1], info.Nl[it2]) + for il1, il2 in itertools.product(range(info.Nl[it1]), range(info.Nl[it2])): + SI[it1, it2][il1][il2] = torch_complex.ComplexTensor( + np.empty( + ( + info.Na[ist][it1], + info.Nm(il1), + info.Ne[it1], + info.Na[ist][it2], + info.Nm(il2), + info.Ne[it2], + ), + dtype=np.float32, + ), + np.empty( + ( + info.Na[ist][it1], + info.Nm(il1), + info.Ne[it1], + info.Na[ist][it2], + info.Nm(il2), + info.Ne[it2], + ), + dtype=np.float32, + ), + ) + for it1 in info.Nt[ist]: + for ia1 in range(info.Na[ist][it1]): + for il1 in range(info.Nl[it1]): + for im1 in range(info.Nm(il1)): + for it2 in info.Nt[ist]: + for ia2 in range(info.Na[ist][it2]): + for il2 in range(info.Nl[it2]): + for im2 in range(info.Nm(il2)): + for ie1 in range(info.Ne[it1]): + for ie2 in range(info.Ne[it2]): + if not line: + line = file.readline().split() + SI[it1, it2][il1][il2].real[ + ia1, im1, ie1, ia2, im2, ie2 + ] = float(line.pop(0)) + if not line: + line = file.readline().split() + SI[it1, it2][il1][il2].imag[ + ia1, im1, ie1, ia2, im2, ie2 + ] = float(line.pop(0)) + for it1, it2 in itertools.product(info.Nt[ist], info.Nt[ist]): + for il1, il2 in itertools.product(range(info.Nl[it1]), range(info.Nl[it2])): + SI[it1, it2][il1][il2] = torch_complex.ComplexTensor( + torch.from_numpy(SI[it1, it2][il1][il2].real), + torch.from_numpy(SI[it1, it2][il1][il2].imag), + ) + return SI, line + + +def read_VI(info, V_info, ist, file, line=None): + if V_info["same_band"]: + """VI[ib]""" + if V_info["init_from_file"]: + VI = np.empty(info.Nb[ist], dtype=np.float32) + for ib in range(info.Nb[ist]): + if not line: + line = file.readline().split() + VI.data[ib] = float(line.pop(0)) + else: + VI = np.ones(info.Nb[ist], dtype=np.float32) + else: + """VI[ib1,ib2]""" + if V_info["init_from_file"]: + VI = np.empty((info.Nb[ist], info.Nb[ist]), dtype=np.float32) + for ib1, ib2 in itertools.product(range(info.Nb[ist]), range(info.Nb[ist])): + if not line: + line = file.readline().split() + VI[ib1, ib2] = float(line.pop(0)) + else: + VI = np.eye(info.Nb[ist], info.Nb[ist], dtype=np.float32) + return torch.from_numpy(VI), line diff --git a/tools/SIAB/PyTorchGradient/source/IO/read_json.py b/tools/SIAB/PyTorchGradient/source/IO/read_json.py index 52887f9775b..aea78f57fd6 100644 --- a/tools/SIAB/PyTorchGradient/source/IO/read_json.py +++ b/tools/SIAB/PyTorchGradient/source/IO/read_json.py @@ -1,64 +1,65 @@ import json from util import Info + def read_json(file_name): - with open(file_name,"r") as file: - input = file.read() - input = json.loads(input) - - info = Info() - for info_attr,info_value in input["info"].items(): - info.__dict__[info_attr] = info_value - info.Nl = { it:len(Nu) for it,Nu in info.Nu.items() } - - return input["file_list"], info, input["C_init_info"], input["V_info"] + with open(file_name, "r") as file: + input = file.read() + input = json.loads(input) + + info = Info() + for info_attr, info_value in input["info"].items(): + info.__dict__[info_attr] = info_value + info.Nl = {it: len(Nu) for it, Nu in info.Nu.items()} + + return input["file_list"], info, input["C_init_info"], input["V_info"] + + """ file_name + { + "file_list": + [ + "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/S2/S2.10.dat", + "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SO2/SO2.10.dat", + "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SO/SO.10.dat" + ], + "info": + { + "Nt_all": ["S","O"], + "Nu": {"S":[3,3,2],"O":[3,3,2]}, + "Nb_true": [7,9,7], + "weight": [2,3,1.5], + "Rcut": {"S":10,"O":10}, + "dr": {"S":0.01,"O":0.01}, + "Ecut": {"S":100,"O":100}, + "lr": 0.01 + }, + "C_init_info": + { + "init_from_file": false, + "C_init_file": "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SIA/ORBITAL_RESULTS.txt" + }, + "V_info": + { + "init_from_file": true, + "same_band": false + } + } + """ - """ file_name - { - "file_list": - [ - "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/S2/S2.10.dat", - "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SO2/SO2.10.dat", - "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SO/SO.10.dat" - ], - "info": - { - "Nt_all": ["S","O"], - "Nu": {"S":[3,3,2],"O":[3,3,2]}, - "Nb_true": [7,9,7], - "weight": [2,3,1.5], - "Rcut": {"S":10,"O":10}, - "dr": {"S":0.01,"O":0.01}, - "Ecut": {"S":100,"O":100}, - "lr": 0.01 - }, - "C_init_info": - { - "init_from_file": false, - "C_init_file": "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SIA/ORBITAL_RESULTS.txt" - }, - "V_info": - { - "init_from_file": true, - "same_band": false - } - } - """ - - """ info - Nt_all ["S", "O"] - Nu {"S":[3,3,2], "O":[3,3,2]} - Nb_true [7, 9, 7] - weight [2, 3, 1.5] - Rcut {"S":10, "O":10} - dr {"S":0.01, "O":0.01} - Ecut {"S":100, "O":100} - lr 0.01 - Nl {"S":2, "O":2} - Nst 3 - Nt [["S"], ["S","O"], ["S","O"]] - Na [{"S":2}, {"S":1,"O":2}, {"S":1,"O":1}] - Nb [7, 9, 7] - Ne {"S":22, "O":19} - """ \ No newline at end of file + """ info + Nt_all ["S", "O"] + Nu {"S":[3,3,2], "O":[3,3,2]} + Nb_true [7, 9, 7] + weight [2, 3, 1.5] + Rcut {"S":10, "O":10} + dr {"S":0.01, "O":0.01} + Ecut {"S":100, "O":100} + lr 0.01 + Nl {"S":2, "O":2} + Nst 3 + Nt [["S"], ["S","O"], ["S","O"]] + Na [{"S":2}, {"S":1,"O":2}, {"S":1,"O":1}] + Nb [7, 9, 7] + Ne {"S":22, "O":19} + """ diff --git a/tools/SIAB/PyTorchGradient/source/inverse.py b/tools/SIAB/PyTorchGradient/source/inverse.py index 311519fae15..87bc82dc329 100644 --- a/tools/SIAB/PyTorchGradient/source/inverse.py +++ b/tools/SIAB/PyTorchGradient/source/inverse.py @@ -1,55 +1,56 @@ -import torch - - -def inverse_DC(A,B,C,D): - tmp_A = inverse(A) # A^{-1} - #print("tmp_A",tmp_A) - tmp_AB = torch.mm(tmp_A,B) # A^{-1} B - #print("tmp_AB",tmp_AB) - tmp_CA = torch.mm(C,tmp_A) # C A^{-1} - #print("tmp_CA",tmp_CA) - tmp_X = inverse(D-torch.mm(tmp_CA,B)) # ( D - C A^{-1} B )^{-1} - #print("tmp_X",tmp_X) - tmp_ABX = torch.mm(tmp_AB,tmp_X) # A^{-1} B ( D - C A^{-1} B )^{-1} - #print("tmp_ABX",tmp_ABX) - tmp_XCA = torch.mm(tmp_X,tmp_CA) # ( D - C A^{-1} B )^{-1} C A^{-1} - #print("tmp_XCA",tmp_XCA) - tmp_ABXCA = torch.mm(tmp_ABX,tmp_CA) # A^{-1} B ( D - C A^{-1} B )^{-1} C A^{-1} - #print("tmp_ABXCA",tmp_ABXCA) - - tmp_up = torch.cat( [ tmp_A+tmp_ABXCA, -tmp_ABX ], dim=1 ) - tmp_down = torch.cat( [ -tmp_XCA, tmp_X ], dim=1 ) - I = torch.cat( [tmp_up,tmp_down], dim=0 ) - return I - - - -def inverse(M): - -# assert len(M.size()) == 2, "inverse must be 2D" -# assert M.size()[0] == M.size()[1], "inverse row != column" - - L = M.size()[0] - - if L==1: - return 1/M - - elif L==2: - det = torch.cat(list( M[:1,:1]*M[1:,1:] - M[:1,1:]*M[1:,:1] )*4).view(2,2) - I_up = torch.cat([M[1:,1:],-M[:1,1:]],dim=1) - I_down = torch.cat([-M[1:,:1],M[:1,:1]],dim=1) - I_all = torch.cat([I_up,I_down],dim=0) - return I_all/det - - elif L==3: - threshold = 1e-10 - if M[0,0].abs() > threshold: - return inverse_DC( M[:1,:1], M[:1,1:], M[1:,:1], M[1:,1:] ) - elif M[2,2].abs() > threshold: - return inverse_DC( M[:2,:2], M[:2,2:], M[2:,:2], M[2:,2:] ) - else: - raise ZeroDivisionError("matrix inverse") - - else: - L2 = L//2 - return inverse_DC( M[:L2,:L2], M[:L2,L2:], M[L2:,:L2], M[L2:,L2:] ) \ No newline at end of file +import torch + + +def inverse_DC(A, B, C, D): + tmp_A = inverse(A) # A^{-1} + # print("tmp_A",tmp_A) + tmp_AB = torch.mm(tmp_A, B) # A^{-1} B + # print("tmp_AB",tmp_AB) + tmp_CA = torch.mm(C, tmp_A) # C A^{-1} + # print("tmp_CA",tmp_CA) + tmp_X = inverse(D - torch.mm(tmp_CA, B)) # ( D - C A^{-1} B )^{-1} + # print("tmp_X",tmp_X) + tmp_ABX = torch.mm(tmp_AB, tmp_X) # A^{-1} B ( D - C A^{-1} B )^{-1} + # print("tmp_ABX",tmp_ABX) + tmp_XCA = torch.mm(tmp_X, tmp_CA) # ( D - C A^{-1} B )^{-1} C A^{-1} + # print("tmp_XCA",tmp_XCA) + tmp_ABXCA = torch.mm(tmp_ABX, tmp_CA) # A^{-1} B ( D - C A^{-1} B )^{-1} C A^{-1} + # print("tmp_ABXCA",tmp_ABXCA) + + tmp_up = torch.cat([tmp_A + tmp_ABXCA, -tmp_ABX], dim=1) + tmp_down = torch.cat([-tmp_XCA, tmp_X], dim=1) + I = torch.cat([tmp_up, tmp_down], dim=0) + return I + + +def inverse(M): + + # assert len(M.size()) == 2, "inverse must be 2D" + # assert M.size()[0] == M.size()[1], "inverse row != column" + + L = M.size()[0] + + if L == 1: + return 1 / M + + elif L == 2: + det = torch.cat(list(M[:1, :1] * M[1:, 1:] - M[:1, 1:] * M[1:, :1]) * 4).view( + 2, 2 + ) + I_up = torch.cat([M[1:, 1:], -M[:1, 1:]], dim=1) + I_down = torch.cat([-M[1:, :1], M[:1, :1]], dim=1) + I_all = torch.cat([I_up, I_down], dim=0) + return I_all / det + + elif L == 3: + threshold = 1e-10 + if M[0, 0].abs() > threshold: + return inverse_DC(M[:1, :1], M[:1, 1:], M[1:, :1], M[1:, 1:]) + elif M[2, 2].abs() > threshold: + return inverse_DC(M[:2, :2], M[:2, 2:], M[2:, :2], M[2:, 2:]) + else: + raise ZeroDivisionError("matrix inverse") + + else: + L2 = L // 2 + return inverse_DC(M[:L2, :L2], M[:L2, L2:], M[L2:, :L2], M[L2:, L2:]) diff --git a/tools/SIAB/PyTorchGradient/source/main.py b/tools/SIAB/PyTorchGradient/source/main.py index d1c94e82051..02444eed3fa 100755 --- a/tools/SIAB/PyTorchGradient/source/main.py +++ b/tools/SIAB/PyTorchGradient/source/main.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys -print( sys.version, flush=True ) + +print(sys.version, flush=True) import IO.read_QSV import IO.print_QSV import IO.func_C @@ -13,70 +14,95 @@ import numpy as np import time -print("\n seed:",torch.initial_seed(), flush=True ) +print("\n seed:", torch.initial_seed(), flush=True) time_start = time.time() file_list, info, C_init_info, V_info = IO.read_json.read_json("INPUT") -QI,SI,VI = IO.read_QSV.read_file(info,file_list,V_info) -print(info, flush=True ) +QI, SI, VI = IO.read_QSV.read_file(info, file_list, V_info) +print(info, flush=True) if C_init_info["init_from_file"]: - C = IO.func_C.read_C_init( C_init_info["C_init_file"], info ) + C = IO.func_C.read_C_init(C_init_info["C_init_file"], info) else: - C = IO.func_C.random_C_init(info) -E = orbital.set_E(info,info.Rcut) -orbital.normalize( orbital.generate_orbital(info,C,E,info.Rcut,info.dr), info.dr,C,flag_norm_C=True) + C = IO.func_C.random_C_init(info) +E = orbital.set_E(info, info.Rcut) +orbital.normalize( + orbital.generate_orbital(info, C, E, info.Rcut, info.dr), + info.dr, + C, + flag_norm_C=True, +) opt_orb = opt_orbital.Opt_Orbital() -#opt = torch.optim.Adam(sum( ([c.real,c.imag] for c in sum(C,[])), []), lr=info.lr, eps=1e-8) -opt = torch.optim.Adam( sum(C.values(),[]), lr=info.lr, eps=1e-20) - -with open("Spillage.dat","w") as S_file: - - loss_old = np.inf - print( " See \"Spillage.dat\" for running status " , flush=True ) - print( "%18s"%"Spillage", "%18s"%"T", "%18s"%"Loss",file=S_file, flush=True ) - - for i in range(20000): - Q = opt_orb.cal_Q(QI,C,info) - S = opt_orb.cal_S(SI,C,info) - V = opt_orb.cal_V(Q,S,info,V_info) - - V_delta = ( torch.abs(VIi-Vi) for VIi,Vi in zip(VI,V) ) # abs or **2? - if V_info["same_band"]: - #print("-------------") - #print( info.Nb_true ) - Spillage = sum( Vi[: int(info.Nb_true[ist]) ].sum() * info.weight[ist] for ist,Vi in enumerate(V_delta) ) / sum( Nb_true*weight for Nb_true,weight in zip(info.Nb_true,info.weight) ) - else: - Spillage = sum( Vi[: int(info.Nb_true[ist]), :info.Nb_true[ist]].sum() * info.weight[ist] for ist,Vi in enumerate(V_delta) ) / sum( Nb_true**2*weight for Nb_true,weight in zip(info.Nb_true,info.weight) ) - T = opt_orb.cal_T(C,E) - if not "TSrate" in vars(): TSrate = torch.abs(0.002*Spillage/T).data[0] - Loss = Spillage + TSrate*T - - #print(Spillage.item(),T.item(),Loss.item(),file=S_file ) - print( '%5s'%i, '%18.14f'%Spillage.item(), '%18.14f'%T.item(), '%18.14f'%Loss.item(),file=S_file, flush=True ) - if Loss.item() < loss_old: - loss_old = Loss.item() - C_old = IO.func_C.copy_C(C,info) - flag_finish = 0 - else: - flag_finish += 1 - if flag_finish > 50: break - - opt.zero_grad() - Loss.backward() - opt.step() -# orbital.normalize( orbital.generate_orbital(info,C,E,info.Rcut,info.dr), info.dr,C,flag_norm_C=True) - - orb = orbital.generate_orbital(info,C_old,E,info.Rcut,info.dr) - orbital.smooth_orbital(orb,info.Rcut,info.dr,0.1) - orbital.orth(orb,info.dr) - IO.print_orbital.print_orbital(orb,info) - IO.print_orbital.plot_orbital(orb,info.Rcut,info.dr) - - IO.func_C.write_C("ORBITAL_RESULTS.txt",info,C_old,Spillage) - - print(" Time (PyTorch): %s\n"%(time.time()-time_start), flush=True ) - +# opt = torch.optim.Adam(sum( ([c.real,c.imag] for c in sum(C,[])), []), lr=info.lr, eps=1e-8) +opt = torch.optim.Adam(sum(C.values(), []), lr=info.lr, eps=1e-20) + +with open("Spillage.dat", "w") as S_file: + + loss_old = np.inf + print(' See "Spillage.dat" for running status ', flush=True) + print("%18s" % "Spillage", "%18s" % "T", "%18s" % "Loss", file=S_file, flush=True) + + for i in range(20000): + Q = opt_orb.cal_Q(QI, C, info) + S = opt_orb.cal_S(SI, C, info) + V = opt_orb.cal_V(Q, S, info, V_info) + + V_delta = (torch.abs(VIi - Vi) for VIi, Vi in zip(VI, V)) # abs or **2? + if V_info["same_band"]: + # print("-------------") + # print( info.Nb_true ) + Spillage = sum( + Vi[: int(info.Nb_true[ist])].sum() * info.weight[ist] + for ist, Vi in enumerate(V_delta) + ) / sum( + Nb_true * weight for Nb_true, weight in zip(info.Nb_true, info.weight) + ) + else: + Spillage = sum( + Vi[: int(info.Nb_true[ist]), : info.Nb_true[ist]].sum() + * info.weight[ist] + for ist, Vi in enumerate(V_delta) + ) / sum( + Nb_true**2 * weight + for Nb_true, weight in zip(info.Nb_true, info.weight) + ) + T = opt_orb.cal_T(C, E) + if not "TSrate" in vars(): + TSrate = torch.abs(0.002 * Spillage / T).data[0] + Loss = Spillage + TSrate * T + + # print(Spillage.item(),T.item(),Loss.item(),file=S_file ) + print( + "%5s" % i, + "%18.14f" % Spillage.item(), + "%18.14f" % T.item(), + "%18.14f" % Loss.item(), + file=S_file, + flush=True, + ) + if Loss.item() < loss_old: + loss_old = Loss.item() + C_old = IO.func_C.copy_C(C, info) + flag_finish = 0 + else: + flag_finish += 1 + if flag_finish > 50: + break + + opt.zero_grad() + Loss.backward() + opt.step() + # orbital.normalize( orbital.generate_orbital(info,C,E,info.Rcut,info.dr), info.dr,C,flag_norm_C=True) + + orb = orbital.generate_orbital(info, C_old, E, info.Rcut, info.dr) + orbital.smooth_orbital(orb, info.Rcut, info.dr, 0.1) + orbital.orth(orb, info.dr) + IO.print_orbital.print_orbital(orb, info) + IO.print_orbital.plot_orbital(orb, info.Rcut, info.dr) + + IO.func_C.write_C("ORBITAL_RESULTS.txt", info, C_old, Spillage) + + print(" Time (PyTorch): %s\n" % (time.time() - time_start), flush=True) diff --git a/tools/SIAB/PyTorchGradient/source/opt_orbital.py b/tools/SIAB/PyTorchGradient/source/opt_orbital.py index 6f3a3579826..cca21342290 100644 --- a/tools/SIAB/PyTorchGradient/source/opt_orbital.py +++ b/tools/SIAB/PyTorchGradient/source/opt_orbital.py @@ -5,133 +5,137 @@ import itertools import torch + class Opt_Orbital: - - def cal_Q(self,QI,C,info): - """ - Q[ist][it][il][ib,ia*im*iu] - = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] - """ - Q = ND_list(info.Nst,element="dict()") - for ist in range(info.Nst): - for it in info.Nt[ist]: - Q[ist][it] = ND_list(info.Nl[it]) - for ist in range(info.Nst): - for it in info.Nt[ist]: - for il in range(info.Nl[it]): - Q[ist][it][il] = torch_complex.mm( QI[ist][it][il], C[it][il] ).view(info.Nb[ist],-1) - return Q + def cal_Q(self, QI, C, info): + """ + Q[ist][it][il][ib,ia*im*iu] + = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] + """ + Q = ND_list(info.Nst, element="dict()") + for ist in range(info.Nst): + for it in info.Nt[ist]: + Q[ist][it] = ND_list(info.Nl[it]) + + for ist in range(info.Nst): + for it in info.Nt[ist]: + for il in range(info.Nl[it]): + Q[ist][it][il] = torch_complex.mm(QI[ist][it][il], C[it][il]).view( + info.Nb[ist], -1 + ) + return Q + + def cal_S(self, SI, C, info): + """ + S[ist][it1,it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2] + = sum_{ie1 ie2} C^*[it1][il1][ie1,iu1] * SI[ist][it1,it2][il1][il2][ia1,im1,ie1,ia2,im2,ie2] * C[it2][[il2][ie2,iu2] + """ + S = ND_list(info.Nst, element="dict()") + for ist in range(info.Nst): + for it1, it2 in itertools.product(info.Nt[ist], info.Nt[ist]): + S[ist][it1, it2] = ND_list(info.Nl[it1], info.Nl[it2]) + + for ist in range(info.Nst): + for it1, it2 in itertools.product(info.Nt[ist], info.Nt[ist]): + for il1, il2 in itertools.product( + range(info.Nl[it1]), range(info.Nl[it2]) + ): + # SI_C[ia1*im1*ie1*ia2*im2,iu2] + SI_C = torch_complex.mm( + SI[ist][it1, it2][il1][il2].view(-1, info.Ne[it2]), C[it2][il2] + ) + # SI_C[ia1*im1,ie1,ia2*im2*iu2] + SI_C = SI_C.view(info.Na[ist][it1] * info.Nm(il1), info.Ne[it1], -1) + # Ct[iu1,ie1] + Ct = C[it1][il1].t() + C_mm = functools.partial(torch_complex.mm, Ct) + # C_SI_C[ia1*im1][iu1,ia2*im2*iu2] + C_SI_C = list(map(C_mm, SI_C)) + # C_SI_C[ia1*im1*iu1,ia2*im2*iu2] + C_SI_C = torch_complex.cat(C_SI_C, dim=0) + # ??? C_SI_C = C_SI_C.view(info.Na[ist][it1]*info.Nm(il1)*info.Nu[it1][il1],-1) + S[ist][it1, it2][il1][il2] = C_SI_C + return S + + def cal_V(self, Q, S, info, V_info): + """ + V[ist][ib] + = sum_{it1,ia1,il1,im1,iu1} sum_{it2,ia2,il2,im2,iu2} + Q[ist][it1][il1][ib,ia1*im1*iu1] * S[ist]{[it1][it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*iu2] + V[ist][ib1,ib2] + = sum_{it1,ia1,il1,im1,iu1} sum_{it2,ia2,il2,im2,iu2} + Q[ist][it1][il1][ib1,ia1*im1*iu1] * S[ist]{[it1][it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2]}^{-1} * Q[ist][it2][il2][ib2,ia2*im2*iu2] + """ + V = ND_list(info.Nst) + for ist in range(info.Nst): - - - def cal_S(self,SI,C,info): - """ - S[ist][it1,it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2] - = sum_{ie1 ie2} C^*[it1][il1][ie1,iu1] * SI[ist][it1,it2][il1][il2][ia1,im1,ie1,ia2,im2,ie2] * C[it2][[il2][ie2,iu2] - """ - S = ND_list(info.Nst,element="dict()") - for ist in range(info.Nst): - for it1,it2 in itertools.product( info.Nt[ist], info.Nt[ist] ): - S[ist][it1,it2] = ND_list(info.Nl[it1],info.Nl[it2]) + # S_s[it1][il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] + S_s = dict() + for it1 in info.Nt[ist]: + # S_st[it2][il1*ia1*im1*iu1,il2*ia2*im2*iu2] + S_st = dict() + for it2 in info.Nt[ist]: + # S_stt[il1][ia1*im1*iu1,il2*ia2*im2*iu2] + S_stt = ND_list(info.Nl[it1]) + for il1 in range(info.Nl[it1]): + S_stt[il1] = torch_complex.cat(S[ist][it1, it2][il1], dim=1) + S_st[it2] = torch_complex.cat(S_stt, dim=0) + S_s[it1] = torch_complex.cat(list(S_st.values()), dim=1) + # S_cat[it1*il1*iat*im1*iu1,iat2*il2*ia2*im2*iu2] + S_cat = torch_complex.cat(list(S_s.values()), dim=0) + S_I = torch_complex.inverse(S_cat) - for ist in range(info.Nst): - for it1,it2 in itertools.product( info.Nt[ist], info.Nt[ist] ): - for il1,il2 in itertools.product( range(info.Nl[it1]), range(info.Nl[it2]) ): - # SI_C[ia1*im1*ie1*ia2*im2,iu2] - SI_C = torch_complex.mm( - SI[ist][it1,it2][il1][il2].view(-1,info.Ne[it2]), - C[it2][il2] ) - # SI_C[ia1*im1,ie1,ia2*im2*iu2] - SI_C = SI_C.view( info.Na[ist][it1]*info.Nm(il1), info.Ne[it1], -1 ) - # Ct[iu1,ie1] - Ct = C[it1][il1].t() - C_mm = functools.partial(torch_complex.mm,Ct) - # C_SI_C[ia1*im1][iu1,ia2*im2*iu2] - C_SI_C = list(map( C_mm, SI_C )) - # C_SI_C[ia1*im1*iu1,ia2*im2*iu2] - C_SI_C = torch_complex.cat( C_SI_C, dim=0 ) -#??? C_SI_C = C_SI_C.view(info.Na[ist][it1]*info.Nm(il1)*info.Nu[it1][il1],-1) - S[ist][it1,it2][il1][il2] = C_SI_C - return S + if V_info["same_band"]: + # V_s[ib] + V_s = ND_list(info.Nb[ist]) + for ib in range(info.Nb[ist]): + # Q_s[it][il*ia*im*iu] + Q_s = dict() + for it in info.Nt[ist]: + # Q_ts[il][ia*im*iu] + Q_ts = [Q_stl[ib] for Q_stl in Q[ist][it]] + Q_s[it] = torch_complex.cat(Q_ts) + # Q_cat[it*il*ia*im*iu] + Q_cat = torch_complex.cat(list(Q_s.values())) + V_s[ib] = torch_complex.dot( + Q_cat.conj(), torch_complex.mv(S_I, Q_cat) + ).real.view(-1) + # V[ist][ib] + V[ist] = torch.cat(V_s) + else: + # Q_b[ib][0,it*il*ia*im*iu] + Q_b = ND_list(info.Nb[ist]) + for ib in range(info.Nb[ist]): + # Q_s[it][il*ia*im*iu] + Q_s = dict() + for it in info.Nt[ist]: + # Q_ts[il][ia*im*iu] + Q_ts = [Q_stl[ib] for Q_stl in Q[ist][it]] + Q_s[it] = torch_complex.cat(Q_ts) + Q_b[ib] = torch_complex.cat(list(Q_s.values())).view(1, -1) + # Q_cat[ib,it*il*ia*im*iu] + Q_cat = torch_complex.cat(Q_b, dim=0) + # V[ist][ib1,ib2] + V[ist] = torch_complex.mm( + Q_cat.conj(), torch_complex.mm(S_I, Q_cat.t()) + ).real - - - def cal_V(self,Q,S,info,V_info): - """ - V[ist][ib] - = sum_{it1,ia1,il1,im1,iu1} sum_{it2,ia2,il2,im2,iu2} - Q[ist][it1][il1][ib,ia1*im1*iu1] * S[ist]{[it1][it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*iu2] - V[ist][ib1,ib2] - = sum_{it1,ia1,il1,im1,iu1} sum_{it2,ia2,il2,im2,iu2} - Q[ist][it1][il1][ib1,ia1*im1*iu1] * S[ist]{[it1][it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2]}^{-1} * Q[ist][it2][il2][ib2,ia2*im2*iu2] - """ - V = ND_list(info.Nst) - for ist in range(info.Nst): - - # S_s[it1][il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] - S_s = dict() - for it1 in info.Nt[ist]: - # S_st[it2][il1*ia1*im1*iu1,il2*ia2*im2*iu2] - S_st = dict() - for it2 in info.Nt[ist]: - # S_stt[il1][ia1*im1*iu1,il2*ia2*im2*iu2] - S_stt = ND_list(info.Nl[it1]) - for il1 in range(info.Nl[it1]): - S_stt[il1] = torch_complex.cat( S[ist][it1,it2][il1], dim=1 ) - S_st[it2] = torch_complex.cat( S_stt, dim=0 ) - S_s[it1] = torch_complex.cat( list(S_st.values()), dim=1 ) - # S_cat[it1*il1*iat*im1*iu1,iat2*il2*ia2*im2*iu2] - S_cat = torch_complex.cat( list(S_s.values()), dim=0 ) - S_I = torch_complex.inverse(S_cat) - - if V_info["same_band"]: - # V_s[ib] - V_s = ND_list(info.Nb[ist]) - for ib in range(info.Nb[ist]): - # Q_s[it][il*ia*im*iu] - Q_s = dict() - for it in info.Nt[ist]: - # Q_ts[il][ia*im*iu] - Q_ts = [ Q_stl[ib] for Q_stl in Q[ist][it] ] - Q_s[it] = torch_complex.cat(Q_ts) - # Q_cat[it*il*ia*im*iu] - Q_cat = torch_complex.cat(list(Q_s.values())) - V_s[ib] = torch_complex.dot( Q_cat.conj(), torch_complex.mv( S_I, Q_cat ) ).real.view(-1) - # V[ist][ib] - V[ist] = torch.cat(V_s) - else: - # Q_b[ib][0,it*il*ia*im*iu] - Q_b = ND_list(info.Nb[ist]) - for ib in range(info.Nb[ist]): - # Q_s[it][il*ia*im*iu] - Q_s = dict() - for it in info.Nt[ist]: - # Q_ts[il][ia*im*iu] - Q_ts = [ Q_stl[ib] for Q_stl in Q[ist][it] ] - Q_s[it] = torch_complex.cat(Q_ts) - Q_b[ib] = torch_complex.cat(list(Q_s.values())).view(1,-1) - # Q_cat[ib,it*il*ia*im*iu] - Q_cat = torch_complex.cat( Q_b, dim=0 ) - # V[ist][ib1,ib2] - V[ist] = torch_complex.mm( Q_cat.conj(), torch_complex.mm( S_I, Q_cat.t() ) ).real + return V - return V - - - def cal_T(self,C,E): - """ T = 0.5* sum_{it,il,iu} sum_{ie} ( E[it][il,ie] * C[it][il][ie,iu] )**2 """ - T = torch.zeros(1) - num = 0 - for it,C_t in C.items(): - for il,C_tl in enumerate(C_t): - for iu in range(C_tl.size()[1]): - T_tlu = torch.zeros(1) - Z_tlu = 0 - for ie in range(C_tl.size()[0]): - T_tlu = T_tlu + ( E[it][il,ie] * C_tl[ie,iu] )**2 - Z_tlu = Z_tlu + E[it][il,ie].item()**2 - T = T + T_tlu/Z_tlu - num += C_tl.size()[1] - T = 0.5 * T / num - return T \ No newline at end of file + def cal_T(self, C, E): + """T = 0.5* sum_{it,il,iu} sum_{ie} ( E[it][il,ie] * C[it][il][ie,iu] )**2""" + T = torch.zeros(1) + num = 0 + for it, C_t in C.items(): + for il, C_tl in enumerate(C_t): + for iu in range(C_tl.size()[1]): + T_tlu = torch.zeros(1) + Z_tlu = 0 + for ie in range(C_tl.size()[0]): + T_tlu = T_tlu + (E[it][il, ie] * C_tl[ie, iu]) ** 2 + Z_tlu = Z_tlu + E[it][il, ie].item() ** 2 + T = T + T_tlu / Z_tlu + num += C_tl.size()[1] + T = 0.5 * T / num + return T diff --git a/tools/SIAB/PyTorchGradient/source/opt_orbital.py_real b/tools/SIAB/PyTorchGradient/source/opt_orbital.py_real index 5ade0f90fc4..65e91aeb0d4 100644 --- a/tools/SIAB/PyTorchGradient/source/opt_orbital.py_real +++ b/tools/SIAB/PyTorchGradient/source/opt_orbital.py_real @@ -1,86 +1,86 @@ -from global_function import ND_list -import inverse -import torch - -class SIA: - - def cal_Q(self,QI,C): - """ - Q[ist][it][il][ib,ia*im*iu] - = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] - """ - Q = ND_list(self.Nst) - for ist in range(self.Nst): - Q[ist] = ND_list(self.Nt[ist]) - for it in range(self.Nt[ist]): - Q[ist][it] = ND_list(self.Nl[it]) - - for ist in range(self.Nst): - for it in range(self.Nt[ist]): - for il in range(self.Nl[it]): - Q[ist][it][il] = torch.mm( QI[ist][it][il], C[it][il] ).view(self.Nb[ist],-1) - return Q - - - - def cal_S(self,SI,C): - """ - S[ist][it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2] - = sum_{ie1 ie2} C[it1][il1][ie1,in1] * SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] * C[it2][[il2][ie2,in2] - """ - S = ND_list(self.Nst) - for ist in range(self.Nst): - S[ist] = ND_list(self.Nt[ist],self.Nt[ist]) - for it1 in range(self.Nt[ist]): - for it2 in range(self.Nt[ist]): - S[ist][it1][it2] = ND_list(self.Nl[it1],self.Nl[it2]) - - for ist in range(self.Nst): - for it1 in range(self.Nt[ist]): - for it2 in range(self.Nt[ist]): - for il1 in range(self.Nl[it1]): - for il2 in range(self.Nl[it2]): - S[ist][it1][it2][il1][il2] = torch.mm( - C[it1][il1].t(), - torch.mm( SI[ist][it1][it2][il1][il2].view(-1,self.Ne), C[it2][il2] ).view(self.Ne,-1) - ).view(self.Nn[it1][il1],self.Na[ist][it1]*self.Nm[il1],-1).transpose(0,1).view(self.Na[ist][it1]*self.Nm[il1]*self.Nn[it1][il1],-1) - return S - - - - def cal_V(self,Q,S): - """ - V[ist][ib] - = sum_{it1,ia1,il1,im1,in1} sum_{it2,ia2,il2,im2,in2} - Q[ist][it1][il1][ib,ia1*im1*in1] * S[ist]{[it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*in2] - """ - V = ND_list(self.Nst) - for ist in range(self.Nst): - V[ist] = ND_list(self.Nb[ist]) - - for ist in range(self.Nst): - - S_s = ND_list(self.Nt[ist]) - for it1 in range(self.Nt[ist]): - S_st = ND_list(self.Nt[ist]) - for it2 in range(self.Nt[ist]): - S_stt = ND_list(self.Nl[it1]) - for il1 in range(self.Nl[it1]): - S_stt[il1] = torch.cat( S[ist][it1][it2][il1], dim=1 ) - S_st[it2] = torch.cat( S_stt, dim=0 ) - S_s[it1] = torch.cat( S_st, dim=1 ) - S_cat = torch.cat( S_s, dim=0 ) - - S_I = inverse.inverse(S_cat) -# S_I = 1/S_cat - - for ib in range(self.Nb[ist]): - - Q_s = ND_list(self.Nt[ist]) - for it in range(self.Nt[ist]): - Q_s[it] = torch.cat([ Q_st[ib] for Q_st in Q[ist][it] ]) - Q_cat = torch.cat(Q_s) - - V[ist][ib] = torch.dot( Q_cat, torch.mv( S_I, Q_cat ) ) - - return V \ No newline at end of file +from global_function import ND_list +import inverse +import torch + +class SIA: + + def cal_Q(self,QI,C): + """ + Q[ist][it][il][ib,ia*im*iu] + = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] + """ + Q = ND_list(self.Nst) + for ist in range(self.Nst): + Q[ist] = ND_list(self.Nt[ist]) + for it in range(self.Nt[ist]): + Q[ist][it] = ND_list(self.Nl[it]) + + for ist in range(self.Nst): + for it in range(self.Nt[ist]): + for il in range(self.Nl[it]): + Q[ist][it][il] = torch.mm( QI[ist][it][il], C[it][il] ).view(self.Nb[ist],-1) + return Q + + + + def cal_S(self,SI,C): + """ + S[ist][it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2] + = sum_{ie1 ie2} C[it1][il1][ie1,in1] * SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] * C[it2][[il2][ie2,in2] + """ + S = ND_list(self.Nst) + for ist in range(self.Nst): + S[ist] = ND_list(self.Nt[ist],self.Nt[ist]) + for it1 in range(self.Nt[ist]): + for it2 in range(self.Nt[ist]): + S[ist][it1][it2] = ND_list(self.Nl[it1],self.Nl[it2]) + + for ist in range(self.Nst): + for it1 in range(self.Nt[ist]): + for it2 in range(self.Nt[ist]): + for il1 in range(self.Nl[it1]): + for il2 in range(self.Nl[it2]): + S[ist][it1][it2][il1][il2] = torch.mm( + C[it1][il1].t(), + torch.mm( SI[ist][it1][it2][il1][il2].view(-1,self.Ne), C[it2][il2] ).view(self.Ne,-1) + ).view(self.Nn[it1][il1],self.Na[ist][it1]*self.Nm[il1],-1).transpose(0,1).view(self.Na[ist][it1]*self.Nm[il1]*self.Nn[it1][il1],-1) + return S + + + + def cal_V(self,Q,S): + """ + V[ist][ib] + = sum_{it1,ia1,il1,im1,in1} sum_{it2,ia2,il2,im2,in2} + Q[ist][it1][il1][ib,ia1*im1*in1] * S[ist]{[it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*in2] + """ + V = ND_list(self.Nst) + for ist in range(self.Nst): + V[ist] = ND_list(self.Nb[ist]) + + for ist in range(self.Nst): + + S_s = ND_list(self.Nt[ist]) + for it1 in range(self.Nt[ist]): + S_st = ND_list(self.Nt[ist]) + for it2 in range(self.Nt[ist]): + S_stt = ND_list(self.Nl[it1]) + for il1 in range(self.Nl[it1]): + S_stt[il1] = torch.cat( S[ist][it1][it2][il1], dim=1 ) + S_st[it2] = torch.cat( S_stt, dim=0 ) + S_s[it1] = torch.cat( S_st, dim=1 ) + S_cat = torch.cat( S_s, dim=0 ) + + S_I = inverse.inverse(S_cat) +# S_I = 1/S_cat + + for ib in range(self.Nb[ist]): + + Q_s = ND_list(self.Nt[ist]) + for it in range(self.Nt[ist]): + Q_s[it] = torch.cat([ Q_st[ib] for Q_st in Q[ist][it] ]) + Q_cat = torch.cat(Q_s) + + V[ist][ib] = torch.dot( Q_cat, torch.mv( S_I, Q_cat ) ) + + return V \ No newline at end of file diff --git a/tools/SIAB/PyTorchGradient/source/orbital.py b/tools/SIAB/PyTorchGradient/source/orbital.py index 75c7748187b..8711ab6284e 100644 --- a/tools/SIAB/PyTorchGradient/source/orbital.py +++ b/tools/SIAB/PyTorchGradient/source/orbital.py @@ -6,75 +6,89 @@ import functools import torch -def generate_orbital(info,C,E,Rcut,dr): - """ C[it][il][ie,iu] """ - """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ - orb = dict() - for it in info.Nt_all: - Nr = int(Rcut[it]/dr[it])+1 - orb[it] = ND_list(info.Nl[it]) - for il in range(info.Nl[it]): - orb[it][il] = ND_list(info.Nu[it][il]) - for iu in range(info.Nu[it][il]): - orb[it][il][iu] = np.zeros(Nr) - for ir in range(Nr): - r = ir * dr[it] - for ie in range(info.Ne[it]): - orb[it][il][iu][ir] += C[it][il][ie,iu].item() * spherical_jn(il,E[it][il,ie].item()*r) - return orb - - -def smooth_orbital(orb,Rcut,dr,smearing_sigma): - for it,orb_t in orb.items(): - for orb_tl in orb_t: - for orb_tlu in orb_tl: - for ir in range(orb_tlu.shape[0]): - assert orb_tlu.shape[0] == int(Rcut[it]/dr[it])+1 - r = ir * dr[it] - orb_tlu[ir] *= 1-np.exp( -(r-Rcut[it])**2/(2*smearing_sigma**2) ) - - - -def inner_product( orb1, orb2, dr ): - assert orb1.shape == orb2.shape - r = np.array(range(orb1.shape[0]))*dr - return simps( orb1 * orb2 * r * r, dx=dr ) - -def normalize(orb,dr,C=None,flag_norm_orb=False,flag_norm_C=False): - """ C[it][il][ie,iu] """ - """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ - for it,orb_t in orb.items(): - for il,orb_tl in enumerate(orb_t): - for iu,orb_tlu in enumerate(orb_tl): - norm = np.sqrt(inner_product(orb_tlu,orb_tlu,dr[it])) - if flag_norm_orb: orb_tlu[:] = orb_tlu / norm - if flag_norm_C: C[it][il].data[:,iu] = C[it][il].data[:,iu] / norm - -def orth(orb,dr): - """ |n'> = 1/Z ( |n> - \sum_{i=0}^{n-1} |i> ) """ - """ orb[it][il][iu,r] """ - for it,orb_t in orb.items(): - for il,orb_tl in enumerate(orb_t): - for iu1,orb_tlu1 in enumerate(orb_tl): - for iu2 in range(iu1): - orb_tlu1[:] -= orb_tl[iu2] * inner_product(orb_tlu1,orb_tl[iu2],dr[it]) - orb_tlu1[:] = orb_tlu1 / np.sqrt(inner_product(orb_tlu1,orb_tlu1,dr[it])) - -def find_eigenvalue(Nl,Ne): - """ E[il,ie] """ - E = np.zeros((Nl,Ne+Nl+1)) - for ie in range(1,Ne+Nl+1): - E[0,ie] = ie*np.pi - for il in range(1,Nl): - jl = functools.partial(spherical_jn,il) - for ie in range(1,Ne+Nl+1-il): - E[il,ie] = fsolve( jl, (E[il-1,ie]+E[il-1,ie+1])/2 ) - return E[:,1:Ne+1] - -def set_E(info,Rcut): - """ E[it][il,ie] """ - eigenvalue = { it:find_eigenvalue(info.Nl[it],info.Ne[it]) for it in info.Nt_all } - E = dict() - for it in Rcut: - E[it] = torch.from_numpy(( eigenvalue[it]/Rcut[it] ).astype("float32")) - return E \ No newline at end of file + +def generate_orbital(info, C, E, Rcut, dr): + """C[it][il][ie,iu]""" + """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ + orb = dict() + for it in info.Nt_all: + Nr = int(Rcut[it] / dr[it]) + 1 + orb[it] = ND_list(info.Nl[it]) + for il in range(info.Nl[it]): + orb[it][il] = ND_list(info.Nu[it][il]) + for iu in range(info.Nu[it][il]): + orb[it][il][iu] = np.zeros(Nr) + for ir in range(Nr): + r = ir * dr[it] + for ie in range(info.Ne[it]): + orb[it][il][iu][ir] += C[it][il][ie, iu].item() * spherical_jn( + il, E[it][il, ie].item() * r + ) + return orb + + +def smooth_orbital(orb, Rcut, dr, smearing_sigma): + for it, orb_t in orb.items(): + for orb_tl in orb_t: + for orb_tlu in orb_tl: + for ir in range(orb_tlu.shape[0]): + assert orb_tlu.shape[0] == int(Rcut[it] / dr[it]) + 1 + r = ir * dr[it] + orb_tlu[ir] *= 1 - np.exp( + -((r - Rcut[it]) ** 2) / (2 * smearing_sigma**2) + ) + + +def inner_product(orb1, orb2, dr): + assert orb1.shape == orb2.shape + r = np.array(range(orb1.shape[0])) * dr + return simps(orb1 * orb2 * r * r, dx=dr) + + +def normalize(orb, dr, C=None, flag_norm_orb=False, flag_norm_C=False): + """C[it][il][ie,iu]""" + """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ + for it, orb_t in orb.items(): + for il, orb_tl in enumerate(orb_t): + for iu, orb_tlu in enumerate(orb_tl): + norm = np.sqrt(inner_product(orb_tlu, orb_tlu, dr[it])) + if flag_norm_orb: + orb_tlu[:] = orb_tlu / norm + if flag_norm_C: + C[it][il].data[:, iu] = C[it][il].data[:, iu] / norm + + +def orth(orb, dr): + """|n'> = 1/Z ( |n> - \sum_{i=0}^{n-1} |i> )""" + """ orb[it][il][iu,r] """ + for it, orb_t in orb.items(): + for il, orb_tl in enumerate(orb_t): + for iu1, orb_tlu1 in enumerate(orb_tl): + for iu2 in range(iu1): + orb_tlu1[:] -= orb_tl[iu2] * inner_product( + orb_tlu1, orb_tl[iu2], dr[it] + ) + orb_tlu1[:] = orb_tlu1 / np.sqrt( + inner_product(orb_tlu1, orb_tlu1, dr[it]) + ) + + +def find_eigenvalue(Nl, Ne): + """E[il,ie]""" + E = np.zeros((Nl, Ne + Nl + 1)) + for ie in range(1, Ne + Nl + 1): + E[0, ie] = ie * np.pi + for il in range(1, Nl): + jl = functools.partial(spherical_jn, il) + for ie in range(1, Ne + Nl + 1 - il): + E[il, ie] = fsolve(jl, (E[il - 1, ie] + E[il - 1, ie + 1]) / 2) + return E[:, 1 : Ne + 1] + + +def set_E(info, Rcut): + """E[it][il,ie]""" + eigenvalue = {it: find_eigenvalue(info.Nl[it], info.Ne[it]) for it in info.Nt_all} + E = dict() + for it in Rcut: + E[it] = torch.from_numpy((eigenvalue[it] / Rcut[it]).astype("float32")) + return E diff --git a/tools/SIAB/PyTorchGradient/source/pf.py b/tools/SIAB/PyTorchGradient/source/pf.py index e518fa02f73..cc3f08f0642 100644 --- a/tools/SIAB/PyTorchGradient/source/pf.py +++ b/tools/SIAB/PyTorchGradient/source/pf.py @@ -1,2 +1,3 @@ import profile -profile.run("import main","profile.dat") \ No newline at end of file + +profile.run("import main", "profile.dat") diff --git a/tools/SIAB/PyTorchGradient/source/torch_complex.py b/tools/SIAB/PyTorchGradient/source/torch_complex.py index d5f338d5d74..62171145f6f 100644 --- a/tools/SIAB/PyTorchGradient/source/torch_complex.py +++ b/tools/SIAB/PyTorchGradient/source/torch_complex.py @@ -1,83 +1,133 @@ -import torch - -class ComplexTensor: - def __init__(self,real,imag): - self.real = real - self.imag = imag - - def view(self,*args,**kwargs): - return ComplexTensor( self.real.view(*args,**kwargs), self.imag.view(*args,**kwargs) ) - def t(self,*args,**kwargs): - return ComplexTensor( self.real.t(*args,**kwargs), self.imag.t(*args,**kwargs) ) -# def transpose(self,*args,**kwargs): -# return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) - def __getitem__(self,*args,**kwargs): - return ComplexTensor( self.real.__getitem__(*args,**kwargs), self.imag.__getitem__(*args,**kwargs) ) - def __str__(self): - return "<{0};{1}>".format(self.real, self.imag) - __repr__=__str__ -# def size(self,*args,**kwargs): -# return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) - - def conj(self): - return ComplexTensor( self.real, -self.imag ) - - - -def dot( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1.real,x2.real, *args,**kwargs ) - torch.dot( x1.imag,x2.imag, *args,**kwargs ), torch.dot( x1.real,x2.imag, *args,**kwargs ) + torch.dot( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.dot( x1.real,x2, *args,**kwargs ), torch.dot( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1,x2.real, *args,**kwargs ), torch.dot( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.dot( x1,x2, *args,**kwargs ) -def mv( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1.real,x2.real, *args,**kwargs ) - torch.mv( x1.imag,x2.imag, *args,**kwargs ), torch.mv( x1.real,x2.imag, *args,**kwargs ) + torch.mv( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mv( x1.real,x2, *args,**kwargs ), torch.mv( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1,x2.real, *args,**kwargs ), torch.mv( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mv( x1,x2, *args,**kwargs ) -def mm( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1.real,x2.real, *args,**kwargs ) - torch.mm( x1.imag,x2.imag, *args,**kwargs ), torch.mm( x1.real,x2.imag, *args,**kwargs ) + torch.mm( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mm( x1.real,x2, *args,**kwargs ), torch.mm( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1,x2.real, *args,**kwargs ), torch.mm( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mm( x1,x2, *args,**kwargs ) - - -def cat( xs, *args,**kwargs ): - if isinstance(xs[0],ComplexTensor): - xs_real = []; xs_imag = [] - for x in xs: - xs_real.append(x.real) - xs_imag.append(x.imag) - return ComplexTensor( torch.cat(xs_real,*args,**kwargs), torch.cat(xs_imag,*args,**kwargs) ) - else: - return torch.cat(xs,*args,**kwargs) - - - -import inverse as inverse_real -def inverse(M): - if isinstance(M,ComplexTensor): - A=M.real - B=M.imag - tmp_AB = torch.mm(A.inverse(),B) # A^{-1} B - tmp_X = (A+torch.mm(B,tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} - return ComplexTensor( tmp_X, -torch.mm(tmp_AB,tmp_X) ) - else: - return M.inverse() \ No newline at end of file +import torch + + +class ComplexTensor: + def __init__(self, real, imag): + self.real = real + self.imag = imag + + def view(self, *args, **kwargs): + return ComplexTensor( + self.real.view(*args, **kwargs), self.imag.view(*args, **kwargs) + ) + + def t(self, *args, **kwargs): + return ComplexTensor(self.real.t(*args, **kwargs), self.imag.t(*args, **kwargs)) + + # def transpose(self,*args,**kwargs): + # return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) + def __getitem__(self, *args, **kwargs): + return ComplexTensor( + self.real.__getitem__(*args, **kwargs), + self.imag.__getitem__(*args, **kwargs), + ) + + def __str__(self): + return "<{0};{1}>".format(self.real, self.imag) + + __repr__ = __str__ + # def size(self,*args,**kwargs): + # return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) + + def conj(self): + return ComplexTensor(self.real, -self.imag) + + +def dot(x1, x2, *args, **kwargs): + if isinstance(x1, ComplexTensor): + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.dot(x1.real, x2.real, *args, **kwargs) + - torch.dot(x1.imag, x2.imag, *args, **kwargs), + torch.dot(x1.real, x2.imag, *args, **kwargs) + + torch.dot(x1.imag, x2.real, *args, **kwargs), + ) + else: + return ComplexTensor( + torch.dot(x1.real, x2, *args, **kwargs), + torch.dot(x1.imag, x2, *args, **kwargs), + ) + else: + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.dot(x1, x2.real, *args, **kwargs), + torch.dot(x1, x2.imag, *args, **kwargs), + ) + else: + return torch.dot(x1, x2, *args, **kwargs) + + +def mv(x1, x2, *args, **kwargs): + if isinstance(x1, ComplexTensor): + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mv(x1.real, x2.real, *args, **kwargs) + - torch.mv(x1.imag, x2.imag, *args, **kwargs), + torch.mv(x1.real, x2.imag, *args, **kwargs) + + torch.mv(x1.imag, x2.real, *args, **kwargs), + ) + else: + return ComplexTensor( + torch.mv(x1.real, x2, *args, **kwargs), + torch.mv(x1.imag, x2, *args, **kwargs), + ) + else: + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mv(x1, x2.real, *args, **kwargs), + torch.mv(x1, x2.imag, *args, **kwargs), + ) + else: + return torch.mv(x1, x2, *args, **kwargs) + + +def mm(x1, x2, *args, **kwargs): + if isinstance(x1, ComplexTensor): + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mm(x1.real, x2.real, *args, **kwargs) + - torch.mm(x1.imag, x2.imag, *args, **kwargs), + torch.mm(x1.real, x2.imag, *args, **kwargs) + + torch.mm(x1.imag, x2.real, *args, **kwargs), + ) + else: + return ComplexTensor( + torch.mm(x1.real, x2, *args, **kwargs), + torch.mm(x1.imag, x2, *args, **kwargs), + ) + else: + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mm(x1, x2.real, *args, **kwargs), + torch.mm(x1, x2.imag, *args, **kwargs), + ) + else: + return torch.mm(x1, x2, *args, **kwargs) + + +def cat(xs, *args, **kwargs): + if isinstance(xs[0], ComplexTensor): + xs_real = [] + xs_imag = [] + for x in xs: + xs_real.append(x.real) + xs_imag.append(x.imag) + return ComplexTensor( + torch.cat(xs_real, *args, **kwargs), torch.cat(xs_imag, *args, **kwargs) + ) + else: + return torch.cat(xs, *args, **kwargs) + + +import inverse as inverse_real + + +def inverse(M): + if isinstance(M, ComplexTensor): + A = M.real + B = M.imag + tmp_AB = torch.mm(A.inverse(), B) # A^{-1} B + tmp_X = (A + torch.mm(B, tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} + return ComplexTensor(tmp_X, -torch.mm(tmp_AB, tmp_X)) + else: + return M.inverse() diff --git a/tools/SIAB/PyTorchGradient/source/unittest_inverse.py b/tools/SIAB/PyTorchGradient/source/unittest_inverse.py index f4d43156108..07aaecc888d 100644 --- a/tools/SIAB/PyTorchGradient/source/unittest_inverse.py +++ b/tools/SIAB/PyTorchGradient/source/unittest_inverse.py @@ -1,29 +1,30 @@ -import unittest -import inverse -import torch - -class unittest_inverse(unittest.TestCase): - - def inverse_test(self,a,ai_true): - - a=torch.Tensor(a) - a=torch.autograd.Variable(a) - - ai_test=inverse.inverse(a) - - ai_true = torch.Tensor(ai_true) - ai_true=torch.autograd.Variable(ai_true) - - self.assertFalse((ai_test!=ai_true).data.sum()) - - def test_inverse_1(self): - self.inverse_test( - [[1,2],[2,3]], - [[-3,2],[2,-1]] ) - def test_inverse_2(self): - self.inverse_test( - [[1,2,3],[2,4,5],[3,5,6]], - [[1,-3,2],[-3,3,-1],[2,-1,0]] ) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file +import unittest +import inverse +import torch + + +class unittest_inverse(unittest.TestCase): + + def inverse_test(self, a, ai_true): + + a = torch.Tensor(a) + a = torch.autograd.Variable(a) + + ai_test = inverse.inverse(a) + + ai_true = torch.Tensor(ai_true) + ai_true = torch.autograd.Variable(ai_true) + + self.assertFalse((ai_test != ai_true).data.sum()) + + def test_inverse_1(self): + self.inverse_test([[1, 2], [2, 3]], [[-3, 2], [2, -1]]) + + def test_inverse_2(self): + self.inverse_test( + [[1, 2, 3], [2, 4, 5], [3, 5, 6]], [[1, -3, 2], [-3, 3, -1], [2, -1, 0]] + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/SIAB/PyTorchGradient/source/util.py b/tools/SIAB/PyTorchGradient/source/util.py index e08d0e09d53..70128938cf9 100644 --- a/tools/SIAB/PyTorchGradient/source/util.py +++ b/tools/SIAB/PyTorchGradient/source/util.py @@ -1,36 +1,44 @@ -def ND_list(*sizes,element=None): - size_1,*size_other = sizes - l = [element] * size_1 - if size_other: - for i in range(len(l)): - l[i] = ND_list(*size_other,element=element) - else: - if element in ["dict()","list()"]: - for i in range(size_1): - l[i] = eval(element) - return l - - -def ignore_line(file,N): - for _ in range(N): - file.readline() - - +def ND_list(*sizes, element=None): + size_1, *size_other = sizes + l = [element] * size_1 + if size_other: + for i in range(len(l)): + l[i] = ND_list(*size_other, element=element) + else: + if element in ["dict()", "list()"]: + for i in range(size_1): + l[i] = eval(element) + return l + + +def ignore_line(file, N): + for _ in range(N): + file.readline() + + class Info: - def Nm(self,il): return 2*il+1 - def __str__(self): - return " "+"\n ".join([name+"\t"+str(value) for name,value in self.__dict__.items()]) - __repr__=__str__ - + def Nm(self, il): + return 2 * il + 1 + + def __str__(self): + return " " + "\n ".join( + [name + "\t" + str(value) for name, value in self.__dict__.items()] + ) + + __repr__ = __str__ + + def change_to_cuda(s): - if isinstance(s,list): - return [change_to_cuda(x) for x in s] - elif isinstance(s,dict): - return {i:change_to_cuda(x) for i,x in s.items()} - elif isinstance(s,torch.Tensor): - return s.cuda() - elif isinstance(s,torch_complex.ComplexTensor): - return torch_complex.ComplexTensor( change_to_cuda(s.real), change_to_cuda(s.imag) ) - else: - print(s) - raise TypeError("change_to_cuda") + if isinstance(s, list): + return [change_to_cuda(x) for x in s] + elif isinstance(s, dict): + return {i: change_to_cuda(x) for i, x in s.items()} + elif isinstance(s, torch.Tensor): + return s.cuda() + elif isinstance(s, torch_complex.ComplexTensor): + return torch_complex.ComplexTensor( + change_to_cuda(s.real), change_to_cuda(s.imag) + ) + else: + print(s) + raise TypeError("change_to_cuda") diff --git a/tools/SIAB/README.md b/tools/SIAB/README.md index 6047f7677a1..36198eede3a 100644 --- a/tools/SIAB/README.md +++ b/tools/SIAB/README.md @@ -1,6 +1,5 @@ # SIAB Package Description - **S**ystematically **I**mprovable @@ -9,7 +8,6 @@ **B**asis generator based on spillage formula - # HOW TO USE SIAB The optimization can choose one of the three minimization methods: @@ -20,21 +18,19 @@ The optimization can choose one of the three minimization methods: The executable files for the three methods are: -- ./SimulatedAnnealing/source/SIA_s.exe, -- ./PyTorchGradient/source/main.py, -- ../opt_orb_pytorch_dpsi/main.py, +- ./SimulatedAnnealing/source/SIA_s.exe, +- ./PyTorchGradient/source/main.py, +- ../opt_orb_pytorch_dpsi/main.py, respectively. +## 1. Write input file -## 1. Write input file - -Firstly, write the input file, such as **ORBITAL_INPUT_DZP** in example-directories, for script **Generate_Orbital_AllInOne.sh**. -All three approachs work with the same bash script and use the same input file. -Please use **absolute path** for each file/directory in input file. - +Firstly, write the input file, such as **ORBITAL_INPUT_DZP** in example-directories, for script +**Generate_Orbital_AllInOne.sh**. All three approachs work with the same bash script and use the +same input file. Please use **absolute path** for each file/directory in input file. -## 2. Set up dependence environment +## 2. Set up dependence environment Secondly, we set up the dependence environment for ABACUS and SIAB, such as: @@ -44,7 +40,6 @@ $ module load hpcx/2.9.0/hpcx-intel-2019.update5 mkl/2019.update5 elpa/2019.05.0 Especially for SIAB with **PyTorch Gradient** approach, we need pytorch v1.1.0. - ### How to install pytorch: Take the HanHai20@USTC system for example: @@ -70,7 +65,6 @@ $ pip3 install --user scipy numpy $ pip3 install --user torch_optimizer ``` - ## 3. Run generation Finally, `cd` into an example folder, and run command like this: @@ -80,4 +74,3 @@ $ ../Generate_Orbital_AllInOne.sh ORBITAL_INPUT_DZP or $ bsub -q idle -n 8 -oo running.log ../Generate_Orbital_AllInOne.sh ORBITAL_INPUT_DZP ``` - diff --git a/tools/SIAB/SimulatedAnnealing/source/Makefile b/tools/SIAB/SimulatedAnnealing/source/Makefile index aa6ff021478..834cb0cb11d 100644 --- a/tools/SIAB/SimulatedAnnealing/source/Makefile +++ b/tools/SIAB/SimulatedAnnealing/source/Makefile @@ -9,7 +9,7 @@ MKLROOT=/home/mohan/intel/oneapi/mkl/021.3.0/ #------------------------------ # for serial version: make s #------------------------------ -CPLUSPLUS = icpc +CPLUSPLUS = icpc #------------------------------ # for parallel version: make p @@ -19,103 +19,103 @@ CPLUSPLUS = icpc CXXFLAGS = -std=c++11 -O3 #CXXFLAGS = -std=c++11 -O2 -xCORE-AVX2 -align -fma -ftz -fomit-frame-pointer -finline-functions \ - -I${MKLROOT}/include -I${MKLROOT}/include/intel64/ilp64 \ - -lmkl_blacs_intelmpi_lp64 -lmkl_scalapack_lp64 -lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread -limf + -I${MKLROOT}/include -I${MKLROOT}/include/intel64/ilp64 \ + -lmkl_blacs_intelmpi_lp64 -lmkl_scalapack_lp64 -lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread -limf LIBS=-L${MKLROOT}/lib/intel64 -Wl,--start-group -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -Wl,--end-group -liomp5 -lpthread -lm TOOLS_OBJS=src_tools/mathzone.o \ - src_tools/matrix.o \ - src_tools/matrix3.o \ - src_tools/realarray.o \ - src_tools/intarray.o \ - src_tools/complexmatrix.o \ - src_tools/complexarray.o\ - src_tools/timer.o \ - src_tools/inverse_matrix.o\ - src_tools/inverse_matrix_iterate.o\ - src_tools/Simulated_Annealing.o\ - + src_tools/matrix.o \ + src_tools/matrix3.o \ + src_tools/realarray.o \ + src_tools/intarray.o \ + src_tools/complexmatrix.o \ + src_tools/complexarray.o\ + src_tools/timer.o \ + src_tools/inverse_matrix.o\ + src_tools/inverse_matrix_iterate.o\ + src_tools/Simulated_Annealing.o\ + SPILLAGE_OBJS=src_spillage/main.o \ - src_spillage/read_INPUT.o\ - src_spillage/ReadData.o\ - src_spillage/Calculate_C4.o\ - src_spillage/Coefficients.o\ - src_spillage/MultiZeta.o\ - src_spillage/SpillageStep.o\ - src_spillage/SpillageValue.o\ - src_spillage/Step_Data.o\ - src_spillage/Inverse_Matrix_S.o\ - src_spillage/Orthogonal.o\ - src_spillage/Type_Information.o\ - src_spillage/Metropolis.o\ - src_spillage/Metropolis_2.o\ - src_spillage/Out_Orbital.o\ - src_spillage/Plot_Psi.o\ - src_spillage/Psi_Second.o\ - src_spillage/tools.o \ - src_spillage/common.o \ - + src_spillage/read_INPUT.o\ + src_spillage/ReadData.o\ + src_spillage/Calculate_C4.o\ + src_spillage/Coefficients.o\ + src_spillage/MultiZeta.o\ + src_spillage/SpillageStep.o\ + src_spillage/SpillageValue.o\ + src_spillage/Step_Data.o\ + src_spillage/Inverse_Matrix_S.o\ + src_spillage/Orthogonal.o\ + src_spillage/Type_Information.o\ + src_spillage/Metropolis.o\ + src_spillage/Metropolis_2.o\ + src_spillage/Out_Orbital.o\ + src_spillage/Plot_Psi.o\ + src_spillage/Psi_Second.o\ + src_spillage/tools.o \ + src_spillage/common.o \ + PARALLEL_OBJS=src_parallel/parallel_global.o\ - src_parallel/parallel_common.o\ - src_parallel/parallel_reduce.o\ - src_parallel/parallel_kpoints.o + src_parallel/parallel_common.o\ + src_parallel/parallel_reduce.o\ + src_parallel/parallel_kpoints.o PW_OBJS=src_pw/pw_basis.o\ - src_pw/pw_complement.o\ - src_pw/heapsort.o\ - src_pw/numerical_basis.o\ - src_pw/bessel_basis.o\ - src_pw/ylm_real.o\ - src_pw/memory_calculation.o\ - + src_pw/pw_complement.o\ + src_pw/heapsort.o\ + src_pw/numerical_basis.o\ + src_pw/bessel_basis.o\ + src_pw/ylm_real.o\ + src_pw/memory_calculation.o\ + OBJS = ${TOOLS_OBJS} \ - ${SPILLAGE_OBJS} \ - ${PARALLEL_OBJS} \ - ${PW_OBJS}\ - -help : - @echo 'make target list: ' - @echo 's : Series version of Monte Carlo Spillage Program.' - @echo 'p : Parallel Version of Monte Carlo Spillage Program.' - @echo 'note : some notes.' + ${SPILLAGE_OBJS} \ + ${PARALLEL_OBJS} \ + ${PW_OBJS}\ + +help : +@echo 'make target list: ' +@echo 's : Series version of Monte Carlo Spillage Program.' +@echo 'p : Parallel Version of Monte Carlo Spillage Program.' +@echo 'note : some notes.' -s : ${OBJS} - ${CPLUSPLUS} ${CXXFLAGS} -o SIA_s.exe ${OBJS} ${LIBS} +s : ${OBJS} +${CPLUSPLUS} ${CXXFLAGS} -o SIA_s.exe ${OBJS} ${LIBS} p : ${OBJS} - ${CPLUSPLUS} -D__MPI ${CXXFLAGS} -o SIA_p.exe ${OBJS} ${LIBS} +${CPLUSPLUS} -D__MPI ${CXXFLAGS} -o SIA_p.exe ${OBJS} ${LIBS} note : - @echo 'atom type label : it ' - @echo 'atom label for each type : ia ' - @echo 'The angular momentum : l ' - @echo 'The multiplicity : n ' - @echo 'The magnetic quantum num : m ' - @echo 'The k point index : ik ' - @echo 'The band index : ib ' - @echo 'The eigenvalue of Jlq : ie ' - @echo 'The radius cutoff (a.u.) : rcut ' - @echo 'The state is : psi(ib,ik) ' - @echo 'The local orbitals is : phi(it,ia,l,n,m) ' - @echo 'The index of local basis : nwfc(it,l,n)' - @echo 'The index of local basis : nwfc2(it,ia,l,n,m) ' - @echo 'The Spherical Bessel func : Jl(ie,rcut) ' - @echo 'The SB transform : \int Jl(ie,rcut) * Jl' - @echo 'The index of Jlq coef : Coef(it,l,n,ie)' - @echo 'The local orbitals formu : phi=\sum_{ie} Coef(it,l,n,ie) * Jl(ie,rcut)' - @echo 'The spillage formula is : S = ' - @echo 'The projector P is : P = \sum_{mu,nu} |phi_mu> S^{-1} = (1-P1) |psi1>' - @echo 'So we can fonud that : P1|psi2> = 0 ' - @echo 'the Q matrix is : Q = ' - @echo 'the S matrix is : S = ' - @echo 'start index of band : BANDS_START(count from 1, not 0) ' - @echo 'end index of band : BANDS_END ' +@echo 'atom type label : it ' +@echo 'atom label for each type : ia ' +@echo 'The angular momentum : l ' +@echo 'The multiplicity : n ' +@echo 'The magnetic quantum num : m ' +@echo 'The k point index : ik ' +@echo 'The band index : ib ' +@echo 'The eigenvalue of Jlq : ie ' +@echo 'The radius cutoff (a.u.) : rcut ' +@echo 'The state is : psi(ib,ik) ' +@echo 'The local orbitals is : phi(it,ia,l,n,m) ' +@echo 'The index of local basis : nwfc(it,l,n)' +@echo 'The index of local basis : nwfc2(it,ia,l,n,m) ' +@echo 'The Spherical Bessel func : Jl(ie,rcut) ' +@echo 'The SB transform : \int Jl(ie,rcut) * Jl' +@echo 'The index of Jlq coef : Coef(it,l,n,ie)' +@echo 'The local orbitals formu : phi=\sum_{ie} Coef(it,l,n,ie) * Jl(ie,rcut)' +@echo 'The spillage formula is : S = ' +@echo 'The projector P is : P = \sum_{mu,nu} |phi_mu> S^{-1} = (1-P1) |psi1>' +@echo 'So we can fonud that : P1|psi2> = 0 ' +@echo 'the Q matrix is : Q = ' +@echo 'the S matrix is : S = ' +@echo 'start index of band : BANDS_START(count from 1, not 0) ' +@echo 'end index of band : BANDS_END ' .cpp.o: - ${CPLUSPLUS} ${CXXFLAGS} -c $< -o $@ +${CPLUSPLUS} ${CXXFLAGS} -c $< -o $@ .PHONY:clean clean: - ${RM} *.o *.exe core* src_tools/*.o src_spillage/*.o tests_s/ORBITAL* tests_s/ORBITAL* src_parallel/*.o src_pw/*.o +${RM} *.o *.exe core* src_tools/*.o src_spillage/*.o tests_s/ORBITAL* tests_s/ORBITAL* src_parallel/*.o src_pw/*.o diff --git a/tools/SIAB/SimulatedAnnealing/source/README.md b/tools/SIAB/SimulatedAnnealing/source/README.md index 89c66410103..2558474e7e1 100644 --- a/tools/SIAB/SimulatedAnnealing/source/README.md +++ b/tools/SIAB/SimulatedAnnealing/source/README.md @@ -1,14 +1,10 @@ The code is used to generate numerical atomic orbitals - The format of orbital file: -(1) First line: -Mesh number - -(2) Second line: -delta r (unit: Bohr) +(1) First line: Mesh number -(3) Type(always 0, you can ignore it), L(angular momentum), N (multizeta) -(4) wave function: psi (note, not psi*r). +(2) Second line: delta r (unit: Bohr) +(3) Type(always 0, you can ignore it), L(angular momentum), N (multizeta) (4) wave function: psi +(note, not psi\*r). diff --git a/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_common.cpp b/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_common.cpp index bc86f2c2fda..1090428bca2 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_common.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_common.cpp @@ -2,100 +2,87 @@ #include //this is needed because strcpy #ifdef __MPI -void Parallel_Common::bcast_string(string &object) -{ - char swap[100]; - if(MY_RANK == 0) strcpy(swap, object.c_str() ); - MPI_Bcast(swap, 100, MPI_CHAR, 0, MPI_COMM_WORLD); - if(MY_RANK != 0) object = static_cast( swap ); -// cout<<"\n"<(swap); + // cout<<"\n"<( swap ); - } - return; +void Parallel_Common::bcast_string(string* object, const int n) { + for (int i = 0; i < n; i++) { + char swap[100]; + if (MY_RANK == 0) + strcpy(swap, object[i].c_str()); + MPI_Bcast(swap, 100, MPI_CHAR, 0, MPI_COMM_WORLD); + if (MY_RANK != 0) + object[i] = static_cast(swap); + } + return; } -void Parallel_Common::bcast_complex_double(complex &object) -{ - double a = object.real(); - double b = object.imag(); - Parallel_Common::bcast_double(a); - Parallel_Common::bcast_double(b); - object = std::complex( a, b); - return; +void Parallel_Common::bcast_complex_double(complex& object) { + double a = object.real(); + double b = object.imag(); + Parallel_Common::bcast_double(a); + Parallel_Common::bcast_double(b); + object = std::complex(a, b); + return; } -void Parallel_Common::bcast_complex_double(complex *object, const int n) -{ - double *a = new double[n]; - double *b = new double[n]; +void Parallel_Common::bcast_complex_double(complex* object, const int n) { + double* a = new double[n]; + double* b = new double[n]; - for(int i=0; i( a[i], b[i]); - } - delete[] a; - delete[] b; + for (int i = 0; i < n; i++) { + object[i] = std::complex(a[i], b[i]); + } + delete[] a; + delete[] b; } -void Parallel_Common::bcast_double(double &object) -{ - MPI_Bcast(&object, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); -// cout<<"\n"<( swap ); -// cout<<"\n"<(swap); + // cout<<"\n"< *object, const int n); - void bcast_string(string *object,const int n); - void bcast_double(double *object,const int n); - void bcast_int(int *object,const int n); - void bcast_char(char *object,const int n); - - //(2) bcast single - void bcast_complex_double( std::complex &object); - void bcast_string(string &object); - void bcast_double(double &object); - void bcast_int(int &object); - void bcast_bool(bool &object); +namespace Parallel_Common { +//(1) bcast array +void bcast_complex_double(std::complex* object, const int n); +void bcast_string(string* object, const int n); +void bcast_double(double* object, const int n); +void bcast_int(int* object, const int n); +void bcast_char(char* object, const int n); -} +//(2) bcast single +void bcast_complex_double(std::complex& object); +void bcast_string(string& object); +void bcast_double(double& object); +void bcast_int(int& object); +void bcast_bool(bool& object); + +} // namespace Parallel_Common #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_global.cpp b/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_global.cpp index 1f6d3a01101..52ad8801324 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_global.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_global.cpp @@ -1,64 +1,59 @@ -//========================================================== -// AUTHOR : fangwei, mohan -// DATE : 2009-11-08 -//========================================================== -#include "parallel_global.h" -#include "parallel_common.h" -#include "parallel_reduce.h" -#include "../src_spillage/tools.h" - -using namespace std; - -#if defined __MPI -MPI_Comm POOL_WORLD; - -void Parallel_Global::myProd(complex *in, std::complex *inout,int *len,MPI_Datatype *dptr) -{ - for(int i=0;i<*len;i++) - { - (*inout).real()=(*inout).real()+(*in).real(); - (*inout).imag()=(*inout).imag()+(*in).imag(); - in++; - inout++; - } - return; -} -#endif - -void Parallel_Global::read_pal_param(int argc,char **argv) -{ -#if defined __MPI -//for test -/* - cout << "\n Hello! Test MPI NOW : argc = "<* in, std::complex* inout, int* len, MPI_Datatype* dptr) { + for (int i = 0; i < *len; i++) { + (*inout).real() = (*inout).real() + (*in).real(); + (*inout).imag() = (*inout).imag() + (*in).imag(); + in++; + inout++; + } + return; +} +#endif + +void Parallel_Global::read_pal_param(int argc, char** argv) { +#if defined __MPI + // for test + /* + cout << "\n Hello! Test MPI NOW : argc = "< -extern MPI_Comm POOL_WORLD; -#endif - -//void myProd(complex *in, std::complex *inout,int *len,MPI_Datatype *dptr); - -namespace Parallel_Global -{ - void read_pal_param(int argc, char **argv); - -#ifdef __MPI - void myProd(complex *in, std::complex *inout,int *len,MPI_Datatype *dptr); -#endif -} - - -#endif // GMPI +//========================================================== +// AUTHOR : Fang Wei, Mohan Chen +// DATE : 2008 +// LAST UPDATE : 2009-3-23 mohan add GATHER_MINIMUM_DOUBLE +//========================================================== +#ifndef PARALLEL_GLOBAL_H +#define PARALLEL_GLOBAL_H +#include "../src_spillage/common.h" + +#ifdef __MPI +#include +extern MPI_Comm POOL_WORLD; +#endif + +// void myProd(complex *in, std::complex *inout,int *len,MPI_Datatype *dptr); + +namespace Parallel_Global { +void read_pal_param(int argc, char** argv); + +#ifdef __MPI +void myProd(complex* in, std::complex* inout, int* len, MPI_Datatype* dptr); +#endif +} // namespace Parallel_Global + +#endif // GMPI diff --git a/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_kpoints.cpp b/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_kpoints.cpp index ef0b281f82b..975cf29d991 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_kpoints.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_parallel/parallel_kpoints.cpp @@ -2,302 +2,241 @@ #include "parallel_global.h" #include "parallel_common.h" -Parallel_Kpoints::Parallel_Kpoints() -{ - nks_pool = new int[1]; - startk_pool = new int[1]; - whichpool = new int[1]; +Parallel_Kpoints::Parallel_Kpoints() { + nks_pool = new int[1]; + startk_pool = new int[1]; + whichpool = new int[1]; } - -Parallel_Kpoints::~Parallel_Kpoints() -{ - delete[] nks_pool; - delete[] startk_pool; - delete[] whichpool; + +Parallel_Kpoints::~Parallel_Kpoints() { + delete[] nks_pool; + delete[] startk_pool; + delete[] whichpool; } -void Parallel_Kpoints::init(void) -{ - //TITLE("Parallel_Kpoints","init"); +void Parallel_Kpoints::init(void) { + // TITLE("Parallel_Kpoints","init"); #ifdef __MPI -//---------------------------------------------------------- -// CALL Function : divide_pools -//---------------------------------------------------------- - this->divide_pools(); - -// for test - - if(MY_RANK==0) - { - cout << "\n " << setw(8) << "MY_RANK" - << setw(8) << "MY_POOL" - << setw(13) << "RANK_IN_POOL" - << setw(6) << "NPROC" - << setw(6) << "KPAR" - << setw(14) << "NPROC_IN_POOL" << endl; - } - - ofs_running << "\n " << setw(8) << "MY_RANK" - << setw(8) << "MY_POOL" - << setw(13) << "RANK_IN_POOL" - << setw(6) << "NPROC" - << setw(6) << "KPAR" - << setw(14) << "NPROC_IN_POOL" << endl; - - for(int i=0;idivide_pools(); + + // for test + + if (MY_RANK == 0) { + cout << "\n " << setw(8) << "MY_RANK" << setw(8) << "MY_POOL" << setw(13) << "RANK_IN_POOL" << setw(6) + << "NPROC" << setw(6) << "KPAR" << setw(14) << "NPROC_IN_POOL" << endl; + } + + ofs_running << "\n " << setw(8) << "MY_RANK" << setw(8) << "MY_POOL" << setw(13) << "RANK_IN_POOL" << setw(6) + << "NPROC" << setw(6) << "KPAR" << setw(14) << "NPROC_IN_POOL" << endl; + + for (int i = 0; i < NPROC; i++) { + if (MY_RANK == i) { + cout << " I'm" << setw(8) << MY_RANK << setw(8) << MY_POOL << setw(13) << RANK_IN_POOL << setw(6) << NPROC + << setw(6) << KPAR << setw(14) << NPROC_IN_POOL << endl; + + ofs_running << " I'm" << setw(8) << MY_RANK << setw(8) << MY_POOL << setw(13) << RANK_IN_POOL << setw(6) + << NPROC << setw(6) << KPAR << setw(14) << NPROC_IN_POOL << endl; + } + MPI_Barrier(MPI_COMM_WORLD); + } + + if (MY_RANK != 0) { + cout.rdbuf(NULL); + } + + return; #endif } -void Parallel_Kpoints::divide_pools(void) -{ +void Parallel_Kpoints::divide_pools(void) { #ifdef __MPI - //cout<<"\n ==> mpi_split()"<= startpro_pool[i]) - { - MY_POOL=i; - } - } - - int key = 1; - RANK_IN_POOL = MY_RANK-startpro_pool[MY_POOL]; - - //======================================================== - // MPI_Comm_Split: Creates new communicators based on - // colors(2nd parameter) and keys(3rd parameter) - // Note: The color must be non-negative or MPI_UNDEFINED. - //======================================================== - MPI_Comm_split(MPI_COMM_WORLD,MY_POOL,key,&POOL_WORLD); + // cout<<"\n ==> mpi_split()"<= startpro_pool[i]) { + MY_POOL = i; + } + } + + int key = 1; + RANK_IN_POOL = MY_RANK - startpro_pool[MY_POOL]; + + //======================================================== + // MPI_Comm_Split: Creates new communicators based on + // colors(2nd parameter) and keys(3rd parameter) + // Note: The color must be non-negative or MPI_UNDEFINED. + //======================================================== + MPI_Comm_split(MPI_COMM_WORLD, MY_POOL, key, &POOL_WORLD); #endif - - return; -} + return; +} // the kpoints here are reduced after symmetry applied. -void Parallel_Kpoints::kinfo(int &nkstot) -{ +void Parallel_Kpoints::kinfo(int& nkstot) { #ifdef __MPI Parallel_Common::bcast_int(nkstot); - this->get_nks_pool(nkstot); - this->get_startk_pool(nkstot); - this->get_whichpool(nkstot); + this->get_nks_pool(nkstot); + this->get_startk_pool(nkstot); + this->get_whichpool(nkstot); #endif - return; + return; } -void Parallel_Kpoints::get_whichpool(const int &nkstot) -{ - delete[] whichpool; - this->whichpool = new int[nkstot]; - ZEROS(whichpool, nkstot); - - for(int i=0; inks_pool[i]; ik++) - { - const int k_now = ik + startk_pool[i]; - this->whichpool[k_now] = i; - //ofs_running << "\n whichpool[" << k_now <<"] = " << whichpool[k_now]; - } - } - - return; -} +void Parallel_Kpoints::get_whichpool(const int& nkstot) { + delete[] whichpool; + this->whichpool = new int[nkstot]; + ZEROS(whichpool, nkstot); -void Parallel_Kpoints::get_nks_pool(const int &nkstot) -{ - delete[] nks_pool; - this->nks_pool = new int[KPAR]; - ZEROS(nks_pool, KPAR); - - const int nks_ave = nkstot/KPAR; - const int remain = nkstot%KPAR; - - //ofs_running << "\n nkstot = " << nkstot; - //ofs_running << "\n KPAR = " << KPAR; - //ofs_running << "\n nks_ave = " << nks_ave; - - for(int i=0; inks_pool[i] = nks_ave; - if(i &object) -{ +void Parallel_Reduce::reduce_complex_double_all(complex& object) { #ifdef __MPI MPI_Allreduce(MPI_IN_PLACE, &object, 1, MPI_DOUBLE_COMPLEX, MPI_SUM, MPI_COMM_WORLD); #endif return; } -void Parallel_Reduce::reduce_complex_double_pool(complex &object) -{ +void Parallel_Reduce::reduce_complex_double_pool(complex& object) { #ifdef __MPI - MPI_Allreduce(MPI_IN_PLACE, &object, 1, MPI_DOUBLE_COMPLEX, MPI_SUM, POOL_WORLD); + MPI_Allreduce(MPI_IN_PLACE, &object, 1, MPI_DOUBLE_COMPLEX, MPI_SUM, POOL_WORLD); #endif - return; + return; } -void Parallel_Reduce::reduce_complex_double_pool(complex *object, const int n) -{ +void Parallel_Reduce::reduce_complex_double_pool(complex* object, const int n) { #ifdef __MPI - MPI_Allreduce(MPI_IN_PLACE, object, n, MPI_DOUBLE_COMPLEX, MPI_SUM, POOL_WORLD); + MPI_Allreduce(MPI_IN_PLACE, object, n, MPI_DOUBLE_COMPLEX, MPI_SUM, POOL_WORLD); #endif - return; + return; } -void Parallel_Reduce::gather_min_int_all(int &v) -{ +void Parallel_Reduce::gather_min_int_all(int& v) { #ifdef __MPI - int *all = new int[NPROC]; - MPI_Allgather(&v, 1, MPI_INT, all, 1, MPI_INT, MPI_COMM_WORLD); - for(int i=0; iall[i]) - { - v = all[i]; - } - } - delete[] all; + int* all = new int[NPROC]; + MPI_Allgather(&v, 1, MPI_INT, all, 1, MPI_INT, MPI_COMM_WORLD); + for (int i = 0; i < NPROC; i++) { + if (v > all[i]) { + v = all[i]; + } + } + delete[] all; #endif } -void Parallel_Reduce::gather_max_double_all(double &v) -{ +void Parallel_Reduce::gather_max_double_all(double& v) { #ifdef __MPI - double *value=new double[NPROC]; - ZEROS(value, NPROC); - MPI_Allgather(&v, 1, MPI_DOUBLE, value, 1, MPI_DOUBLE, MPI_COMM_WORLD); - for(int i=0; ivalue[i]) - { - v = value[i]; - } - } - delete[] value; + if (NPROC_IN_POOL == 1) + return; + double* value = new double[NPROC_IN_POOL]; + ZEROS(value, NPROC_IN_POOL); + MPI_Allgather(&v, 1, MPI_DOUBLE, value, 1, MPI_DOUBLE, POOL_WORLD); + for (int i = 0; i < NPROC_IN_POOL; i++) { + if (v > value[i]) { + v = value[i]; + } + } + delete[] value; #endif } -void Parallel_Reduce::gather_min_double_all(double &v) -{ +void Parallel_Reduce::gather_min_double_all(double& v) { #ifdef __MPI - double *value=new double[NPROC]; - ZEROS(value, NPROC); - MPI_Allgather(&v, 1, MPI_DOUBLE, value, 1, MPI_DOUBLE, MPI_COMM_WORLD); - for(int i=0; ivalue[i]) - { - v = value[i]; - } - } - delete[] value; + double* value = new double[NPROC]; + ZEROS(value, NPROC); + MPI_Allgather(&v, 1, MPI_DOUBLE, value, 1, MPI_DOUBLE, MPI_COMM_WORLD); + for (int i = 0; i < NPROC; i++) { + if (v > value[i]) { + v = value[i]; + } + } + delete[] value; #endif -} - -bool Parallel_Reduce::check_if_equal(double &v) -{ -#ifdef __MPI - double *all=new double[NPROC]; - MPI_Allgather(&v, 1, MPI_DOUBLE, all, 1, MPI_DOUBLE, MPI_COMM_WORLD); - for(int i=0; i 1.0e-9 ) - { - for(int j=0; jDk = dk; +void Bessel_Basis::init(const double& dk, const double& dr) { + TITLE("Bessel_Basis", "init"); + this->Dk = dk; - // to make a table - this->init_TableOne( SMOOTH, SIGMA, ECUT, RCUT, dr, Dk, LMAXALL, NE, TOLERENCE); + // to make a table + this->init_TableOne(SMOOTH, SIGMA, ECUT, RCUT, dr, Dk, LMAXALL, NE, TOLERENCE); - return; + return; } -double Bessel_Basis::Polynomial_Interpolation2 - (const int &l, const int &ie, const double &gnorm)const -{ - const double position = gnorm / this->Dk; - const int iq = static_cast(position); -// if(iq 0.0); - assert(dr > 0.0); - assert(dk > 0.0); - - // init kmesh - this->kmesh = static_cast(sqrt(ecutwfc) / dk) +1 + 4; - if (kmesh % 2 == 0)++kmesh; - cout << "\n kmesh = " << kmesh; - - // init Table One - this->TableOne.create(lmax+1, ecut_number, kmesh); - - // init rmesh - int rmesh = static_cast( rcut / dr ) + 4; - if (rmesh % 2 == 0) ++rmesh; - cout << "\n rmesh = " << rmesh; - - // allocate rmesh and Jlk and eigenvalue of Jlq - double *r = new double[rmesh]; - double *rab = new double[rmesh]; - double *jle = new double[rmesh]; - double *jlk = new double[rmesh]; - double *g = new double[rmesh]; // smooth function - double *function = new double[rmesh]; - double *en = new double[ecut_number]; - - for(int ir=0; ir(ir) * dr; - rab[ir] = dr; - if(smooth_in) - { - g[ir] = 1.0 - std::exp(-( (r[ir]-rcut)*(r[ir]-rcut)/2.0/sigma_in/sigma_in ) ); - } - } - - // init eigenvalue of Jl - for(int l=0; lTableOne(l, ie, ik) ); - } - - }// end ie - }// end ; - - delete[] en; - delete[] jle; - delete[] jlk; - delete[] rab; - delete[] g; - delete[] r; - delete[] function; - timer::tick("Spillage","TableOne"); - return; +void Bessel_Basis::init_TableOne(const bool smooth_in, // mohan add 2009-08-28 + const double& sigma_in, // mohan add 2009-08-28 + const double& ecutwfc, + const double& rcut, + const double& dr, + const double& dk, + const int& lmax, + const int& ecut_number, + const double& tolerence) { + TITLE("Bessel_Basis", "init_TableOne"); + timer::tick("Spillage", "TableOne"); + // check + assert(ecutwfc > 0.0); + assert(dr > 0.0); + assert(dk > 0.0); + + // init kmesh + this->kmesh = static_cast(sqrt(ecutwfc) / dk) + 1 + 4; + if (kmesh % 2 == 0) + ++kmesh; + cout << "\n kmesh = " << kmesh; + + // init Table One + this->TableOne.create(lmax + 1, ecut_number, kmesh); + + // init rmesh + int rmesh = static_cast(rcut / dr) + 4; + if (rmesh % 2 == 0) + ++rmesh; + cout << "\n rmesh = " << rmesh; + + // allocate rmesh and Jlk and eigenvalue of Jlq + double* r = new double[rmesh]; + double* rab = new double[rmesh]; + double* jle = new double[rmesh]; + double* jlk = new double[rmesh]; + double* g = new double[rmesh]; // smooth function + double* function = new double[rmesh]; + double* en = new double[ecut_number]; + + for (int ir = 0; ir < rmesh; ir++) { + r[ir] = static_cast(ir) * dr; + rab[ir] = dr; + if (smooth_in) { + g[ir] = 1.0 - std::exp(-((r[ir] - rcut) * (r[ir] - rcut) / 2.0 / sigma_in / sigma_in)); + } + } + + // init eigenvalue of Jl + for (int l = 0; l < lmax + 1; l++) { + ZEROS(en, ecut_number); + ZEROS(jle, rmesh); + ZEROS(jlk, rmesh); + + // calculate eigenvalue for l + Mathzone::Spherical_Bessel_Roots(ecut_number, l, tolerence, en, rcut); + + // for each eigenvalue + for (int ie = 0; ie < ecut_number; ie++) { + // calculate J_{l}( en[ir]*r) + Mathzone::Spherical_Bessel(rmesh, r, en[ie], l, jle); + + for (int ir = 0; ir < rmesh; ir++) { + jle[ir] = jle[ir] * r[ir] * r[ir]; + } + + // mohan add 2009-08-28 + if (smooth_in) { + for (int ir = 0; ir < rmesh; ir++) { + jle[ir] *= g[ir]; + } + } + + for (int ik = 0; ik < kmesh; ik++) { + // calculate J_{l}( ik*dk*r ) + Mathzone::Spherical_Bessel(rmesh, r, ik * dk, l, jlk); + + // calculate the function will be integrated + for (int ir = 0; ir < rmesh; ir++) { + function[ir] = jle[ir] * jlk[ir]; + } + + // make table value + Mathzone::Simpson_Integral(rmesh, function, rab, this->TableOne(l, ie, ik)); + } + + } // end ie + } // end ; + + delete[] en; + delete[] jle; + delete[] jlk; + delete[] rab; + delete[] g; + delete[] r; + delete[] function; + timer::tick("Spillage", "TableOne"); + return; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/bessel_basis.h b/tools/SIAB/SimulatedAnnealing/source/src_pw/bessel_basis.h index 0857edffa53..e3f33ca6772 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/bessel_basis.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/bessel_basis.h @@ -11,37 +11,33 @@ // CLASS : // NAME : Bessel_Basis //========================================================== -class Bessel_Basis -{ -public: - Bessel_Basis(); - ~Bessel_Basis(); +class Bessel_Basis { + public: + Bessel_Basis(); + ~Bessel_Basis(); - // used for a specific group of C4 coefficients. - void init( - const double &dk = 0.01, - const double &dr = 0.01); + // used for a specific group of C4 coefficients. + void init(const double& dk = 0.01, const double& dr = 0.01); - // get value from interpolation - double Polynomial_Interpolation2(const int &l, const int &ie, const double &gnorm)const; + // get value from interpolation + double Polynomial_Interpolation2(const int& l, const int& ie, const double& gnorm) const; - realArray TableOne; + realArray TableOne; -private: - int kmesh; - double Dk; + private: + int kmesh; + double Dk; - // init table, used for output overlap Q. - void init_TableOne( - const bool smooth_in, - const double &sigma_in, - const double &ecut, - const double &rcut, - const double &dr, - const double &dk, - const int &lmax, - const int &ecut_number, - const double &tolerence); + // init table, used for output overlap Q. + void init_TableOne(const bool smooth_in, + const double& sigma_in, + const double& ecut, + const double& rcut, + const double& dr, + const double& dk, + const int& lmax, + const int& ecut_number, + const double& tolerence); }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/heapsort.cpp b/tools/SIAB/SimulatedAnnealing/source/src_pw/heapsort.cpp index 67ecac6489b..fde2eabd986 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/heapsort.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/heapsort.cpp @@ -1,18 +1,18 @@ #include "../src_spillage/common.h" #include "heapsort.h" -void heapAjust(double *r, int *ind, int s, int m) -{ +void heapAjust(double* r, int* ind, int s, int m) { int j, ic; double rc; rc = r[s]; ic = ind[s]; - for (j = 2 * s;j <= m;j *= 2) - { - if (j < m && (r[j] < r[j+1])) j++; + for (j = 2 * s; j <= m; j *= 2) { + if (j < m && (r[j] < r[j + 1])) + j++; - if (!(rc < r[j])) break; + if (!(rc < r[j])) + break; r[s] = r[j]; @@ -27,27 +27,22 @@ void heapAjust(double *r, int *ind, int s, int m) return; } -void heapsort(const int n, double *r, int *ind) -{ - timer::tick("mymath","heapsort"); +void heapsort(const int n, double* r, int* ind) { + timer::tick("mymath", "heapsort"); int i, ic; double rc; - if (ind[0] == 0) - { - for (i = 0;i < n;i++) - { + if (ind[0] == 0) { + for (i = 0; i < n; i++) { ind[i] = i; } } - for (i = n / 2;i >= 0;i--) - { + for (i = n / 2; i >= 0; i--) { heapAjust(r, ind, i, n - 1); } - for (i= n - 1;i > 0;i--) - { + for (i = n - 1; i > 0; i--) { rc = r[0]; r[0] = r[i]; r[i] = rc; @@ -56,7 +51,7 @@ void heapsort(const int n, double *r, int *ind) ind[i] = ic; heapAjust(r, ind, 0, i - 1); } - timer::tick("mymath","heapsort"); + timer::tick("mymath", "heapsort"); return; } @@ -81,87 +76,76 @@ c adapted from Numerical Recipes pg. 329 (new edition) *********************************************************************/ // from hpsort.f90 -void hpsort(int n, double *ra, int *ind) -{ +void hpsort(int n, double* ra, int* ind) { int i, ir, j, k, iind; double rra; - if (ind[1] == 0) - { - for (i = 1;i <= n;i++) + if (ind[1] == 0) { + for (i = 1; i <= n; i++) ind[i] = i; } - if (n < 2) return; // nothing to order + if (n < 2) + return; // nothing to order - k = n / 2 + 1; + k = n / 2 + 1; ir = n; - while (true) - { - if (k > 1) // still in hiring phase + while (true) { + if (k > 1) // still in hiring phase { - k = k - 1; + k = k - 1; rra = ra[k]; iind = ind[k]; - } - else // in retirement-promotion phase. + } else // in retirement-promotion phase. { - rra = ra[ir]; // clear a space at the end of the array - iind = ind[ir]; // - ra[ir] = ra[1]; // retire the top of the heap into it - ind[ir] = ind[1]; // - ir = ir - 1; // decrease the size of the corporation + rra = ra[ir]; // clear a space at the end of the array + iind = ind[ir]; // + ra[ir] = ra[1]; // retire the top of the heap into it + ind[ir] = ind[1]; // + ir = ir - 1; // decrease the size of the corporation - if (ir == 1) // done with the last promotion + if (ir == 1) // done with the last promotion { - ra[1] = rra; // the least competent worker at all // - ind[1] = iind; // + ra[1] = rra; // the least competent worker at all // + ind[1] = iind; // return; } } - i = k; // wheter in hiring or promotion phase, we + i = k; // wheter in hiring or promotion phase, we - j = k + k; // set up to place rra in its proper level + j = k + k; // set up to place rra in its proper level - while (j <= ir) - { - if (j < ir) - { - if (ra[j] < ra[j+1]) // compare to better underling + while (j <= ir) { + if (j < ir) { + if (ra[j] < ra[j + 1]) // compare to better underling { j = j + 1; - } - else if (ra[j] == ra[j+1]) - { - if (ind[j] < ind[j+1]) + } else if (ra[j] == ra[j + 1]) { + if (ind[j] < ind[j + 1]) j = j + 1; } } - if (rra < ra[j]) // demote rra + if (rra < ra[j]) // demote rra { ra[i] = ra[j]; ind[i] = ind[j]; i = j; j = j + j; - } - else if (rra == ra[j]) - { - if (iind < ind[j]) // demote rra + } else if (rra == ra[j]) { + if (iind < ind[j]) // demote rra { ra[i] = ra[j]; ind[i] = ind[j]; i = j; j = j + j; - } - else - j = ir + 1; // set j to terminate do-while loop - } - else // this is the right place for rra - j = ir + 1; // set j to terminate do-while loop + } else + j = ir + 1; // set j to terminate do-while loop + } else // this is the right place for rra + j = ir + 1; // set j to terminate do-while loop } ra[i] = rra; diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/heapsort.h b/tools/SIAB/SimulatedAnnealing/source/src_pw/heapsort.h index ae40098c5a2..96697fa6e4b 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/heapsort.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/heapsort.h @@ -2,10 +2,8 @@ #define HEAPSROT_H #include "../src_spillage/common.h" -void heapsort(int n, double *r, int *ind); +void heapsort(int n, double* r, int* ind); void heapAjust(double r[], int ind[], int s, int m); -void hpsort(int n, double *ra, int *ind); +void hpsort(int n, double* ra, int* ind); #endif // HEAPSORT_H - - diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/memory_calculation.cpp b/tools/SIAB/SimulatedAnnealing/source/src_pw/memory_calculation.cpp index 70ce802cd20..f2bd4867996 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/memory_calculation.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/memory_calculation.cpp @@ -2,65 +2,56 @@ #include "../src_tools/complexmatrix_inline.h" -Memory::Memory() -{} - -Memory::~Memory() -{} - -void Memory::calculation(void) -{ - TITLE("Memory","calculation"); - - const double dk = 0.01; - int kmesh = static_cast(sqrt(ECUT) / dk) +1 + 4; - if (kmesh % 2 == 0)++kmesh; - - const int n1 = NTYPE; - const int n2 = LMAXUSED + 1; - const int n3 = NMAXUSED; - const int n4 = kmesh; - const int n1234 = n1 * n2 * n3 * n4; - - cout << "\n psi1d dimension(NTYPE, LMAXUSED+1, NMAXUSED, kmesh) : " << n1234 - << " = " << n1 << " * " << n2 << " * " - << n3 << " * " << n4 << " = " << n1234 * 8 / (double)1024 / (double)1024 << " MB"; - - for(int i=0; i(sqrt(ECUT) / dk) + 1 + 4; + if (kmesh % 2 == 0) + ++kmesh; + + const int n1 = NTYPE; + const int n2 = LMAXUSED + 1; + const int n3 = NMAXUSED; + const int n4 = kmesh; + const int n1234 = n1 * n2 * n3 * n4; + + cout << "\n psi1d dimension(NTYPE, LMAXUSED+1, NMAXUSED, kmesh) : " << n1234 << " = " << n1 << " * " << n2 << " * " + << n3 << " * " << n4 << " = " << n1234 * 8 / (double)1024 / (double)1024 << " MB"; + + for (int i = 0; i < mz.nlevel; i++) { + int nwfc2 = 0; + for (int it = 0; it < NTYPE; it++) { + for (int l = 0; l < mz.lmax_type[it] + 1; l++) { + nwfc2 += NA[it] * (2 * l + 1); + cout << "\n na=" << NA[it] << " 2*l+1=" << 2 * l + 1 << " n=1"; + } + } + cout << "\n newfc2=" << nwfc2; + cout << "\n psi3d dimension(NKSTOT=" << NKSTOT << ", nwfc2=" << nwfc2 << ", npwx=" << PW.npwx + << ")=" << NKSTOT * nwfc2 * PW.npwx * 16 / (double)1024 / (double)1024 << " MB"; + + cout << "\n S matrix dim = " << nwfc2 * nwfc2; + + // complex* haha = new std::complex[PW.npwx]; + // ZEROS(haha, PW.npwx); + + ComplexMatrix haha(3, PW.npwx); + + complex sum = std::complex(0, 0); + for (int t = 0; t < nwfc2 * nwfc2; t++) { + timer::tick("Memory", "test"); + for (int j = 0; j < PW.npwx; j++) { + // sum += conj(haha[j]) * haha[j]; + sum += conj(haha(2, j)) * haha(2, j); + } + timer::tick("Memory", "test"); + } + } + + return; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/memory_calculation.h b/tools/SIAB/SimulatedAnnealing/source/src_pw/memory_calculation.h index 6a669b10d46..8ff7fc0f304 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/memory_calculation.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/memory_calculation.h @@ -2,14 +2,12 @@ #define MEMORY_CALCULATION_H #include "../src_spillage/tools.h" -class Memory -{ - public: - Memory(); - ~Memory(); - - void calculation(void); +class Memory { + public: + Memory(); + ~Memory(); + void calculation(void); }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/numerical_basis.cpp b/tools/SIAB/SimulatedAnnealing/source/src_pw/numerical_basis.cpp index af2eabf7b18..263139559de 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/numerical_basis.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/numerical_basis.cpp @@ -3,12 +3,12 @@ Bessel_Basis Numerical_Basis::bessel_basis; -Numerical_Basis::Numerical_Basis(){} +Numerical_Basis::Numerical_Basis() {} -Numerical_Basis::~Numerical_Basis(){} +Numerical_Basis::~Numerical_Basis() {} //============================================================ -// MEMBER FUNCTION : +// MEMBER FUNCTION : // NAME : init // Firstly, use check(0) to call bessel_basis,init // to generate TableOne @@ -16,12 +16,10 @@ Numerical_Basis::~Numerical_Basis(){} //============================================================ // The function is called in run_fp.cpp. -void Numerical_Basis::init_table(void) -{ - TITLE("Numerical_Basis","output_overlap"); +void Numerical_Basis::init_table(void) { + TITLE("Numerical_Basis", "output_overlap"); - Numerical_Basis::bessel_basis.init(); - - return; -} + Numerical_Basis::bessel_basis.init(); + return; +} diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/numerical_basis.h b/tools/SIAB/SimulatedAnnealing/source/src_pw/numerical_basis.h index 12aab7f6745..0bd893c7a04 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/numerical_basis.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/numerical_basis.h @@ -9,21 +9,18 @@ #include "bessel_basis.h" //========================================================== // CLASS : -// NAME : Numerical_Basis +// NAME : Numerical_Basis //========================================================== -class Numerical_Basis -{ - public: - Numerical_Basis(); - ~Numerical_Basis(); +class Numerical_Basis { + public: + Numerical_Basis(); + ~Numerical_Basis(); - void init_table(void); - - static Bessel_Basis bessel_basis; - - private: + void init_table(void); + static Bessel_Basis bessel_basis; + private: }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_basis.cpp b/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_basis.cpp index 20b81df804d..df6bb69b269 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_basis.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_basis.cpp @@ -5,8 +5,7 @@ #include "../src_parallel/parallel_reduce.h" #include "../src_tools/complexmatrix_inline.h" -PW_Basis::PW_Basis() -{ +PW_Basis::PW_Basis() { // if not parallel, gg_global == gg, gdirect_global == gdirect // gcar_global == gcar gg_global = new double[1]; @@ -27,40 +26,38 @@ PW_Basis::PW_Basis() ylm = new matrix[1]; Jlq = new std::complex[1]; - save = new std::complex[1]; - posmu = new int[1]; - posnu = new int[1]; + save = new std::complex[1]; + posmu = new int[1]; + posnu = new int[1]; } -PW_Basis::~PW_Basis() -{ - delete [] gcar_global; - delete [] gdirect_global; - delete [] gg_global; +PW_Basis::~PW_Basis() { + delete[] gcar_global; + delete[] gdirect_global; + delete[] gg_global; #ifdef __MPI - delete [] gcar; - delete [] gdirect; - delete [] gg; + delete[] gcar; + delete[] gdirect; + delete[] gg; #endif - delete [] ig1; - delete [] ig2; - delete [] ig3; + delete[] ig1; + delete[] ig2; + delete[] ig3; delete[] psi3d; delete[] ylm; delete[] Jlq; - delete[] save; - delete[] posmu; - delete[] posnu; + delete[] save; + delete[] posmu; + delete[] posnu; } -void PW_Basis::init(void) -{ - TITLE("PW_Basis","init"); - timer::tick("PW_Basis","init"); +void PW_Basis::init(void) { + TITLE("PW_Basis", "init"); + timer::tick("PW_Basis", "init"); // (1) setup the energy cutoff, which is different in each pool, // because the number of k points is differnt. @@ -69,47 +66,43 @@ void PW_Basis::init(void) // (2) setup the FFT dimension according to energy cutoff. this->setup_FFT_dimension(); - OUT(ofs_running,"ggwfc2(Ry)",ggwfc2); + OUT(ofs_running, "ggwfc2(Ry)", ggwfc2); // (3) get the number of plane waves for wave functions. this->ngmc_g = PW_complement::get_total_pw_number(0.0, ggchg, nx, ny, nz, GGT); this->ngmw_g = PW_complement::get_total_pw_number(0.0, ggwfc2, nx, ny, nz, GGT); - OUT(ofs_running,"ngmc_g",ngmc_g); - OUT(ofs_running,"ngmw_g",ngmw_g); + OUT(ofs_running, "ngmc_g", ngmc_g); + OUT(ofs_running, "ngmw_g", ngmw_g); // (4) get the local number of plane waves. - assert(NPROC_IN_POOL>0); + assert(NPROC_IN_POOL > 0); const int remain = ngmw_g % NPROC_IN_POOL; this->ngmw = this->ngmw_g / NPROC_IN_POOL; - if (RANK_IN_POOL < remain) - { + if (RANK_IN_POOL < remain) { this->ngmw++; } - if (RANK_IN_POOL < remain) - { + if (RANK_IN_POOL < remain) { ngmw_start = ngmw * RANK_IN_POOL; + } else { + ngmw_start = (ngmw + 1) * remain + ngmw * (RANK_IN_POOL - remain); } - else - { - ngmw_start = (ngmw+1) * remain + ngmw * (RANK_IN_POOL-remain); - } - - OUT(ofs_running,"ngmw",ngmw); - //ofs_running << "\n ngmw_start = " << ngmw_start; + + OUT(ofs_running, "ngmw", ngmw); + // ofs_running << "\n ngmw_start = " << ngmw_start; // (5) init |g|, g_direct, g_cartesian delete[] gdirect_global; delete[] gcar_global; delete[] gg_global; - gdirect_global = new Vector3[ngmc_g];// indices of G vectors + gdirect_global = new Vector3[ngmc_g]; // indices of G vectors gcar_global = new Vector3[ngmc_g]; - gg_global = new double[ngmc_g];// store the |G|^2 of the 1d array + gg_global = new double[ngmc_g]; // store the |G|^2 of the 1d array PW_complement::get_total_pw(gg_global, gdirect_global, 0.0, ggchg, nx, ny, nz, this->GGT, ngmc_g); - //PW_complement::get_total_pw(gg_global, gdirect_global, 0.0, ggwfc2, nx, ny, nz, this->GGT, ngmw_g); + // PW_complement::get_total_pw(gg_global, gdirect_global, 0.0, ggwfc2, nx, ny, nz, this->GGT, ngmw_g); PW_complement::setup_GVectors(this->G, ngmc_g, gg_global, gdirect_global, gcar_global); // (6) get ig1, ig2, ig3 @@ -118,28 +111,26 @@ void PW_Basis::init(void) #else this->get_GVectors(); #endif - // mohan add on 2011-07-23 - stringstream ss; - ss << "ORBITAL_PW_GK" << MY_RANK+1 << ".dat"; - ofstream ofs(ss.str().c_str()); - ofs << ggwfc2 << " (ggwfc2, Ry)" << endl; - ofs << ngmw << " (Number of plane wave basis for wave functions)" << endl; - for(int ig=0; igset_igk(); this->setup_structure_factor(); - timer::tick("PW_Basis","init"); + timer::tick("PW_Basis", "init"); return; } -void PW_Basis::setup_gg(void) -{ - TITLE("PW_Basis","setup_gg"); +void PW_Basis::setup_gg(void) { + TITLE("PW_Basis", "setup_gg"); //(1.1) lattice parameters this->GT = LATVEC.Inverse(); @@ -148,39 +139,37 @@ void PW_Basis::setup_gg(void) // (1.2) tpiba and ecut assert(LAT0 > 0.0); - this->tpiba = TWO_PI/LAT0; + this->tpiba = TWO_PI / LAT0; this->tpiba2 = tpiba * tpiba; this->ggpsi = ECUT / tpiba2; - double wfac = 4.0; - this->ggchg = wfac * this->ggpsi; + double wfac = 4.0; + this->ggchg = wfac * this->ggpsi; // (1.3) get ggwfc2 - assert( NKS > 0); - assert( CARKX != NULL ); - assert( CARKY != NULL ); - assert( CARKZ != NULL ); + assert(NKS > 0); + assert(CARKX != NULL); + assert(CARKY != NULL); + assert(CARKZ != NULL); - for (int ik=0; ikggpsi) + k_mod; - const double tmp2 = tmp * tmp ; - if (this->ggwfc2 < tmp2) this->ggwfc2 = tmp2; + const double tmp2 = tmp * tmp; + if (this->ggwfc2 < tmp2) + this->ggwfc2 = tmp2; } - OUT(ofs_running,"NKS",NKS); - OUT(ofs_running,"ggpsi(Ry)",ggpsi*tpiba2); - OUT(ofs_running,"ggwfc2(Ry)",ggwfc2*tpiba2); + OUT(ofs_running, "NKS", NKS); + OUT(ofs_running, "ggpsi(Ry)", ggpsi * tpiba2); + OUT(ofs_running, "ggwfc2(Ry)", ggwfc2 * tpiba2); // (1.4) initialize itia2iat this->itia2iat = new int*[NTYPE]; - int iat=0; - for (int it=0; itnpwx = 0; this->ngk = new int[NKS]; ZEROS(this->ngk, NKS); - assert(this->ngmw>0); + assert(this->ngmw > 0); -// ofs_running << "\n\n ngmw = " << ngmw; -// ofs_running << "\n gg[ngmw-1]=" << gg[ngmw-1]; - for (int ik=0; ikigk = new int*[NKS]; - for (int ik=0; ikngk[ik]]; ZEROS(igk[ik], ngk[ik]); } - for (int ik=0; ik kcar(CARKX[ik], CARKY[ik], CARKZ[ik]); - int ng=0; + int ng = 0; const double k2 = kcar * kcar; - for (int ig=0; ig f = this->gcar[ig] + kcar; const double gk2 = f * f; - if (sqrt(this->gg[ig]) > sqrt(this->ggpsi) + sqrt(k2)) - { + if (sqrt(this->gg[ig]) > sqrt(this->ggpsi) + sqrt(k2)) { break; } - if (gk2 <= this->ggpsi) - { + if (gk2 <= this->ggpsi) { this->igk[ik][ng] = ig; ++ng; } @@ -265,40 +242,34 @@ void PW_Basis::set_igk(void) // First stage Basis initialization. // Set up crystal structure parameters. -void PW_Basis::setup_FFT_dimension() -{ - TITLE("PW_Basis","setup_FFT_dimension"); +void PW_Basis::setup_FFT_dimension() { + TITLE("PW_Basis", "setup_FFT_dimension"); PW_complement::get_FFT_dimension(LATVEC, this->ggchg, nx, ny, nz); this->nxyz = nx * ny * nz; - OUT(ofs_running,"FFT wavefunctions",nx,ny,nz); + OUT(ofs_running, "FFT wavefunctions", nx, ny, nz); return; } - - #ifdef __MPI -void PW_Basis::get_MPI_GVectors(void) -{ - TITLE("PW_Basis","get_MPI_GVectors"); +void PW_Basis::get_MPI_GVectors(void) { + TITLE("PW_Basis", "get_MPI_GVectors"); - assert(ngmw>0); + assert(ngmw > 0); // (1) first part delete[] gdirect; delete[] gcar; delete[] gg; this->gdirect = new Vector3[ngmw]; - this->gcar = new Vector3[ngmw]; + this->gcar = new Vector3[ngmw]; this->gg = new double[ngmw]; - for (int ig=0; igig2 = new int[ngmw]; this->ig3 = new int[ngmw]; -// cout << "\n dim of ig1,2,3 = " << ngmw; + // cout << "\n dim of ig1,2,3 = " << ngmw; - for (int i = 0; i < ngmw; i++) - { + for (int i = 0; i < ngmw; i++) { this->ig1[i] = int(this->gdirect[i].x) + nx; this->ig2[i] = int(this->gdirect[i].y) + ny; this->ig3[i] = int(this->gdirect[i].z) + nz; } return; -}//end setup_mpi_GVectors +} // end setup_mpi_GVectors #else -void PW_Basis::get_GVectors(void) -{ - TITLE("PW_Basis","get_GVectors"); - timer::tick("PW_Basis","get_GVectors"); +void PW_Basis::get_GVectors(void) { + TITLE("PW_Basis", "get_GVectors"); + timer::tick("PW_Basis", "get_GVectors"); //************************************************************ // g : Store the G vectors in 1d array (Cartian coordinate) @@ -345,7 +314,7 @@ void PW_Basis::get_GVectors(void) this->gg = this->gg_global; // (2) calculate ig1, ig2, ig3 - assert(ngmw>0); + assert(ngmw > 0); delete[] ig1; delete[] ig2; delete[] ig3; @@ -353,178 +322,151 @@ void PW_Basis::get_GVectors(void) this->ig2 = new int[ngmw]; this->ig3 = new int[ngmw]; - for (int i = 0; i < ngmw; i++) - { + for (int i = 0; i < ngmw; i++) { this->ig1[i] = int(this->gdirect[i].x) + nx; this->ig2[i] = int(this->gdirect[i].y) + ny; this->ig3[i] = int(this->gdirect[i].z) + nz; } - timer::tick("PW_Basis","get_GVectors"); + timer::tick("PW_Basis", "get_GVectors"); return; -}//end get_GVectors; +} // end get_GVectors; #endif - // Calculate structure factor -void PW_Basis::setup_structure_factor(void) -{ - TITLE("PW_Basis","setup_structure_factor"); - timer::tick("PW_Basis","setup_struc_factor"); +void PW_Basis::setup_structure_factor(void) { + TITLE("PW_Basis", "setup_structure_factor"); + timer::tick("PW_Basis", "setup_struc_factor"); std::complex ci_tpi = NEG_IMAG_UNIT * TWO_PI; std::complex x; this->strucFac = new std::complex*[NTYPE]; - for (int it=0; itstrucFac[it] = new std::complex[ngmw]; - ZEROS( strucFac[it], ngmw); + ZEROS(strucFac[it], ngmw); } - for (int it=0; it< NTYPE; it++) - { - for (int ig=0; igstrucFac[it][ig] = std::complex( sum_cos, -sum_sin ); + this->strucFac[it][ig] = std::complex(sum_cos, -sum_sin); - double tmpx = strucFac[it][ig].real() ; - double tmpy = strucFac[it][ig].imag() ; + double tmpx = strucFac[it][ig].real(); + double tmpy = strucFac[it][ig].imag(); } } int nat = 0; - for (int it=0; iteigts1.create(nat, 2*this->nx + 1); - this->eigts2.create(nat, 2*this->ny + 1); - this->eigts3.create(nat, 2*this->nz + 1); + int i, j, ng; + this->eigts1.create(nat, 2 * this->nx + 1); + this->eigts2.create(nat, 2 * this->ny + 1); + this->eigts3.create(nat, 2 * this->nz + 1); Vector3 gtau; Vector3 tau; int iat = 0; - for (int it = 0; it < NTYPE; it++) - { - for (int ia = 0; ia < NA[it]; ia++) - { + for (int it = 0; it < NTYPE; it++) { + for (int ia = 0; ia < NA[it]; ia++) { tau.x = CARPOSX[it][ia]; tau.y = CARPOSY[it][ia]; tau.z = CARPOSZ[it][ia]; - gtau = this->G * tau; //HLX: fixed on 10/13/2006 + gtau = this->G * tau; // HLX: fixed on 10/13/2006 - for (int n1 = -nx; n1 <= nx; n1++) - { + for (int n1 = -nx; n1 <= nx; n1++) { double arg = n1 * gtau.x; - this->eigts1(iat, n1 + nx) = exp( ci_tpi*arg ); + this->eigts1(iat, n1 + nx) = exp(ci_tpi * arg); } - for (int n2 = -ny; n2 <= ny; n2++) - { + for (int n2 = -ny; n2 <= ny; n2++) { double arg = n2 * gtau.y; - this->eigts2(iat, n2 + ny) = exp( ci_tpi*arg ); + this->eigts2(iat, n2 + ny) = exp(ci_tpi * arg); } - for (int n3 = -nz; n3 <= nz; n3++) - { + for (int n3 = -nz; n3 <= nz; n3++) { double arg = n3 * gtau.z; - this->eigts3(iat, n3 + nz) = exp( ci_tpi*arg ); + this->eigts3(iat, n3 + nz) = exp(ci_tpi * arg); } iat++; } } - timer::tick("PW_Basis","setup_struc_factor"); + timer::tick("PW_Basis", "setup_struc_factor"); return; } -complex* PW_Basis::get_sk(const int ik, const int it, const int ia)const -{ - timer::tick("PW_Basis","get_sk"); - const double arg = (CARKX[ik] * CARPOSX[it][ia] - + CARKY[ik] * CARPOSY[it][ia] - + CARKZ[ik] * CARPOSZ[it][ia] ) * TWO_PI; - const std::complex kphase = complex ( cos(arg), -sin(arg) ); - std::complex *sk = new std::complex[ this->ngk[ik] ]; +complex* PW_Basis::get_sk(const int ik, const int it, const int ia) const { + timer::tick("PW_Basis", "get_sk"); + const double arg = + (CARKX[ik] * CARPOSX[it][ia] + CARKY[ik] * CARPOSY[it][ia] + CARKZ[ik] * CARPOSZ[it][ia]) * TWO_PI; + const std::complex kphase = complex(cos(arg), -sin(arg)); + std::complex* sk = new std::complex[this->ngk[ik]]; const int iat = this->itia2iat[it][ia]; - for (int ig=0; ig< this->ngk[ik]; ig++) - { -// cout << "\n ig=" << ig << endl; + for (int ig = 0; ig < this->ngk[ik]; ig++) { + // cout << "\n ig=" << ig << endl; const int iig = this->igk[ik][ig]; - assert( iig < ngmw ); + assert(iig < ngmw); - if (!(ig1[iig] >= 0 && ig1[iig] < 2*nx + 1) ) - { + if (!(ig1[iig] >= 0 && ig1[iig] < 2 * nx + 1)) { cout << "\n ig1[iig] = " << ig1[iig] << endl; - QUIT(); + QUIT(); } - if (!(ig2[iig] >= 0 && ig2[iig] < 2*ny + 1) ) - { + if (!(ig2[iig] >= 0 && ig2[iig] < 2 * ny + 1)) { cout << "\n ig2[iig] = " << ig2[iig] << endl; - QUIT(); + QUIT(); } - if (!(ig3[iig] >= 0 && ig3[iig] < 2*nz + 1) ) - { + if (!(ig3[iig] >= 0 && ig3[iig] < 2 * nz + 1)) { cout << "\n iig = " << iig << endl; cout << "\n ig3[iig] = " << ig3[iig] << endl; - QUIT(); + QUIT(); } - sk[ig] = kphase - * this->eigts1(iat, this->ig1[iig]) - * this->eigts2(iat, this->ig2[iig]) - * this->eigts3(iat, this->ig3[iig]); + sk[ig] = kphase * this->eigts1(iat, this->ig1[iig]) * this->eigts2(iat, this->ig2[iig]) * + this->eigts3(iat, this->ig3[iig]); } - timer::tick("PW_Basis","get_sk"); + timer::tick("PW_Basis", "get_sk"); return sk; } -Vector3 PW_Basis::get_1qvec_cartesian(const int ik,const int ig)const -{ +Vector3 PW_Basis::get_1qvec_cartesian(const int ik, const int ig) const { Vector3 kvec = Vector3(CARKX[ik], CARKY[ik], CARKZ[ik]); - Vector3 qvec = kvec + this->gcar[ this->igk[ik][ig] ]; + Vector3 qvec = kvec + this->gcar[this->igk[ik][ig]]; return qvec; } -void PW_Basis::table(void) -{ +void PW_Basis::table(void) { TITLE("PW_Basis", "table"); NBasis.init_table(); - const int total_lm = ( LMAXUSED + 1) * ( LMAXUSED + 1); + const int total_lm = (LMAXUSED + 1) * (LMAXUSED + 1); delete[] ylm; this->ylm = new matrix[NKS]; - for (int ik=0; ikylm[ik].create(total_lm, npw); // (1) get the vector k+G - Vector3 *gk = new Vector3 [npw]; - for (int ig=0; ig* gk = new Vector3[npw]; + for (int ig = 0; ig < npw; ig++) { gk[ig] = this->get_1qvec_cartesian(ik, ig); } @@ -535,106 +477,90 @@ void PW_Basis::table(void) delete[] gk; } - - // init index of iw00 - assert(NWFCALL>0); - this->iwindex = new Way2iw[NWFCALL]; - - int iw=0; - for(int it=0; it 0); + this->iwindex = new Way2iw[NWFCALL]; + + int iw = 0; + for (int it = 0; it < NTYPE; it++) { + for (int ia = 0; ia < NA[it]; ia++) { + for (int l = 0; l < LMAXALL + 1; l++) { + for (int m = 0; m < 2 * l + 1; m++) { + iwindex[iw].type = it; + iwindex[iw].i = ia; + iwindex[iw].L = l; + iwindex[iw].m = m; + ++iw; + } + } + } + } + assert(iw == NWFCALL); return; } - // init psi1d for each Level. -void PW_Basis::allocate_psi1d(const int &il) -{ +void PW_Basis::allocate_psi1d(const int& il) { TITLE("PW_Basis", "allocate_psi1d"); this->nwfc2 = mz.Level[il].nwfc2; this->Dk = 0.01; this->kmesh = static_cast(sqrt(ECUT) / Dk) + 1 + 4; - if (kmesh % 2 == 0) ++kmesh; - - this->psi1d.create(NTYPE, LMAXUSED+1, NMAXUSED, kmesh); - - delete[] save; - delete[] posmu; - delete[] posnu; - - const int dim = nwfc2 * nwfc2; - save = new std::complex[dim]; - posmu = new int[dim]; - posnu = new int[dim]; - ZEROS(save, dim); - ZEROS(posmu, dim); - ZEROS(posnu, dim); + if (kmesh % 2 == 0) + ++kmesh; + + this->psi1d.create(NTYPE, LMAXUSED + 1, NMAXUSED, kmesh); + + delete[] save; + delete[] posmu; + delete[] posnu; + + const int dim = nwfc2 * nwfc2; + save = new std::complex[dim]; + posmu = new int[dim]; + posnu = new int[dim]; + ZEROS(save, dim); + ZEROS(posmu, dim); + ZEROS(posnu, dim); return; } -void PW_Basis::calculate_psi1d(void) -{ - timer::tick("PW_Basis","calculate_psi1d"); +void PW_Basis::calculate_psi1d(void) { + timer::tick("PW_Basis", "calculate_psi1d"); psi1d.zero_out(); - for (int it=0; itpsi1d(it,l,n,ikm) += input.Coef.C4(it, l, n ,ie) - * Numerical_Basis::bessel_basis.TableOne(l, ie, ikm); + for (int it = 0; it < NTYPE; it++) { + for (int l = 0; l < LMAXUSED + 1; l++) { + for (int n = 0; n < NMAXUSED; n++) { + for (int ie = 0; ie < NE; ie++) { + for (int ikm = 0; ikm < kmesh; ikm++) { + this->psi1d(it, l, n, ikm) += + input.Coef.C4(it, l, n, ie) * Numerical_Basis::bessel_basis.TableOne(l, ie, ikm); } } } } } - timer::tick("PW_Basis","calculate_psi1d"); + timer::tick("PW_Basis", "calculate_psi1d"); return; } -void PW_Basis::allocate_psi3d(const int &level) -{ +void PW_Basis::allocate_psi3d(const int& level) { // allocate the number of wave functions. // consider(it, ia, l, n, m) delete[] psi3d; psi3d = new ComplexMatrix[NKS]; - for (int ik=0; ikpsi3d[ik].create(nwfc2, npwx); } return; } - -void PW_Basis::calculate_psi3d(const int &ilevel, const int &ik) -{ - //TITLE("PW_Basis", "calculate_psi3d"); +void PW_Basis::calculate_psi3d(const int& ilevel, const int& ik) { + // TITLE("PW_Basis", "calculate_psi3d"); timer::tick("PW_Basis", "calculate_psi3d"); // (1) get the vector k+G @@ -643,36 +569,32 @@ void PW_Basis::calculate_psi3d(const int &ilevel, const int &ik) const int npw = ngk[ik]; - Vector3 *gk = new Vector3 [npw]; - for (int ig=0; ig* gk = new Vector3[npw]; + for (int ig = 0; ig < npw; ig++) { gk[ig] = this->get_1qvec_cartesian(ik, ig); } - double *flq = new double[npw]; - for (int iw=0; iwnwfc2; iw++) - { + double* flq = new double[npw]; + for (int iw = 0; iw < this->nwfc2; iw++) { // for each wave function in nwfc2(it, i, l, n) const int it = mz.Level[ilevel].wayd[iw].type; const int ia = mz.Level[ilevel].wayd[iw].i; - const int l = mz.Level[ilevel].wayd[iw].L; - const int n = mz.Level[ilevel].wayd[iw].N; - const int m = mz.Level[ilevel].wayd[iw].m; + const int l = mz.Level[ilevel].wayd[iw].L; + const int n = mz.Level[ilevel].wayd[iw].N; + const int m = mz.Level[ilevel].wayd[iw].m; std::complex lphase = pow(IMAG_UNIT, l); // get flq from psi1d for each k point - for (int ig=0; igPolynomial_Interpolation(it, l, n, gk[ig].norm() * this->tpiba ); + for (int ig = 0; ig < npw; ig++) { + flq[ig] = this->Polynomial_Interpolation(it, l, n, gk[ig].norm() * this->tpiba); } // get the structure wave functions for each k point. - std::complex *sk = this->get_sk(ik, it, ia); + std::complex* sk = this->get_sk(ik, it, ia); - const int lm = l*l+m; - for (int ig=0; ig PW_Basis::calculateS(const int &iw, const int &iw2, const int &ik) -{ +complex PW_Basis::calculateS(const int& iw, const int& iw2, const int& ik) { std::complex overlap = 0.0; - for (int ig=0; igpsi3d[ik](iw, ig)) * this->psi3d[ik](iw2, ig); } // move this outside to get_spillage @@ -698,11 +618,8 @@ complex PW_Basis::calculateS(const int &iw, const int &iw2, const int &i return overlap; } - -void PW_Basis::update_psi1d(const int &il, const int &ic, const int &ie, - const double &c4_now, const double &c4_old) -{ - timer::tick("PW_Basis","update_psi1d"); +void PW_Basis::update_psi1d(const int& il, const int& ic, const int& ie, const double& c4_now, const double& c4_old) { + timer::tick("PW_Basis", "update_psi1d"); // a small trick // ALGORITHM : when we change psi1d, we don't know @@ -718,34 +635,25 @@ void PW_Basis::update_psi1d(const int &il, const int &ic, const int &ie, const int l_now = mz.Level[il].wayc[ic].L; const int n_now = mz.Level[il].wayc[ic].N; - for (int it=0; itpsi1d(it,l,n,ikm) = sum; + this->psi1d(it, l, n, ikm) = sum; + } + } else if (it == it_now || l == l_now || n == n_now) { + for (int ikm = 0; ikm < kmesh; ikm++) { + // a small trick + this->psi1d(it, l, n, ikm) += + (c4_now - c4_old) * Numerical_Basis::bessel_basis.TableOne(l, ie, ikm); } } - else if(it==it_now || l==l_now || n==n_now) - { - for (int ikm=0; ikmpsi1d(it,l,n,ikm) += (c4_now-c4_old) * Numerical_Basis::bessel_basis.TableOne(l, ie, ikm); - } - } } } } @@ -754,27 +662,26 @@ void PW_Basis::update_psi1d(const int &il, const int &ic, const int &ie, l_last = l_now; n_last = n_now; - timer::tick("PW_Basis","update_psi1d"); + timer::tick("PW_Basis", "update_psi1d"); return; } -void PW_Basis::update_psi3d( const int &il, const int &ic, const int &ik) -{ -// TITLE("PW_Basis","update_psi1d3d"); - timer::tick("PW_Basis","update_psi3d"); +void PW_Basis::update_psi3d(const int& il, const int& ic, const int& ik) { + // TITLE("PW_Basis","update_psi1d3d"); + timer::tick("PW_Basis", "update_psi3d"); const int npw = ngk[ik]; static int it_old; static int ia_old; static int l_old; static int n_old; - static bool allocate=false; - static int *ic_last; - if (!allocate) - { + static bool allocate = false; + static int* ic_last; + if (!allocate) { ic_last = new int[NKS]; - for (int ik=0; ik *gk = new Vector3 [npw]; - for (int ig=0; ig* gk = new Vector3[npw]; + for (int ig = 0; ig < npw; ig++) { gk[ig] = this->get_1qvec_cartesian(ik, ig); } - double *flq = new double[npw]; - std::complex *sk = new std::complex[1]; - std::complex *samepart = new std::complex[npw]; - for (int iw=0; iwnwfc2; iw++) - { + double* flq = new double[npw]; + std::complex* sk = new std::complex[1]; + std::complex* samepart = new std::complex[npw]; + for (int iw = 0; iw < this->nwfc2; iw++) { const int ic1 = mz.Level[il].wayd[iw].ic; - if (ic1 == ic || ic1 == ic_last[ik]) - { + if (ic1 == ic || ic1 == ic_last[ik]) { // for each wave function in nwfc2(it, i, l, n) const int it = mz.Level[il].wayd[iw].type; const int ia = mz.Level[il].wayd[iw].i; - const int l = mz.Level[il].wayd[iw].L; - const int n = mz.Level[il].wayd[iw].N; - const int m = mz.Level[il].wayd[iw].m; + const int l = mz.Level[il].wayd[iw].L; + const int n = mz.Level[il].wayd[iw].N; + const int m = mz.Level[il].wayd[iw].m; std::complex lphase = pow(IMAG_UNIT, l); // a small trick: get the structure wave functions for each k point. - if (it==it_old && ia==ia_old) - { + if (it == it_old && ia == ia_old) { // do nothing - } - else - { + } else { delete[] sk; sk = this->get_sk(ik, it, ia); } // small trick (2) : get flq from psi1d for each k point - if (it==it_old && l==l_old && n==n_old) - { + if (it == it_old && l == l_old && n == n_old) { // do nothing - } - else - { - for (int ig=0; igPolynomial_Interpolation(it, l, n, gk[ig].norm() * this->tpiba ); + } else { + for (int ig = 0; ig < npw; ig++) { + flq[ig] = this->Polynomial_Interpolation(it, l, n, gk[ig].norm() * this->tpiba); } } // small trick (3) - if (it==it_old && ia==ia_old && l==l_old && n==n_old) - { - //samepart is the same as the previous one. - } - else - { - for (int ig=0; igDk; +double PW_Basis::Polynomial_Interpolation(const int& it, const int& l, const int& n, const double& gnorm) const { + const double position = gnorm / this->Dk; const int iq = static_cast(position); - assert(iq < kmesh-4); + assert(iq < kmesh - 4); const double x0 = position - static_cast(iq); const double x1 = 1.0 - x0; const double x2 = 2.0 - x0; const double x3 = 3.0 - x0; - const double y= - this->psi1d(it, l, n, iq) * x1 * x2 * x3 / 6.0 + - this->psi1d(it, l, n, iq) * x0 * x2 * x3 / 2.0 - - this->psi1d(it, l, n, iq) * x1 * x0 * x3 / 2.0 + - this->psi1d(it, l, n, iq) * x1 * x2 * x0 / 6.0 ; + const double y = this->psi1d(it, l, n, iq) * x1 * x2 * x3 / 6.0 + this->psi1d(it, l, n, iq) * x0 * x2 * x3 / 2.0 - + this->psi1d(it, l, n, iq) * x1 * x0 * x3 / 2.0 + this->psi1d(it, l, n, iq) * x1 * x2 * x0 / 6.0; return y; } - -void PW_Basis::calculate_Jlq(const int &ik, const int &iw, const int &ie) -{ - //TITLE("PW_Basis", "calculate_Jlq"); - timer::tick("PW_Basis","calculate_Jlq"); +void PW_Basis::calculate_Jlq(const int& ik, const int& iw, const int& ie) { + // TITLE("PW_Basis", "calculate_Jlq"); + timer::tick("PW_Basis", "calculate_Jlq"); const int npw = this->ngk[ik]; - const int it= iwindex[iw].type; - const int ia= iwindex[iw].i; - const int l = iwindex[iw].L; - const int m = iwindex[iw].m; + const int it = iwindex[iw].type; + const int ia = iwindex[iw].i; + const int l = iwindex[iw].L; + const int m = iwindex[iw].m; // generate 1d Jlq. - Vector3 *gk = new Vector3 [npw]; - double* flq=new double[npw]; - for (int ig=0; ig* gk = new Vector3[npw]; + double* flq = new double[npw]; + for (int ig = 0; ig < npw; ig++) { gk[ig] = this->get_1qvec_cartesian(ik, ig); } - for (int ig=0; igtpiba ); + for (int ig = 0; ig < npw; ig++) { + flq[ig] = Numerical_Basis::bessel_basis.Polynomial_Interpolation2(l, ie, gk[ig].norm() * this->tpiba); } // generate 3d Jlq. delete[] Jlq; Jlq = new std::complex[npw]; - std::complex *sk = this->get_sk(ik, it, ia); + std::complex* sk = this->get_sk(ik, it, ia); - const int lm = l*l+m; + const int lm = l * l + m; std::complex lphase = pow(IMAG_UNIT, l); - for (int ig=0; ig PW_Basis::calculate_Jlq_Phi(const int &ik, const int &mu) -{ - const int npw = this->ngk[ik]; - complex overlap = std::complex(0,0); - for(int ig=0; ig PW_Basis::calculate_Jlq_Phi(const int& ik, const int& mu) { + const int npw = this->ngk[ik]; + complex overlap = std::complex(0, 0); + for (int ig = 0; ig < npw; ig++) { + overlap += conj(Jlq[ig]) * psi3d[ik](mu, ig); + } #ifdef __MPI Parallel_Reduce::reduce_complex_double_pool(overlap); #endif - return overlap; + return overlap; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_basis.h b/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_basis.h index 21e7b57f8ce..b5f49bba9b8 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_basis.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_basis.h @@ -11,125 +11,121 @@ struct Way2iw // dimension : WFCALL { int type; - int i; // atom + int i; // atom int L; - int m; + int m; }; -class PW_Basis -{ -public: - - // about lattice. - Matrix3 G; - Matrix3 GT; - Matrix3 GGT; - double tpiba; // 2pi/lat0 - double tpiba2; // tpiba^2 - - // about k point - int* ngk; - int** igk; - int** itia2iat; - int npwx; - - // about fft grid. - int nx; - int ny; - int nz; - int nxyz; - - double ggpsi; // planewave cut off for the wavefunctions, unit (2*PI/lat0)^2 - double ggwfc2; // ggwav=wfact*ggpsi, default value: wfact=4.0 - double ggchg; - - std::complex** strucFac; // StrucFac [ntype,ngmax] - - int ngmw; //(= ngmax) / num. of G vectors within ggfft - int ngmw_g; - int ngmw_start; - - int ngmc; - int ngmc_g; - int ngmc_start; - - Vector3 *gdirect; //(= *G1d) ; // ig = new Vector igc[ngmc], - Vector3 *gdirect_global; //(= *G1d) ; // ig = new Vector igc[ngmc], - Vector3 *gcar; //G vectors in cartesian corrdinate - Vector3 *gcar_global; //G vectors in cartesian corrdinate - double *gg; // modulus (G^2) of G vectors - double *gg_global; // modulus (G^2) of G vectors - - ComplexMatrix eigts1; // - ComplexMatrix eigts2; //the phases e^{-iG*tau_s} - ComplexMatrix eigts3; // - int *ig1; // - int *ig2; // the indices of G components - int *ig3; // +class PW_Basis { + public: + // about lattice. + Matrix3 G; + Matrix3 GT; + Matrix3 GGT; + double tpiba; // 2pi/lat0 + double tpiba2; // tpiba^2 + + // about k point + int* ngk; + int** igk; + int** itia2iat; + int npwx; + + // about fft grid. + int nx; + int ny; + int nz; + int nxyz; + + double ggpsi; // planewave cut off for the wavefunctions, unit (2*PI/lat0)^2 + double ggwfc2; // ggwav=wfact*ggpsi, default value: wfact=4.0 + double ggchg; + + std::complex** strucFac; // StrucFac [ntype,ngmax] + + int ngmw; //(= ngmax) / num. of G vectors within ggfft + int ngmw_g; + int ngmw_start; + + int ngmc; + int ngmc_g; + int ngmc_start; + + Vector3* gdirect; //(= *G1d) ; // ig = new Vector igc[ngmc], + Vector3* gdirect_global; //(= *G1d) ; // ig = new Vector igc[ngmc], + Vector3* gcar; // G vectors in cartesian corrdinate + Vector3* gcar_global; // G vectors in cartesian corrdinate + double* gg; // modulus (G^2) of G vectors + double* gg_global; // modulus (G^2) of G vectors + + ComplexMatrix eigts1; // + ComplexMatrix eigts2; // the phases e^{-iG*tau_s} + ComplexMatrix eigts3; // + int* ig1; // + int* ig2; // the indices of G components + int* ig3; // PW_Basis(); ~PW_Basis(); void init(void); - void setup_structure_factor(void); // Calculate structur factors - void get_sk(void); - complex* get_sk(const int ik, const int it, const int ia)const; - Vector3 get_1qvec_cartesian(const int ik,const int ig)const; - - void table(void); - Numerical_Basis NBasis; - - void allocate_psi1d(const int &il); - void allocate_psi3d(const int &level); - realArray psi1d; - ComplexMatrix *psi3d; - matrix *ylm; - - void calculate_psi1d(void); - // FUNCTION: - // use psi1d to generate 3D wave functions. - // psi3d(it, ia, l, n, m) for each k point. - void calculate_psi3d(const int &ilevel, const int &ik); - - void update_psi1d(const int &il, const int &ic, const int &ie, - const double &c4_now, const double &c4_old); - - int nwfc2; - - void update_psi3d( const int &il, const int &ic, const int &ik); - - int kmesh; - double Dk; - - // FNCTION: - // calculate the overlap between psi(it, ia, l, n, m) - // be called in SpillageStep::init_QS_matrix - complex calculateS(const int &iw, const int &iw2, const int &ik); - - void calculate_Jlq(const int &ik, const int &iw, const int &ie); - complex *Jlq; - complex calculate_Jlq_Phi(const int &ik, const int &mu); - - complex *save; - int* posmu; - int* posnu; - -private: - void set_igk(void); + void setup_structure_factor(void); // Calculate structur factors + void get_sk(void); + complex* get_sk(const int ik, const int it, const int ia) const; + Vector3 get_1qvec_cartesian(const int ik, const int ig) const; + + void table(void); + Numerical_Basis NBasis; + + void allocate_psi1d(const int& il); + void allocate_psi3d(const int& level); + realArray psi1d; + ComplexMatrix* psi3d; + matrix* ylm; + + void calculate_psi1d(void); + // FUNCTION: + // use psi1d to generate 3D wave functions. + // psi3d(it, ia, l, n, m) for each k point. + void calculate_psi3d(const int& ilevel, const int& ik); + + void update_psi1d(const int& il, const int& ic, const int& ie, const double& c4_now, const double& c4_old); + + int nwfc2; + + void update_psi3d(const int& il, const int& ic, const int& ik); + + int kmesh; + double Dk; + + // FNCTION: + // calculate the overlap between psi(it, ia, l, n, m) + // be called in SpillageStep::init_QS_matrix + complex calculateS(const int& iw, const int& iw2, const int& ik); + + void calculate_Jlq(const int& ik, const int& iw, const int& ie); + complex* Jlq; + complex calculate_Jlq_Phi(const int& ik, const int& mu); + + complex* save; + int* posmu; + int* posnu; + + private: + void set_igk(void); void setup_gg(void); - void setup_FFT_dimension(void); // set up FFT dimensions + void setup_FFT_dimension(void); // set up FFT dimensions #ifdef __MPI void get_MPI_GVectors(void); #else void get_GVectors(void); #endif - // FUNCTION: - // use interpolation scheme to get the one dimension wave function for - // each k point - double Polynomial_Interpolation(const int &it, const int &l, const int &n, const double &gnorm)const; + // FUNCTION: + // use interpolation scheme to get the one dimension wave function for + // each k point + double Polynomial_Interpolation(const int& it, const int& l, const int& n, const double& gnorm) const; - Way2iw* iwindex; - + Way2iw* iwindex; }; -#endif //PlaneWave class +#endif // PlaneWave class diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_complement.cpp b/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_complement.cpp index a2ab75cadad..3342d2d3cf4 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_complement.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/pw_complement.cpp @@ -1,21 +1,18 @@ #include "pw_complement.h" #include "heapsort.h" -int PW_complement::get_total_pw_number( - const double& ggcut_start, - const double& ggcut_end, - const int& nx, - const int& ny, - const int& nz, - const Matrix3& GGT) -{ - TITLE("PW_complement","get_total_pw_number"); - if (ggcut_end<=0.0) - { - WARNING_QUIT("PW_complement::get_total_pw_number","ggcut <= 0.0"); +int PW_complement::get_total_pw_number(const double& ggcut_start, + const double& ggcut_end, + const int& nx, + const int& ny, + const int& nz, + const Matrix3& GGT) { + TITLE("PW_complement", "get_total_pw_number"); + if (ggcut_end <= 0.0) { + WARNING_QUIT("PW_complement::get_total_pw_number", "ggcut <= 0.0"); } // First, figure out the number of G-vectors within the cutoff G2max. - int ibox[3]={0,0,0}; + int ibox[3] = {0, 0, 0}; // mohan modify 2008-3-25 nx -> ncx ,ny-> ncy, nz->ncz ibox[0] = int(nx / 2) + 1; @@ -24,20 +21,16 @@ int PW_complement::get_total_pw_number( // first create the auxiliary arrays for the 1D G vectors Vector3 f; - int ngm = 0 ; - for (int i = -ibox[0]; i <= ibox[0]; i++) - { - for (int j = -ibox[1]; j <= ibox[1]; j++) - { - for (int k = -ibox[2]; k <= ibox[2]; k++) - { + int ngm = 0; + for (int i = -ibox[0]; i <= ibox[0]; i++) { + for (int j = -ibox[1]; j <= ibox[1]; j++) { + for (int k = -ibox[2]; k <= ibox[2]; k++) { f.x = i; f.y = j; f.z = k; - double g2 = f * (GGT * f); //G2= |f|^2 in the unit of (2Pi/lat0)^2 - - if (g2 < ggcut_end && g2 >= ggcut_start) - { + double g2 = f * (GGT * f); // G2= |f|^2 in the unit of (2Pi/lat0)^2 + + if (g2 < ggcut_end && g2 >= ggcut_start) { ngm++; } } @@ -46,26 +39,23 @@ int PW_complement::get_total_pw_number( return ngm; } -void PW_complement::get_total_pw( - double* gg, - Vector3 *ig, - const double& ggcut_start, - const double& ggcut_end, - const int& nx, - const int& ny, - const int& nz, - const Matrix3& GGT, // GGT = G*GT. - int& ngm// number of total plane waves. -) -{ - TITLE("PW_complement","get_total_pw"); - timer::tick("PW_complement","get_total_pw"); - if (ggcut_end<=0.0) - { - WARNING_QUIT("PW_complement::get_total_pw","ggcut <= 0.0"); +void PW_complement::get_total_pw(double* gg, + Vector3* ig, + const double& ggcut_start, + const double& ggcut_end, + const int& nx, + const int& ny, + const int& nz, + const Matrix3& GGT, // GGT = G*GT. + int& ngm // number of total plane waves. +) { + TITLE("PW_complement", "get_total_pw"); + timer::tick("PW_complement", "get_total_pw"); + if (ggcut_end <= 0.0) { + WARNING_QUIT("PW_complement::get_total_pw", "ggcut <= 0.0"); } // First, figure out the number of G-vectors within the cutoff G2max. - int ibox[3]={0,0,0}; + int ibox[3] = {0, 0, 0}; // mohan modify 2008-3-25 nx -> ncx ,ny-> ncy, nz->ncz ibox[0] = int(nx / 2) + 1; @@ -75,48 +65,42 @@ void PW_complement::get_total_pw( // first create the auxiliary arrays for the 1D G vectors Vector3 f; int ng = 0; - for (int i = -ibox[0]; i <= ibox[0]; i++) - { - for (int j = -ibox[1]; j <= ibox[1]; j++) - { - for (int k = -ibox[2]; k <= ibox[2]; k++) - { + for (int i = -ibox[0]; i <= ibox[0]; i++) { + for (int j = -ibox[1]; j <= ibox[1]; j++) { + for (int k = -ibox[2]; k <= ibox[2]; k++) { f.x = i; f.y = j; f.z = k; - double g2 = f * (GGT * f); //G2= |f|^2 in the unit of (2Pi/lat0)^2 - if (g2 < ggcut_end && g2 >= ggcut_start) - { + double g2 = f * (GGT * f); // G2= |f|^2 in the unit of (2Pi/lat0)^2 + if (g2 < ggcut_end && g2 >= ggcut_start) { /*** g vector indices f=(i,j,k) ***/ - ig[ng] = f ; + ig[ng] = f; gg[ng] = g2; - //cout<0,use the input // FFT grid, otherwise generate the FFT grid in the code. int i = 0; Vector3 lat; - int ibox[3]={0,0,0}; + int ibox[3] = {0, 0, 0}; // ibox[i] are the minimal FFT dimensions, lat.x = latvec.e11; @@ -133,15 +117,14 @@ void PW_complement::get_FFT_dimension( lat.y = latvec.e32; lat.z = latvec.e33; ibox[2] = 2 * int(sqrt(ggcut) * sqrt(lat * lat)) + 1; - //lat*lat=lat.x*lat.x+lat.y*lat.y+lat.z+lat.z + // lat*lat=lat.x*lat.x+lat.y*lat.y+lat.z+lat.z /* Find the minimal FFT box size the factors into the primes (2,3,5,7). */ -// log << "\n ibox[0]= "<< ibox[0] << " ibox[1] = "<* ig, + Vector3* g) { + TITLE("PW_complement", "setup_GVectors"); + timer::tick("PW_complement", "setup_GVectors"); + + int* ind = new int[ngmc_g_in]; // auxiliary array for the 1d G vector index + ZEROS(ind, ngmc_g_in); + ind[0] = 0; // ind[0]=0, meaning ind[] is not initialized. //---------------------------------------------------------- // CALL GLOBAL FUNCTION : @@ -236,15 +213,14 @@ void PW_complement::setup_GVectors( // G1d[i] is the vector in 3d grid, G1d2[i] is its norm. /***************************************************************/ - Vector3 *igsort = new Vector3[ngmc_g_in]; - for (int i=0;i* igsort = new Vector3[ngmc_g_in]; + for (int i = 0; i < ngmc_g_in; i++) { igsort[i] = ig[ind[i]]; -// cout << i << " " << ind[i] << " " << ig[ind[i]].x << " " << ig[ind[i]].y << " " << ig[ind[i]].z << endl; + // cout << i << " " << ind[i] << " " << ig[ind[i]].x << " " << ig[ind[i]].y << " " << ig[ind[i]].z << + // endl; } - for (int i=0; i *igsort, - const double& ggcut_start, const double& ggcut_end, - const int& nx, const int& ny, const int& nz, const Matrix3& GGT, // GGT = G*GT - int& ngm); // number of total plane waves. +namespace PW_complement { +int get_total_pw_number(const double& ggcut_start, + const double& ggcut_end, + const int& nx, + const int& ny, + const int& nz, + const Matrix3& GGT); + +void get_total_pw(double* ig2sort, + Vector3* igsort, + const double& ggcut_start, + const double& ggcut_end, + const int& nx, + const int& ny, + const int& nz, + const Matrix3& GGT, // GGT = G*GT + int& ngm); // number of total plane waves. // output nx, ny, nz according to input: latve and ggcut. -void get_FFT_dimension(const Matrix3& latvec, const double &ggcut, int &nx, int &ny, int &nz); +void get_FFT_dimension(const Matrix3& latvec, const double& ggcut, int& nx, int& ny, int& nz); //========================================================== // MEMBER FUNCTION : @@ -30,10 +38,7 @@ void get_FFT_dimension(const Matrix3& latvec, const double &ggcut, int &nx, int // the 3D G-grid and the FFT grid. // generate : gg_global, g_global, ig_global //========================================================== -void setup_GVectors(const Matrix3& G, const int &ngmc_g, double* gg, - Vector3* ig, Vector3* g); -} - +void setup_GVectors(const Matrix3& G, const int& ngmc_g, double* gg, Vector3* ig, Vector3* g); +} // namespace PW_complement #endif - diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/ylm_real.cpp b/tools/SIAB/SimulatedAnnealing/source/src_pw/ylm_real.cpp index 5fcc7724f4a..5a508af0b5d 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/ylm_real.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/ylm_real.cpp @@ -7,142 +7,112 @@ // NAME : YLM_REAL(Real spherical harmonics ylm(G) up to l=lmax // Use Numerical recursive algorithm as given in Numerical Recipes //========================================================== -void Ylm_Real -( - const int lmax2, // lmax2 = (lmax+1)^2 - const int ng, // - const Vector3 *g, // g_cartesian_vec(x,y,z) - matrix &ylm // output -) -{ -// TITLE("Mathzone","Ylm_Real"); -// timer::tick("Mathzone","Ylm_Real"); - - if (ng<1 || lmax2<1) - { - cout << "\n YLM_REAL: ng < 1 or lmax2 < 1"; - QUIT(); - timer::tick("Mathzone","Ylm_Real"); +void Ylm_Real(const int lmax2, // lmax2 = (lmax+1)^2 + const int ng, // + const Vector3* g, // g_cartesian_vec(x,y,z) + matrix& ylm // output +) { + // TITLE("Mathzone","Ylm_Real"); + // timer::tick("Mathzone","Ylm_Real"); + + if (ng < 1 || lmax2 < 1) { + cout << "\n YLM_REAL: ng < 1 or lmax2 < 1"; + QUIT(); + timer::tick("Mathzone", "Ylm_Real"); return; } -//---------------------------------------------------------- -// EXPLAIN : find out lmax -//---------------------------------------------------------- + //---------------------------------------------------------- + // EXPLAIN : find out lmax + //---------------------------------------------------------- bool out_of_range = true; int lmax = 0; - for (int l= 0; l< 30; l++) - { - if ((l+1)*(l+1) == lmax2) - { + for (int l = 0; l < 30; l++) { + if ((l + 1) * (l + 1) == lmax2) { lmax = l; out_of_range = false; break; } } - if (out_of_range) - { - WARNING_QUIT("YLM_REAL","l>30 or l<0"); + if (out_of_range) { + WARNING_QUIT("YLM_REAL", "l>30 or l<0"); } -//---------------------------------------------------------- -// EXPLAIN : if lmax = 1,only use Y00 , output result. -//---------------------------------------------------------- - if (lmax == 0) - { - for (int i=0;i 1.0e-9) - { + if (g[ig].x > 1.0e-9) { phi[ig] = atan(g[ig].y / g[ig].x); - } - else if (g[ig].x < -1.e-9) - { + } else if (g[ig].x < -1.e-9) { phi[ig] = atan(g[ig].y / g[ig].x) + PI; - } - else - { - phi[ig] = PI_HALF * ((g[ig].y >= 0.0) ? 1.0 : -1.0); //HLX: modified on 10/13/2006 + } else { + phi[ig] = PI_HALF * ((g[ig].y >= 0.0) ? 1.0 : -1.0); // HLX: modified on 10/13/2006 } // end if } // enddo -//========================================================== -// NAME : p(Legendre Polynomials) (0 <= m <= l) -//========================================================== - realArray p(lmax+1,lmax+1,ng); + //========================================================== + // NAME : p(Legendre Polynomials) (0 <= m <= l) + //========================================================== + realArray p(lmax + 1, lmax + 1, ng); int m; int i; double x1, x2; int lm = -1; - for (int l=0; l<=lmax; l++) - { - const double c = sqrt((2*l+1) / FOUR_PI); - if (l == 0) - { - for (i=0;i(l) / 2.0) ;//mohan modify 2007-10-13 - if (l%2 == 1) - { + p(l, l, i) = Semi_Fact(l3) * pow(x2, static_cast(l) / 2.0); // mohan modify 2007-10-13 + if (l % 2 == 1) { p(l, l, i) = -p(l, l, i); } } @@ -150,115 +120,101 @@ void Ylm_Real // Y_lm, m = 0 ++lm; - for (i=0;i 0 - const double same = c * sqrt - ( - static_cast(Fact(l - m)) / - static_cast(Fact(l + m)) - ) - *SQRT2; + const double same = c * sqrt(static_cast(Fact(l - m)) / static_cast(Fact(l + m))) * SQRT2; ++lm; - for (i=0;i1; i--) - { + for (int i = n; i > 1; i--) { f *= i; -// if(n>16) -// { -// cout<<"\n n="<16) + // { + // cout<<"\n n="<16) QUIT(); + // if(n>16) QUIT(); return f; } -int Semi_Fact(const int n) -{ +int Semi_Fact(const int n) { int semif = 1; - for (int i=n; i>2; i -= 2) - { + for (int i = n; i > 2; i -= 2) { semif *= i; } return semif; } - diff --git a/tools/SIAB/SimulatedAnnealing/source/src_pw/ylm_real.h b/tools/SIAB/SimulatedAnnealing/source/src_pw/ylm_real.h index 84a344392e7..14805846880 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_pw/ylm_real.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_pw/ylm_real.h @@ -3,14 +3,11 @@ #include "../src_tools/vector3.h" #include "../src_tools/realarray.h" #include "../src_tools/matrix.h" -using namespace std; -void Ylm_Real -( - const int lmax2, // lmax2 = (lmax+1)^2 - const int ng, // - const Vector3 *g, // g_cartesian_vec(x,y,z) - matrix &ylm // output +void Ylm_Real(const int lmax2, // lmax2 = (lmax+1)^2 + const int ng, // + const Vector3* g, // g_cartesian_vec(x,y,z) + matrix& ylm // output ); long double Fact(const int n); diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Calculate_C4.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Calculate_C4.cpp index 9a96e259c03..00780013ab7 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Calculate_C4.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Calculate_C4.cpp @@ -8,36 +8,36 @@ #include "tools.h" int Calculate_C4::test = 0; -Calculate_C4::Calculate_C4(){} -Calculate_C4::~Calculate_C4(){} +Calculate_C4::Calculate_C4() {} +Calculate_C4::~Calculate_C4() {} //=================================================================== // FUNCTION : Find_Eigenvalues -// DESCRIPTION : Find 'Enumber' number of eigenvalues of +// DESCRIPTION : Find 'Enumber' number of eigenvalues of // spherical bessel function from '0~lmax', and put the -// result eigenvalues in 'en' matrix. +// result eigenvalues in 'en' matrix. // P.S: (1) The eigenvalues are calculated '< tolerence' // accuracy. // P.S: (2) The rcut is important for cacluating eigenvalues // because it makes jl( rcut * eigenvalue ) = 0.00 //==================================================================== -void Calculate_C4::Find_Eigenvalues(const int &Enumber, matrix &en, - const int &lmax, const double &rcut, const double &tolerence) -{ - double *e = new double[Enumber]; - for(int l=0; l( rcut / dr)+1; - if(mesh % 2 == 0) mesh++; - cout << "\n\n Mesh for test = " << mesh << " L = " << L; - - double *r = new double[mesh]; - double *rab = new double[mesh]; - double *e = new double[Enumber]; - double *jle = new double[mesh]; - double *jtest = new double[mesh]; - double *function = new double[mesh]; - - for(int i=0; i(rcut / dr) + 1; + if (mesh % 2 == 0) + mesh++; + cout << "\n\n Mesh for test = " << mesh << " L = " << L; + + double* r = new double[mesh]; + double* rab = new double[mesh]; + double* e = new double[Enumber]; + double* jle = new double[mesh]; + double* jtest = new double[mesh]; + double* function = new double[mesh]; + + for (int i = 0; i < Enumber; i++) { + e[i] = en(L, i); + } + + for (int ir = 0; ir < mesh; ir++) { + r[ir] = ir * dr; + rab[ir] = dr; + } + + Mathzone::Spherical_Bessel(mesh, r, e[test_ei], L, jtest); + + cout << "\n r=" << r[mesh - 1] << "(a.u.) jtest=" << jtest[mesh - 1]; + + double C4 = 0.0; + for (int i = 0; i < Enumber; i++) { + Mathzone::Spherical_Bessel(mesh, r, e[i], L, jle); + for (int ir = 0; ir < mesh; ir++) { + function[ir] = jle[ir] * jtest[ir] * r[ir] * r[ir]; + } + Mathzone::Simpson_Integral(mesh, function, rab, C4); + // if( abs(C4) < 10e-5 ) + // { + // cout << "\n" << setw(5) << i << setw(15) << "0"; + // } + // else + // { + cout << "\n" << setw(5) << i << setw(15) << C4; + // } + } + + delete[] function; + delete[] jtest; + delete[] r; + delete[] rab; + delete[] e; + delete[] jle; + return; } //=================================================================== @@ -120,441 +120,414 @@ void Calculate_C4::Test_Orthogonal(const double &rcut, const double &dr, // (5) ues int_{0}^{Rc} J1(q1*r)*Jl(q1*r)*r*r dr ==> norm // (6) C4 = C4_firstly / norm //=================================================================== -void Calculate_C4::key_solver(const string &name, const int &L, const matrix &en, const int &Enumber, double *C4) -{ - ifstream ifs(name.c_str()); - if(!ifs) - { - cout << "\n Can't find file : " << name; - } - else - { - cout << "\n Open file " << name; - } - - string title; - - int mesh; - ifs >> title >> mesh; - assert(mesh > 0); - cout << "\t mesh = "<> title >> title >> title; - - for(int i=0; i> r[i] >> psi[i] >> rab[i]; - } - - double norm = 0.0; - for(int i=0; i> title >> mesh; + assert(mesh > 0); + cout << "\t mesh = " << mesh; + + double* r = new double[mesh]; + double* psi = new double[mesh]; + double* rab = new double[mesh]; + double* e = new double[Enumber]; + double* jle = new double[mesh]; + double* function = new double[mesh]; + double* function2 = new double[mesh]; + + for (int i = 0; i < Enumber; i++) { + e[i] = en(L, i); + } + + ifs >> title >> title >> title; + + for (int i = 0; i < mesh; i++) { + ifs >> r[i] >> psi[i] >> rab[i]; + } + + double norm = 0.0; + for (int i = 0; i < Enumber; i++) { + Mathzone::Spherical_Bessel(mesh, r, e[i], L, jle); + for (int ir = 0; ir < mesh; ir++) { + function[ir] = jle[ir] * psi[ir] * r[ir]; + } + + for (int ir = 0; ir < mesh; ir++) { + function2[ir] = jle[ir] * jle[ir] * r[ir] * r[ir]; + } + + Mathzone::Simpson_Integral(mesh, function, rab, C4[i]); + Mathzone::Simpson_Integral(mesh, function2, rab, norm); + assert(norm != 0.0); + C4[i] /= norm; + // cout << "\n norm = "<(rcut / dr)+1; //mohan update 2009-10-10 - if(mesh % 2 == 0) mesh++; - - if(test==1) - { - cout << "\n norm : mesh = " << mesh; - cout << "\n type = " << ntype; - cout << "\n lmax = " << lmax; - cout << "\n enumber = " << enumber; - } - - // init radial mesh - double *r = new double[mesh]; - for(int i=0; i(rcut / dr) + 1; // mohan update 2009-10-10 + if (mesh % 2 == 0) + mesh++; + + if (test == 1) { + cout << "\n norm : mesh = " << mesh; + cout << "\n type = " << ntype; + cout << "\n lmax = " << lmax; + cout << "\n enumber = " << enumber; + } + + // init radial mesh + double* r = new double[mesh]; + for (int i = 0; i < mesh; i++) { + r[i] = i * dr; + } + + // init relta r, used in simpson integral + double* rab = new double[mesh]; + for (int i = 0; i < mesh; i++) { + rab[i] = dr; + } + + double* e = new double[enumber]; + double* psi = new double[mesh]; + double* function = new double[mesh]; + double* jle = new double[mesh]; + + for (int it = 0; it < ntype; it++) { + for (int l = 0; l < lmax + 1; l++) { + // init eigenvalue of order l + for (int i = 0; i < enumber; i++) { + e[i] = en(l, i); + } + for (int n = 0; n < nmax; n++) { + ZEROS(jle, mesh); + ZEROS(psi, mesh); + for (int ie = 0; ie < enumber; ie++) { + Mathzone::Spherical_Bessel(mesh, r, e[ie], l, jle); + for (int ir = 0; ir < mesh; ir++) { + psi[ir] += C4(it, l, n, ie) * jle[ir]; + } + } + + for (int ir = 0; ir < mesh; ir++) { + function[ir] = psi[ir] * psi[ir] * r[ir] * r[ir]; + } + double norm = 0.0; + Mathzone::Simpson_Integral(mesh, function, rab, norm); + + if (test == 2) + cout << "it=" << it << " L=" << l << " N=" << n << " norm = " << norm << endl; + norm = sqrt(norm); + assert(norm > 1.0e-5); + for (int ie = 0; ie < enumber; ie++) { + C4(it, l, n, ie) /= norm; + accept_rate(it, l, n, ie) /= norm; // Peize Lin add 2015-12-24 + } + } + } + } + + delete[] r; + delete[] psi; + delete[] e; + delete[] jle; + return; } -void Calculate_C4::plot(ifstream &ifs) -{ - TITLE("Calculate_C4","plot"); - int nfiles; - double dr; - READ_VALUE( ifs, nfiles); - READ_VALUE( ifs, dr); - cout << "\n Number of files to plot : " << nfiles; - cout << "\n dr = " << dr; - assert( nfiles > 0); - assert( dr > 0.0 ); - - int l; - double ecut; - double rcut; - int enumber = 0; - double tolerence; - double *c4; - double *r; - double *e; - double *psi; - double *jle; - for(int i=0; i") ) - { - string filedir; - READ_VALUE( ifs, filedir ); - READ_VALUE( ifs, l ); - READ_VALUE( ifs, ecut ); - READ_VALUE( ifs, rcut ); - READ_VALUE( ifs, enumber ); - READ_VALUE( ifs, tolerence ); - cout << "\n l = " << l; - cout << "\n ecut = " << ecut; - cout << "\n enumber = " << enumber; - SCAN_END(ifs, ""); - } - - // init c4 - c4 = new double[enumber]; - ZEROS(c4, enumber); - if( SCAN_BEGIN(ifs,"") ) - { - assert(enumber>0); - for(int i=0; i> id >> c4[i]; - // cout << "\n c4[" << i << "]=" << c4[i]; - } - SCAN_END(ifs, ""); - } - - // init mesh - int mesh = static_cast(rcut / dr)+1; - if(mesh % 2 == 0) mesh++; - cout << "\n mesh = " << mesh; - - // init r - r = new double[mesh]; - for(int i=0; i")) { + string filedir; + READ_VALUE(ifs, filedir); + READ_VALUE(ifs, l); + READ_VALUE(ifs, ecut); + READ_VALUE(ifs, rcut); + READ_VALUE(ifs, enumber); + READ_VALUE(ifs, tolerence); + cout << "\n l = " << l; + cout << "\n ecut = " << ecut; + cout << "\n enumber = " << enumber; + SCAN_END(ifs, ""); + } + + // init c4 + c4 = new double[enumber]; + ZEROS(c4, enumber); + if (SCAN_BEGIN(ifs, "")) { + assert(enumber > 0); + for (int i = 0; i < enumber; i++) { + int id; + ifs >> id >> c4[i]; + // cout << "\n c4[" << i << "]=" << c4[i]; + } + SCAN_END(ifs, ""); + } + + // init mesh + int mesh = static_cast(rcut / dr) + 1; + if (mesh % 2 == 0) + mesh++; + cout << "\n mesh = " << mesh; + + // init r + r = new double[mesh]; + for (int i = 0; i < mesh; i++) { + r[i] = dr * i; + } + + // init eigenvalue en + assert(l < 3); + matrix en(l + 1, enumber); + Find_Eigenvalues(enumber, en, l, rcut, tolerence); + + // init e + e = new double[enumber]; + for (int i = 0; i < enumber; i++) { + e[i] = en(l, i); + } + + // init psi + psi = new double[mesh]; + ZEROS(psi, mesh); + + // init jle + jle = new double[mesh]; + + // sum all jle + for (int ie = 0; ie < enumber; ie++) { + ZEROS(jle, mesh); + Mathzone::Spherical_Bessel(mesh, r, e[ie], l, jle); + for (int ir = 0; ir < mesh; ir++) { + psi[ir] += c4[ie] * jle[ir]; + } + } + + // unit + double norm; + double* function = new double[mesh]; + double* rab = new double[mesh]; + for (int ir = 0; ir < mesh; ir++) { + rab[ir] = dr; + function[ir] = psi[ir] * psi[ir] * r[ir] * r[ir]; + } + + Mathzone::Simpson_Integral(mesh, function, rab, norm); + cout << "\n norm = " << norm; + assert(norm > 1.0e-5); // small number, + norm = sqrt(norm); + + stringstream ss; + ss << filenames << ".plot.txt"; + + ofstream ofs(ss.str().c_str()); + for (int ir = 0; ir < mesh; ir++) { + ofs << ir * dr << " " << psi[ir] / norm << endl; + } + + delete[] c4; + delete[] r; + delete[] e; + delete[] psi; + delete[] jle; + delete[] function; + delete[] rab; + } + + exit(0); + return; } -void Calculate_C4::Test(ifstream &ifs, const double &ecut, const double &tolerence ) -{ - TITLE("Calculate_C4","Test"); - double rcut;// rcut for input orbitals - double dr;// dr for simpson integrals( only used in test case), - // in output C4 case : dr is read from file as 'rab' - int test_ei;// the eigenvalue we want to test - int lmax; // max value of L - - READ_VALUE( ifs, rcut ); - READ_VALUE( ifs, dr ); - READ_VALUE( ifs, test_ei); - READ_VALUE( ifs, lmax ); - - cout << "\n Energy cutoff = "<< ecut; - cout << "\n tolerence = " << tolerence; - cout << "\n rcut = "< get_C4 Program Start." << endl; - - cout << "\n rcut = " << rcut << " (a.u.)"; - cout << "\n ecut = " << ecut << " (Ry)"; - cout << "\n tolerence = " << tolerence; - cout << "\n lmax = " << lmax; - - int nw;//number of orbitals(files) to calculate C4. - string *name;// file name, containing psi(r)*r, rab, radial - int *L;//angular momentum for each file( each orbital); - - READ_VALUE( ifs, nw ); - assert(nw>0); - cout << "\n Files = " << nw; - - name = new string[nw]; - L = new int[nw]; - //================================================ - // read in the file name and the corresponding L. - //================================================ - for(int i=0; i( sqrt( ecut * 2) * rcut / Mathzone::PI ); - cout << "\n Eigenvalue number(Jl) = " << Enumber; - - //================================================ - // Calculate eigenvalue of Jl - // CALL FUNCTION : Find_Eigenvalues - //================================================ - matrix en( lmax+1, Enumber); - Find_Eigenvalues(Enumber, en, lmax, rcut, tolerence); - - for(int i=0; ikey_solver(name[i], L[i], en, Enumber, C4); - stringstream ss; - ss << name[i] << ".C4"; - ofstream ofs( ss.str().c_str() ); - - ofs << "Calculate_C4_Program"; - ofs << "\n"; - ofs << "\n AUTHOR : Mohan Chen"; - ofs << "\n Date : 2009-4-1"; - ofs << "\n LOCATION : LQCC, Hefei, China"; - ofs << "\n EMAIL : mohan@mail.ustc.edu.cn"; - ofs << "\n Description : Calculate the coefficients C4 of f(r) in Spherical Bessel Basis J(qr)."; - ofs << "\n Formula : C4 = integral(r)[ f(r)*jl(qr)*r^{2} ]dr "; - ofs << "\n P.S. : We default consider f(r) read from file is in the form : ( f(r) * r )."; - ofs << "\n"; - - ofs << "\n\n"; - ofs << "\n" << name[i] << " ( f(r) read from this file)"; - ofs << "\n" << setw(8) << L[i] << " angular momentum for this orbital."; - ofs << "\n" << setw(8) << ecut << " Energy cutoff(Ry.)."; - ofs << "\n" << setw(8) << rcut << " rcut (a.u.)"; - ofs << "\n" << setw(8) << Enumber << " eigenvalue number( sqrt(ecut*2)*rcut/PI )."; - ofs << "\n" << setw(8) << tolerence << " tolerence to calculate eigenvalue."; - ofs << "\n"; - - ofs << "\n\n"; - for(int j=0; j"; - ofs.close(); - delete[] C4; - } - - delete[] name; - delete[] L; +void Calculate_C4::init(ifstream& ifs, + const double& ecut, + const double& rcut, + const double& tolerence, + const int& lmax) { + cout << "\n\n ==> get_C4 Program Start." << endl; + + cout << "\n rcut = " << rcut << " (a.u.)"; + cout << "\n ecut = " << ecut << " (Ry)"; + cout << "\n tolerence = " << tolerence; + cout << "\n lmax = " << lmax; + + int nw; // number of orbitals(files) to calculate C4. + string* name; // file name, containing psi(r)*r, rab, radial + int* L; // angular momentum for each file( each orbital); + + READ_VALUE(ifs, nw); + assert(nw > 0); + cout << "\n Files = " << nw; + + name = new string[nw]; + L = new int[nw]; + //================================================ + // read in the file name and the corresponding L. + //================================================ + for (int i = 0; i < nw; i++) { + READ_VALUE(ifs, name[i]); + READ_VALUE(ifs, L[i]); + } + + //================================================ + // Calculate the eigenvalues number from ecut. + //================================================ + const int Enumber = static_cast(sqrt(ecut * 2) * rcut / Mathzone::PI); + cout << "\n Eigenvalue number(Jl) = " << Enumber; + + //================================================ + // Calculate eigenvalue of Jl + // CALL FUNCTION : Find_Eigenvalues + //================================================ + matrix en(lmax + 1, Enumber); + Find_Eigenvalues(Enumber, en, lmax, rcut, tolerence); + + for (int i = 0; i < nw; i++) { + double* C4 = new double[Enumber]; + //=========================================== + // CALL FUNCTION : Calculate + // calculate C4. + //=========================================== + this->key_solver(name[i], L[i], en, Enumber, C4); + stringstream ss; + ss << name[i] << ".C4"; + ofstream ofs(ss.str().c_str()); + + ofs << "Calculate_C4_Program"; + ofs << "\n"; + ofs << "\n AUTHOR : Mohan Chen"; + ofs << "\n Date : 2009-4-1"; + ofs << "\n LOCATION : LQCC, Hefei, China"; + ofs << "\n EMAIL : mohan@mail.ustc.edu.cn"; + ofs << "\n Description : Calculate the coefficients C4 of f(r) in Spherical Bessel Basis J(qr)."; + ofs << "\n Formula : C4 = integral(r)[ f(r)*jl(qr)*r^{2} ]dr "; + ofs << "\n P.S. : We default consider f(r) read from file is in the form : ( f(r) * r )."; + ofs << "\n"; + + ofs << "\n\n"; + ofs << "\n" << name[i] << " ( f(r) read from this file)"; + ofs << "\n" << setw(8) << L[i] << " angular momentum for this orbital."; + ofs << "\n" << setw(8) << ecut << " Energy cutoff(Ry.)."; + ofs << "\n" << setw(8) << rcut << " rcut (a.u.)"; + ofs << "\n" << setw(8) << Enumber << " eigenvalue number( sqrt(ecut*2)*rcut/PI )."; + ofs << "\n" << setw(8) << tolerence << " tolerence to calculate eigenvalue."; + ofs << "\n"; + + ofs << "\n\n"; + for (int j = 0; j < Enumber; j++) { + ofs << "\n" << setw(5) << j << setiosflags(ios::scientific) << setprecision(8) << setw(25) << C4[j]; + } + ofs << "\n"; + ofs.close(); + delete[] C4; + } + + delete[] name; + delete[] L; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Calculate_C4.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Calculate_C4.h index d50a2fbda5c..ff73b1aa009 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Calculate_C4.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Calculate_C4.h @@ -3,37 +3,40 @@ #include "common.h" -class Calculate_C4 -{ - public: - - Calculate_C4(); - ~Calculate_C4(); - - void init( ifstream &ifs, const double &ecut, const double &rcut, const double &tolerence, const int &lmax ); - void Test( ifstream &ifs, const double &ecut, const double &tolerence); - void plot( ifstream &ifs ); - - // Peize Lin add accept_rate 2015-12-24 - static void norm_ic( realArray &C4, realArray &accept_rate, const int &ntype, const int &lmax, - const int &nmax, const int &enumber, const double &tolerence, - const double &rcut, const double &dr); - - static void Find_Eigenvalues(const int &Enumber, matrix &en, - const int &lmax, const double &rcut, const double &tolerence); - - private: - - void Test_Orthogonal(const double &rcut, const double &dr, - const int &L, const matrix &en, const int &Enumber, const int &test_ei); - - void key_solver(const string &name, const int &L, - const matrix &en, const int &Enumber, double *C4); - - static int test; - - - +class Calculate_C4 { + public: + Calculate_C4(); + ~Calculate_C4(); + + void init(ifstream& ifs, const double& ecut, const double& rcut, const double& tolerence, const int& lmax); + void Test(ifstream& ifs, const double& ecut, const double& tolerence); + void plot(ifstream& ifs); + + // Peize Lin add accept_rate 2015-12-24 + static void norm_ic(realArray& C4, + realArray& accept_rate, + const int& ntype, + const int& lmax, + const int& nmax, + const int& enumber, + const double& tolerence, + const double& rcut, + const double& dr); + + static void + Find_Eigenvalues(const int& Enumber, matrix& en, const int& lmax, const double& rcut, const double& tolerence); + + private: + void Test_Orthogonal(const double& rcut, + const double& dr, + const int& L, + const matrix& en, + const int& Enumber, + const int& test_ei); + + void key_solver(const string& name, const int& L, const matrix& en, const int& Enumber, double* C4); + + static int test; }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Coefficients.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Coefficients.cpp index 5d7cf79c257..ef100548be2 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Coefficients.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Coefficients.cpp @@ -3,29 +3,26 @@ bool Coefficients::write_c4_flag; -Coefficients::Coefficients() -{ +Coefficients::Coefficients() { test = 0; output_c4_name = new string[1]; - accumulate_num = 0;//mohan add 2009-09-25 + accumulate_num = 0; // mohan add 2009-09-25 } -Coefficients::~Coefficients() -{ - if (TEST1) cout << "\n ~Coefficients()" << endl; +Coefficients::~Coefficients() { + if (TEST1) + cout << "\n ~Coefficients()" << endl; delete[] output_c4_name; } -void Coefficients::init( - const int &ntype_in, - const int &lmax_in, - const int &nmax_in, - const double &ecut_in, - const double &ecut_jlq_in, // mohan add 2009-07-23 - const double &rcut_in, - const double &tolerence_in) -{ - TITLE(ofs_running,"Coefficients", "Constructor"); +void Coefficients::init(const int& ntype_in, + const int& lmax_in, + const int& nmax_in, + const double& ecut_in, + const double& ecut_jlq_in, // mohan add 2009-07-23 + const double& rcut_in, + const double& tolerence_in) { + TITLE(ofs_running, "Coefficients", "Constructor"); ntype = ntype_in; lmax = lmax_in; @@ -33,21 +30,21 @@ void Coefficients::init( ecut = ecut_in; ecut_jlq = ecut_jlq_in; // mohan add 2009-07-23 rcut = rcut_in; -// in Rydberg Unit - enumber = static_cast( sqrt( ecut )* rcut/PI ); - enumber_jlq = static_cast ( sqrt( ecut_jlq) * rcut/PI ); // mohan add 2009-07-23 - tolerence = tolerence_in; - - OUT(ofs_running,"ntype",ntype); - OUT(ofs_running,"lmax",lmax); - OUT(ofs_running,"nmax",nmax); - OUT(ofs_running,"ecut(Ry)",ecut); - OUT(ofs_running,"ecut_jlq(Ry)",ecut_jlq); - OUT(ofs_running,"rcut(Bohr)",rcut); - OUT(ofs_running,"enumber",enumber); - OUT(ofs_running,"enumber_jlq",enumber_jlq); - OUT(ofs_running,"tolerence",tolerence); - + // in Rydberg Unit + enumber = static_cast(sqrt(ecut) * rcut / PI); + enumber_jlq = static_cast(sqrt(ecut_jlq) * rcut / PI); // mohan add 2009-07-23 + tolerence = tolerence_in; + + OUT(ofs_running, "ntype", ntype); + OUT(ofs_running, "lmax", lmax); + OUT(ofs_running, "nmax", nmax); + OUT(ofs_running, "ecut(Ry)", ecut); + OUT(ofs_running, "ecut_jlq(Ry)", ecut_jlq); + OUT(ofs_running, "rcut(Bohr)", rcut); + OUT(ofs_running, "enumber", enumber); + OUT(ofs_running, "enumber_jlq", enumber_jlq); + OUT(ofs_running, "tolerence", tolerence); + assert(ntype > 0); assert(lmax >= 0); assert(nmax > 0); @@ -67,60 +64,49 @@ void Coefficients::init( return; } -void Coefficients::allocate_C4(void) -{ - if (test==1)TITLE("Coefficients", "allocate_C4"); +void Coefficients::allocate_C4(void) { + if (test == 1) + TITLE("Coefficients", "allocate_C4"); this->C4.create(ntype, lmax + 1, nmax, enumber); this->C4_old.create(ntype, lmax + 1, nmax, enumber); this->C4_accumulate.create(ntype, lmax + 1, nmax, enumber); // mohan add 2009-09-25 -// this->acc_count.create(ntype, lmax+1, nmax, enumber); - this->accept_number.create(ntype, lmax+1, nmax, enumber); // mohan add 2009-10-16 - this->accept_rate.create(ntype, lmax+1, nmax, enumber);// mohan add 2009-10-31 + // this->acc_count.create(ntype, lmax+1, nmax, enumber); + this->accept_number.create(ntype, lmax + 1, nmax, enumber); // mohan add 2009-10-16 + this->accept_rate.create(ntype, lmax + 1, nmax, enumber); // mohan add 2009-10-31 // init accept_rate - for (int i=0; iaccept_rate.ptr[i] = 1.0; } - for (int it = 0; it < ntype; it++) - { - for (int il = 0; il < lmax+1; il++) - { - for (int in = 0; in < nmax; in++) - { - ofs_running << "\n Init C4: T=" << it+1 << " L=" << il << " N=" << in; - for (int ie = 0; ie < enumber; ie++) - { + for (int it = 0; it < ntype; it++) { + for (int il = 0; il < lmax + 1; il++) { + for (int in = 0; in < nmax; in++) { + ofs_running << "\n Init C4: T=" << it + 1 << " L=" << il << " N=" << in; + for (int ie = 0; ie < enumber; ie++) { // mohan modify 2009-08-26 int ne_cut; int ne_cut_min = -1; // must initalized - if (BLOCK_NE_MIN>0) - { + if (BLOCK_NE_MIN > 0) { ne_cut_min = BLOCK_NE_MIN; } - if (BLOCK_NE<0) - { + if (BLOCK_NE < 0) { ne_cut = enumber_jlq; - } - else - { + } else { ne_cut = BLOCK_NE; } - if (iene_cut_min) - { + if (ie < ne_cut && ie > ne_cut_min) { this->C4(it, il, in, ie) = Random::between0and1(); this->C4_old(it, il, in, ie) = this->C4(it, il, in, ie); - } - else - { + } else { this->C4(it, il, in, ie) = 0.0; this->C4_old(it, il, in, ie) = 0.0; } - if (ie%4==0)ofs_running< BLOCK, // how many C4 you want to read in! // remain bug when ntype > 1. - if (RESTART) - { - if (MY_RANK==0) - { - ifstream ifs( "ORBITAL_RESULTS.txt" ); - if (!ifs) - { - WARNING_QUIT("Coefficients::allocate_C4()","can't find the restart file: ORBITAL_RESULTS.txt"); - } - else - { + if (RESTART) { + if (MY_RANK == 0) { + ifstream ifs("ORBITAL_RESULTS.txt"); + if (!ifs) { + WARNING_QUIT("Coefficients::allocate_C4()", "can't find the restart file: ORBITAL_RESULTS.txt"); + } else { cout << "\n Read in RESTART information from : ORBITAL_RESULTS.txt" << endl; } double ecut_in; double rcut_in; int ne_in; - if ( SCAN_BEGIN(ifs,"") ) - { + if (SCAN_BEGIN(ifs, "")) { READ_VALUE(ifs, ecut_in); READ_VALUE(ifs, rcut_in); READ_VALUE(ifs, ne_in); - if (ne_in != enumber) - { + if (ne_in != enumber) { cout << "\n ne_in = " << ne_in; cout << "\n enumber = " << enumber; - WARNING_QUIT("Coefficients::Allocate_C4()","enumber != ne_in"); + WARNING_QUIT("Coefficients::Allocate_C4()", "enumber != ne_in"); } } - if ( SCAN_BEGIN(ifs,"") ) - { + if (SCAN_BEGIN(ifs, "")) { int nchi_in; READ_VALUE(ifs, nchi_in); assert(nchi_in > 0); @@ -172,92 +150,79 @@ void Coefficients::allocate_C4(void) int it2, il2, in2; bool hold_on = false; int count_nchi = 0; - for (int it = 0; it < ntype; it++) - { - for (int il = 0; il < lmax+1; il++) - { - for (int in = 0; in < nmax; in++) - { - if (!hold_on) - { + for (int it = 0; it < ntype; it++) { + for (int il = 0; il < lmax + 1; il++) { + for (int in = 0; in < nmax; in++) { + if (!hold_on) { ifs >> no_use1 >> no_use2 >> no_use3; assert(no_use1 == "Type"); assert(no_use2 == "L"); assert(no_use3 == "Zeta-Orbital"); - ifs >> it2>> il2>> in2; - it2 -= 1; - in2 -= 1; + ifs >> it2 >> il2 >> in2; + it2 -= 1; + in2 -= 1; } - if (it2!=it || il2!=il || in2!=in) - { + if (it2 != it || il2 != il || in2 != in) { hold_on = true; continue; - } - else - { + } else { hold_on = false; - cout << "\n\n Read in T=" << it+1 << " L=" << il << " Zeta-Orbital=" << in; - for (int ie=0; ieC4.getSize(); i++) - { +void Coefficients::copy_c4_to_old(void) { + for (int i = 0; i < this->C4.getSize(); i++) { this->C4_old.ptr[i] = this->C4.ptr[i]; } return; } - -void Coefficients::trial_c4( const int &t, const int &l, const int &n, const int &ie ) -{ +void Coefficients::trial_c4(const int& t, const int& l, const int& n, const int& ie) { // (1) this->C4_old(t, l, n, ie) = this->C4(t, l, n, ie); // update between -0.1~0.1 // (2) - this->C4(t, l, n, ie) += Random::betweenMinus1and1()/10.0* this->accept_rate(t, l, n, ie); + this->C4(t, l, n, ie) += Random::betweenMinus1and1() / 10.0 * this->accept_rate(t, l, n, ie); #ifdef __MPI - // don't need to bcast ! it's a random seed. -// ofs_running << "\n C4=" << this->C4(t, l, n, ie); -// Parallel_Common::bcast_double( this->C4(t, l, n, ie) ); + // don't need to bcast ! it's a random seed. +// ofs_running << "\n C4=" << this->C4(t, l, n, ie); +// Parallel_Common::bcast_double( this->C4(t, l, n, ie) ); #endif -// if( abs(this->C4(t, l, n, ie)) < 1.0e-3) //mohan modify 2009-10-10 -// { -// this->C4(t, l, n, ie) = 0.0; -// } -// this->C4(t, l, n, ie) += Random::betweenMinus1and1(); + // if( abs(this->C4(t, l, n, ie)) < 1.0e-3) //mohan modify 2009-10-10 + // { + // this->C4(t, l, n, ie) = 0.0; + // } + // this->C4(t, l, n, ie) += Random::betweenMinus1and1(); // this->C4(t, l, n, ie) *= Random::betweenMinus2and2(); // cout << "\n ic = " << ic << " ie = " << ie << " C4 = " << C4(t, l, n, ie); @@ -267,40 +232,38 @@ void Coefficients::trial_c4( const int &t, const int &l, const int &n, const int /* void Coefficients::accumulate_num_zero(void) { - cout << "\n Accumulate_num = " << this->accumulate_num; - this->accumulate_num = 0; + cout << "\n Accumulate_num = " << this->accumulate_num; + this->accumulate_num = 0; } */ /* void Coefficients::accumulating_C4( const int &t, const int &l, const int &n, const int &ie ) { - // mohan add 2009-09-25 - double mix = this->C4_accumulate(t, l, n, ie) * this->acc_count(t,l,n,ie) + this->C4_old(t, l, n, ie); - ++acc_count(t,l,n,ie); - ++accumulate_num; + // mohan add 2009-09-25 + double mix = this->C4_accumulate(t, l, n, ie) * this->acc_count(t,l,n,ie) + this->C4_old(t, l, n, ie); + ++acc_count(t,l,n,ie); + ++accumulate_num; this->C4_accumulate(t, l, n, ie) = mix / acc_count(t,l,n,ie); -// cout << "\n Accumulate_num = " << this->accumulate_num; +// cout << "\n Accumulate_num = " << this->accumulate_num; - return; + return; } */ -void Coefficients::update_c4( const int &t, const int &l, const int &n, const int &ie ) -{ +void Coefficients::update_c4(const int& t, const int& l, const int& n, const int& ie) { //=============================================== // store the new c4 parameters(random accepted!! // then next c4 will replace by a new set. //=============================================== this->C4_old(t, l, n, ie) = this->C4(t, l, n, ie); - ++accept_number(t,l,n,ie); + ++accept_number(t, l, n, ie); return; } -void Coefficients::go_back_c4( const int &t, const int &l, const int &n, const int &ie ) -{ +void Coefficients::go_back_c4(const int& t, const int& l, const int& n, const int& ie) { //================================== // give up the random added number; //================================== @@ -311,40 +274,40 @@ void Coefficients::go_back_c4( const int &t, const int &l, const int &n, const i /* void Coefficients::kinetic_energy( const int &t, const int &l, const int &n, const int &ie) { - if(!ke_flip_flag) - { - if(ke_up_flag) - { - // C4>0.0 and C4_old>0.0 - this->ke_total_up += ( C4(t, l, n, ie) - C4_old(t, l, n, ie) ) * ie * ie; - } - else - { - // C4<0.0 and C4_old>0.0 - this->ke_total_down += ( C4_old(t, l, n, ie) - C4(t, l, n, ie) ) * ie * ie; - } - } - else - { - // (1) C4>0.0 and C4_old<0.0, - // so ke_total_up energy increase - // ke_total_down energy decrease - // - // (2) C4<0.0 and C4_old>0.0, - // so ke_total_up energy decrease - // and ke_total_down energy increase - this->ke_total_up += C4(t, l, n, ie) * ie * ie; - this->ke_total_down += C4_old(t, l, n, ie) * ie * ie; - } - - this->ke_total_old = this->ke_total_new; - this->ke_total_new = abs(abs(ke_total_up) - abs(ke_total_down)); - -// cout << "\n ke_total_up = " << ke_total_up; -// cout << "\n ke_total_down = " << ke_total_down; -// cout << "\n ke_total_old = " << ke_total_old; -// cout << "\n ke_total_new = " << ke_total_new << endl; - - return; + if(!ke_flip_flag) + { + if(ke_up_flag) + { + // C4>0.0 and C4_old>0.0 + this->ke_total_up += ( C4(t, l, n, ie) - C4_old(t, l, n, ie) ) * ie * ie; + } + else + { + // C4<0.0 and C4_old>0.0 + this->ke_total_down += ( C4_old(t, l, n, ie) - C4(t, l, n, ie) ) * ie * ie; + } + } + else + { + // (1) C4>0.0 and C4_old<0.0, + // so ke_total_up energy increase + // ke_total_down energy decrease + // + // (2) C4<0.0 and C4_old>0.0, + // so ke_total_up energy decrease + // and ke_total_down energy increase + this->ke_total_up += C4(t, l, n, ie) * ie * ie; + this->ke_total_down += C4_old(t, l, n, ie) * ie * ie; + } + + this->ke_total_old = this->ke_total_new; + this->ke_total_new = abs(abs(ke_total_up) - abs(ke_total_down)); + +// cout << "\n ke_total_up = " << ke_total_up; +// cout << "\n ke_total_down = " << ke_total_down; +// cout << "\n ke_total_old = " << ke_total_old; +// cout << "\n ke_total_new = " << ke_total_new << endl; + + return; } */ diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Coefficients.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Coefficients.h index 32c692e3452..8ca31bc949e 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Coefficients.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Coefficients.h @@ -2,53 +2,56 @@ #define COEFFICIENTS_H #include "common.h" -class Coefficients -{ - public: - //============================ - // C4(type, L, N, ie) - //============================ - realArray C4; - realArray C4_old; - realArray C4_accumulate; - //IntArray acc_count; - IntArray accept_number; - realArray accept_rate; - - // constructor, available for SZ, DZ, DZP... - Coefficients(); - ~Coefficients(); - - void init( const int &ntype, const int &lmax, const int &namx, - const double &ecut, const double &ecut_jlq, - const double &rcut, const double &tolerence); - void trial_c4( const int &t, const int &l, const int &n, const int &ie ); - - void update_c4( const int &t, const int &l, const int &n, const int &ie ); - void go_back_c4( const int &t, const int &l, const int &n, const int &ie ); - void copy_c4_to_old(void); // for normalize - void kinetic_energy( const int &t, const int &l, const int &n, const int &ie);// mohan add 2009-07-23 - void accumulate_num_zero(void); - void accumulating_C4( const int &t, const int &l, const int &n, const int &ie ); - - int ntype; - int lmax; - int nmax; - int enumber; - double rcut; - double tolerence; - int fix; - - string *output_c4_name; - static bool write_c4_flag; - - private: - void allocate_C4(); - double ecut; - double ecut_jlq; // mohan add 2009-07-23 - int enumber_jlq; // mohan add 2009-07-23 - int test; - int accumulate_num; +class Coefficients { + public: + //============================ + // C4(type, L, N, ie) + //============================ + realArray C4; + realArray C4_old; + realArray C4_accumulate; + // IntArray acc_count; + IntArray accept_number; + realArray accept_rate; + + // constructor, available for SZ, DZ, DZP... + Coefficients(); + ~Coefficients(); + + void init(const int& ntype, + const int& lmax, + const int& namx, + const double& ecut, + const double& ecut_jlq, + const double& rcut, + const double& tolerence); + void trial_c4(const int& t, const int& l, const int& n, const int& ie); + + void update_c4(const int& t, const int& l, const int& n, const int& ie); + void go_back_c4(const int& t, const int& l, const int& n, const int& ie); + void copy_c4_to_old(void); // for normalize + void kinetic_energy(const int& t, const int& l, const int& n, const int& ie); // mohan add 2009-07-23 + void accumulate_num_zero(void); + void accumulating_C4(const int& t, const int& l, const int& n, const int& ie); + + int ntype; + int lmax; + int nmax; + int enumber; + double rcut; + double tolerence; + int fix; + + string* output_c4_name; + static bool write_c4_flag; + + private: + void allocate_C4(); + double ecut; + double ecut_jlq; // mohan add 2009-07-23 + int enumber_jlq; // mohan add 2009-07-23 + int test; + int accumulate_num; }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S.cpp index d4a38a0e5b9..a60a38a4f42 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S.cpp @@ -2,47 +2,40 @@ #include "Inverse_Matrix_S_inline.h" #include "../src_tools/inverse_matrix_iterate_inline.h" -void Inverse_Matrix_S::init( int dim_in) -{ - this->dim = dim_in; - this->inverse.init(this->dim); - this->inverse_iterate.init(this->dim); - this->inverse_iterate.set_iterate_num(20); // test, undetermined - this->inverse_iterate.set_tolerate_error(1e-10); // test, undetermined - this->inverse_iterate.set_symmetric_info('H', 'U'); - this->set_exact_loop_num(1); // test, undetermined - return; +void Inverse_Matrix_S::init(int dim_in) { + this->dim = dim_in; + this->inverse.init(this->dim); + this->inverse_iterate.init(this->dim); + this->inverse_iterate.set_iterate_num(20); // test, undetermined + this->inverse_iterate.set_tolerate_error(1e-10); // test, undetermined + this->inverse_iterate.set_symmetric_info('H', 'U'); + this->set_exact_loop_num(1); // test, undetermined + return; } -const ComplexMatrix & Inverse_Matrix_S::cal_inverse(ComplexMatrix &S) -{ - if(0==loop_count) - { - inverse.using_zpotrf(S); - } - else - { - inverse_iterate.set_X0(*this->inverse_old) - .set_A(S); - try - { - if (1==loop_count) { copy_matrix_U2L(const_cast(*this->inverse_old)); } -// copy_matrix_U2L(const_cast(*this->inverse_old)); -// copy_matrix_U2L(S); +const ComplexMatrix& Inverse_Matrix_S::cal_inverse(ComplexMatrix& S) { + if (0 == loop_count) { + inverse.using_zpotrf(S); + } else { + inverse_iterate.set_X0(*this->inverse_old).set_A(S); + try { + if (1 == loop_count) { + copy_matrix_U2L(const_cast(*this->inverse_old)); + } + // copy_matrix_U2L(const_cast(*this->inverse_old)); + // copy_matrix_U2L(S); - inverse_iterate.cal_inverse(); - -// zero_matrix_L(const_cast(*this->inverse_old)); -// zero_matrix_L(S); - } - catch(const Inverse_Matrix_Iterate::Unstable &e) - { -// zero_matrix_L(const_cast(*this->inverse_old)); -// zero_matrix_L(S); - - loop_count = 0; - inverse.using_zpotrf(S); - } - } - return this->get_inverse(); + inverse_iterate.cal_inverse(); + + // zero_matrix_L(const_cast(*this->inverse_old)); + // zero_matrix_L(S); + } catch (const Inverse_Matrix_Iterate::Unstable& e) { + // zero_matrix_L(const_cast(*this->inverse_old)); + // zero_matrix_L(S); + + loop_count = 0; + inverse.using_zpotrf(S); + } + } + return this->get_inverse(); } \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S.h index f177b534da8..94b2747f07c 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S.h @@ -4,32 +4,34 @@ #include "../src_tools/inverse_matrix.h" #include "../src_tools/inverse_matrix_iterate.h" -class Inverse_Matrix_S -{ -public: - Inverse_Matrix inverse; - Inverse_Matrix_Iterate inverse_iterate; +class Inverse_Matrix_S { + public: + Inverse_Matrix inverse; + Inverse_Matrix_Iterate inverse_iterate; - void init( int dim_in); - const ComplexMatrix & cal_inverse(ComplexMatrix &S); - const ComplexMatrix & get_inverse() { return (0==loop_count) ? inverse.A : inverse_iterate.get_inverse(); } - inline void update(); - void reset_loop() { loop_count = 0; } + void init(int dim_in); + const ComplexMatrix& cal_inverse(ComplexMatrix& S); + const ComplexMatrix& get_inverse() { return (0 == loop_count) ? inverse.A : inverse_iterate.get_inverse(); } + inline void update(); + void reset_loop() { loop_count = 0; } -private: - size_t dim{0}; - size_t loop_count{0}; - size_t exact_loop_num{1}; - const ComplexMatrix *inverse_old = NULL; - - inline void copy_matrix_U2L(ComplexMatrix &matrix); - inline void zero_matrix_L(ComplexMatrix &matrix); - -public: - size_t get_exact_loop_num() { return this->exact_loop_num; } - size_t get_loop_count() { return this->loop_count; } - Inverse_Matrix_S & set_exact_loop_num(size_t exact_loop_num_in) { this->exact_loop_num = exact_loop_num_in; return *this;} - size_t get_dim() { return this->dim; } + private: + size_t dim{0}; + size_t loop_count{0}; + size_t exact_loop_num{1}; + const ComplexMatrix* inverse_old = NULL; + + inline void copy_matrix_U2L(ComplexMatrix& matrix); + inline void zero_matrix_L(ComplexMatrix& matrix); + + public: + size_t get_exact_loop_num() { return this->exact_loop_num; } + size_t get_loop_count() { return this->loop_count; } + Inverse_Matrix_S& set_exact_loop_num(size_t exact_loop_num_in) { + this->exact_loop_num = exact_loop_num_in; + return *this; + } + size_t get_dim() { return this->dim; } }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S_inline.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S_inline.h index bc102813645..066df9bd0d5 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S_inline.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Inverse_Matrix_S_inline.h @@ -1,29 +1,22 @@ #include "Inverse_Matrix_S.h" -void Inverse_Matrix_S::copy_matrix_U2L(ComplexMatrix &matrix) -{ - for( size_t iw1(0); iw1dim; ++iw1) - { - for( size_t iw2(0); iw2dim; ++iw1) { + for (size_t iw2(0); iw2 < iw1; ++iw2) { + matrix(iw1, iw2) = conj(matrix(iw2, iw1)); + } + } } -void Inverse_Matrix_S::zero_matrix_L(ComplexMatrix &matrix) -{ - for( size_t iw1(0); iw1dim; ++iw1) - { - for( size_t iw2(0); iw2dim; ++iw1) { + for (size_t iw2(0); iw2 < iw1; ++iw2) { + matrix(iw1, iw2) = 0; + } + } } -void Inverse_Matrix_S::update() -{ - inverse_old = &get_inverse(); - loop_count = (loop_count+1)%exact_loop_num; +void Inverse_Matrix_S::update() { + inverse_old = &get_inverse(); + loop_count = (loop_count + 1) % exact_loop_num; } \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis.cpp index 466e5ecad63..b1f72b5edfa 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis.cpp @@ -4,156 +4,143 @@ #include "../src_tools/Simulated_Annealing.h" #include "Simulated_Annealing_Orbital.h" -Metropolis::Metropolis() -{ - prob_old = 0.0; - prob_new = 0.0; - temperature = 0.0; - random_c4number = 0; - output_each_istep = 0; - kin_last = new double[1]; - kin_temp = new double[1]; +Metropolis::Metropolis() { + prob_old = 0.0; + prob_new = 0.0; + temperature = 0.0; + random_c4number = 0; + output_each_istep = 0; + kin_last = new double[1]; + kin_temp = new double[1]; } - -Metropolis::~Metropolis() -{ - delete[] kin_last; - delete[] kin_temp; +Metropolis::~Metropolis() { + delete[] kin_last; + delete[] kin_temp; } // read in Metropolis parameters. -void Metropolis::init(void) -{ - if(test==1) TITLE("Metropolis","init"); +void Metropolis::init(void) { + if (test == 1) + TITLE("Metropolis", "init"); - bool begin = false; + bool begin = false; - if(MY_RANK==0) - { - if(SCAN_BEGIN(input.ifs, "")) - { - begin = true; - } - } + if (MY_RANK == 0) { + if (SCAN_BEGIN(input.ifs, "")) { + begin = true; + } + } #ifdef __MPI - Parallel_Common::bcast_bool(begin); + Parallel_Common::bcast_bool(begin); #endif - ofs_running << "\n begin read in Metropolis parameter." << endl; - - if(begin) - { - if(MY_RANK==0) - { - READ_VALUE( input.ifs, this->spi_ini_temp); - READ_VALUE( input.ifs, this->spi_rate); - READ_VALUE( input.ifs, this->spi_ntemp); - READ_VALUE( input.ifs, this->spi_nsteps); - - READ_VALUE( input.ifs, this->kin_ini_temp); - READ_VALUE( input.ifs, this->kin_rate); - READ_VALUE( input.ifs, this->kin_ntemp); - READ_VALUE( input.ifs, this->kin_nsteps); - - READ_VALUE( input.ifs, this->delta_kappa); - READ_VALUE( input.ifs, this->output_each_istep); - - READ_VALUE( input.ifs, ACCEPTANCE_STEPS ); // mohan add 2009-10-31 - READ_VALUE( input.ifs, ACCEPTANCE_HIGH ); - READ_VALUE( input.ifs, ACCEPTANCE_LOW ); - - READ_VALUE( input.ifs, KINETIC_MAX ); // mohan add 2009-10-31 - READ_VALUE( input.ifs, KINETIC_DR); //mohan add 2010-04-12 - READ_VALUE( input.ifs, OPTIMIZE_METHOD); // mohan add 2010-04-14 - //SCAN_END(input.ifs, ""); - } - + ofs_running << "\n begin read in Metropolis parameter." << endl; + + if (begin) { + if (MY_RANK == 0) { + READ_VALUE(input.ifs, this->spi_ini_temp); + READ_VALUE(input.ifs, this->spi_rate); + READ_VALUE(input.ifs, this->spi_ntemp); + READ_VALUE(input.ifs, this->spi_nsteps); + + READ_VALUE(input.ifs, this->kin_ini_temp); + READ_VALUE(input.ifs, this->kin_rate); + READ_VALUE(input.ifs, this->kin_ntemp); + READ_VALUE(input.ifs, this->kin_nsteps); + + READ_VALUE(input.ifs, this->delta_kappa); + READ_VALUE(input.ifs, this->output_each_istep); + + READ_VALUE(input.ifs, ACCEPTANCE_STEPS); // mohan add 2009-10-31 + READ_VALUE(input.ifs, ACCEPTANCE_HIGH); + READ_VALUE(input.ifs, ACCEPTANCE_LOW); + + READ_VALUE(input.ifs, KINETIC_MAX); // mohan add 2009-10-31 + READ_VALUE(input.ifs, KINETIC_DR); // mohan add 2010-04-12 + READ_VALUE(input.ifs, OPTIMIZE_METHOD); // mohan add 2010-04-14 + // SCAN_END(input.ifs, ""); + } + #ifdef __MPI - MPI_Barrier(MPI_COMM_WORLD); + MPI_Barrier(MPI_COMM_WORLD); - Parallel_Common::bcast_double(this->spi_ini_temp); - Parallel_Common::bcast_double(this->spi_rate); - Parallel_Common::bcast_int(this->spi_ntemp); - Parallel_Common::bcast_int(this->spi_nsteps); + Parallel_Common::bcast_double(this->spi_ini_temp); + Parallel_Common::bcast_double(this->spi_rate); + Parallel_Common::bcast_int(this->spi_ntemp); + Parallel_Common::bcast_int(this->spi_nsteps); - Parallel_Common::bcast_double(this->kin_ini_temp); - Parallel_Common::bcast_double(this->kin_rate); - Parallel_Common::bcast_int(this->kin_ntemp); - Parallel_Common::bcast_int(this->kin_nsteps); + Parallel_Common::bcast_double(this->kin_ini_temp); + Parallel_Common::bcast_double(this->kin_rate); + Parallel_Common::bcast_int(this->kin_ntemp); + Parallel_Common::bcast_int(this->kin_nsteps); - Parallel_Common::bcast_double(this->delta_kappa); - Parallel_Common::bcast_int(this->output_each_istep); + Parallel_Common::bcast_double(this->delta_kappa); + Parallel_Common::bcast_int(this->output_each_istep); - Parallel_Common::bcast_int(ACCEPTANCE_STEPS ); - Parallel_Common::bcast_double(ACCEPTANCE_HIGH ); - Parallel_Common::bcast_double(ACCEPTANCE_LOW ); + Parallel_Common::bcast_int(ACCEPTANCE_STEPS); + Parallel_Common::bcast_double(ACCEPTANCE_HIGH); + Parallel_Common::bcast_double(ACCEPTANCE_LOW); - Parallel_Common::bcast_double(KINETIC_MAX ); - Parallel_Common::bcast_double(KINETIC_DR ); - Parallel_Common::bcast_int(OPTIMIZE_METHOD); + Parallel_Common::bcast_double(KINETIC_MAX); + Parallel_Common::bcast_double(KINETIC_DR); + Parallel_Common::bcast_int(OPTIMIZE_METHOD); #endif - } - this->temperature = this->spi_ini_temp; - - // check whether the parameters are in the range. - assert(spi_ini_temp >= 0.0); - assert(spi_rate >= 0.0); + this->temperature = this->spi_ini_temp; + + // check whether the parameters are in the range. + assert(spi_ini_temp >= 0.0); + assert(spi_rate >= 0.0); assert(spi_ntemp >= 0); - assert(spi_nsteps >= 0); + assert(spi_nsteps >= 0); - assert(kin_ini_temp >= 0.0); - assert(kin_rate >= 0.0); + assert(kin_ini_temp >= 0.0); + assert(kin_rate >= 0.0); assert(kin_ntemp >= 0); - assert(kin_nsteps >= 0); + assert(kin_nsteps >= 0); + + assert(delta_kappa >= 0.0); + assert(output_each_istep > 0); - assert(delta_kappa >= 0.0); - assert(output_each_istep>0); - return; } // be called in MultiZeta::init(), reset the start temperature. -void Metropolis::reset_temperature(const int &istep) -{ - temperature = this->spi_ini_temp; - for(int i=0; ispi_ini_temp; + for (int i = 0; i < istep; i++) { + temperature *= 0.8; + // I think 0.8 is more reasonable than 0.1, mohan note, 2009-08-20 + } + return; } -void Metropolis::move_various_temperature( SpillageStep &Level) -{ - timer::tick("Metropolis","move_various_t"); - - // there are two parts of this algorithm, - // first part is about spillage, - // the second part is about kinetic energy. - - Simulated_Annealing_Orbital_Spillage sap(this,Level); - sap.set_temperature_num(this->spi_ntemp) - .set_step_num(this->spi_nsteps); - try - { - sap.cal_all_temperature(); - } - catch(File_Finish_Metropolis()) { return; } - - Simulated_Annealing_Orbital_Kinetic sak(this,Level); - sak.set_temperature_num(this->kin_ntemp) - .set_step_num(this->kin_nsteps); - try - { - sak.cal_all_temperature(); - } - catch(File_Finish_Metropolis()) { return; } - - timer::tick("Metropolis","move_various_t"); - return; +void Metropolis::move_various_temperature(SpillageStep& Level) { + timer::tick("Metropolis", "move_various_t"); + + // there are two parts of this algorithm, + // first part is about spillage, + // the second part is about kinetic energy. + + Simulated_Annealing_Orbital_Spillage sap(this, Level); + sap.set_temperature_num(this->spi_ntemp).set_step_num(this->spi_nsteps); + try { + sap.cal_all_temperature(); + } catch (File_Finish_Metropolis()) { + return; + } + + Simulated_Annealing_Orbital_Kinetic sak(this, Level); + sak.set_temperature_num(this->kin_ntemp).set_step_num(this->kin_nsteps); + try { + sak.cal_all_temperature(); + } catch (File_Finish_Metropolis()) { + return; + } + + timer::tick("Metropolis", "move_various_t"); + return; } \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis.h index bfad62267e0..2202c2d3f52 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis.h @@ -5,104 +5,99 @@ #include "Psi_Second.h" // use to calculaet oscillation #include "Metropolis_Info.h" -class Metropolis -{ - public: - Metropolis(); - ~Metropolis(); - - void init(void); - - void move_various_temperature(SpillageStep &SS); - - void move_one_step(const int &itemp, const int &istep, SpillageStep &Level, const int &nsteps_now); - - bool accept(const double &v_old, const double &v_new, const double &temperature_in); - - void reset_temperature(const int &istep); - - - // (1) start temperature - const double& get_spi_ini_temp(void) const {return spi_ini_temp;} - const double& get_kin_ini_temp(void) const {return kin_ini_temp;} - - // (2) cooling rate for each new temperature - const double& get_spi_rate(void) const { return spi_rate;} - const double& get_kin_rate(void) const { return kin_rate;} - - // (3) number of temperature - const int& get_spi_ntemp(void) const { return spi_ntemp;} - const int& get_kin_ntemp(void) const { return kin_ntemp;} - - // (4) number of steps in each temperature - const int& get_spi_nsteps(void) const { return spi_nsteps;} - const int& get_kin_nsteps(void) const { return kin_nsteps;} - - - Psi_Second Psi2; - - private: - - // (1) - double spi_ini_temp; // initial temperature for spillage. - double kin_ini_temp; // initial temperature for kinetic energy. - - // (2) - double spi_rate; // decrease rate for spillage value - double kin_rate; // decrease rate for kinetic energy - - // (3) - int spi_ntemp; // number of temperatures (for spillage) - int kin_ntemp; // number of temperatures (for kinetical energy) - - // (4) - int spi_nsteps; // number of steps per temperature for spillage - int kin_nsteps; // number of steps per temperature for kinetical energy - - - double temperature; - double kappa; // mohan add 2009-10-11 - double delta_kappa; // mohan add 2009-10-31 - int try_kappa; - - double min_spillage; // mohan add 2009-10-15 - double *kin_last; // mohan add 2009-10-15 - double *kin_temp; // mohan add 2009-10-15, temperature for each orbital. - int nchi; // mohan add 2009-10-15 - int output_each_istep; // mohan add 2009-10-16 - - double prob_new; - double prob_old; - - public: - int test; - int random_c4number; - - void preprocess_all_temperature(SpillageStep &Level); - void cout_1(size_t itemperature); - void file_finish_metropolis(size_t istep); - void update_t(void); - void change_accept_rate(size_t istep, SpillageStep &Level); - void reset_high_kinetic_energy(size_t itemperature,size_t istep); - void init_spi_states(size_t itemperature); - void cout_2(size_t itemperature, SpillageStep &Level); - void init_kin_states(); - void init_temperature_kinetic(size_t itemperature, SpillageStep &Level); - void ofs_1(size_t istep, SpillageStep &Level); - void norm_C4(size_t istep, SpillageStep &Level, size_t nsteps_now); - void small_jql(); - void trial_c4(); - double cal_spillage(SpillageStep &Level); - double cal_kinetic_energy(SpillageStep &Level); - void accept_process(SpillageStep &Level); - void reject_process(); - - Metropolis_Info info; - - private: - class Simulated_Annealing_Orbital; - class Simulated_Annealing_Orbital_Spillage; - class Simulated_Annealing_Orbital_Kinetic; +class Metropolis { + public: + Metropolis(); + ~Metropolis(); + + void init(void); + + void move_various_temperature(SpillageStep& SS); + + void move_one_step(const int& itemp, const int& istep, SpillageStep& Level, const int& nsteps_now); + + bool accept(const double& v_old, const double& v_new, const double& temperature_in); + + void reset_temperature(const int& istep); + + // (1) start temperature + const double& get_spi_ini_temp(void) const { return spi_ini_temp; } + const double& get_kin_ini_temp(void) const { return kin_ini_temp; } + + // (2) cooling rate for each new temperature + const double& get_spi_rate(void) const { return spi_rate; } + const double& get_kin_rate(void) const { return kin_rate; } + + // (3) number of temperature + const int& get_spi_ntemp(void) const { return spi_ntemp; } + const int& get_kin_ntemp(void) const { return kin_ntemp; } + + // (4) number of steps in each temperature + const int& get_spi_nsteps(void) const { return spi_nsteps; } + const int& get_kin_nsteps(void) const { return kin_nsteps; } + + Psi_Second Psi2; + + private: + // (1) + double spi_ini_temp; // initial temperature for spillage. + double kin_ini_temp; // initial temperature for kinetic energy. + + // (2) + double spi_rate; // decrease rate for spillage value + double kin_rate; // decrease rate for kinetic energy + + // (3) + int spi_ntemp; // number of temperatures (for spillage) + int kin_ntemp; // number of temperatures (for kinetical energy) + + // (4) + int spi_nsteps; // number of steps per temperature for spillage + int kin_nsteps; // number of steps per temperature for kinetical energy + + double temperature; + double kappa; // mohan add 2009-10-11 + double delta_kappa; // mohan add 2009-10-31 + int try_kappa; + + double min_spillage; // mohan add 2009-10-15 + double* kin_last; // mohan add 2009-10-15 + double* kin_temp; // mohan add 2009-10-15, temperature for each orbital. + int nchi; // mohan add 2009-10-15 + int output_each_istep; // mohan add 2009-10-16 + + double prob_new; + double prob_old; + + public: + int test; + int random_c4number; + + void preprocess_all_temperature(SpillageStep& Level); + void cout_1(size_t itemperature); + void file_finish_metropolis(size_t istep); + void update_t(void); + void change_accept_rate(size_t istep, SpillageStep& Level); + void reset_high_kinetic_energy(size_t itemperature, size_t istep); + void init_spi_states(size_t itemperature); + void cout_2(size_t itemperature, SpillageStep& Level); + void init_kin_states(); + void init_temperature_kinetic(size_t itemperature, SpillageStep& Level); + void ofs_1(size_t istep, SpillageStep& Level); + void norm_C4(size_t istep, SpillageStep& Level, size_t nsteps_now); + void small_jql(); + void trial_c4(); + double cal_spillage(SpillageStep& Level); + double cal_kinetic_energy(SpillageStep& Level); + void accept_process(SpillageStep& Level); + void reject_process(); + + Metropolis_Info info; + + private: + class Simulated_Annealing_Orbital; + class Simulated_Annealing_Orbital_Spillage; + class Simulated_Annealing_Orbital_Kinetic; }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis_2.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis_2.cpp index 05fc8a3f37c..af8f6f1c936 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis_2.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis_2.cpp @@ -4,499 +4,405 @@ #include #include -void Metropolis::preprocess_all_temperature(SpillageStep &Level) -{ - this->nchi = Level.nchi; - - // firstly, make the initia kappa value. - // mohan add 2009-11-12 - // this 0.001 must be added to the second step - // to avoid the oscillation of first orbital. - this->kappa = 1.0 + this->delta_kappa; - - delete[] this->kin_last; - this->kin_last = new double[nchi]; - ZEROS(this->kin_last, nchi); - - delete[] this->kin_temp; - this->kin_temp = new double[nchi]; - ZEROS(this->kin_temp, nchi); +void Metropolis::preprocess_all_temperature(SpillageStep& Level) { + this->nchi = Level.nchi; + + // firstly, make the initia kappa value. + // mohan add 2009-11-12 + // this 0.001 must be added to the second step + // to avoid the oscillation of first orbital. + this->kappa = 1.0 + this->delta_kappa; + + delete[] this->kin_last; + this->kin_last = new double[nchi]; + ZEROS(this->kin_last, nchi); + + delete[] this->kin_temp; + this->kin_temp = new double[nchi]; + ZEROS(this->kin_temp, nchi); } -void Metropolis::file_finish_metropolis(size_t istep) -{ - // P.S.: a method to quit this whole program. - // you only need to create a file name : FINISH - // another function: if there existep a file 'FINISH' - // in the current dir, the program quit at the first - // iteration. - // Here I choose a proper parameter: 500 steps, - // you can change on your own. - const int check_finish_file(500); - if( 0 == (istep%check_finish_file) ) - { - // mohan add 2009-08-28 - ifstream ifs("FINISH"); - if( ifs ) - { - throw File_Finish_Metropolis(); - } - } +void Metropolis::file_finish_metropolis(size_t istep) { + // P.S.: a method to quit this whole program. + // you only need to create a file name : FINISH + // another function: if there existep a file 'FINISH' + // in the current dir, the program quit at the first + // iteration. + // Here I choose a proper parameter: 500 steps, + // you can change on your own. + const int check_finish_file(500); + if (0 == (istep % check_finish_file)) { + // mohan add 2009-08-28 + ifstream ifs("FINISH"); + if (ifs) { + throw File_Finish_Metropolis(); + } + } } -void Metropolis::update_t(void) -{ - if(this->info.states == "Spi") - { - this->temperature *= this->spi_rate; -// cout << " New Temperature for spillage = " << temperature << endl; - } - else if(this->info.states == "Kin"||this->info.states=="Ecut") - { - // mohan add high 2009-11-05 - for(int ic=0; ic< this->nchi; ic++) - { - this->kin_temp[ic] *= this->kin_rate; - } - const double high = *max_element(this->kin_temp, this->kin_temp+this->nchi); - for(int ic=0; ic< this->nchi; ic++) - { - this->kin_temp[ic] = high; - ofs_running << setprecision(6) //<< setiosflags(ios::scientific) - << " Temperature for orbital " << ic+1 << " = " << kin_temp[ic] << endl; - } - - ofs_running << " new kappa=" << kappa << endl; - } - return; +void Metropolis::update_t(void) { + if (this->info.states == "Spi") { + this->temperature *= this->spi_rate; + // cout << " New Temperature for spillage = " << temperature << endl; + } else if (this->info.states == "Kin" || this->info.states == "Ecut") { + // mohan add high 2009-11-05 + for (int ic = 0; ic < this->nchi; ic++) { + this->kin_temp[ic] *= this->kin_rate; + } + const double high = *max_element(this->kin_temp, this->kin_temp + this->nchi); + for (int ic = 0; ic < this->nchi; ic++) { + this->kin_temp[ic] = high; + ofs_running << setprecision(6) //<< setiosflags(ios::scientific) + << " Temperature for orbital " << ic + 1 << " = " << kin_temp[ic] << endl; + } + + ofs_running << " new kappa=" << kappa << endl; + } + return; } -void Metropolis::change_accept_rate(size_t istep, SpillageStep &Level) -{ - // Here is the part about changing Metropolis algorithm's accept rate. - // we want to calculate the accept rate every 'ACCEPTANCE_STEPS' steps. - // but we don't want to calculate at istep=0; - if(istep%ACCEPTANCE_STEPS == 0) - { - if(istep>0) - { - for(int ic = 0; ic < this->nchi; ic++) - { - const int T = Level.wayc[ic].type; - const int L = Level.wayc[ic].L; - const int N = Level.wayc[ic].N; - for(int ie2=0; ie2 ACCEPTANCE_HIGH) - { - input.Coef.accept_rate(T,L,N,ie2) *= 2.0; // You can DIY 0.5 - } - else if(rate < ACCEPTANCE_LOW) - { - input.Coef.accept_rate(T,L,N,ie2) *= 0.5; // You can DIY 2.0 - } - // output information - //if(ie2%5==0) cout << "\n"; - //cout << setw(8) << rate*100 << "%"; - //cout << setw(8) << input.Coef.accept_rate(T,L,N,ie2); - } - } - } - input.Coef.accept_number.zero_out(); - } // end accept_rate -} - -void Metropolis::reset_high_kinetic_energy(size_t itemperature,size_t istep) -{ - // because the initia temperature may be too high - // which caused by the high kinetic energy, so - // we need to reset the temperature. - if( 0 == itemperature && 50 == istep ) - { - for(int ic=0; icnchi; ic++) - { - this->kin_temp[ic] = this->kin_last[ic] * this->kin_ini_temp; - } - const double high = *max_element(this->kin_temp, this->kin_temp+this->nchi); - for(int ic=0; icnchi; ic++) - { - this->kin_temp[ic] = high; - ofs_running << " Notice: Change temperature of orbital " << ic+1 << " to " << kin_temp[ic] << endl; - } - } +void Metropolis::change_accept_rate(size_t istep, SpillageStep& Level) { + // Here is the part about changing Metropolis algorithm's accept rate. + // we want to calculate the accept rate every 'ACCEPTANCE_STEPS' steps. + // but we don't want to calculate at istep=0; + if (istep % ACCEPTANCE_STEPS == 0) { + if (istep > 0) { + for (int ic = 0; ic < this->nchi; ic++) { + const int T = Level.wayc[ic].type; + const int L = Level.wayc[ic].L; + const int N = Level.wayc[ic].N; + for (int ie2 = 0; ie2 < Level.ne; ie2++) { + assert(input.Coef.accept_number(T, L, N, ie2) <= ACCEPTANCE_STEPS); + + const double rate = (double)input.Coef.accept_number(T, L, N, ie2) / (double)ACCEPTANCE_STEPS; + + if (rate > ACCEPTANCE_HIGH) { + input.Coef.accept_rate(T, L, N, ie2) *= 2.0; // You can DIY 0.5 + } else if (rate < ACCEPTANCE_LOW) { + input.Coef.accept_rate(T, L, N, ie2) *= 0.5; // You can DIY 2.0 + } + // output information + // if(ie2%5==0) cout << "\n"; + // cout << setw(8) << rate*100 << "%"; + // cout << setw(8) << input.Coef.accept_rate(T,L,N,ie2); + } + } + } + input.Coef.accept_number.zero_out(); + } // end accept_rate } -void Metropolis::init_spi_states(size_t itemperature) -{ - ofs_running << "\n" << " ---> SpillageTemp " << setw(3) << itemperature+1 << endl; - ofs_running << " Temperature " << setw(6) << this->temperature << endl; - this->info.states = "Spi"; - ofs_running << setw(5) << "STEPS" - << setw(20) << "SPILLAGE" - << setw(10) << "UPDATES" << endl; - - if(0==itemperature) - { - cout << setw(5) << "STEP" << setw(10) << "TEMP" - << setw(20) << "SPILLAGE" << endl; - } +void Metropolis::reset_high_kinetic_energy(size_t itemperature, size_t istep) { + // because the initia temperature may be too high + // which caused by the high kinetic energy, so + // we need to reset the temperature. + if (0 == itemperature && 50 == istep) { + for (int ic = 0; ic < this->nchi; ic++) { + this->kin_temp[ic] = this->kin_last[ic] * this->kin_ini_temp; + } + const double high = *max_element(this->kin_temp, this->kin_temp + this->nchi); + for (int ic = 0; ic < this->nchi; ic++) { + this->kin_temp[ic] = high; + ofs_running << " Notice: Change temperature of orbital " << ic + 1 << " to " << kin_temp[ic] << endl; + } + } } -void Metropolis::init_kin_states() -{ - // if the kinetic energy is not small enough, we try new kappa again. - //try_new_kappa_again: - // Please DIY, mohan 2010-04-14 - if(OPTIMIZE_METHOD==1) - { - this->info.states="Kin"; - } - else if(OPTIMIZE_METHOD==2) - { - this->info.states = "Ecut"; - } - else - { - WARNING_QUIT("move_various_temperature","Check OPTIMIZE_METHOD"); - } +void Metropolis::init_spi_states(size_t itemperature) { + ofs_running << "\n" + << " ---> SpillageTemp " << setw(3) << itemperature + 1 << endl; + ofs_running << " Temperature " << setw(6) << this->temperature << endl; + this->info.states = "Spi"; + ofs_running << setw(5) << "STEPS" << setw(20) << "SPILLAGE" << setw(10) << "UPDATES" << endl; + + if (0 == itemperature) { + cout << setw(5) << "STEP" << setw(10) << "TEMP" << setw(20) << "SPILLAGE" << endl; + } } -void Metropolis::init_temperature_kinetic(size_t itemperature, SpillageStep &Level) -{ - // set the initial temperature and kinetic energy value. - if(0==itemperature) - { - this->min_spillage = input.SV.cal_defined_value(0); // save the spillage value. - ofs_running << "\n\n Spillage at final temperature " << min_spillage << endl; - - for(int ic=0; icnchi; ic++) - { - const int T = Level.wayc[ic].type; - const int L = Level.wayc[ic].L; - const int N = Level.wayc[ic].N; - - double *c4_last = new double[Level.ne]; - for(int ie2=0; ie2kin_last[ic] = 0.0; - - if(this->info.states=="Kin") - { - for(int ie2=0; ie2kin_last[ic] += pow( c4_last[ie2]*(ie2+1)*PI/RCUT,2 ) - *this->Psi2.jjnorm(L,ie2); - } - } - else if(this->info.states=="Ecut") - { - this->kin_last[ic] = this->Psi2.get_ecut( c4_last, L ); - } - - // set the start temperature of kinetic part of Metropolis algorithms. - this->kin_temp[ic] = this->kin_last[ic] * this->kin_ini_temp; - - ofs_running << " Orbital " << ic+1 << " Initial E_kin " << setw(15) << this->kin_last[ic] << endl; - - delete[] c4_last; - } - } +void Metropolis::init_kin_states() { + // if the kinetic energy is not small enough, we try new kappa again. + // try_new_kappa_again: + // Please DIY, mohan 2010-04-14 + if (OPTIMIZE_METHOD == 1) { + this->info.states = "Kin"; + } else if (OPTIMIZE_METHOD == 2) { + this->info.states = "Ecut"; + } else { + WARNING_QUIT("move_various_temperature", "Check OPTIMIZE_METHOD"); + } } -void Metropolis::norm_C4(size_t istep, SpillageStep &Level, size_t nsteps_now) -{ - // because we choose c4 randomly between -0.1~0.1 - // so we need to normalize the set of c4 after a few - // steps, here I choose a proper number: 50 - // you can change on you own, but please notice it can't - // be too small, because we need to update all Q and S - // matrix after this normalization, which may affect the - // speed of the program. You can't choose too large, - // because it makes the update not efficient. - if ( (istep % 50 == 0 && istep !=0 ) || istep == nsteps_now-1) // Peize Lin test -// if ( (istep % 1 == 0 && istep !=0 ) || istep == nsteps_now-1) // Peize Lin test - { - // use to describe the real space mesh. - // don't need to choose too accuray, because - // it may affect the speed of running. - // you can change on your own, too. - double dr = 0.01; // a.u. - - // norm ic for all radial wave functions. - // after this call, all c4 will change/update. - // but the spillage will not change. - // (because we just normalize the wavefunctions). - - Calculate_C4::norm_ic( - input.Coef.C4, - input.Coef.accept_rate, // Peize Lin update 2015-12-24 - input.Coef.ntype, - input.Coef.lmax, - input.Coef.nmax, - input.Coef.enumber, - input.Coef.tolerence, - input.Coef.rcut, - dr); - - // get new set of C4, so we copy the set of C4 - // to C4_old. This will also not affect the - // spillage value. - input.Coef.copy_c4_to_old(); - - // for each structure, we need to update their - // Q matrix and S matrix, which may be time - // consuming. - for (int istr(0); istr < STRNUM; ++istr) - { - Level.init_QS_matrix(istr); - } - } +void Metropolis::init_temperature_kinetic(size_t itemperature, SpillageStep& Level) { + // set the initial temperature and kinetic energy value. + if (0 == itemperature) { + this->min_spillage = input.SV.cal_defined_value(0); // save the spillage value. + ofs_running << "\n\n Spillage at final temperature " << min_spillage << endl; + + for (int ic = 0; ic < this->nchi; ic++) { + const int T = Level.wayc[ic].type; + const int L = Level.wayc[ic].L; + const int N = Level.wayc[ic].N; + + double* c4_last = new double[Level.ne]; + for (int ie2 = 0; ie2 < Level.ne; ie2++) { + c4_last[ie2] = input.Coef.C4_old(T, L, N, ie2); + } + + this->kin_last[ic] = 0.0; + + if (this->info.states == "Kin") { + for (int ie2 = 0; ie2 < Level.ne; ie2++) { + this->kin_last[ic] += pow(c4_last[ie2] * (ie2 + 1) * PI / RCUT, 2) * this->Psi2.jjnorm(L, ie2); + } + } else if (this->info.states == "Ecut") { + this->kin_last[ic] = this->Psi2.get_ecut(c4_last, L); + } + + // set the start temperature of kinetic part of Metropolis algorithms. + this->kin_temp[ic] = this->kin_last[ic] * this->kin_ini_temp; + + ofs_running << " Orbital " << ic + 1 << " Initial E_kin " << setw(15) << this->kin_last[ic] << endl; + + delete[] c4_last; + } + } } -void Metropolis::small_jql() -{ - // mohan add 2009-08-26 - // this judgement means, - // If users don't want to use Jlq(ie) - // which is too oscillation(large), they - // can use only small part of Jlq. - // mohan add BLOCK_NE_MIN 2009-08-27 - if( (this->info.ieinfo.ie>=BLOCK_NE)) - throw Small_Jlq(); +void Metropolis::norm_C4(size_t istep, SpillageStep& Level, size_t nsteps_now) { + // because we choose c4 randomly between -0.1~0.1 + // so we need to normalize the set of c4 after a few + // steps, here I choose a proper number: 50 + // you can change on you own, but please notice it can't + // be too small, because we need to update all Q and S + // matrix after this normalization, which may affect the + // speed of the program. You can't choose too large, + // because it makes the update not efficient. + if ((istep % 50 == 0 && istep != 0) || istep == nsteps_now - 1) // Peize Lin test + // if ( (istep % 1 == 0 && istep !=0 ) || istep == nsteps_now-1) // Peize Lin test + { + // use to describe the real space mesh. + // don't need to choose too accuray, because + // it may affect the speed of running. + // you can change on your own, too. + double dr = 0.01; // a.u. + + // norm ic for all radial wave functions. + // after this call, all c4 will change/update. + // but the spillage will not change. + // (because we just normalize the wavefunctions). + + Calculate_C4::norm_ic(input.Coef.C4, + input.Coef.accept_rate, // Peize Lin update 2015-12-24 + input.Coef.ntype, + input.Coef.lmax, + input.Coef.nmax, + input.Coef.enumber, + input.Coef.tolerence, + input.Coef.rcut, + dr); + + // get new set of C4, so we copy the set of C4 + // to C4_old. This will also not affect the + // spillage value. + input.Coef.copy_c4_to_old(); + + // for each structure, we need to update their + // Q matrix and S matrix, which may be time + // consuming. + for (int istr(0); istr < STRNUM; ++istr) { + Level.init_QS_matrix(istr); + } + } } -void Metropolis::trial_c4() -{ - //======================================================== - // if we want to move step, we need the set of C4 from CS - // in single zeta, the C4 can be either read in or random, - // in double zeta, the C4 should start from random, in - // most cases. - //======================================================== - const int ie = this->info.ie; - const int T = this->info.T; - const int L = this->info.L; - const int N = this->info.N; - // trial a new value of c4(T,L,N). - input.Coef.trial_c4( T, L, N, ie); +void Metropolis::small_jql() { + // mohan add 2009-08-26 + // this judgement means, + // If users don't want to use Jlq(ie) + // which is too oscillation(large), they + // can use only small part of Jlq. + // mohan add BLOCK_NE_MIN 2009-08-27 + if ((this->info.ie < BLOCK_NE_MIN) || (this->info.ie >= BLOCK_NE)) + throw Small_Jlq(); } -double Metropolis::cal_spillage(SpillageStep &Level) -{ - const int ie = this->info.ie; - const int ic = this->info.ic; - for ( size_t istr = 0; istr < STRNUM; ++istr) - { - input.SV.value[istr] = Level.get_spillage(istr, ic, ie); - } - return input.SV.cal_defined_value(1); +void Metropolis::trial_c4() { + //======================================================== + // if we want to move step, we need the set of C4 from CS + // in single zeta, the C4 can be either read in or random, + // in double zeta, the C4 should start from random, in + // most cases. + //======================================================== + const int ie = this->info.ie; + const int T = this->info.T; + const int L = this->info.L; + const int N = this->info.N; + // trial a new value of c4(T,L,N). + input.Coef.trial_c4(T, L, N, ie); } -double Metropolis::cal_kinetic_energy(SpillageStep &Level) -{ - double *c4tmp = new double[Level.ne]; - - const int T = this->info.T; - const int L = this->info.L; - const int N = this->info.N; - for(int ie2=0; ie2info.states=="Kin") - { - // get the normalized parameters: c4 - this->Psi2.norm_c4( c4tmp, L ); - - // and then calculate the new set of kinetic energy. - for(int ie2=0; ie2Psi2.jjnorm(L,ie2);//In Rydberg Unit. - } - } - else if(this->info.states=="Ecut") - { - value2 = this->Psi2.get_ecut( c4tmp, L ); - } - delete[] c4tmp; - return value2; +double Metropolis::cal_spillage(SpillageStep& Level) { + const int ie = this->info.ie; + const int ic = this->info.ic; + for (size_t istr = 0; istr < STRNUM; ++istr) { + input.SV.value[istr] = Level.get_spillage(istr, ic, ie); + } + return input.SV.cal_defined_value(1); } -void Metropolis::accept_process(SpillageStep &Level) -{ - ++this->info.update_number; - - for (int istr = 0; istr< STRNUM; ++istr) - { - Level.updateQS( istr ); // (1) update Soverlap and Qoverlap for each structure, - // S matrix and Q matrix has changed due to the change of c4 - } - - input.SV.update_value();// (2) update spillage value - - for(int istr=0; istrPsi2.norm_c4(c4tmp, L); + + // and then calculate the new set of kinetic energy. + for (int ie2 = 0; ie2 < Level.ne; ie2++) { + value2 += pow(c4tmp[ie2] * (ie2 + 1) * PI / RCUT, 2) * this->Psi2.jjnorm(L, ie2); // In Rydberg Unit. + } + } else if (this->info.states == "Ecut") { + value2 = this->Psi2.get_ecut(c4tmp, L); + } + delete[] c4tmp; + return value2; } -void Metropolis::reject_process() -{ - const int ie = this->info.ie; - const int T = this->info.T; - const int L = this->info.L; - const int N = this->info.N; - input.Coef.go_back_c4( T, L, N, ie ); +void Metropolis::accept_process(SpillageStep& Level) { + ++this->info.update_number; + + for (int istr = 0; istr < STRNUM; ++istr) { + Level.updateQS(istr); // (1) update Soverlap and Qoverlap for each structure, + // S matrix and Q matrix has changed due to the change of c4 + } + + input.SV.update_value(); // (2) update spillage value + + for (int istr = 0; istr < STRNUM; istr++) { + Level.data[istr].Mkb = Level.data[istr].Mkb_used; // (2.5) mohan add 2010-05-02 + + /* + for(int ik=0; ikinfo.update_number << endl; - - // output each structure's spillage value. - // for(int is=0; is< input.str_num; is++) - // { - // cout << setw(10) << input.SV.value_old[is]*100 << "%"; - // } - } - else if(this->info.states=="Kin"||this->info.states=="Ecut") - { - //<< " ----> " << states << "Temp " << setw(15) - //<< istep+1 << "\n" ; -// << " SpiVal" -// << setprecision(6) -// << setiosflags(ios::fixed) -// << setw(15) << input.SV.cal_defined_value(0); - for(int ic=0; ic< this->nchi; ic++) - { - ofs_running << setw(4) << istep+1 << Level.wayc[ic].spd; - - ofs_running << setprecision(3) - << setiosflags(ios::scientific) - << setw(10)<< this->kin_temp[ic] - << resetiosflags(ios::scientific); - - ofs_running << setprecision(10) - << setiosflags(ios::fixed) - << setw(20)<< this->kin_last[ic] << endl - << resetiosflags(ios::fixed); - } - } - } +void Metropolis::reject_process() { + const int ie = this->info.ie; + const int T = this->info.T; + const int L = this->info.L; + const int N = this->info.N; + input.Coef.go_back_c4(T, L, N, ie); } -void Metropolis::cout_1(size_t itemperature) -{ - cout << setw(5) << itemperature+1 - << setiosflags(ios::showpoint) - << setiosflags(ios::scientific) - << setprecision(3) - << setw(10) - << this->temperature - << resetiosflags(ios::scientific) - << setiosflags(ios::fixed) - << setprecision(10) - << setw(19) - << input.SV.cal_defined_value(0)*100 << "%" - << resetiosflags(ios::fixed) - << resetiosflags(ios::showpoint) - << endl; +void Metropolis::ofs_1(size_t istep, SpillageStep& Level) { + if (0 == (istep % this->output_each_istep)) { + if (this->info.states == "Spi") { + ofs_running << setw(5) << istep + 1 << setprecision(10) << setiosflags(ios::fixed) << setw(20) + << input.SV.cal_defined_value(0) << setw(10) << this->info.update_number << endl; + + // output each structure's spillage value. + // for(int is=0; is< input.str_num; is++) + // { + // cout << setw(10) << input.SV.value_old[is]*100 << "%"; + // } + } else if (this->info.states == "Kin" || this->info.states == "Ecut") { + //<< " ----> " << states << "Temp " << setw(15) + //<< istep+1 << "\n" ; + // << " SpiVal" + // << setprecision(6) + // << setiosflags(ios::fixed) + // << setw(15) << input.SV.cal_defined_value(0); + for (int ic = 0; ic < this->nchi; ic++) { + ofs_running << setw(4) << istep + 1 << Level.wayc[ic].spd; + + ofs_running << setprecision(3) << setiosflags(ios::scientific) << setw(10) << this->kin_temp[ic] + << resetiosflags(ios::scientific); + + ofs_running << setprecision(10) << setiosflags(ios::fixed) << setw(20) << this->kin_last[ic] << endl + << resetiosflags(ios::fixed); + } + } + } } -void Metropolis::cout_2(size_t itemperature, SpillageStep &Level) -{ - //------------------------------------------- - // it's about minimizing kinetic energy. - //------------------------------------------- - for(int ic=0; icnchi; ic++) - { - cout << setw(5) << Level.wayc[ic].spd; - cout << setiosflags(ios::showpoint) - << setiosflags(ios::scientific) - << setprecision(3) - << setw(10)<< this->kin_temp[ic] - << resetiosflags(ios::scientific); - cout << setprecision(10) - << setiosflags(ios::fixed) - << setw(20)<< this->kin_last[ic] - << resetiosflags(ios::fixed) - << resetiosflags(ios::showpoint) - << endl; - } - - for(int ic=0; icnchi; ic++) - { - if(this->kin_last[ic] > KINETIC_MAX) - { - cout << "\n kin_last[" << ic << "]=" << kin_last[ic] << " KINETIC_MAX = " << KINETIC_MAX << endl; - cout << " There maybe 2 reasons, first: The starting temperature for kinetical energy is too small." << endl; - cout << " Second: The kappa is too small." << endl; - //WARNING_QUIT("Minimizing Kinetic Energy","Kinetical Energy Too Large!"); - cout << "Kinetical Energy Too Large!"<kappa += this->delta_kappa; - //goto try_new_kappa_again; - } +void Metropolis::cout_1(size_t itemperature) { + cout << setw(5) << itemperature + 1 << setiosflags(ios::showpoint) << setiosflags(ios::scientific) + << setprecision(3) << setw(10) << this->temperature << resetiosflags(ios::scientific) + << setiosflags(ios::fixed) << setprecision(10) << setw(19) << input.SV.cal_defined_value(0) * 100 << "%" + << resetiosflags(ios::fixed) << resetiosflags(ios::showpoint) << endl; } +void Metropolis::cout_2(size_t itemperature, SpillageStep& Level) { + //------------------------------------------- + // it's about minimizing kinetic energy. + //------------------------------------------- + for (int ic = 0; ic < this->nchi; ic++) { + cout << setw(5) << Level.wayc[ic].spd; + cout << setiosflags(ios::showpoint) << setiosflags(ios::scientific) << setprecision(3) << setw(10) + << this->kin_temp[ic] << resetiosflags(ios::scientific); + cout << setprecision(10) << setiosflags(ios::fixed) << setw(20) << this->kin_last[ic] + << resetiosflags(ios::fixed) << resetiosflags(ios::showpoint) << endl; + } + + for (int ic = 0; ic < this->nchi; ic++) { + if (this->kin_last[ic] > KINETIC_MAX) { + cout << "\n kin_last[" << ic << "]=" << kin_last[ic] << " KINETIC_MAX = " << KINETIC_MAX << endl; + cout << " There maybe 2 reasons, first: The starting temperature for kinetical energy is too small." + << endl; + cout << " Second: The kappa is too small." << endl; + // WARNING_QUIT("Minimizing Kinetic Energy","Kinetical Energy Too Large!"); + cout << "Kinetical Energy Too Large!" << endl; + } + // this->kappa += this->delta_kappa; + // goto try_new_kappa_again; + } +} diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis_Info.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis_Info.h index 0caddd3d379..479fd0fa191 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis_Info.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Metropolis_Info.h @@ -1,30 +1,37 @@ #ifndef METROPOLIS_INFO_H #define METROPOLIS_INFO_H -struct Metropolis_Info -{ - int ie; - int ic; - int T; - int L; - int N; - int update_number; - string states; // mohan add 2009-10-15 +struct Metropolis_Info { + int ie; + int ic; + int T; + int L; + int N; + int update_number; + string states; // mohan add 2009-10-15 - Metropolis_Info &set_ie(int ie_in){ ie = ie_in; return *this;} - Metropolis_Info &set_ic(int ic_in){ ic = ic_in; return *this;} - Metropolis_Info &set_update_number(int update_number_in){ update_number = update_number_in; return *this;} + Metropolis_Info& set_ie(int ie_in) { + ie = ie_in; + return *this; + } + Metropolis_Info& set_ic(int ic_in) { + ic = ic_in; + return *this; + } + Metropolis_Info& set_update_number(int update_number_in) { + update_number = update_number_in; + return *this; + } - void unpack_ic(SpillageStep &Level) - { - T = Level.wayc[ic].type; - L = Level.wayc[ic].L; - N = Level.wayc[ic].N; - } + void unpack_ic(SpillageStep& Level) { + T = Level.wayc[ic].type; + L = Level.wayc[ic].L; + N = Level.wayc[ic].N; + } }; -class File_Finish_Metropolis: public exception{}; +class File_Finish_Metropolis : public exception {}; -class Small_Jlq: public exception{}; +class Small_Jlq : public exception {}; #endif \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/MultiZeta.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/MultiZeta.cpp index 17f4088e35d..b86022aac24 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/MultiZeta.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/MultiZeta.cpp @@ -4,72 +4,62 @@ #include "../src_parallel/parallel_common.h" #include "tools.h" -//Peize Lin test +// Peize Lin test #include "../src_tools/complexmatrix_inline.h" #include "../src_unittest/src_tools/common_test.h" -MultiZeta::MultiZeta() -{ +MultiZeta::MultiZeta() { test = 0; // output function name Level = new SpillageStep[1]; lmax_type = new int[1]; } -MultiZeta::~MultiZeta() -{ +MultiZeta::~MultiZeta() { delete[] Level; delete[] lmax_type; } // be called in main.cpp program. -void MultiZeta::init(void) -{ - TITLE(ofs_running,"MultiZeta","init"); +void MultiZeta::init(void) { + TITLE(ofs_running, "MultiZeta", "init"); //============================= // nlevel : optimization levels //============================= - for (int is=0; isilevel = is+1;// 0 means level 1. + this->ilevel = is + 1; // 0 means level 1. // mohan add 2009-09-25 - //input.Coef.accumulate_num_zero(); + // input.Coef.accumulate_num_zero(); // if start temperature is different for each level // ( I don't think this is a very good idea for high level orbitals!! // mohan note:2009-8-20, it's better to make temperature from "high enough" to // "low enough" for each level) - metro.reset_temperature( is ); + metro.reset_temperature(is); this->Level[is].ilevel = is; this->Level[is].set_nchi(); this->Level[is].set_nwfc(); - this->Level[is].set_iw00();// to get Sq1q2 - this->Level[is].allocate_data( 0 ); // to get Qin - + this->Level[is].set_iw00(); // to get Sq1q2 + this->Level[is].allocate_data(0); // to get Qin // if is=0, means it's the first time, spillage0 = 1.0; - if (is==0) - { - for (int istr=0; istrLevel[is].data[istr].spillage0 = 1.0; } - } - else if (is>0) - { - for (int istr=0; istr 0) { + for (int istr = 0; istr < STRNUM; istr++) { this->Level[is].data[istr].spillage0 = input.SV.value_old[istr]; } cout << "\n Orthogonal......." << endl; @@ -78,17 +68,15 @@ void MultiZeta::init(void) // (2): Orthogonal to get new Bloch space! // This subroutine is very important. //**************************************** - Orth.start( this->Level[is-1], this->Level[is] ); + Orth.start(this->Level[is - 1], this->Level[is]); } - if(USEPW) - { - PW.allocate_psi1d(is); - PW.allocate_psi3d(is); - } + if (USEPW) { + PW.allocate_psi1d(is); + PW.allocate_psi3d(is); + } - for (int istr=0; istrLevel[is].data[istr].initQS(); this->Level[is].init_QS_matrix(istr); input.SV.value_old[istr] = this->Level[is].get_spillage(istr, 0, 0); @@ -102,75 +90,69 @@ void MultiZeta::init(void) //******************************************************************* // main part: Use Metropolis algorithm, move different temperature, //******************************************************************* - this->metro.move_various_temperature( this->Level[is]); - + this->metro.move_various_temperature(this->Level[is]); + // save spillage value for each level input.SV.save_level(is); this->saveC(); -// Peize Lin test -for ( size_t istr = 0; istr < STRNUM; ++istr) -{ - Step_Data* Stru = &this->Level[is].data[istr]; - for (int ik = 0; ik < Stru->nks ; ik++) - { - //cout<<"ik:\t"<Strial[ik]); - //cout_matrix( Stru->inverse_S[ik].get_inverse()); - for( size_t i=0; iStrial[ik].nr; ++i) - for( size_t j=0; jStrial[ik](i,j) = conj(Stru->Strial[ik](j,i)); - ComplexMatrix inverse_tmp(Stru->inverse_S[ik].get_inverse()); - for( size_t i=0; iStrial[ik] * inverse_tmp); - } -} + // Peize Lin test + for (size_t istr = 0; istr < STRNUM; ++istr) { + Step_Data* Stru = &this->Level[is].data[istr]; + for (int ik = 0; ik < Stru->nks; ik++) { + // cout<<"ik:\t"<Strial[ik]); + // cout_matrix( Stru->inverse_S[ik].get_inverse()); + for (size_t i = 0; i < Stru->Strial[ik].nr; ++i) + for (size_t j = 0; j < i; ++j) + Stru->Strial[ik](i, j) = conj(Stru->Strial[ik](j, i)); + ComplexMatrix inverse_tmp(Stru->inverse_S[ik].get_inverse()); + for (size_t i = 0; i < inverse_tmp.nr; ++i) + for (size_t j = 0; j < i; ++j) + inverse_tmp(i, j) = conj(inverse_tmp(j, i)); + // cout_matrix( Stru->Strial[ik] * inverse_tmp); + } + } } - return;; + return; + ; } - - // read in paramters from BLOCK , called by MultiZeta::init(); -void MultiZeta::set_levels(void) -{ - TITLE(ofs_running,"MultiZeta","set_levels"); +void MultiZeta::set_levels(void) { + TITLE(ofs_running, "MultiZeta", "set_levels"); - bool begin = false; + bool begin = false; - if(MY_RANK==0) - { - if ( SCAN_BEGIN(input.ifs, "") ) begin = true; - } + if (MY_RANK == 0) { + if (SCAN_BEGIN(input.ifs, "")) + begin = true; + } #ifdef __MPI - Parallel_Common::bcast_bool(begin); + Parallel_Common::bcast_bool(begin); #endif // read in parameters in BLOCK : 'OPTIMIZE' - if ( begin ) - { + if (begin) { // (1) read in important parameter: nlevel. // nlevel means the number of orbital shells we need. - - if(MY_RANK==0) - { - READ_VALUE(input.ifs, this->nlevel); - assert(nlevel>-1); - assert(nlevel<100); - } - -#ifdef __MPI - Parallel_Common::bcast_int(nlevel); + + if (MY_RANK == 0) { + READ_VALUE(input.ifs, this->nlevel); + assert(nlevel > -1); + assert(nlevel < 100); + } + +#ifdef __MPI + Parallel_Common::bcast_int(nlevel); #endif - + input.nlevel = this->nlevel; // mohan add 2009-06-09 -// cout << " nlevel = " << nlevel << endl; - OUT(ofs_running,"nlevel",nlevel); + // cout << " nlevel = " << nlevel << endl; + OUT(ofs_running, "nlevel", nlevel); // (2) init 'SpillageStep' class, each level has // different parameters. @@ -179,73 +161,65 @@ void MultiZeta::set_levels(void) string useless; - if(MY_RANK==0) - { - READ_VALUE(input.ifs, useless); - } + if (MY_RANK == 0) { + READ_VALUE(input.ifs, useless); + } #ifdef __MPI - Parallel_Common::bcast_string(useless); + Parallel_Common::bcast_string(useless); #endif // (3) read in information concerning each level. - for (int i=0; i>>>> Level=" << i+1 ; + for (int i = 0; i < nlevel; i++) { + ofs_running << "\n >>>>> Level=" << i + 1; this->Level[i].set_info(NTYPE); - for (int it=0; it> Level[i].info[it].id //id for this type - >> Level[i].info[it].na //number of atoms. - >> Level[i].info[it].state// new or skip, mohan 2009-08-27 - >> Level[i].info[it].lmax;//lmax in this level - } + + if (MY_RANK == 0) { + input.ifs >> Level[i].info[it].id // id for this type + >> Level[i].info[it].na // number of atoms. + >> Level[i].info[it].state // new or skip, mohan 2009-08-27 + >> Level[i].info[it].lmax; // lmax in this level + } #ifdef __MPI - Parallel_Common::bcast_int(Level[i].info[it].id); - Parallel_Common::bcast_int(Level[i].info[it].na); - Parallel_Common::bcast_string(Level[i].info[it].state); - Parallel_Common::bcast_int(Level[i].info[it].lmax); + Parallel_Common::bcast_int(Level[i].info[it].id); + Parallel_Common::bcast_int(Level[i].info[it].na); + Parallel_Common::bcast_string(Level[i].info[it].state); + Parallel_Common::bcast_int(Level[i].info[it].lmax); #endif - if (!RESTART && Level[i].info[it].state=="skip") - { + if (!RESTART && Level[i].info[it].state == "skip") { ofs_running << "\n Level = " << i; ofs_running << "\n it = " << it; - WARNING_QUIT("MultiZeta::set_levels","skip is not available if RESTART = false."); + WARNING_QUIT("MultiZeta::set_levels", "skip is not available if RESTART = false."); } - if ( Level[i].info[it].state!="new" && Level[i].info[it].state!="skip") - { + if (Level[i].info[it].state != "new" && Level[i].info[it].state != "skip") { ofs_running << "\n Level = " << i; ofs_running << "\n it = " << it; ofs_running << "\n state = " << Level[i].info[it].state << endl; - WARNING_QUIT("MultiZeta::set_levels","new or skip?"); + WARNING_QUIT("MultiZeta::set_levels", "new or skip?"); } ofs_running << "\n id=" << Level[i].info[it].id; ofs_running << " na=" << Level[i].info[it].na; ofs_running << " lmax=" << Level[i].info[it].lmax; - if(Level[i].info[it].id==0) - { - ofs_running << " The id of elements should be numbers!" << endl; - ofs_running << " check the id of elements." << endl; - WARNING_QUIT("MultiZeta::set_levels","id=0"); - } + if (Level[i].info[it].id == 0) { + ofs_running << " The id of elements should be numbers!" << endl; + ofs_running << " check the id of elements." << endl; + WARNING_QUIT("MultiZeta::set_levels", "id=0"); + } // lmax=0(s), 1(p), 2(d), 3(f), 4(g) - if (Level[i].info[it].lmax>=5 || Level[i].info[it].lmax<0) - { + if (Level[i].info[it].lmax >= 5 || Level[i].info[it].lmax < 0) { ofs_running << "\n lmax=" << Level[i].info[it].lmax << endl; - WARNING_QUIT("MultiZeta::set_levels"," lmax out of range."); + WARNING_QUIT("MultiZeta::set_levels", " lmax out of range."); } // 'info' stands for "Type_Information" @@ -253,11 +227,10 @@ void MultiZeta::set_levels(void) // allocate Level[i].info[it].init(); - for (int L=0; L>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - // read in nchi for each L and full/average orbital. + // read in nchi for each L and full/average orbital. int nz; string fain; string combine; @@ -266,30 +239,28 @@ void MultiZeta::set_levels(void) input.ifs >> combine; #ifdef __MPI - Parallel_Common::bcast_string(combine); + Parallel_Common::bcast_string(combine); #endif - - //ofs_running << "\n lenght = " << combine.length() << endl; + + // ofs_running << "\n lenght = " << combine.length() << endl; // firstly, we need to find the position of the label: '/' const int index1 = combine.find_first_of("/"); - //ofs_running << "\n index1 = " << index1 << endl; + // ofs_running << "\n index1 = " << index1 << endl; // if index1==-1, means the combine didn't contain // '/' label - if (index1 == -1) - { + if (index1 == -1) { // f stands for 'full' fain = "f"; // this 'atoi' command change string to int type. - nz = std::atoi( combine.c_str() ); - } - else // mean containing "/" + nz = std::atoi(combine.c_str()); + } else // mean containing "/" { - nz = std::atoi( combine.substr(0,index1+1).c_str() ); + nz = std::atoi(combine.substr(0, index1 + 1).c_str()); // substrate the front int and remain the character. // the second parameter '1' means the position is 'index+2' - fain = combine.substr(index1+1, 1); + fain = combine.substr(index1 + 1, 1); } ofs_running << "\n L=" << L; @@ -299,7 +270,7 @@ void MultiZeta::set_levels(void) // assert number of zeta < 20, you can change on your own, // typically, we only need nz=2 or 3. - assert( nz < 20 ); + assert(nz < 20); Level[i].info[it].n[L] = nz; Level[i].info[it].fa[L] = fain; @@ -310,37 +281,30 @@ void MultiZeta::set_levels(void) // (hard to understand, right? Try to figure out!) // this parameter is very useful. // nbase provide a base to count radial wave functions. - if (i==0) - { + if (i == 0) { Level[i].info[it].nbase[L] = 0; - } - else if (i>0) - { - for (int j=0; j 0) { + for (int j = 0; j < i; j++) { + if (L < Level[j].info[it].lmax + 1) { Level[i].info[it].nbase[L] = Level[j].info[it].nbase[L] + Level[j].info[it].n[L]; } } } - ofs_running << " start_n(" << L << ")=" << Level[i].info[it].nbase[L]+1; - }// end L + ofs_running << " start_n(" << L << ")=" << Level[i].info[it].nbase[L] + 1; + } // end L Level[i].info[it].cal_nmax(); ofs_running << endl; - }// end Type - }// end Level - }// end + } // end Type + } // end Level + } // end return; } - // be called by MultiZeta::init() -void MultiZeta::cal_lmax_nmax(void) -{ - TITLE(ofs_running,"MultZeta","cal_lmax_nmax"); +void MultiZeta::cal_lmax_nmax(void) { + TITLE(ofs_running, "MultZeta", "cal_lmax_nmax"); //==================================== // (1) calculate LMAXUSED and NMAXUSED //==================================== @@ -353,29 +317,24 @@ void MultiZeta::cal_lmax_nmax(void) // in all levels. delete[] lmax_type; this->lmax_type = new int[NTYPE]; - for (int it=0; itlmax_type[it] = -1; } // sum information from all levels. - NMAXUSED = 0; - for (int k=0; knlevel; k++) - { - for (int it=0; it< NTYPE; it++) - { - this->lmax_type[it] = std::max( this->lmax_type[it], this->Level[k].info[it].lmax ); - LMAXUSED = std::max( LMAXUSED, this->lmax_type[it] ); - NMAXUSED = std::max( NMAXUSED, this->Level[k].info[it].nmax ); + NMAXUSED = 0; + for (int k = 0; k < this->nlevel; k++) { + for (int it = 0; it < NTYPE; it++) { + this->lmax_type[it] = std::max(this->lmax_type[it], this->Level[k].info[it].lmax); + LMAXUSED = std::max(LMAXUSED, this->lmax_type[it]); + NMAXUSED = std::max(NMAXUSED, this->Level[k].info[it].nmax); } } // for test. - if (test==2) - { - for (int it=0; it *sum = new std::complex[nbands]; - for (int iw=0; iw first_part = std::complex(0,0); - if(USEPW) - { - const int Mmu = step1.wayd[mu].m; - const int Imu = step1.wayd[mu].i; - PW.calculate_Jlq(ik,iw,ie); - first_part = PW.calculate_Jlq_Phi(ik,mu); - - // if( norm(first_part) > 0.1 ) - // { - // cout << "\n iw=" << iw << " ie=" << ie << " mu=" << mu << " first_part=" << first_part; - // BLOCK_HERE("haha"); - // } - } - else - { - for (int iemu=0; iemu* sum = new std::complex[nbands]; + for (int iw = 0; iw < nwfc_all; iw++) { + for (int ie = 0; ie < ne; ie++) { + ZEROS(sum, nbands); + for (int mu = 0; mu < nwfc2; mu++) { + const int Tmu = step1.wayd[mu].type; + const int Lmu = step1.wayd[mu].L; + const int Nmu = step1.wayd[mu].N; + const int iw00 = step1.wayd[mu].iw00; + + std::complex first_part = std::complex(0, 0); + if (USEPW) { + const int Mmu = step1.wayd[mu].m; + const int Imu = step1.wayd[mu].i; + PW.calculate_Jlq(ik, iw, ie); + first_part = PW.calculate_Jlq_Phi(ik, mu); + + // if( norm(first_part) > 0.1 ) + // { + // cout << "\n iw=" << iw << " ie=" << ie << " mu=" << mu << " first_part=" << + // first_part; BLOCK_HERE("haha"); + // } + } else { + for (int iemu = 0; iemu < ne; iemu++) { + first_part += input.Coef.C4(Tmu, Lmu, Nmu, iemu) * + input.QS_data[istr].Sq1q2[ik](iw, iw00, ie, iemu); } } - for (int ib=0; ib sum = std::complex(0,0); - for(int mu=0; mu first_part = std::complex(0,0); - - for(int iemu=0; iemu sum = std::complex(0,0); + for(int mu=0; mu first_part = std::complex(0,0); + + for(int iemu=0; iemuversion_information( ofs ); - this->INPUTs_information( ofs ); - this->spillage_information( ofs, mz.ilevel ); - this->metropolis_information( ofs); - this->c4_information( ofs ); - } - this->mkb_information( ofs); + if (MY_RANK == 0) { + ofs.open("ORBITAL_RESULTS.txt"); + this->version_information(ofs); + this->INPUTs_information(ofs); + this->spillage_information(ofs, mz.ilevel); + this->metropolis_information(ofs); + this->c4_information(ofs); + } + this->mkb_information(ofs); - if(MY_RANK==0) - { - ofs.close(); - } + if (MY_RANK == 0) { + ofs.close(); + } - return; + return; } -void Out_Orbital::version_information( ofstream &ofs ) -{ +void Out_Orbital::version_information(ofstream& ofs) { ofs << "\n "; ofs << "\n AUTHOR : Mohan Chen"; ofs << "\n StartDate : 2009-4-01"; - ofs << "\n LastModify: 2012-6-27"; + ofs << "\n LastModify: 2012-6-27"; ofs << "\n LOCATION : LQCC, Hefei, China"; ofs << "\n EMAIL : mohan@mail.ustc.edu.cn"; ofs << "\n Description : Calculate the coefficients C4 of f(r) in Spherical Bessel Basis J(qr)."; @@ -45,199 +41,168 @@ void Out_Orbital::version_information( ofstream &ofs ) ofs << "\n"; } -void Out_Orbital::INPUTs_information( ofstream &ofs ) -{ +void Out_Orbital::INPUTs_information(ofstream& ofs) { ofs << "\n\n"; ofs << "\n" << setw(20) << ECUT << " Energy cutoff(Hartree.)."; ofs << "\n" << setw(20) << RCUT << " rcut (a.u.)"; ofs << "\n" << setw(20) << NE << " eigenvalue number( sqrt(ecut*2)*rcut/PI )."; ofs << "\n" << setw(20) << TOLERENCE << " tolerence to calculate eigenvalue."; - ofs << "\n" << setw(20) << NTYPE << " Number of atom types."; - for(int it=0; it"; } -void Out_Orbital::spillage_information( ofstream &ofs, const int &ilevel) -{ - ofs << "\n\n"; - ofs << "\n" << setw(20) << STRNUM << " kinds of structures."; - - // (1) mohan add average information 2010-04-11 - ofs << "\nAverage Spillage Value"; - for(int k=0; k"; - ofs << resetiosflags(ios::scientific); - return; +void Out_Orbital::spillage_information(ofstream& ofs, const int& ilevel) { + ofs << "\n\n"; + ofs << "\n" << setw(20) << STRNUM << " kinds of structures."; + + // (1) mohan add average information 2010-04-11 + ofs << "\nAverage Spillage Value"; + for (int k = 0; k < ilevel; k++) { + double average = 0.0; + for (int i = 0; i < STRNUM; i++) { + average += input.SV.value_each_level(i, k); + } + ofs << "\n " << setw(8) << k + 1 << setiosflags(ios::scientific) << setprecision(6) << setw(20) + << average / STRNUM; + } + + // (2) SV stands for 'spillage value' + // value_old containing the newest accepted spillage value. + for (int i = 0; i < STRNUM; i++) { + ofs << "\nStructureIndex " << i + 1; + for (int k = 0; k < ilevel; k++) { + ofs << "\n " << setw(8) << k + 1 << setiosflags(ios::scientific) << setprecision(6) << setw(20) + << input.SV.value_each_level(i, k); + } + } + ofs << "\n"; + ofs << resetiosflags(ios::scientific); + return; } -void Out_Orbital::metropolis_information( ofstream &ofs) -{ - ofs << "\n\n"; - ofs << "\n" << setw(20) << mz.metro.get_spi_ini_temp() << " Start temperature (Kelvin) for spillage minimization."; - ofs << "\n" << setw(20) << mz.metro.get_spi_rate() << " Decreasing rate of temperature."; - ofs << "\n" << setw(20) << mz.metro.get_spi_ntemp() << " Number of different temperature (for spillage)."; - ofs << "\n" << setw(20) << mz.metro.get_spi_nsteps() << " Number of steps for each temperature (for spillage)."; - - ofs << "\n" << setw(20) << mz.metro.get_kin_ini_temp() << " Start temperature (Kelvin) for kinetical energy minimization."; - ofs << "\n" << setw(20) << mz.metro.get_kin_rate() << " Decreasing rate of temperature."; - ofs << "\n" << setw(20) << mz.metro.get_kin_ntemp() << " Number of different temperature (for kinetical)."; - ofs << "\n" << setw(20) << mz.metro.get_kin_nsteps() << " Number of steps for each temperature (for kineitcal)."; - ofs << "\n"; +void Out_Orbital::metropolis_information(ofstream& ofs) { + ofs << "\n\n"; + ofs << "\n" << setw(20) << mz.metro.get_spi_ini_temp() << " Start temperature (Kelvin) for spillage minimization."; + ofs << "\n" << setw(20) << mz.metro.get_spi_rate() << " Decreasing rate of temperature."; + ofs << "\n" << setw(20) << mz.metro.get_spi_ntemp() << " Number of different temperature (for spillage)."; + ofs << "\n" << setw(20) << mz.metro.get_spi_nsteps() << " Number of steps for each temperature (for spillage)."; + + ofs << "\n" + << setw(20) << mz.metro.get_kin_ini_temp() << " Start temperature (Kelvin) for kinetical energy minimization."; + ofs << "\n" << setw(20) << mz.metro.get_kin_rate() << " Decreasing rate of temperature."; + ofs << "\n" << setw(20) << mz.metro.get_kin_ntemp() << " Number of different temperature (for kinetical)."; + ofs << "\n" << setw(20) << mz.metro.get_kin_nsteps() << " Number of steps for each temperature (for kineitcal)."; + ofs << "\n"; } -void Out_Orbital::c4_information( ofstream &ofs) -{ - ofs << "\n\n"; - ofs << "\n" << setw(20) << NCHIUSED << " Total number of radial orbitals."; - - // use multize parameters: ntype, *lmax_type, l_nchi, ne; - for(int it=0; it"; - return; +void Out_Orbital::c4_information(ofstream& ofs) { + ofs << "\n\n"; + ofs << "\n" << setw(20) << NCHIUSED << " Total number of radial orbitals."; + + // use multize parameters: ntype, *lmax_type, l_nchi, ne; + for (int it = 0; it < NTYPE; it++) { + for (int L = 0; L < mz.lmax_type[it] + 1; L++) { + // last step, nmax is different if L is different + for (int N = 0; N < mz.l_nchi(it, L); N++) { + ofs << "\n" << setw(20) << "Type" << setw(20) << "L" << setw(20) << "Zeta-Orbital"; + ofs << "\n" << setw(20) << it + 1 << setw(20) << L << setw(20) << N + 1; + for (int ie = 0; ie < mz.Level[0].ne; ie++) { + if (ie % 4 == 0) + ofs << endl; + // mohan modify 2009-09-25 + // ofs << setw(20) << input.Coef.C4_accumulate(it, L, N, ie); + ofs << setw(25) << setiosflags(ios::showpoint) << setiosflags(ios::scientific) << setprecision(15) + << input.Coef.C4_old(it, L, N, ie); + } + } + } + } + ofs << "\n"; + return; } -void Out_Orbital::mkb_information( ofstream &ofs) -{ - ofs_running << "\n mkb_information." << endl; - if(MY_RANK==0) - { - ofs << "\n\n"; - ofs << "\n" << setw(20) << mz.nlevel << " Total number of orbitals optimized levels." ; - } - - double sum0 = 0.0; - double *sum1 = new double[NBANDS]; - ZEROS(sum1, NBANDS); - - int bands_start; - int bands_end; - int bands_number; - - if (BANDS_CONTROL) - { - bands_start = BANDS_START; - bands_end = BANDS_END; - bands_number = bands_end - bands_start; - } - else - { - bands_start = 0; - bands_end = NBANDS; - bands_number = bands_end - bands_start; - } - - ofs << "\nBands start from " << bands_start; - ofs << "\nBands ended at " << bands_end; - ofs << "\nOptimized bands number " << bands_number; - ofs << "\nSpillage per band is " << 1.0/bands_number; - - //ofs << setioflags(ios::fixed); - for(int il=0; il"; + ofs << "\n" << setw(20) << mz.nlevel << " Total number of orbitals optimized levels."; + } + + double sum0 = 0.0; + double* sum1 = new double[NBANDS]; + ZEROS(sum1, NBANDS); + + int bands_start; + int bands_end; + int bands_number; + + if (BANDS_CONTROL) { + bands_start = BANDS_START; + bands_end = BANDS_END; + bands_number = bands_end - bands_start; + } else { + bands_start = 0; + bands_end = NBANDS; + bands_number = bands_end - bands_start; + } + + ofs << "\nBands start from " << bands_start; + ofs << "\nBands ended at " << bands_end; + ofs << "\nOptimized bands number " << bands_number; + ofs << "\nSpillage per band is " << 1.0 / bands_number; + + // ofs << setioflags(ios::fixed); + for (int il = 0; il < mz.ilevel; il++) { + if (MY_RANK == 0) { + ofs << "\n\nFill Left Hilbert space of each band(average) by LCAO for Level " << il + 1; + ofs << "\n" + << setw(5) << "BANDS" << setw(20) << "New Fill" << setw(20) << "Total Fill" << setw(20) + << "Left Spillage"; + ofs << setprecision(10); + } + double conb = 0.0; + ofs_running << "\n NBANDS=" << NBANDS << " STRNUM=" << STRNUM << endl; + + for (int ib = bands_start; ib < bands_end; ib++) { + double mm = 0.0; + // calculate the average fill gution from all k points. + for (int is = 0; is < STRNUM; is++) { + + for (int ik = 0; ik < mz.Level[il].data[is].nks; ik++) { + mm += mz.Level[il].data[is].Mkb(ik, ib) * mz.Level[il].data[is].weight[ik] / (double)bands_number / + (double)STRNUM; + } #ifdef __MPI - Parallel_Reduce::reduce_double_allpool(mm); + Parallel_Reduce::reduce_double_allpool(mm); #endif - } - sum1[ib] += mm; - - if(MY_RANK==0) - { - ofs << "\n" << setw(5) << ib+1 << setw(20) << mm << setw(20) << sum1[ib] << setw(20) << 1.0/(double)bands_number - sum1[ib]; - } - - conb += mm; - } - sum0 += conb; - ofs << "\nNew Fill Contribution = " << conb; - ofs << "\nTotal Fill Contribution = " << sum0; - - ofs << "\nLeft spillage = " << 1.0 - sum0; - } - ofs << "\n"; - delete[] sum1; - - return; + } + sum1[ib] += mm; + + if (MY_RANK == 0) { + ofs << "\n" + << setw(5) << ib + 1 << setw(20) << mm << setw(20) << sum1[ib] << setw(20) + << 1.0 / (double)bands_number - sum1[ib]; + } + + conb += mm; + } + sum0 += conb; + ofs << "\nNew Fill Contribution = " << conb; + ofs << "\nTotal Fill Contribution = " << sum0; + + ofs << "\nLeft spillage = " << 1.0 - sum0; + } + ofs << "\n"; + delete[] sum1; + + return; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Out_Orbital.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Out_Orbital.h index 228ed3857d8..b526304069c 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Out_Orbital.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Out_Orbital.h @@ -4,22 +4,20 @@ #include "common.h" // output orbital information -class Out_Orbital -{ - public: - Out_Orbital(); - ~Out_Orbital(); +class Out_Orbital { + public: + Out_Orbital(); + ~Out_Orbital(); - void write(void); + void write(void); - private: - void version_information( ofstream &ofs ); - void INPUTs_information( ofstream &ofs); - void spillage_information( ofstream &ofs, const int &ilevel); - void metropolis_information( ofstream &ofs); - void c4_information( ofstream &ofs); - void mkb_information( ofstream &ofs); - + private: + void version_information(ofstream& ofs); + void INPUTs_information(ofstream& ofs); + void spillage_information(ofstream& ofs, const int& ilevel); + void metropolis_information(ofstream& ofs); + void c4_information(ofstream& ofs); + void mkb_information(ofstream& ofs); }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Plot_Psi.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Plot_Psi.cpp index 468c14ea315..0b49f6ef1d3 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Plot_Psi.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Plot_Psi.cpp @@ -2,624 +2,557 @@ #include "tools.h" #include "../src_tools/Gram_Schmidt_Orth.h" -Plot_Psi::Plot_Psi() -{ - test=0; - rcut = 0.0; - - dr = 0.01; - - meshU = 0; // uniform mesh. - meshL = 0; // Log mesh. - - rU = new double[1]; - rL = new double[1]; - - xmin = -6; - zed = 4;//charge on the atom - dx = 1.0e-2; - xmax = 10; +Plot_Psi::Plot_Psi() { + test = 0; + rcut = 0.0; + + dr = 0.01; + + meshU = 0; // uniform mesh. + meshL = 0; // Log mesh. + + rU = new double[1]; + rL = new double[1]; + + xmin = -6; + zed = 4; // charge on the atom + dx = 1.0e-2; + xmax = 10; } -Plot_Psi::~Plot_Psi() -{ - delete[] rU; - delete[] rL; +Plot_Psi::~Plot_Psi() { + delete[] rU; + delete[] rL; } -void Plot_Psi::allocate(void) -{ - // (1) read in parameters. - if(SCAN_BEGIN(input.ifs, "")) - { - READ_VALUE(input.ifs, this->dr); - assert( this->dr > 0.0); - - // mohan add 2009-11-23 - READ_VALUE(input.ifs, this->xmin); - READ_VALUE(input.ifs, this->zed);//charge? - READ_VALUE(input.ifs, this->dx); - READ_VALUE(input.ifs, this->xmax); - assert(zed>0.0); - assert(dx>0.0); - assert(xmax>=0.0); - - SCAN_END(input.ifs, ""); - } - - this->ne = NE; - this->meshU = static_cast(RCUT/dr); - this->meshL = ( std::log( xmax * zed ) - xmin ) / dx; - // mesh should be odd. - if(meshU%2==0) meshU++; - if(meshL%2==0) meshL++; - - /* - cout << "\n dr = " << dr; - cout << "\n meshU = " << meshU; - cout << "\n meshL = " << meshL; - - cout << "\n xmin = " << xmin; - cout << "\n zed = " << zed; - cout << "\n dx = " << dx; - cout << "\n xmax = " << xmax; - */ - - // other parameters. - this->rcut = RCUT; - - delete[] rU; - delete[] rL; - rU = new double[meshU]; - rL = new double[meshL]; - - for(int ir=0; irlmax = LMAXUSED; - this->total_nchi = NCHIUSED; - this->psiU.create( this->total_nchi, this->meshU); - this->psiL.create( this->total_nchi, this->meshL); - - return; +void Plot_Psi::allocate(void) { + // (1) read in parameters. + if (SCAN_BEGIN(input.ifs, "")) { + READ_VALUE(input.ifs, this->dr); + assert(this->dr > 0.0); + + // mohan add 2009-11-23 + READ_VALUE(input.ifs, this->xmin); + READ_VALUE(input.ifs, this->zed); // charge? + READ_VALUE(input.ifs, this->dx); + READ_VALUE(input.ifs, this->xmax); + assert(zed > 0.0); + assert(dx > 0.0); + assert(xmax >= 0.0); + + SCAN_END(input.ifs, ""); + } + + this->ne = NE; + this->meshU = static_cast(RCUT / dr); + this->meshL = (std::log(xmax * zed) - xmin) / dx; + // mesh should be odd. + if (meshU % 2 == 0) + meshU++; + if (meshL % 2 == 0) + meshL++; + + /* + cout << "\n dr = " << dr; + cout << "\n meshU = " << meshU; + cout << "\n meshL = " << meshL; + + cout << "\n xmin = " << xmin; + cout << "\n zed = " << zed; + cout << "\n dx = " << dx; + cout << "\n xmax = " << xmax; + */ + + // other parameters. + this->rcut = RCUT; + + delete[] rU; + delete[] rL; + rU = new double[meshU]; + rL = new double[meshL]; + + for (int ir = 0; ir < meshU; ir++) { + rU[ir] = dr * ir; + } + + for (int ir = 0; ir < meshL; ir++) { + rL[ir] = std::exp(xmin + dx * ir) / zed; + } + + this->lmax = LMAXUSED; + this->total_nchi = NCHIUSED; + this->psiU.create(this->total_nchi, this->meshU); + this->psiL.create(this->total_nchi, this->meshL); + + return; } // be called in main.cpp -void Plot_Psi::radial_wave_function(void) -{ - TITLE("Plot_Psi","radial_wave_function"); - timer::tick("Plot_Psi","radial_wf"); - - this->allocate(); - - // calculate all psi - int ichi = 0; - for(int it=0; it>>>>>>>>> - //The two formula are exactly same. - //<< setw(15) << abs(c4[ie])*pow(eigen1[ie],2) - //<< setw(15) << abs(c4[ie])*pow((ie+1)*PI/input.inputs.get_rcut(),2); - //<<<<<<<<<< - } - mz.metro.Psi2.ofsk << "\n Total kinetic energy = " << kin_sum; - - double *psi1 = new double[meshU]; - double *psi2 = new double[meshL]; - this->get_psi( meshU, rU, L, psi1, c4, eigen1, 0 ); - this->get_psi( meshL, rL, L, psi2, c4, eigen1, 1 ); - - for(int ir=0; irorthogonalization(meshU, rU, psiU); - this->orthogonalization(meshL, rL, psiL); - - this->print_orbitalsU_used(); - this->print_orbitalsL_used(); - - // mohan add 2010-04-13 - // use uniform grid to establish the energy cutoff of each orbital - ofstream ofs("ORBITAL_ECUT.txt"); - ofs << setprecision(12); - this->dk = 0.01; - this->meshK = 1500;// (1500*0.01)^2 * 2 = 450 Rydberg. - if(meshK%2==0)meshK++; - this->psiUK.create(total_nchi,meshK); - double *psi = new double[meshU]; - ichi = 0; - for(int it=0; itallocate(); + + // calculate all psi + int ichi = 0; + for (int it = 0; it < NTYPE; it++) { + if (test == 2) + cout << "\n mz.lmax_type[" << it << "]=" << mz.lmax_type[it]; + for (int L = 0; L < mz.lmax_type[it] + 1; L++) { + double* eigen1 = new double[ne]; + for (int ie = 0; ie < ne; ie++) { + eigen1[ie] = mz.metro.Psi2.eigenvalue(L, ie); + // cout << "\n eigen1[" << ie << "]=" << eigen1[ie]; + } + + for (int N = 0; N < mz.l_nchi(it, L); N++) { + if (test == 2) + cout << "\n T=" << it << " L=" << L << " N=" << N; + double* c4 = new double[ne]; + + for (int ie = 0; ie < ne; ie++) { + c4[ie] = input.Coef.C4_old(it, L, N, ie); + } + + // call the function to renormalize the wave functions. + mz.metro.Psi2.norm_c4(c4, L); + + // calculate kinetical energy + mz.metro.Psi2.ofsk << "\n" + << "Type=" << it + 1 << " L=" << L << " N=" << N + 1; + mz.metro.Psi2.ofsk << "\n" + << setw(5) << "nq" << setw(20) << "Coefficient" << setw(20) << "Eigen(Ry)" + << setw(20) << "Kinetic_Energy"; + double kin_sum = 0.0; + for (int ie = 0; ie < ne; ie++) { + // double kin = abs(c4[ie])*pow((ie+1)*PI/input.inputs.get_rcut(),2);//In Rydberg Unit. + // double kin = abs(c4[ie])*pow(eigen1[ie]*PI/input.inputs.get_rcut(),2);//In Rydberg Unit. + double kin = pow(c4[ie] * eigen1[ie], 2) * mz.metro.Psi2.jjnorm(L, ie); + kin_sum += kin; + mz.metro.Psi2.ofsk << "\n" + << setw(5) << ie << setiosflags(ios::fixed) << setprecision(10) + << setiosflags(ios::showpoint) + //<< setiosflags(ios::scientific) + << setw(20) << c4[ie] << setw(20) << eigen1[ie] * eigen1[ie] << setw(20) << kin + << " (Rydberg)" << setprecision(6); + + //>>>>>>>>>> + // The two formula are exactly same. + //<< setw(15) << abs(c4[ie])*pow(eigen1[ie],2) + //<< setw(15) << abs(c4[ie])*pow((ie+1)*PI/input.inputs.get_rcut(),2); + //<<<<<<<<<< + } + mz.metro.Psi2.ofsk << "\n Total kinetic energy = " << kin_sum; + + double* psi1 = new double[meshU]; + double* psi2 = new double[meshL]; + this->get_psi(meshU, rU, L, psi1, c4, eigen1, 0); + this->get_psi(meshL, rL, L, psi2, c4, eigen1, 1); + + for (int ir = 0; ir < meshU; ir++) { + psiU(ichi, ir) = psi1[ir]; + } + for (int ir = 0; ir < meshL; ir++) { + psiL(ichi, ir) = psi2[ir]; + } + delete[] psi2; + delete[] psi1; + delete[] c4; + ++ichi; + } + delete[] eigen1; + } + } + + // Peize Lin add 2015-11-20 + this->orthogonalization(meshU, rU, psiU); + this->orthogonalization(meshL, rL, psiL); + + this->print_orbitalsU_used(); + this->print_orbitalsL_used(); + + // mohan add 2010-04-13 + // use uniform grid to establish the energy cutoff of each orbital + ofstream ofs("ORBITAL_ECUT.txt"); + ofs << setprecision(12); + this->dk = 0.01; + this->meshK = 1500; // (1500*0.01)^2 * 2 = 450 Rydberg. + if (meshK % 2 == 0) + meshK++; + this->psiUK.create(total_nchi, meshK); + double* psi = new double[meshU]; + ichi = 0; + for (int it = 0; it < NTYPE; it++) { + for (int L = 0; L < mz.lmax_type[it] + 1; L++) { + for (int N = 0; N < mz.l_nchi(it, L); N++) { + ofs << "WaveFunctionIndex=" << ichi << endl; + ofs << "T=" << it << " L=" << L << " N=" << N << endl; + for (int ir = 0; ir < meshU; ir++) { + psi[ir] = this->psiU(ichi, ir); + } + this->establish_ecut(ofs, ichi, psi, L); + ++ichi; + } + } + } + assert(ichi == total_nchi); + delete[] psi; + ofs.close(); + + // print the orbitals which can be viewed imediately. + this->print_orbitals_plot(); + timer::tick("Plot_Psi", "radial_wf"); + return; } -void Plot_Psi::print_orbitals_plot(void)const -{ - ofstream f1( "ORBITAL_PLOTU.dat"); - ofstream f2( "ORBITAL_PLOTL.dat"); - ofstream f3( "ORBITAL_PLOTUK.dat"); - - f1 << setprecision(12) - << setiosflags(ios::fixed); - f2 << setprecision(12) - << setiosflags(ios::fixed); - f3 << setprecision(12) - << setiosflags(ios::fixed); - for(int ir=0; ir " << setw(7) << mz.l_nchi(it,L) << endl; - } - f1 << "---------------------------------------------------------------------------"<psiU(ichi, ir); - } - ++ichi; - } - } - f1.close(); - } - return; +void Plot_Psi::print_orbitalsU_used(void) const { + //==================================== + // (5) + //==================================== + // output orbital for standard use form + int ichi = 0; + // because we can't read in r = 0 term now. + // but liaochen suggest we should know psi(r) + // instead of psi(r)*r at zero point, + // I think it's correct. + int start = 0; + for (int it = 0; it < NTYPE; it++) { + // output the wave function in uniform mesh. + stringstream ss; + ss << "ORBITAL_" << mz.Level[0].info[it].id << "U.dat"; + + ofstream f1(ss.str().c_str()); // pengfei 2014-10-13 + f1 << "---------------------------------------------------------------------------" << endl; + f1 << "Element" << setw(22) << LABEL[it] << endl; + f1 << "Energy Cutoff(Ry)" << setw(13) << ECUT << endl; + f1 << "Radius Cutoff(a.u.)" << setw(10) << RCUT << endl; + f1 << "Lmax " << setw(24) << mz.lmax_type[it] << endl; + for (int L = 0; L < mz.lmax_type[it] + 1; L++) { + string orbital_type; + switch (L) { + case 0: + orbital_type = "S"; + break; + case 1: + orbital_type = "P"; + break; + case 2: + orbital_type = "D"; + break; + case 3: + orbital_type = "F"; + break; + case 4: + orbital_type = "G"; + break; + } + + f1 << "Number of " << orbital_type << "orbital--> " << setw(7) << mz.l_nchi(it, L) << endl; + } + f1 << "---------------------------------------------------------------------------" << endl; + f1 << "SUMMARY" << " " << "END" << endl; + f1 << endl; + f1 << "Mesh " << setw(26) << meshU - start << endl; // mohan fix bug 2010-04-15 + f1 << "dr " << setw(29) << dr; + + for (int L = 0; L < mz.lmax_type[it] + 1; L++) { + double* eigen1 = new double[ne]; + for (int ie = 0; ie < ne; ie++) { + eigen1[ie] = mz.metro.Psi2.eigenvalue(L, ie); + } + for (int N = 0; N < mz.l_nchi(it, L); N++) { + f1 << "\n" << setw(20) << "Type" << setw(20) << "L" << setw(20) << "N"; + f1 << "\n" << setw(20) << it << setw(20) << L << setw(20) << N; + f1 << setiosflags(ios::scientific) << setprecision(12); + for (int ir = start; ir < meshU; ir++) { + if (ir % 4 == 0) + f1 << endl; + f1 << " " << this->psiU(ichi, ir); + } + ++ichi; + } + } + f1.close(); + } + return; } -void Plot_Psi::print_orbitalsL_used(void)const -{ - //==================================== - // (5) - //==================================== - // output orbital for standard use form - int ichi = 0; - // because we can't read in r = 0 term now. - for(int it=0; itpsiL(ichi, ir); - } - ++ichi; - } - } - f1.close(); - } - return; +void Plot_Psi::print_orbitalsL_used(void) const { + //==================================== + // (5) + //==================================== + // output orbital for standard use form + int ichi = 0; + // because we can't read in r = 0 term now. + for (int it = 0; it < NTYPE; it++) { + // output the wave function in uniform mesh. + stringstream ss; + ss << "ORBITAL_" << mz.Level[0].info[it].id << "L.dat"; + + ofstream f1(ss.str().c_str()); + + f1 << "Mesh " << meshL << endl; + f1 << "zed " << zed << endl; + f1 << "dx " << dx << endl; + f1 << "xmin " << xmin << endl; + f1 << "xmax " << xmax; + + for (int L = 0; L < mz.lmax_type[it] + 1; L++) { + double* eigen1 = new double[ne]; + for (int ie = 0; ie < ne; ie++) { + eigen1[ie] = mz.metro.Psi2.eigenvalue(L, ie); + } + for (int N = 0; N < mz.l_nchi(it, L); N++) { + f1 << "\n" << setw(20) << "Type" << setw(20) << "L" << setw(20) << "N"; + f1 << "\n" << setw(20) << it << setw(20) << L << setw(20) << N << endl; + f1 << setiosflags(ios::scientific) << setprecision(12); + for (int ir = 0; ir < meshL; ir++) { + if (ir % 4 == 0) + f1 << endl; + f1 << " " << this->psiL(ichi, ir); + } + ++ichi; + } + } + f1.close(); + } + return; } -void Plot_Psi::get_psi( - const int &mesh, - const double *r, - const int &l, - double *psi, - double *c4, - const double *eigen1, bool logmesh)const -{ - // (1) get psi1 - double *jle = new double[mesh]; - double *g = new double[mesh]; // smooth function - - if(SMOOTH) - { - double sigma2 = SIGMA*SIGMA; - for(int ir=0; irrcut)*(r[ir]-this->rcut)/2.0/sigma2) ); - //if(ir==mesh-1) cout << "\n g[" << ir << "]=" << g[ir] << endl; - } - } - - ZEROS(psi,mesh); - for(int ie=0; ie and - // using smooth Jlq, here we output the - // smooth functions. - if(SMOOTH) - { - for(int ir=0; irdr; - } - } - - for(int ir=0; ir0.9900)=" << pow(dk*kmesh_used,2)*2 << endl; - - while(normk*fpi< 0.999 && kmesh_used < this->meshK) - { - kmesh_used += 2; - Mathzone::Simpson_Integral(kmesh_used, functionk, rabk, normk ); - } -// ofs << "Psi(k) norm(0.999)=" << normk * fpi << endl; - ofs << "Ecut(Ry)(norm>0.9990)=" << pow(dk*kmesh_used,2)*2 << endl; - - while(normk*fpi< 0.9999 && kmesh_used < this->meshK) - { - kmesh_used += 2; - Mathzone::Simpson_Integral(kmesh_used, functionk, rabk, normk ); - } -// ofs << "Psi(k) norm(0.999)=" << normk * fpi << endl; - ofs << "Ecut(Ry)(norm>0.9999)=" << pow(dk*kmesh_used,2)*2 << endl; - - ofs << endl; - - delete[] function; - delete[] functionk; - delete[] rabk; - delete[] rab; - delete[] psik; - delete[] jj; - return; +void Plot_Psi::establish_ecut(ofstream& ofs, const int& ichi, double* psi, const int& L) { + //(1) init the parameters + double pi = 3.1415926535; + double fpi = 4 * pi; + + for (int ir = 0; ir < this->meshU; ir++) { + psi[ir] /= sqrt(fpi); + } + + // (2) check the norm of psi + double norm = 0.0; + double* function = new double[meshU]; + double* rab = new double[meshU]; + for (int ir = 0; ir < meshU; ir++) { + rab[ir] = dr; + function[ir] = std::pow(psi[ir] * this->rU[ir], 2); + } + Mathzone::Simpson_Integral(meshU, function, rab, norm); + ofs << "Psi(r) norm=" << norm * fpi << endl; + + // (3) get psik + double* psik = new double[meshK]; + double* jj = new double[meshU]; + for (int ik = 0; ik < meshK; ik++) { + double q = ik * this->dk; + Mathzone::Spherical_Bessel(this->meshU, this->rU, q, L, jj); + for (int ir = 0; ir < this->meshU; ir++) { + function[ir] = psi[ir] * this->rU[ir] * this->rU[ir] * jj[ir]; + } + Mathzone::Simpson_Integral(this->meshU, function, rab, psik[ik]); + } + double prefac_k = fpi / pow(2 * pi, 1.5); + for (int ik = 0; ik < meshK; ik++) { + psik[ik] *= prefac_k; + this->psiUK(ichi, ik) = psik[ik]; + } + + // (4) prepare for the integral of psik. + double normk = 0.0; + double* rabk = new double[meshK]; + double* functionk = new double[meshK]; + for (int ik = 0; ik < meshK; ik++) { + rabk[ik] = dk; + } + for (int ik = 0; ik < meshK; ik++) { + functionk[ik] = std::pow(psik[ik] * ik * this->dk, 2); + } + Mathzone::Simpson_Integral(this->meshK, functionk, rabk, normk); + ofs << "Psi(k) norm=" << normk * fpi << endl; + + // (5) Find out the energy cut for each orbital. + normk = 0.0; + int kmesh_used = 1; + + //=================================================== + // 0.999 is the accepted value of norm, according + // to the value we establish the energy cutoff. + //=================================================== + while (normk * fpi < 0.99 && kmesh_used < this->meshK) { + kmesh_used += 2; + Mathzone::Simpson_Integral(kmesh_used, functionk, rabk, normk); + } + // ofs << "Psi(k) norm(0.99)=" << normk * fpi << endl; + ofs << "Ecut(Ry)(norm>0.9900)=" << pow(dk * kmesh_used, 2) * 2 << endl; + + while (normk * fpi < 0.999 && kmesh_used < this->meshK) { + kmesh_used += 2; + Mathzone::Simpson_Integral(kmesh_used, functionk, rabk, normk); + } + // ofs << "Psi(k) norm(0.999)=" << normk * fpi << endl; + ofs << "Ecut(Ry)(norm>0.9990)=" << pow(dk * kmesh_used, 2) * 2 << endl; + + while (normk * fpi < 0.9999 && kmesh_used < this->meshK) { + kmesh_used += 2; + Mathzone::Simpson_Integral(kmesh_used, functionk, rabk, normk); + } + // ofs << "Psi(k) norm(0.999)=" << normk * fpi << endl; + ofs << "Ecut(Ry)(norm>0.9999)=" << pow(dk * kmesh_used, 2) * 2 << endl; + + ofs << endl; + + delete[] function; + delete[] functionk; + delete[] rabk; + delete[] rab; + delete[] psik; + delete[] jj; + return; } // Peize Lin add 2015-11-20 -void Plot_Psi::orthogonalization( - const int &mesh, - double *r, - const matrix &psi -) -{ - Gram_Schmidt_Orth gs_orth; - gs_orth.set_coordinate(1); - gs_orth.set_variable_num(mesh); - gs_orth.set_rab_element(this->dr); - gs_orth.set_r(r); - - double * tmp_index(psi.c); - - for(int it=0; it gs_orth; + gs_orth.set_coordinate(1); + gs_orth.set_variable_num(mesh); + gs_orth.set_rab_element(this->dr); + gs_orth.set_r(r); + + double* tmp_index(psi.c); + + for (int it = 0; it < NTYPE; it++) { + for (int L = 0; L < mz.lmax_type[it] + 1; L++) { + gs_orth.set_func_num(mz.l_nchi(it, L)); + double** psi_TL = new double*[mz.l_nchi(it, L)]; + for (int N = 0; N < mz.l_nchi(it, L); N++) { + psi_TL[N] = tmp_index; + tmp_index += mesh; + } + gs_orth.set_func(psi_TL); + gs_orth.orth(); + delete[] psi_TL; + } + } + + return; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Plot_Psi.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Plot_Psi.h index b95015b2673..4f596fa13d1 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Plot_Psi.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Plot_Psi.h @@ -3,55 +3,58 @@ #include "common.h" -class Plot_Psi -{ - public: - Plot_Psi(); - ~Plot_Psi(); - - void radial_wave_function(void); - - private: - - // (1) about uniform mesh. - double dr; - int meshU; // U stands for uniform. - int meshL;// L stands for log. - double* rU;// uniform mesh. - double* rL;// log mesh. - int meshK; - double dk;//classic bug, change dk to 'int' type. then see .... - - // (2) about logmesh. - double xmin; - double zed; - double dx; - double xmax; - - // (3) about the wave functions. - matrix psiU; // sum c*j(l,x) - matrix psiL; // - matrix psiUK; - - int total_nchi; - double rcut; - int lmax; - int ne; - int test; - - void allocate(void); - - // mohan add smooth, sigam and rcut 2009-08-28 - void get_psi( const int &mesh, const double *r,const int &l, - double *psi1, double *c4, const double *eigen1, bool logmesh)const; - void orthogonalization( const int &mesh, double *r, const matrix &psi ); - - void print_orbitals_plot(void)const; - void print_orbitalsU_used(void)const; - void print_orbitalsL_used(void)const; - - // mohan add 2010-04-13 - void establish_ecut( ofstream &ofs, const int &ik, double *psi, const int &L); +class Plot_Psi { + public: + Plot_Psi(); + ~Plot_Psi(); + + void radial_wave_function(void); + + private: + // (1) about uniform mesh. + double dr; + int meshU; // U stands for uniform. + int meshL; // L stands for log. + double* rU; // uniform mesh. + double* rL; // log mesh. + int meshK; + double dk; // classic bug, change dk to 'int' type. then see .... + + // (2) about logmesh. + double xmin; + double zed; + double dx; + double xmax; + + // (3) about the wave functions. + matrix psiU; // sum c*j(l,x) + matrix psiL; // + matrix psiUK; + + int total_nchi; + double rcut; + int lmax; + int ne; + int test; + + void allocate(void); + + // mohan add smooth, sigam and rcut 2009-08-28 + void get_psi(const int& mesh, + const double* r, + const int& l, + double* psi1, + double* c4, + const double* eigen1, + bool logmesh) const; + void orthogonalization(const int& mesh, double* r, const matrix& psi); + + void print_orbitals_plot(void) const; + void print_orbitalsU_used(void) const; + void print_orbitalsL_used(void) const; + + // mohan add 2010-04-13 + void establish_ecut(ofstream& ofs, const int& ik, double* psi, const int& L); }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Psi_Second.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Psi_Second.cpp index 2f7a5c84e77..959aebaec97 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Psi_Second.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Psi_Second.cpp @@ -2,331 +2,291 @@ #include "Calculate_C4.h" #include "tools.h" -Psi_Second::Psi_Second() -{ - test=0; - r = new double[1]; - rab = new double[1]; - psi = new double[1]; - psi_first = new double[1]; - psi_second = new double[1]; - eigen1 = new double[1]; - os_position = new double[100]; - below_max_os = new bool[1]; - count = 0; +Psi_Second::Psi_Second() { + test = 0; + r = new double[1]; + rab = new double[1]; + psi = new double[1]; + psi_first = new double[1]; + psi_second = new double[1]; + eigen1 = new double[1]; + os_position = new double[100]; + below_max_os = new bool[1]; + count = 0; } -Psi_Second::~Psi_Second() -{ - delete[] r; - delete[] rab; - delete[] psi; - delete[] psi_first; - delete[] psi_second; - delete[] eigen1; - delete[] os_position; - delete[] below_max_os; +Psi_Second::~Psi_Second() { + delete[] r; + delete[] rab; + delete[] psi; + delete[] psi_first; + delete[] psi_second; + delete[] eigen1; + delete[] os_position; + delete[] below_max_os; } -void Psi_Second::init( - ifstream &ifs, - const int &ne_in, - const int &lmax_in, - const double &rcut_in, - const int &total_nchi_in, - const double &tolerence) -{ - TITLE("Psi_Second","init"); - - this->dr = KINETIC_DR; - assert( dr > 0.0); - cout << "\n KINETIC_DR=" << dr; - -// this->start = 5; // start away from 0, which may be some strange oscillation. - this->start = 1; // mohan fix 2010-04-16 - - // number of Jlq used. - this->ne = ne_in; - // lmax needed. - this->lmax = lmax_in; - // Cutoff radius. - this->rcut = rcut_in; - // Total number of radial wave functions. - this->total_nchi = total_nchi_in; - - this->mesh = static_cast(this->rcut/this->dr); - if(this->mesh%2==0) this->mesh++; - - if(test==2) - { - cout << "\n ne=" << ne; - cout << "\n lmax=" << lmax; - cout << "\n mesh=" << mesh; - cout << "\n total_nchi=" << total_nchi; - cout << "\n dr=" << dr; - } - - // init psi matrix, generate eigenvalue matrix - // this eigenvalue will be used in many functions. - this->eigenvalue.create( this->lmax+1, this->ne); - this->jjnorm.create( this->lmax+1, this->ne); - - delete[] this->eigen1; - this->eigen1 = new double[ne]; - - delete[] this->r; - delete[] this->rab; - delete[] this->psi; - delete[] this->psi_first; - delete[] this->psi_second; - delete[] this->below_max_os; - delete[] this->os_number; - - this->r = new double[mesh]; - this->rab = new double[mesh]; - this->psi = new double[mesh]; - this->psi_first = new double[mesh]; - this->psi_second = new double[mesh]; - - this->below_max_os = new bool[total_nchi]; - this->os_number = new int[total_nchi]; - - for(int ir=0; irne, - this->eigenvalue, - this->lmax, - this->rcut, - tolerence); - - // (2) to calculate jl(qr) - this->jle = new double**[this->lmax+1]; - double* g; - if(SMOOTH) - { - g = new double[mesh]; - double sigma2 = SIGMA*SIGMA; - for(int ir=0; irrcut)*(r[ir]-this->rcut)/2.0/sigma2) ); - } - } - - for(int l=0; leigen1[ie] = this->eigenvalue(l, ie);} - - // allocate space - this->jle[l] = new double*[ne]; - - for(int ie=0; iene; ie++) - { - this->jle[l][ie] = new double[this->mesh]; - Mathzone::Spherical_Bessel( this->mesh, this->r, this->eigen1[ie], l, jle[l][ie]); - - // (3) to calculate the jjnorm - double* f = new double[mesh]; - for(int ir=0; irjjnorm(l,ie) ); - jjnorm(l,ie)*=4.0*PI; -// cout << "\n jj = " << jjnorm(l,ie); - delete[] f; - - if(SMOOTH) - for(int ir=0; irofso.open("ORBITAL_OSCILATION.txt"); - this->ofsk.open("ORBITAL_KINETIC.txt"); - - return; +void Psi_Second::init(ifstream& ifs, + const int& ne_in, + const int& lmax_in, + const double& rcut_in, + const int& total_nchi_in, + const double& tolerence) { + TITLE("Psi_Second", "init"); + + this->dr = KINETIC_DR; + assert(dr > 0.0); + cout << "\n KINETIC_DR=" << dr; + + // this->start = 5; // start away from 0, which may be some strange oscillation. + this->start = 1; // mohan fix 2010-04-16 + + // number of Jlq used. + this->ne = ne_in; + // lmax needed. + this->lmax = lmax_in; + // Cutoff radius. + this->rcut = rcut_in; + // Total number of radial wave functions. + this->total_nchi = total_nchi_in; + + this->mesh = static_cast(this->rcut / this->dr); + if (this->mesh % 2 == 0) + this->mesh++; + + if (test == 2) { + cout << "\n ne=" << ne; + cout << "\n lmax=" << lmax; + cout << "\n mesh=" << mesh; + cout << "\n total_nchi=" << total_nchi; + cout << "\n dr=" << dr; + } + + // init psi matrix, generate eigenvalue matrix + // this eigenvalue will be used in many functions. + this->eigenvalue.create(this->lmax + 1, this->ne); + this->jjnorm.create(this->lmax + 1, this->ne); + + delete[] this->eigen1; + this->eigen1 = new double[ne]; + + delete[] this->r; + delete[] this->rab; + delete[] this->psi; + delete[] this->psi_first; + delete[] this->psi_second; + delete[] this->below_max_os; + delete[] this->os_number; + + this->r = new double[mesh]; + this->rab = new double[mesh]; + this->psi = new double[mesh]; + this->psi_first = new double[mesh]; + this->psi_second = new double[mesh]; + + this->below_max_os = new bool[total_nchi]; + this->os_number = new int[total_nchi]; + + for (int ir = 0; ir < mesh; ir++) { + r[ir] = dr * ir; + rab[ir] = dr; + } + + // (1) call to find the eigenvalues of Jlq. + Calculate_C4::Find_Eigenvalues(this->ne, this->eigenvalue, this->lmax, this->rcut, tolerence); + + // (2) to calculate jl(qr) + this->jle = new double**[this->lmax + 1]; + double* g; + if (SMOOTH) { + g = new double[mesh]; + double sigma2 = SIGMA * SIGMA; + for (int ir = 0; ir < mesh; ir++) { + g[ir] = 1.0 - std::exp(-((r[ir] - this->rcut) * (r[ir] - this->rcut) / 2.0 / sigma2)); + } + } + + for (int l = 0; l < lmax + 1; l++) { + // get eigenvalues. + for (int ie = 0; ie < ne; ie++) { + this->eigen1[ie] = this->eigenvalue(l, ie); + } + + // allocate space + this->jle[l] = new double*[ne]; + + for (int ie = 0; ie < this->ne; ie++) { + this->jle[l][ie] = new double[this->mesh]; + Mathzone::Spherical_Bessel(this->mesh, this->r, this->eigen1[ie], l, jle[l][ie]); + + // (3) to calculate the jjnorm + double* f = new double[mesh]; + for (int ir = 0; ir < mesh; ir++) { + f[ir] = std::pow(jle[l][ie][ir], 2); + } + Mathzone::Simpson_Integral(mesh, f, rab, this->jjnorm(l, ie)); + jjnorm(l, ie) *= 4.0 * PI; + // cout << "\n jj = " << jjnorm(l,ie); + delete[] f; + + if (SMOOTH) + for (int ir = 0; ir < mesh; ir++) { + jle[l][ie][ir] *= g[ir]; + } + } + } + + if (SMOOTH) + delete[] g; + + // this->ofso.open("ORBITAL_OSCILATION.txt"); + this->ofsk.open("ORBITAL_KINETIC.txt"); + + return; } - -double Psi_Second::get_ecut( double *c4, const int &L) -{ - timer::tick("Psi_Second","get_ecut"); - - static double fpi = 4*PI; - static double sfpi = sqrt(fpi); - static double prefac_k = fpi / pow(2*PI,1.5); - static double dk = 0.01; - static int meshK = 800; // 8*8*2=128Ry - static double* g; - static double* rab; - static double* rabk; - static double* functionk; - static bool init = false; - static double norm; - static double normk; - static double ecut; - - if(!init) - { - if(meshK%2==0) ++meshK; - - g = new double[mesh]; // smooth function - rab = new double[mesh]; - rabk = new double[meshK]; - functionk = new double[meshK]; - if(SMOOTH) - { - double sigma2 = SIGMA*SIGMA; - for(int ir=0; irrcut)*(r[ir]-this->rcut)/2.0/sigma2) ); - } - } - for(int ir=0; ireigen1[ie] = this->eigenvalue(L, ie);} - - ZEROS(psi,mesh); - for(int ie=0; ie0.999)=" << ecut << endl; - - delete[] jj; - delete[] psik; - delete[] function; - timer::tick("Psi_Second","get_ecut"); - return ecut; +double Psi_Second::get_ecut(double* c4, const int& L) { + timer::tick("Psi_Second", "get_ecut"); + + static double fpi = 4 * PI; + static double sfpi = sqrt(fpi); + static double prefac_k = fpi / pow(2 * PI, 1.5); + static double dk = 0.01; + static int meshK = 800; // 8*8*2=128Ry + static double* g; + static double* rab; + static double* rabk; + static double* functionk; + static bool init = false; + static double norm; + static double normk; + static double ecut; + + if (!init) { + if (meshK % 2 == 0) + ++meshK; + + g = new double[mesh]; // smooth function + rab = new double[mesh]; + rabk = new double[meshK]; + functionk = new double[meshK]; + if (SMOOTH) { + double sigma2 = SIGMA * SIGMA; + for (int ir = 0; ir < mesh; ir++) { + g[ir] = 1.0 - std::exp(-((r[ir] - this->rcut) * (r[ir] - this->rcut) / 2.0 / sigma2)); + } + } + for (int ir = 0; ir < mesh; ir++) { + rab[ir] = dr; + } + for (int ik = 0; ik < meshK; ik++) { + rabk[ik] = dk; + } + init = true; + } + + // get the eigenvalues. + for (int ie = 0; ie < ne; ie++) { + this->eigen1[ie] = this->eigenvalue(L, ie); + } + + ZEROS(psi, mesh); + for (int ie = 0; ie < ne; ie++) { + for (int ir = 0; ir < mesh; ir++) { + psi[ir] += c4[ie] * jle[L][ie][ir]; + } + } + + double* function = new double[mesh]; + for (int ir = 0; ir < mesh; ir++) { + function[ir] = pow(psi[ir] * r[ir], 2); + } + + Mathzone::Simpson_Integral(mesh, function, rab, norm); + // cout << "\n norm = " << norm * fpi<< endl; + assert(norm != 0.0); + // exit(0); + + norm = sqrt(norm); + for (int ir = 0; ir < mesh; ir++) { + psi[ir] /= norm; + } + + for (int ie = 0; ie < ne; ie++) { + c4[ie] /= norm; + } + + // NOTICE !!!! here psi ==> psi*r*r + for (int ir = 0; ir < mesh; ir++) { + psi[ir] = psi[ir] / sfpi * r[ir] * r[ir]; + } + + // calculate psik. + double* psik = new double[meshK]; + double* jj = new double[mesh]; + for (int ik = 0; ik < meshK; ik++) { + double q = ik * dk; + Mathzone::Spherical_Bessel(mesh, r, q, L, jj); + for (int ir = 0; ir < mesh; ir++) { + function[ir] = psi[ir] * jj[ir]; + } + Mathzone::Simpson_Integral(mesh, function, rab, psik[ik]); + } + + for (int ik = 0; ik < meshK; ik++) { + psik[ik] *= prefac_k; + } + + // + for (int ik = 0; ik < meshK; ik++) { + functionk[ik] = std::pow(psik[ik] * ik * dk, 2); + } + Mathzone::Simpson_Integral(meshK, functionk, rabk, normk); + // cout << "\n Psi(k) norm=" << normk * fpi; + + if (normk * fpi < 0.999) { + ecut = pow(dk * meshK, 2) * 2; + } else { + int kmesh_used = meshK; + while (normk * fpi > 0.999 && kmesh_used >= 0) { + kmesh_used -= 2; + Mathzone::Simpson_Integral(kmesh_used, functionk, rabk, normk); + } + ecut = pow(dk * kmesh_used, 2) * 2; + } + // cout << "Ecut(Ry)(norm>0.999)=" << ecut << endl; + + delete[] jj; + delete[] psik; + delete[] function; + timer::tick("Psi_Second", "get_ecut"); + return ecut; } +void Psi_Second::norm_c4(double* c4, const int& L) { + ZEROS(this->psi, mesh); + for (int ie = 0; ie < ne; ie++) { + // ZEROS(this->jle, mesh); + // Mathzone::Spherical_Bessel( this->mesh, this->r, this->eigen1[ie], L, jle); -void Psi_Second::norm_c4( double *c4, const int &L) -{ - ZEROS(this->psi,mesh); - for(int ie=0; iejle, mesh); -// Mathzone::Spherical_Bessel( this->mesh, this->r, this->eigen1[ie], L, jle); - - for(int ir=0; irpsi[ir] += c4[ie] * jle[L][ie][ir];} - } - - double* function = new double[mesh]; - for(int ir=0; ir0.0); - for(int ie=0; iepsi[ir] += c4[ie] * jle[L][ie][ir]; + } + } + + double* function = new double[mesh]; + for (int ir = 0; ir < mesh; ir++) { + function[ir] = pow(psi[ir] * r[ir], 2); + } + double norm; + Mathzone::Simpson_Integral(mesh, function, rab, norm); + delete[] function; + assert(norm > 0.0); + for (int ie = 0; ie < ne; ie++) { + c4[ie] /= std::sqrt(norm); + } + + return; +} diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Psi_Second.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Psi_Second.h index 0772cf0b0f6..5fe0327d016 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Psi_Second.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Psi_Second.h @@ -3,61 +3,59 @@ #include "common.h" -class Psi_Second -{ - public: - Psi_Second(); - ~Psi_Second(); - - // be called in MultiZeta.cpp. - void init(ifstream &ifs, - const int &ne_in, - const int &lmax_in, - const double &rcut_in, - const int &total_nchi_in, - const double &tolerence); - - int calculate_oscillation(const int &L, const int &N, const double *c4, const int &ic); - - int oscillation; - - ofstream ofso; - ofstream ofsk; - - bool* below_max_os; - - int *os_number; - - void norm_c4( double *c4, const int &L); - // new method, mohan 2010-04-14 - double get_ecut( double *c4, const int &L); - - matrix eigenvalue; - matrix jjnorm; //mohan add 2010-04-18 - double*** jle; - - private: - - double dr; // about mesh - int mesh; // about mesh - double* r; // about mesh - double* rab; // about mesh - double rcut; // about mesh - - double* eigen1; - - int total_nchi; - int lmax; - int ne; - int test; - int start; - int max_os; - - double* psi; // psi - double* psi_first;//first derivative - double* psi_second; //second derivative - double* os_position; - int count; +class Psi_Second { + public: + Psi_Second(); + ~Psi_Second(); + + // be called in MultiZeta.cpp. + void init(ifstream& ifs, + const int& ne_in, + const int& lmax_in, + const double& rcut_in, + const int& total_nchi_in, + const double& tolerence); + + int calculate_oscillation(const int& L, const int& N, const double* c4, const int& ic); + + int oscillation; + + ofstream ofso; + ofstream ofsk; + + bool* below_max_os; + + int* os_number; + + void norm_c4(double* c4, const int& L); + // new method, mohan 2010-04-14 + double get_ecut(double* c4, const int& L); + + matrix eigenvalue; + matrix jjnorm; // mohan add 2010-04-18 + double*** jle; + + private: + double dr; // about mesh + int mesh; // about mesh + double* r; // about mesh + double* rab; // about mesh + double rcut; // about mesh + + double* eigen1; + + int total_nchi; + int lmax; + int ne; + int test; + int start; + int max_os; + + double* psi; // psi + double* psi_first; // first derivative + double* psi_second; // second derivative + double* os_position; + int count; }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/ReadData.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/ReadData.cpp index 7fbab7cd8b4..69fdaac17ea 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/ReadData.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/ReadData.cpp @@ -1,16 +1,12 @@ #include "ReadData.h" #include "../src_parallel/parallel_common.h" -ReadData::ReadData() -: test(0) -{ - weight = new double[1]; -} +ReadData::ReadData() : test(0) { weight = new double[1]; } -ReadData::~ReadData() -{ - if(TEST1) cout << "\n ~ReadData()" << endl; - delete[] weight; +ReadData::~ReadData() { + if (TEST1) + cout << "\n ~ReadData()" << endl; + delete[] weight; } //========================================================== @@ -20,540 +16,460 @@ ReadData::~ReadData() // The number of ie is : ne // The number of k points : nks; //========================================================== -void ReadData::OverlapQandS(const string &name) -{ - TITLE(ofs_running, "ReadData", "OverlapQandS"); - - ifstream ifs; - - double* weighttmp = new double[NKSTOT]; - double* carkx = new double[NKSTOT]; - double* carky = new double[NKSTOT]; - double* carkz = new double[NKSTOT]; - ZEROS(weighttmp, NKSTOT); - - if(MY_RANK==0) - { - ifs.open(name.c_str()); - - if (!ifs) - { - cout << "\n Can't find file : " << name; - WARNING_QUIT("ReadData::OverlapQandS","Can't find file."); - } - else - { - cout << " FILE : " << name << endl; - } - - double lat0; - ifs >> lat0; - assert(lat0 == LAT0); - - double e11,e12,e13,e21,e22,e23,e31,e32,e33; - - ifs >> e11 >> e12 >> e13; - ifs >> e21 >> e22 >> e23; - ifs >> e31 >> e32 >> e33; - - assert( e11 == LATVEC.e11); - assert( e12 == LATVEC.e12); - assert( e13 == LATVEC.e13); - assert( e21 == LATVEC.e21); - assert( e22 == LATVEC.e22); - assert( e23 == LATVEC.e23); - assert( e31 == LATVEC.e31); - assert( e32 == LATVEC.e32); - assert( e33 == LATVEC.e33); - - int ntype; - READ_VALUE(ifs, ntype); // 1 - assert(ntype==NTYPE); - - double x,y,z; - for(int it=0; it> x >> y >> z; - } - } - - double tmp_ecutwfc; - double tmp_ecutwfc_jlq; - double tmp_rcut; - - READ_VALUE(ifs, tmp_ecutwfc);// 4 - READ_VALUE(ifs, tmp_ecutwfc_jlq);// 5 - READ_VALUE(ifs, tmp_rcut);// 6 - - assert(tmp_ecutwfc == ECUT); - assert(tmp_ecutwfc_jlq == ECUT_JLQ); - assert(tmp_rcut == RCUT); - - // mohan add 2009-08-28 - // make sure all structures have - // same SMOOTH and SIGMA value! - bool tmp_smooth; - double tmp_sigma; - double tmp_tolerence; - - READ_VALUE(ifs, tmp_smooth); // 7 - READ_VALUE(ifs, tmp_sigma); // 8 - READ_VALUE(ifs, tmp_tolerence); // 9 - - assert(tmp_smooth == SMOOTH); - assert(tmp_sigma == SIGMA); - assert(tmp_tolerence == TOLERENCE); - - int lmaxall, nkstot, nbands, nwfcall, ne; - - READ_VALUE(ifs, lmaxall); // 10 - READ_VALUE(ifs, nkstot);// 11 - READ_VALUE(ifs, nbands);// 12 - READ_VALUE(ifs, nwfcall);// 13 - READ_VALUE(ifs, ne);// 14 - - assert(lmaxall == LMAXALL); - assert(nkstot == NKSTOT); - assert(nbands == NBANDS); - assert(nwfcall == NWFCALL); - assert(ne == NE); - - //========================================== - // if use IBZ k-points, weight is different - // for each k point - //========================================== - // 0 means don't need to search from start. - if( SCAN_BEGIN(ifs,"",0) ) - { - ofs_running << " Kx/Ky/Kz/Kweight" ; - for(int ik=0; ik> carkx[ik] - >> carky[ik] - >> carkz[ik] - >> weighttmp[ik]; - ofs_running << " " << carkx[ik] - << " " << carky[ik] - << " " << carkz[ik] - << " " << weighttmp[ik] << endl; - } - SCAN_END(ifs,""); - } - - double sum = 0; - for(int ik=0; ik> lat0; + assert(lat0 == LAT0); + + double e11, e12, e13, e21, e22, e23, e31, e32, e33; + + ifs >> e11 >> e12 >> e13; + ifs >> e21 >> e22 >> e23; + ifs >> e31 >> e32 >> e33; + + assert(e11 == LATVEC.e11); + assert(e12 == LATVEC.e12); + assert(e13 == LATVEC.e13); + assert(e21 == LATVEC.e21); + assert(e22 == LATVEC.e22); + assert(e23 == LATVEC.e23); + assert(e31 == LATVEC.e31); + assert(e32 == LATVEC.e32); + assert(e33 == LATVEC.e33); + + int ntype; + READ_VALUE(ifs, ntype); // 1 + assert(ntype == NTYPE); + + double x, y, z; + for (int it = 0; it < ntype; it++) { + string tmp_label; + READ_VALUE(ifs, tmp_label); // 2 + assert(tmp_label == LABEL[it]); + + int na; + READ_VALUE(ifs, na); // 3 + assert(na == NA[it]); + for (int ia = 0; ia < NA[it]; ia++) { + // mohan fix bug 2010-09-27 + // x,y,z is useless. + // And CARPOSX, CASPOSY, CASPOSZ + // only contains the first structure. + ifs >> x >> y >> z; + } + } + + double tmp_ecutwfc; + double tmp_ecutwfc_jlq; + double tmp_rcut; + + READ_VALUE(ifs, tmp_ecutwfc); // 4 + READ_VALUE(ifs, tmp_ecutwfc_jlq); // 5 + READ_VALUE(ifs, tmp_rcut); // 6 + + assert(tmp_ecutwfc == ECUT); + assert(tmp_ecutwfc_jlq == ECUT_JLQ); + assert(tmp_rcut == RCUT); + + // mohan add 2009-08-28 + // make sure all structures have + // same SMOOTH and SIGMA value! + bool tmp_smooth; + double tmp_sigma; + double tmp_tolerence; + + READ_VALUE(ifs, tmp_smooth); // 7 + READ_VALUE(ifs, tmp_sigma); // 8 + READ_VALUE(ifs, tmp_tolerence); // 9 + + assert(tmp_smooth == SMOOTH); + assert(tmp_sigma == SIGMA); + assert(tmp_tolerence == TOLERENCE); + + int lmaxall, nkstot, nbands, nwfcall, ne; + + READ_VALUE(ifs, lmaxall); // 10 + READ_VALUE(ifs, nkstot); // 11 + READ_VALUE(ifs, nbands); // 12 + READ_VALUE(ifs, nwfcall); // 13 + READ_VALUE(ifs, ne); // 14 + + assert(lmaxall == LMAXALL); + assert(nkstot == NKSTOT); + assert(nbands == NBANDS); + assert(nwfcall == NWFCALL); + assert(ne == NE); + + //========================================== + // if use IBZ k-points, weight is different + // for each k point + //========================================== + // 0 means don't need to search from start. + if (SCAN_BEGIN(ifs, "", 0)) { + ofs_running << " Kx/Ky/Kz/Kweight"; + for (int ik = 0; ik < NKSTOT; ik++) { + if (ik % 4 == 0) + ofs_running << endl; + ifs >> carkx[ik] >> carky[ik] >> carkz[ik] >> weighttmp[ik]; + ofs_running << " " << carkx[ik] << " " << carky[ik] << " " << carkz[ik] << " " << weighttmp[ik] << endl; + } + SCAN_END(ifs, ""); + } + + double sum = 0; + for (int ik = 0; ik < NKSTOT; ik++) + sum += weighttmp[ik]; + + // ofs_running << "\n sum kpoint weight = " << sum; + if (abs(sum - 1.0) > 1.0e-5) { + ofs_running << "\n sum of k weight = " << sum << endl; + WARNING_QUIT("ReadData::OverlapQandS", "sum of k weight is wrong."); + } + } #ifdef __MPI - Parallel_Common::bcast_double(weighttmp, NKSTOT); - Parallel_Common::bcast_double(carkx, NKSTOT); - Parallel_Common::bcast_double(carky, NKSTOT); - Parallel_Common::bcast_double(carkz, NKSTOT); + Parallel_Common::bcast_double(weighttmp, NKSTOT); + Parallel_Common::bcast_double(carkx, NKSTOT); + Parallel_Common::bcast_double(carky, NKSTOT); + Parallel_Common::bcast_double(carkz, NKSTOT); #endif - ofs_running << " NKS=" << NKS << endl; - - - delete[] this->weight; - this->weight = new double[NKS]; - ZEROS(weight, NKS); + ofs_running << " NKS=" << NKS << endl; - CARKX = new double[NKS]; - CARKY = new double[NKS]; - CARKZ = new double[NKS]; - ZEROS(CARKX, NKS); - ZEROS(CARKY, NKS); - ZEROS(CARKZ, NKS); + delete[] this->weight; + this->weight = new double[NKS]; + ZEROS(weight, NKS); + CARKX = new double[NKS]; + CARKY = new double[NKS]; + CARKZ = new double[NKS]; + ZEROS(CARKX, NKS); + ZEROS(CARKY, NKS); + ZEROS(CARKZ, NKS); - for(int ik=0; ikweight[iknow] = weighttmp[ik]; - CARKX[iknow] = carkx[ik]; - CARKY[iknow] = carky[ik]; - CARKZ[iknow] = carkz[ik]; - //ofs_running << "\n iknow = " << iknow << " ik = " << ik << " weight = " << weight[iknow]; - } + const int iknow = ik - Pkpoints.startk_pool[MY_POOL]; + const int pool = Pkpoints.whichpool[ik]; + if (MY_POOL == pool) { + this->weight[iknow] = weighttmp[ik]; + CARKX[iknow] = carkx[ik]; + CARKY[iknow] = carky[ik]; + CARKZ[iknow] = carkz[ik]; + // ofs_running << "\n iknow = " << iknow << " ik = " << ik << " weight = " << weight[iknow]; + } #else - weight[ik] = weighttmp[ik]; - CARKX[ik] = carkx[ik]; - CARKY[ik] = carky[ik]; - CARKZ[ik] = carkz[ik]; + weight[ik] = weighttmp[ik]; + CARKX[ik] = carkx[ik]; + CARKY[ik] = carky[ik]; + CARKZ[ik] = carkz[ik]; #endif - } - - - delete[] weighttmp; - delete[] carkx; - delete[] carky; - delete[] carkz; + } - + delete[] weighttmp; + delete[] carkx; + delete[] carky; + delete[] carkz; - this->OverlapQ(ifs); + this->OverlapQ(ifs); + this->OverlapSq1q2(ifs); - - this->OverlapSq1q2(ifs); - - - - return; + return; } -void ReadData::OverlapSq1q2(ifstream &ifs) -{ -// TITLE("ReadData", "OverlapSq1q2"); - timer::tick("ReadData", "OverlapSq1q2"); - - USEPW = true; - if(MY_RANK==0) - { - bool restart = false; - bool quit = false; - if( SCAN_BEGIN(ifs,"",restart,quit) ) - { - USEPW = false; - } - } +void ReadData::OverlapSq1q2(ifstream& ifs) { + // TITLE("ReadData", "OverlapSq1q2"); + timer::tick("ReadData", "OverlapSq1q2"); + + USEPW = true; + if (MY_RANK == 0) { + bool restart = false; + bool quit = false; + if (SCAN_BEGIN(ifs, "", restart, quit)) { + USEPW = false; + } + } #ifdef __MPI - Parallel_Common::bcast_bool(USEPW); + Parallel_Common::bcast_bool(USEPW); #endif - - if(USEPW) - { - ofs_running << " USE PLANE WAVE BASIS" << endl; - } - else - { - ofs_running << " USE Q and S matrix" << endl; - } - - if(CALSPI==0) return; - - if(!USEPW) - { - this->Sq1q2 = new ComplexArray[ NKS ]; - for(int ik=0; ikSq1q2[ik].create(NWFCALL, NWFCALL, NE, NE); - } - } + if (USEPW) { + ofs_running << " USE PLANE WAVE BASIS" << endl; + } else { + ofs_running << " USE Q and S matrix" << endl; + } + + if (CALSPI == 0) + return; + + if (!USEPW) { + this->Sq1q2 = new ComplexArray[NKS]; + for (int ik = 0; ik < NKS; ik++) { + this->Sq1q2[ik].create(NWFCALL, NWFCALL, NE, NE); + } + } #ifdef __MPI - if(!USEPW) - { - const int ndata = NWFCALL * NWFCALL * NE * NE; - double* buffera = new double[ndata]; - double* bufferb = new double[ndata]; - for(int ik=0; ik> buffera[id] >> bufferb[id]; - } - } - //ofs_running << "\n ik=" << ik; - MPI_Status ierror; - const int pool = Pkpoints.whichpool[ik]; - const int iknow = ik - Pkpoints.startk_pool[MY_POOL]; - const int startdata = 0; // this is differnt from Q. - - //ofs_running << " this k point belong to pool : " << pool; - //ofs_running << " my pool : " << MY_POOL << endl; - - if(MY_RANK==0) - { - // always ready to send data to other processors. - if(pool==0) - { - // send copies (nproc - 1). - for(int ip=1; ipSq1q2[iknow].ptr[id + startdata] = std::complex (buffera[id], bufferb[id]); - } - // ofs_running << "\n local data copy "; - } - else - { - // send copys: nproc - for(int ip=0; ipSq1q2[iknow].ptr[id + startdata] = std::complex (buffera[id], bufferb[id]); - } - // ofs_running << "\n receive data end" << endl; - } - else - { - // ofs_running << "\n do nothing"; - } - } - MPI_Barrier(MPI_COMM_WORLD); - } - delete[] buffera; - delete[] bufferb; - }// end begin + if (!USEPW) { + const int ndata = NWFCALL * NWFCALL * NE * NE; + double* buffera = new double[ndata]; + double* bufferb = new double[ndata]; + for (int ik = 0; ik < NKSTOT; ik++) { + ZEROS(buffera, ndata); + ZEROS(bufferb, ndata); + if (MY_RANK == 0) { + for (int id = 0; id < ndata; id++) { + ifs >> buffera[id] >> bufferb[id]; + } + } + // ofs_running << "\n ik=" << ik; + MPI_Status ierror; + const int pool = Pkpoints.whichpool[ik]; + const int iknow = ik - Pkpoints.startk_pool[MY_POOL]; + const int startdata = 0; // this is differnt from Q. + + // ofs_running << " this k point belong to pool : " << pool; + // ofs_running << " my pool : " << MY_POOL << endl; + + if (MY_RANK == 0) { + // always ready to send data to other processors. + if (pool == 0) { + // send copies (nproc - 1). + for (int ip = 1; ip < Pkpoints.nproc_pool[pool]; ip++) { + MPI_Send(buffera, ndata, MPI_DOUBLE, ip, ik, MPI_COMM_WORLD); + MPI_Send(bufferb, ndata, MPI_DOUBLE, ip, ik, MPI_COMM_WORLD); + // ofs_running << "\n send data to processor " << ip; + } + + // local copy + for (int id = 0; id < ndata; id++) { + this->Sq1q2[iknow].ptr[id + startdata] = std::complex(buffera[id], bufferb[id]); + } + // ofs_running << "\n local data copy "; + } else { + // send copys: nproc + for (int ip = 0; ip < Pkpoints.nproc_pool[pool]; ip++) { + const int ipall = ip + Pkpoints.startpro_pool[pool]; + MPI_Send(buffera, ndata, MPI_DOUBLE, ipall, ik, MPI_COMM_WORLD); + MPI_Send(bufferb, ndata, MPI_DOUBLE, ipall, ik, MPI_COMM_WORLD); + // ofs_running << "\n send data to processor " << ipall; + } + } + } // end MY_RANK==0 + else { + if (pool == MY_POOL) { + // ofs_running << "\n begin receive, ndata : " << ndata << endl; + MPI_Recv(buffera, ndata, MPI_DOUBLE, 0, ik, MPI_COMM_WORLD, &ierror); + MPI_Recv(bufferb, ndata, MPI_DOUBLE, 0, ik, MPI_COMM_WORLD, &ierror); + + for (int id = 0; id < ndata; id++) { + this->Sq1q2[iknow].ptr[id + startdata] = std::complex(buffera[id], bufferb[id]); + } + // ofs_running << "\n receive data end" << endl; + } else { + // ofs_running << "\n do nothing"; + } + } + MPI_Barrier(MPI_COMM_WORLD); + } + delete[] buffera; + delete[] bufferb; + } // end begin #else - assert(NKS==NKSTOT); - if(!USEPW) - { - double a,b; - for (int ik = 0; ik < NKSTOT; ik++) - { - this->Sq1q2[ik].create(NWFCALL, NWFCALL, NE, NE); - - for (int i = 0; i < Sq1q2[ik].getSize(); i++) - { - ifs >> a >> b; - Sq1q2[ik].ptr[i] = std::complex(a,b); - } - } - } + assert(NKS == NKSTOT); + if (!USEPW) { + double a, b; + for (int ik = 0; ik < NKSTOT; ik++) { + this->Sq1q2[ik].create(NWFCALL, NWFCALL, NE, NE); + + for (int i = 0; i < Sq1q2[ik].getSize(); i++) { + ifs >> a >> b; + Sq1q2[ik].ptr[i] = std::complex(a, b); + } + } + } #endif -// SCAN_END(ifs,""); + // SCAN_END(ifs,""); - timer::tick("ReadData", "OverlapSq1q2"); - return; + timer::tick("ReadData", "OverlapSq1q2"); + return; } -void ReadData::OverlapQ(ifstream &ifs) -{ - if(CALSPI==0) return; -// TITLE("ReadData", "OverlapQ"); - timer::tick("ReadData", "OverlapQ"); - - assert(NKS > 0); - assert(NBANDS > 0); - assert(NWFCALL > 0); - assert(NE > 0); - - this->Qin.create(NKS, NBANDS, NWFCALL, NE); - - ofs_running << " DIMENSION OF Q=" << endl; - OUT(ofs_running,"NKS",NKS); - OUT(ofs_running,"NBANDS",NBANDS); - OUT(ofs_running,"NWFCALL",NWFCALL); - OUT(ofs_running,"NE",NE); - - bool begin = false; - - if(MY_RANK ==0 ) - { - if( SCAN_BEGIN(ifs,"",0) ) - { - begin = true; - } - } +void ReadData::OverlapQ(ifstream& ifs) { + if (CALSPI == 0) + return; + // TITLE("ReadData", "OverlapQ"); + timer::tick("ReadData", "OverlapQ"); -#ifdef __MPI - Parallel_Common::bcast_bool(begin); -#endif + assert(NKS > 0); + assert(NBANDS > 0); + assert(NWFCALL > 0); + assert(NE > 0); + + this->Qin.create(NKS, NBANDS, NWFCALL, NE); + ofs_running << " DIMENSION OF Q=" << endl; + OUT(ofs_running, "NKS", NKS); + OUT(ofs_running, "NBANDS", NBANDS); + OUT(ofs_running, "NWFCALL", NWFCALL); + OUT(ofs_running, "NE", NE); + bool begin = false; + + if (MY_RANK == 0) { + if (SCAN_BEGIN(ifs, "", 0)) { + begin = true; + } + } - if(begin) - { - double a,b; #ifdef __MPI - const int ndata = NBANDS * NWFCALL * NE; - double* buffera = new double[ndata]; - double* bufferb = new double[ndata]; - for(int ik=0; ik> buffera[id] >> bufferb[id]; - } - } - - //ofs_running << "\n ik=" << ik; - - MPI_Status ierror; - const int pool = Pkpoints.whichpool[ik]; - const int iknow = ik - Pkpoints.startk_pool[MY_POOL]; - const int startdata = iknow * ndata; - - //ofs_running << "\n this k point belong to pool : " << pool; - //ofs_running << "\n my pool : " << MY_POOL; - - if(MY_RANK==0) - { - // always ready to send data to other processors. - if(pool==0) - { - // send copies (nproc - 1). - for(int ip=1; ipQin.ptr[id + startdata] = std::complex (buffera[id], bufferb[id]); - } - //ofs_running << "\n local data copy "; - } - else - { - // send copys: nproc - for(int ip=0; ipQin.ptr[id + startdata] = std::complex (buffera[id], bufferb[id]); - } - //ofs_running << "\n receive data end" << endl; - } - else - { - //ofs_running << "\n do nothing"; - } - } - - MPI_Barrier(MPI_COMM_WORLD); - }// endik - delete[] buffera; - delete[] bufferb; -#else - for(int i=0; i> a >> b; - this->Qin.ptr[i] = std::complex( a, b ); - } + Parallel_Common::bcast_bool(begin); #endif - } + if (begin) { + double a, b; +#ifdef __MPI + const int ndata = NBANDS * NWFCALL * NE; + double* buffera = new double[ndata]; + double* bufferb = new double[ndata]; + for (int ik = 0; ik < NKSTOT; ik++) { + ZEROS(buffera, ndata); + ZEROS(bufferb, ndata); + if (MY_RANK == 0) { + for (int id = 0; id < ndata; id++) { + ifs >> buffera[id] >> bufferb[id]; + } + } + + // ofs_running << "\n ik=" << ik; + + MPI_Status ierror; + const int pool = Pkpoints.whichpool[ik]; + const int iknow = ik - Pkpoints.startk_pool[MY_POOL]; + const int startdata = iknow * ndata; + + // ofs_running << "\n this k point belong to pool : " << pool; + // ofs_running << "\n my pool : " << MY_POOL; + + if (MY_RANK == 0) { + // always ready to send data to other processors. + if (pool == 0) { + // send copies (nproc - 1). + for (int ip = 1; ip < Pkpoints.nproc_pool[pool]; ip++) { + MPI_Send(buffera, ndata, MPI_DOUBLE, ip, ik, MPI_COMM_WORLD); + MPI_Send(bufferb, ndata, MPI_DOUBLE, ip, ik, MPI_COMM_WORLD); + // ofs_running << "\n send data to processor " << ip; + } + + // local copy + for (int id = 0; id < ndata; id++) { + this->Qin.ptr[id + startdata] = std::complex(buffera[id], bufferb[id]); + } + // ofs_running << "\n local data copy "; + } else { + // send copys: nproc + for (int ip = 0; ip < Pkpoints.nproc_pool[pool]; ip++) { + const int ipall = ip + Pkpoints.startpro_pool[pool]; + MPI_Send(buffera, ndata, MPI_DOUBLE, ipall, ik, MPI_COMM_WORLD); + MPI_Send(bufferb, ndata, MPI_DOUBLE, ipall, ik, MPI_COMM_WORLD); + // ofs_running << "\n send data to processor " << ipall; + } + } + } // end MY_RANK==0 + else { + if (pool == MY_POOL) { + // ofs_running << "\n begin receive, ndata : " << ndata << endl; + MPI_Recv(buffera, ndata, MPI_DOUBLE, 0, ik, MPI_COMM_WORLD, &ierror); + MPI_Recv(bufferb, ndata, MPI_DOUBLE, 0, ik, MPI_COMM_WORLD, &ierror); + for (int id = 0; id < ndata; id++) { + this->Qin.ptr[id + startdata] = std::complex(buffera[id], bufferb[id]); + } + // ofs_running << "\n receive data end" << endl; + } else { + // ofs_running << "\n do nothing"; + } + } + + MPI_Barrier(MPI_COMM_WORLD); + } // endik + delete[] buffera; + delete[] bufferb; +#else + for (int i = 0; i < Qin.getSize(); i++) { + ifs >> a >> b; + this->Qin.ptr[i] = std::complex(a, b); + } +#endif + } + // SCAN_END(ifs,""); - //SCAN_END(ifs,""); - - timer::tick("ReadData", "OverlapQ"); + timer::tick("ReadData", "OverlapQ"); - return; + return; } //========================================================== // Readin inverse S matrix. // Sinv is fail to use if C4 change. //========================================================== -void ReadData::OverlapSinv(const string &name) -{ -// TITLE("ReadData", "OverlapSinv"); - ifstream ifs(name.c_str()); - - if (!ifs) - { - cout << "\n Can't find file : " << name; - cout << "\n But maybe we don't need it."; - return; - } - - assert(NKS > 0); - assert(NWFCALL > 0); - - this->Sinv.create(NKS, NWFCALL, NWFCALL); - - return; - - string tmp; - int row, col; - - for (int i = 0; i < NKS; i++) - { - ifs >> tmp >> row >> col; -// cout << "\n" << tmp << " row=" << row << " col=" << col << endl; - assert(row == NWFCALL); - assert(col == NWFCALL); - - for (int j = 0; j < row; j++) - { - for (int k = 0; k < col; k++) - { - double a,b; - ifs >> a >> b; - Sinv(i,j,k) = std::complex(a,b); - } - } - } - ifs.close(); - return; +void ReadData::OverlapSinv(const string& name) { + // TITLE("ReadData", "OverlapSinv"); + ifstream ifs(name.c_str()); + + if (!ifs) { + cout << "\n Can't find file : " << name; + cout << "\n But maybe we don't need it."; + return; + } + + assert(NKS > 0); + assert(NWFCALL > 0); + + this->Sinv.create(NKS, NWFCALL, NWFCALL); + + return; + + string tmp; + int row, col; + + for (int i = 0; i < NKS; i++) { + ifs >> tmp >> row >> col; + // cout << "\n" << tmp << " row=" << row << " col=" << col << endl; + assert(row == NWFCALL); + assert(col == NWFCALL); + + for (int j = 0; j < row; j++) { + for (int k = 0; k < col; k++) { + double a, b; + ifs >> a >> b; + Sinv(i, j, k) = std::complex(a, b); + } + } + } + ifs.close(); + return; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/ReadData.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/ReadData.h index 4e4d356d4b0..210dedb0488 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/ReadData.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/ReadData.h @@ -3,38 +3,35 @@ #include "common.h" -class ReadData -{ - public: - - ComplexArray Qin; - ComplexArray *Sq1q2; - ComplexArray Sinv; - - //=================================== - // read in data Q= , S= - //=================================== - void OverlapQandS( const string &name); - - //======================================================== - // inverse matrix of S directly, - // used for checking the correctness - // of spillage calculation - //======================================================== - void OverlapSinv( const string &name); - - double *weight; - - private: - void OverlapQ( ifstream &ifs); - void OverlapSq1q2( ifstream &ifs ); - - int test; - - public: - ReadData(); - ~ReadData(); - +class ReadData { + public: + ComplexArray Qin; + ComplexArray* Sq1q2; + ComplexArray Sinv; + + //=================================== + // read in data Q= , S= + //=================================== + void OverlapQandS(const string& name); + + //======================================================== + // inverse matrix of S directly, + // used for checking the correctness + // of spillage calculation + //======================================================== + void OverlapSinv(const string& name); + + double* weight; + + private: + void OverlapQ(ifstream& ifs); + void OverlapSq1q2(ifstream& ifs); + + int test; + + public: + ReadData(); + ~ReadData(); }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Simulated_Annealing_Orbital.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Simulated_Annealing_Orbital.h index 6fed0be4bcb..8e5201fd6a7 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Simulated_Annealing_Orbital.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Simulated_Annealing_Orbital.h @@ -3,154 +3,122 @@ class Metropolis; -class Metropolis::Simulated_Annealing_Orbital: public Simulated_Annealing -{ - public: - Simulated_Annealing_Orbital( Metropolis *metropolis_in, SpillageStep &Level_in) - :Simulated_Annealing(), - metropolis(metropolis_in), - Level(Level_in){} - protected: - virtual void preprocess_all_temperature() - { - metropolis->preprocess_all_temperature(Level); - } - virtual void preprocess_each_temperature(size_t itemperature) - { - metropolis->Psi2.ofso << "spillage_ntemp = " << itemperature << " kappa = " << metropolis->kappa << endl; - } - virtual void update_temperature(size_t itemperature) - { - metropolis->update_t(); // change temperature - } - virtual void preprocess_each_step( size_t itemperature, size_t istep) - { - metropolis->small_jql(); - } - virtual void cal_each_step( size_t itemperature, size_t istep) - { - preprocess_each_step_beyondloop(itemperature, istep); - // for each (atom_type,L,N), we need a set of C4 - // to describe the radial wave functions. - // after each radial wave function is update(ne parameters), - // we call it 'a step under a particular temperature is done' - for (int ic = 0; ic < metropolis->nchi; ic++) - { - metropolis->info.set_ic(ic).unpack_ic(Level); - const int T = Level.wayc[ic].type; // get the type index of this radial wave function. - if(Level.info[T].state=="skip") continue; // if "skip", the C4 will not changed in this 'Big step' // mohan add 2009-01-27 - for (int ie = 0; ie < Level.ne; ie++) - { - metropolis->info.set_ie(ie); - try - { - this->Simulated_Annealing::cal_each_step(itemperature, istep); - } - catch(Small_Jlq &e) { continue; } - } - } - reprocess_each_step_beyondloop(itemperature, istep); - } - virtual void preprocess_each_step_beyondloop(size_t itemperature, size_t istep){} - virtual void reprocess_each_step_beyondloop(size_t itemperature, size_t istep) - { - metropolis->ofs_1(istep, this->Level); - metropolis->norm_C4(istep, this->Level, this->step_num); - } - virtual void move_variable(size_t itemperature, size_t istep) - { - metropolis->trial_c4(); - } - virtual void accept_process( double new_function, size_t itemperature, size_t istep) - { - metropolis->accept_process(this->Level); - } - virtual void reject_process( double new_function, size_t itemperature, size_t istep) - { - metropolis->reject_process(); - } - Metropolis *metropolis; - SpillageStep &Level; +class Metropolis::Simulated_Annealing_Orbital : public Simulated_Annealing { + public: + Simulated_Annealing_Orbital(Metropolis* metropolis_in, SpillageStep& Level_in) + : Simulated_Annealing(), metropolis(metropolis_in), Level(Level_in) {} + + protected: + virtual void preprocess_all_temperature() { metropolis->preprocess_all_temperature(Level); } + virtual void preprocess_each_temperature(size_t itemperature) { + metropolis->Psi2.ofso << "spillage_ntemp = " << itemperature << " kappa = " << metropolis->kappa << endl; + } + virtual void update_temperature(size_t itemperature) { + metropolis->update_t(); // change temperature + } + virtual void preprocess_each_step(size_t itemperature, size_t istep) { metropolis->small_jql(); } + virtual void cal_each_step(size_t itemperature, size_t istep) { + preprocess_each_step_beyondloop(itemperature, istep); + // for each (atom_type,L,N), we need a set of C4 + // to describe the radial wave functions. + // after each radial wave function is update(ne parameters), + // we call it 'a step under a particular temperature is done' + for (int ic = 0; ic < metropolis->nchi; ic++) { + metropolis->info.set_ic(ic).unpack_ic(Level); + const int T = Level.wayc[ic].type; // get the type index of this radial wave function. + if (Level.info[T].state == "skip") + continue; // if "skip", the C4 will not changed in this 'Big step' // mohan add 2009-01-27 + for (int ie = 0; ie < Level.ne; ie++) { + metropolis->info.set_ie(ie); + try { + this->Simulated_Annealing::cal_each_step(itemperature, istep); + } catch (Small_Jlq& e) { + continue; + } + } + } + reprocess_each_step_beyondloop(itemperature, istep); + } + virtual void preprocess_each_step_beyondloop(size_t itemperature, size_t istep) {} + virtual void reprocess_each_step_beyondloop(size_t itemperature, size_t istep) { + metropolis->ofs_1(istep, this->Level); + metropolis->norm_C4(istep, this->Level, this->step_num); + } + virtual void move_variable(size_t itemperature, size_t istep) { metropolis->trial_c4(); } + virtual void accept_process(double new_function, size_t itemperature, size_t istep) { + metropolis->accept_process(this->Level); + } + virtual void reject_process(double new_function, size_t itemperature, size_t istep) { + metropolis->reject_process(); + } + Metropolis* metropolis; + SpillageStep& Level; }; -class Metropolis::Simulated_Annealing_Orbital_Spillage: public Simulated_Annealing_Orbital -{ - public: - Simulated_Annealing_Orbital_Spillage( Metropolis *metropolis_in, SpillageStep &Level_in) - :Simulated_Annealing_Orbital(metropolis_in, Level_in){} - private: - virtual void preprocess_each_temperature(size_t itemperature) - { - metropolis->init_spi_states(itemperature); - Simulated_Annealing_Orbital::preprocess_each_temperature(itemperature); - } - virtual void reprocess_each_temperature(size_t itemperature) - { - metropolis->cout_1(itemperature); - } - virtual void preprocess_each_step_beyondloop(size_t itemperature, size_t istep) - { - metropolis->file_finish_metropolis(istep); - metropolis->change_accept_rate(istep,Level); - metropolis->info.set_update_number(0); // each step we renew every Jlq one by one. - } - virtual void move_variable(size_t itemperature, size_t istep) - { - Simulated_Annealing_Orbital::move_variable(itemperature, istep); - set_temperature( metropolis->temperature ); - } - virtual double cal_new_function(size_t itemperature, size_t istep) - { - set_old_function(input.SV.cal_defined_value(0)); - return metropolis->cal_spillage(this->Level); - } +class Metropolis::Simulated_Annealing_Orbital_Spillage : public Simulated_Annealing_Orbital { + public: + Simulated_Annealing_Orbital_Spillage(Metropolis* metropolis_in, SpillageStep& Level_in) + : Simulated_Annealing_Orbital(metropolis_in, Level_in) {} + + private: + virtual void preprocess_each_temperature(size_t itemperature) { + metropolis->init_spi_states(itemperature); + Simulated_Annealing_Orbital::preprocess_each_temperature(itemperature); + } + virtual void reprocess_each_temperature(size_t itemperature) { metropolis->cout_1(itemperature); } + virtual void preprocess_each_step_beyondloop(size_t itemperature, size_t istep) { + metropolis->file_finish_metropolis(istep); + metropolis->change_accept_rate(istep, Level); + metropolis->info.set_update_number(0); // each step we renew every Jlq one by one. + } + virtual void move_variable(size_t itemperature, size_t istep) { + Simulated_Annealing_Orbital::move_variable(itemperature, istep); + set_temperature(metropolis->temperature); + } + virtual double cal_new_function(size_t itemperature, size_t istep) { + set_old_function(input.SV.cal_defined_value(0)); + return metropolis->cal_spillage(this->Level); + } }; -class Metropolis::Simulated_Annealing_Orbital_Kinetic: public Simulated_Annealing_Orbital -{ - public: - Simulated_Annealing_Orbital_Kinetic( Metropolis *metropolis_in, SpillageStep &Level_in) - :Simulated_Annealing_Orbital(metropolis_in, Level_in){} - private: - virtual void preprocess_each_temperature(size_t itemperature) - { - metropolis->init_kin_states(); - Simulated_Annealing_Orbital::preprocess_each_temperature(itemperature); - metropolis->init_temperature_kinetic(itemperature, this->Level); - } - virtual void reprocess_each_temperature(size_t itemperature) - { - metropolis->cout_1(itemperature); - metropolis->cout_2(itemperature, this->Level); - } - virtual void preprocess_each_step_beyondloop(size_t itemperature, size_t istep) - { - metropolis->file_finish_metropolis(istep); - metropolis->reset_high_kinetic_energy(itemperature, istep); - metropolis->change_accept_rate(istep, this->Level); - metropolis->info.update_number = 0; // each step we renew every Jlq one by one. - } - virtual void move_variable(size_t itemperature, size_t istep) - { - Simulated_Annealing_Orbital::move_variable(itemperature, istep); - set_temperature( metropolis->kin_temp[metropolis->info.ic] ); - } - virtual bool must_reject_before(double new_function, size_t itemperature, size_t istep) - { - // make sure the new spillage value is in the range. - // otherwise, we don't even calculate the kinetic energy. - return metropolis->cal_spillage(this->Level) >= metropolis->min_spillage * metropolis->kappa; - } - virtual double cal_new_function(size_t itemperature, size_t istep) - { - set_old_function(metropolis->kin_last[metropolis->info.ic]); - return metropolis->cal_kinetic_energy(this->Level); - } - virtual void accept_process( double new_function, size_t itemperature, size_t istep) - { - Simulated_Annealing_Orbital::accept_process( new_function, itemperature, istep); - metropolis->kin_last[metropolis->info.ic] = new_function; - } +class Metropolis::Simulated_Annealing_Orbital_Kinetic : public Simulated_Annealing_Orbital { + public: + Simulated_Annealing_Orbital_Kinetic(Metropolis* metropolis_in, SpillageStep& Level_in) + : Simulated_Annealing_Orbital(metropolis_in, Level_in) {} + + private: + virtual void preprocess_each_temperature(size_t itemperature) { + metropolis->init_kin_states(); + Simulated_Annealing_Orbital::preprocess_each_temperature(itemperature); + metropolis->init_temperature_kinetic(itemperature, this->Level); + } + virtual void reprocess_each_temperature(size_t itemperature) { + metropolis->cout_1(itemperature); + metropolis->cout_2(itemperature, this->Level); + } + virtual void preprocess_each_step_beyondloop(size_t itemperature, size_t istep) { + metropolis->file_finish_metropolis(istep); + metropolis->reset_high_kinetic_energy(itemperature, istep); + metropolis->change_accept_rate(istep, this->Level); + metropolis->info.update_number = 0; // each step we renew every Jlq one by one. + } + virtual void move_variable(size_t itemperature, size_t istep) { + Simulated_Annealing_Orbital::move_variable(itemperature, istep); + set_temperature(metropolis->kin_temp[metropolis->info.ic]); + } + virtual bool must_reject_before(double new_function, size_t itemperature, size_t istep) { + // make sure the new spillage value is in the range. + // otherwise, we don't even calculate the kinetic energy. + return metropolis->cal_spillage(this->Level) >= metropolis->min_spillage * metropolis->kappa; + } + virtual double cal_new_function(size_t itemperature, size_t istep) { + set_old_function(metropolis->kin_last[metropolis->info.ic]); + return metropolis->cal_kinetic_energy(this->Level); + } + virtual void accept_process(double new_function, size_t itemperature, size_t istep) { + Simulated_Annealing_Orbital::accept_process(new_function, itemperature, istep); + metropolis->kin_last[metropolis->info.ic] = new_function; + } }; #endif \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageStep.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageStep.cpp index cbddc11550d..797a1a35681 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageStep.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageStep.cpp @@ -7,28 +7,24 @@ #include "../src_unittest/src_tools/common_test.h" #ifdef _OPENMP -#include +#include #endif -SpillageStep::SpillageStep() -{ +SpillageStep::SpillageStep() { test = 0; info = new Type_Information[1]; data = new Step_Data[1]; wayc = new Way2c4[1]; wayd = new Way2Data[1]; } -SpillageStep::~SpillageStep() -{ +SpillageStep::~SpillageStep() { delete[] info; delete[] data; delete[] wayc; delete[] wayd; } - -void SpillageStep::set_info(const int &ntype_in) -{ +void SpillageStep::set_info(const int& ntype_in) { this->ntype = ntype_in; cout << "\n Element type = " << ntype; assert(ntype > 0); @@ -37,17 +33,15 @@ void SpillageStep::set_info(const int &ntype_in) return; } -void SpillageStep::set_nwfc() -{ - TITLE("SpillageStep","set_nwfc"); - assert( ntype > 0); +void SpillageStep::set_nwfc() { + TITLE("SpillageStep", "set_nwfc"); + assert(ntype > 0); //=============================== // (1) generate nwfc, nwfc2 //=============================== this->nwfc = 0; this->nwfc2 = 0; - for (int i=0; iwayd[iw2].ic = ic; - if (test==2) cout << "\n iw2=" << iw2 << " ic=" << ic; + if (test == 2) + cout << "\n iw2=" << iw2 << " ic=" << ic; ++iw2; - }// end m - } - else if (info[it].fa[l] == "a") - { + } // end m + } else if (info[it].fa[l] == "a") { this->wayd[iw2].ic = ic; ++iw2; } ++ic; - }// end n - }// end l + } // end n + } // end l nw_this_type = iw2 - index_copy; - } - else - { - for (int j=index_copy; jwayd[iw2].ic = this->wayd[j].ic; - if (test==2) cout << "\n iw2=" << iw2 << " ic=" << wayd[iw2].ic; + if (test == 2) + cout << "\n iw2=" << iw2 << " ic=" << wayd[iw2].ic; iw2++; } } } } - //cout << "\n iw2 = " << iw2; - //cout << "\n nwfc2 = " << nwfc2; - assert(iw2==nwfc2); + // cout << "\n iw2 = " << iw2; + // cout << "\n nwfc2 = " << nwfc2; + assert(iw2 == nwfc2); return; } - -void SpillageStep::set_iw00(void) -{ +void SpillageStep::set_iw00(void) { //========================= // (3) generate iw00 //========================= int iw00 = 0; int iw2 = 0; - for (int it=0; it not equal."); + WARNING_QUIT("SpillageStep::set_iw00", "in not equal."); } - //cout << " type=" << it << " lmax=" << info[it].lmax << endl; - for (int i=0; i< NA[it]; i++) - { - //for (int l=0; l<= mz.lmax_type[it]; l++) - for (int l=0; l<= LMAXALL; l++) // mohan fix bug 2010-08-06 + // cout << " type=" << it << " lmax=" << info[it].lmax << endl; + for (int i = 0; i < NA[it]; i++) { + // for (int l=0; l<= mz.lmax_type[it]; l++) + for (int l = 0; l <= LMAXALL; l++) // mohan fix bug 2010-08-06 { - if ( l <= info[it].lmax ) - { - for (int n=0; nwayd[iw2].iw00 = copy;// position to get overlap. - if (test == 2) - { + for (int m = 0; m < 2 * l + 1; m++) { + this->wayd[iw2].iw00 = copy; // position to get overlap. + if (test == 2) { cout << "\n iw2=" << iw2 << " iw00=" << copy; } ++copy; ++iw2; } - } - else if ( info[it].fa[l] == "a" ) - { + } else if (info[it].fa[l] == "a") { this->wayd[iw2].iw00 = iw00; // just the start position to get overlap. ++iw2; } } } - iw00 += 2*l + 1; + iw00 += 2 * l + 1; } } } - if (iw00!=NWFCALL) - { + if (iw00 != NWFCALL) { cout << "\n iw00=" << iw00 << " NWFCALL=" << NWFCALL; - WARNING_QUIT("SpillageStep::set_iw00","iw00!=input.QS_data[0].nwfc"); + WARNING_QUIT("SpillageStep::set_iw00", "iw00!=input.QS_data[0].nwfc"); } - assert(iw2==nwfc2); + assert(iw2 == nwfc2); return; } - -void SpillageStep::set_nchi() -{ - if (test==1)TITLE("SpillageStep","set_nchi"); - assert( ntype >0 ); +void SpillageStep::set_nchi() { + if (test == 1) + TITLE("SpillageStep", "set_nchi"); + assert(ntype > 0); //========================= // (1) generate nchi //========================= this->nchi = 0; - for (int i=0; i 0 ); +void SpillageStep::allocate_data(const int& istep) { + if (test == 1) + TITLE("SpillageStep", "allocate_data"); + assert(nwfc > 0); delete[] this->data; - this->data = new Step_Data[ STRNUM ]; + this->data = new Step_Data[STRNUM]; this->ne = NE; - for ( int is=0; isnwfc, - this->nwfc2, - NWFCALL // all read in wave functions number + data[is].init(NKS, + input.QS_data[is].weight, + NBANDS, + NE, + this->nwfc, + this->nwfc2, + NWFCALL // all read in wave functions number ); - if (istep == 0) - { - for (int ik=0; ik 0 ) - { - for(int ik=0; ik< data[is].nks; ik++) - { - for(int ib=0; ib< data[is].nbands; ib++) - { - for(int ie=0; ie< data[is].ne; ie++) - { - data[is].Qin(ik, ib, iw_step, ie) = input.QS_data[is].Qin(ik, ib, iw, ie); - } - } - } - if(test==2)cout << "\n iw_step=" << iw_step << " iw=" << iw; - iw_step++; - } - } - iw++; - } - } - } + assert( info[it].na == input.QS_data[is].na[it] ); + for(int i=0; i< input.QS_data[is].na[it]; i++) + { + for(int l=0; l< input.QS_data[is].lmax+1; l++) + { + for(int m=0; m<2*l+1; m++) + { + // a break.. + if( l <= info[it].lmax ) + { + if( info[it].n[l] > 0 ) + { + for(int ik=0; ik< data[is].nks; ik++) + { + for(int ib=0; ib< data[is].nbands; ib++) + { + for(int ie=0; ie< data[is].ne; ie++) + { + data[is].Qin(ik, ib, iw_step, ie) = input.QS_data[is].Qin(ik, ib, iw, ie); + } + } + } + if(test==2)cout << "\n iw_step=" << iw_step << " iw=" << iw; + iw_step++; + } + } + iw++; + } + } + } } */ -// cout << "\n iw_step = " << iw_step; -// cout << "\n iw = " << iw; + // cout << "\n iw_step = " << iw_step; + // cout << "\n iw = " << iw; } return; } -void SpillageStep::init_QS_matrix( const int &istr) -{ - if (test==1)TITLE("SpillageStep","init_QS_matrix"); +void SpillageStep::init_QS_matrix(const int& istr) { + if (test == 1) + TITLE("SpillageStep", "init_QS_matrix"); - if (USEPW) - { + if (USEPW) { // notice! calculate_psi1d must consistent // with psi3d in the same init_QS_matrix // function. because the init_QS_matrix @@ -424,47 +377,36 @@ void SpillageStep::init_QS_matrix( const int &istr) PW.calculate_psi1d(); } - for (int ik = 0; ik < this->data[istr].nks; ik++) - { - if (USEPW) - { + for (int ik = 0; ik < this->data[istr].nks; ik++) { + if (USEPW) { PW.calculate_psi3d(ilevel, ik); } this->data[istr].Soverlap[ik].zero_out(); this->data[istr].Qoverlap[ik].zero_out(); // init Q matrix - for (int ib = 0; ib < this->data[istr].nbands; ib++) - { - for (int iw = 0; iw < this->data[istr].nwfc2; iw++) - { + for (int ib = 0; ib < this->data[istr].nbands; ib++) { + for (int iw = 0; iw < this->data[istr].nwfc2; iw++) { const int jw = this->wayd[iw].iw00; const int T = this->wayd[iw].type; const int L = this->wayd[iw].L; const int N = this->wayd[iw].N; - for (int ie=0; iedata[istr].ne; ie++) - { + for (int ie = 0; ie < this->data[istr].ne; ie++) { //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // if use 'full orbitals' - if ( this->wayd[iw].average == false) + if (this->wayd[iw].average == false) { + data[istr].Qoverlap[ik](iw, ib) += input.Coef.C4(T, L, N, ie) * data[istr].Qin(ik, ib, jw, ie); + } else // if use 'average orbitals' { - data[istr].Qoverlap[ik](iw,ib) += - input.Coef.C4( T, L, N, ie ) * - data[istr].Qin(ik, ib, jw, ie); - } - else// if use 'average orbitals' - { - const int nofm = 2*L+1; // number of m + const int nofm = 2 * L + 1; // number of m std::complex avalue = std::complex(0.0, 0.0); - for (int m=0; m< nofm; m++) - { - avalue += data[istr].Qin(ik, ib, jw+m, ie); + for (int m = 0; m < nofm; m++) { + avalue += data[istr].Qin(ik, ib, jw + m, ie); } avalue /= nofm; - data[istr].Qoverlap[ik](iw,ib) += - input.Coef.C4( T, L, N, ie ) * avalue; + data[istr].Qoverlap[ik](iw, ib) += input.Coef.C4(T, L, N, ie) * avalue; } //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> } @@ -472,123 +414,103 @@ void SpillageStep::init_QS_matrix( const int &istr) } // init S matrix - for (int iw=0; iwwayd[iw].type; const int L1 = this->wayd[iw].L; const int N1 = this->wayd[iw].N; const int iw001 = this->wayd[iw].iw00; //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - for (int iw2 = iw; iw2 < nwfc2; iw2++) - { + for (int iw2 = iw; iw2 < nwfc2; iw2++) { const int T2 = this->wayd[iw2].type; const int L2 = this->wayd[iw2].L; const int N2 = this->wayd[iw2].N; const int iw002 = this->wayd[iw2].iw00; - if (USEPW) - { + if (USEPW) { this->data[istr].Soverlap[ik](iw, iw2) = PW.calculateS(iw, iw2, ik); #ifdef __MPI Parallel_Reduce::reduce_complex_double_pool(this->data[istr].Soverlap[ik](iw, iw2)); #endif - } - else - { -// double value = 0.0; - for (int ie = 0; ie < ne; ie++) - { - for (int ie2 = 0; ie2 < ne; ie2++) - { + } else { + // double value = 0.0; + for (int ie = 0; ie < ne; ie++) { + for (int ie2 = 0; ie2 < ne; ie2++) { //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // case 1 - if ( !wayd[iw].average && !wayd[iw2].average) - { + if (!wayd[iw].average && !wayd[iw2].average) { this->data[istr].Soverlap[ik](iw, iw2) += - input.Coef.C4( T1, L1, N1, ie ) * - input.Coef.C4( T2, L2, N2, ie2) * + input.Coef.C4(T1, L1, N1, ie) * input.Coef.C4(T2, L2, N2, ie2) * input.QS_data[istr].Sq1q2[ik](iw001, iw002, ie, ie2); } // case 2 - else - { + else { std::complex avalue = std::complex(0.0, 0.0); // case 21 - if ( wayd[iw].average && wayd[iw2].average) - { - for (int m1=0; m1<2*L1+1; m1++) - { - for (int m2=0; m2<2*L2+1; m2++) - { - avalue += input.QS_data[istr].Sq1q2[ik](iw001+m1, iw002+m2, ie, ie2); + if (wayd[iw].average && wayd[iw2].average) { + for (int m1 = 0; m1 < 2 * L1 + 1; m1++) { + for (int m2 = 0; m2 < 2 * L2 + 1; m2++) { + avalue += input.QS_data[istr].Sq1q2[ik](iw001 + m1, iw002 + m2, ie, ie2); } } - avalue /= ((2*L1+1) * (2*L2+1)); + avalue /= ((2 * L1 + 1) * (2 * L2 + 1)); } // case 22 - if ( !wayd[iw].average && wayd[iw2].average) - { - for (int m2=0; m2<2*L2+1; m2++) - { - avalue += input.QS_data[istr].Sq1q2[ik](iw001, iw002+m2, ie, ie2); + if (!wayd[iw].average && wayd[iw2].average) { + for (int m2 = 0; m2 < 2 * L2 + 1; m2++) { + avalue += input.QS_data[istr].Sq1q2[ik](iw001, iw002 + m2, ie, ie2); } - avalue /= (2*L2+1); + avalue /= (2 * L2 + 1); } // case 23 - if ( wayd[iw].average && !wayd[iw2].average) - { - for (int m1=0; m1<2*L1+1; m1++) - { - avalue += input.QS_data[istr].Sq1q2[ik](iw001+m1, iw002, ie, ie2); + if (wayd[iw].average && !wayd[iw2].average) { + for (int m1 = 0; m1 < 2 * L1 + 1; m1++) { + avalue += input.QS_data[istr].Sq1q2[ik](iw001 + m1, iw002, ie, ie2); } - avalue /= (2*L1+1); + avalue /= (2 * L1 + 1); } this->data[istr].Soverlap[ik](iw, iw2) += - input.Coef.C4( T1, L1, N1, ie ) * - input.Coef.C4( T2, L2, N2, ie2) * - avalue; + input.Coef.C4(T1, L1, N1, ie) * input.Coef.C4(T2, L2, N2, ie2) * avalue; //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> } - }// ie2 - }// ie - }// iw - -// if(iw==3) -// { -// ofs_running << "\n iw=" << iw << " iw2=" << iw2 << " S[" << ik << "]=" << this->data[istr].Soverlap[ik](iw, iw2); -// } - }// ib + } // ie2 + } // ie + } // iw + + // if(iw==3) + // { + // ofs_running << "\n iw=" << iw << " iw2=" << iw2 << " S[" << ik << "]=" << + // this->data[istr].Soverlap[ik](iw, iw2); + // } + } // ib //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - }//ik - + } // ik -// if(ik==0) -// { -// PRINTCM("S", data[istr].Soverlap[ik]); -// PRINTCM("Q", data[istr].Qoverlap[ik]); -// } + // if(ik==0) + // { + // PRINTCM("S", data[istr].Soverlap[ik]); + // PRINTCM("Q", data[istr].Qoverlap[ik]); + // } // because S has symmetry : S^{+} = S -// for(int iw=0; iwdata[istr].inverse_S[ik].reset_loop(); - this->data[istr].inverse_S[ik].cal_inverse(this->data[istr].Soverlap[ik]); + this->data[istr].inverse_S[ik].reset_loop(); + this->data[istr].inverse_S[ik].cal_inverse(this->data[istr].Soverlap[ik]); // notice : only half A is stored!!! this->data[istr].Sinv[ik] = this->data[istr].inverse_S[ik].get_inverse(); - //if(ik==0) - //PRINTCM("init_QS_matrix :: Sinv",data[istr].inverse.A); + // if(ik==0) + // PRINTCM("init_QS_matrix :: Sinv",data[istr].inverse.A); } return; @@ -596,12 +518,10 @@ void SpillageStep::init_QS_matrix( const int &istr) // (1) Calculate The Spillage Value // (2) For each Coefficient(type,l,n,ie) changed orbital. -double SpillageStep::get_spillage( - const int &istr, // index of structure - const int &ic, // index of orbitals: (type,l,n) - const int &ie // index of eigenvalue of Jlq -) -{ +double SpillageStep::get_spillage(const int& istr, // index of structure + const int& ic, // index of orbitals: (type,l,n) + const int& ie // index of eigenvalue of Jlq +) { double spillage; // not need to initialized. double fill = 0.0; Step_Data* Stru = &this->data[istr]; @@ -613,61 +533,48 @@ double SpillageStep::get_spillage( static int bands_end; static int bands_number; - if (BANDS_CONTROL) - { + if (BANDS_CONTROL) { bands_start = BANDS_START; bands_end = BANDS_END; assert(BANDS_END <= Stru->nbands); bands_number = bands_end - bands_start; assert(bands_number <= Stru->nbands); - } - else - { + } else { bands_start = 0; bands_end = Stru->nbands; bands_number = bands_end - bands_start; } // (2) get new c4 coefficient from ic. - const double c4_new = input.Coef.C4( - this->wayc[ic].type, - this->wayc[ic].L, - this->wayc[ic].N, - ie); + const double c4_new = input.Coef.C4(this->wayc[ic].type, this->wayc[ic].L, this->wayc[ic].N, ie); // (3) get old c4 coefficient. - const double c4_old = input.Coef.C4_old( - this->wayc[ic].type, - this->wayc[ic].L, - this->wayc[ic].N, - ie); + const double c4_old = input.Coef.C4_old(this->wayc[ic].type, this->wayc[ic].L, this->wayc[ic].N, ie); int unstable = 0; - if (USEPW) - { + if (USEPW) { PW.nwfc2 = nwfc2; PW.update_psi1d(ilevel, ic, ie, c4_new, c4_old); } - //ofs_running << "\n ic_now = " << ic << " ie_now=" << ie; - - #ifdef _OPENMP // Peize Lin add 2016-01-18 - omp_lock_t unstable_lock; - omp_init_lock(&unstable_lock); - #endif - - //#ifdef _OPENMP - //omp_set_num_threads(8); // Peize Lin test - //#endif - - #ifdef _OPENMP - #pragma omp parallel for // Peize Lin add 2016-01-18 - #endif - for (int ik = 0; ik < Stru->nks ; ik++) - { - // cout << "ik=" << ik << endl; - // cout << "\n ik = " << ik <<" c4_new=" << c4_new << " c4_old=" << c4_old << " nks=" << Stru->nks << endl; + // ofs_running << "\n ic_now = " << ic << " ie_now=" << ie; + +#ifdef _OPENMP // Peize Lin add 2016-01-18 + omp_lock_t unstable_lock; + omp_init_lock(&unstable_lock); +#endif + + // #ifdef _OPENMP + // omp_set_num_threads(8); // Peize Lin test + // #endif + +#ifdef _OPENMP +#pragma omp parallel for // Peize Lin add 2016-01-18 +#endif + for (int ik = 0; ik < Stru->nks; ik++) { + // cout << "ik=" << ik << endl; + // cout << "\n ik = " << ik <<" c4_new=" << c4_new << " c4_old=" << c4_old << " nks=" << Stru->nks << endl; // If new Q,S corespodding to the new C4 // is not accepted. @@ -676,53 +583,43 @@ double SpillageStep::get_spillage( this->newQ(istr, ic, ie, ik, c4_new, c4_old); - if (USEPW) - { + if (USEPW) { PW.update_psi3d(ilevel, ic, ik); - timer::tick("PW_Basis","calculateS"); + timer::tick("PW_Basis", "calculateS"); // old version need to change pw_basis too - if (NPROC_IN_POOL==1) - { - for (int mu=0; muwayd[mu ].ic; + if (NPROC_IN_POOL == 1) { + for (int mu = 0; mu < nwfc2; mu++) { + for (int nu = mu; nu < nwfc2; nu++) { + const int ic1 = this->wayd[mu].ic; const int ic2 = this->wayd[nu].ic; - if (ic1==ic || ic2==ic) - { + if (ic1 == ic || ic2 == ic) { this->data[istr].Strial[ik](mu, nu) = PW.calculateS(mu, nu, ik); } } } - } - else - { - // may error when openmp? unchecked // Peize Lin note 2016-01-18 - #ifdef _OPENMP - if(0==omp_get_thread_num()) - cout<<"src_spillage/SpillageStep.cpp line1103 openmp "<wayd[mu].ic; const int ic2 = this->wayd[nu].ic; // a small trick - if (ic1==ic || ic2==ic) - { + if (ic1 == ic || ic2 == ic) { PW.save[count] = PW.calculateS(mu, nu, ik); PW.posmu[count] = mu; PW.posnu[count] = nu; - //this->data[istr].Strial[ik](mu, nu) = PW.calculateS(mu, nu, ik); - //ofs_running << "\n save=" << save[count] << " mu=" << mu << " nu=" << nu; + // this->data[istr].Strial[ik](mu, nu) = PW.calculateS(mu, nu, ik); + // ofs_running << "\n save=" << save[count] << " mu=" << mu << " nu=" << nu; ++count; } } @@ -730,141 +627,125 @@ double SpillageStep::get_spillage( #ifdef __MPI Parallel_Reduce::reduce_complex_double_pool(PW.save, count); #endif - for (int index=0; indexdata[istr].Strial[ik](PW.posmu[index], PW.posnu[index]) = PW.save[index]; - // ofs_running << "\n mu=" << pos[index*2] << " nu=" << pos[index*2+1] << " save=" << save[index]; + // ofs_running << "\n mu=" << pos[index*2] << " nu=" << pos[index*2+1] << " save=" << + // save[index]; } } - timer::tick("PW_Basis","calculateS"); - } - else - { + timer::tick("PW_Basis", "calculateS"); + } else { this->newS(istr, ic, ie, ik, c4_new, c4_old); } - Stru->inverse_S[ik].cal_inverse(Stru->Strial[ik]); // Peize Lin update 2015-12-05 - -// if(ik==3) -// { -// PRINTCM("S",data[istr].Strial[ik]); -// PRINTCM("Q",data[istr].Qtrial[ik]); -// PRINTCM("Sinv",Stru->inverse.A); -// } + Stru->inverse_S[ik].cal_inverse(Stru->Strial[ik]); // Peize Lin update 2015-12-05 -// BLOCK_HERE("spillage"); + // if(ik==3) + // { + // PRINTCM("S",data[istr].Strial[ik]); + // PRINTCM("Q",data[istr].Qtrial[ik]); + // PRINTCM("Sinv",Stru->inverse.A); + // } + + // BLOCK_HERE("spillage"); // assert all 'Stru' have same k points and bands. // mohan 2010-05-02 Stru->Mk[ik] = 0.00; -//>>>>> -// Keep the flexibility to calculate the spillage value -// of different number of bands for different structures - //for (int ib = 0; ib < Stru->nbands; ib++) -//<<<<< - //but now I want to calculate the spillage of given number of bands + //>>>>> + // Keep the flexibility to calculate the spillage value + // of different number of bands for different structures + // for (int ib = 0; ib < Stru->nbands; ib++) + //<<<<< + // but now I want to calculate the spillage of given number of bands //(1)from input, for all steps. (2) for each step. - for (int ib=bands_start; ibMkb_used(ik,ib) = 0.0; - for (int iw = 0; iw < Stru->nwfc2; iw++) - { - for (int iw2 = 0; iw2 < Stru->nwfc2; iw2++) - { - //Mk += (conj(Qtrial[ik](iw, ib)) * sinv(iw, iw2) * Qtrial[ik](iw2, ib)).real(); - if (iw <= iw2) - { - Stru->Mkb_used(ik,ib) += (conj( Stru->Qtrial[ik](iw, ib)) - * Stru->inverse_S[ik].get_inverse()(iw, iw2) // Peize Lin update 2015-12-05 - * Stru->Qtrial[ik](iw2, ib)).real(); - } - else - { - Stru->Mkb_used(ik,ib) += (conj( Stru->Qtrial[ik](iw, ib)) - * conj( Stru->inverse_S[ik].get_inverse()(iw2, iw)) // Peize Lin update 2015-12-05 - * Stru->Qtrial[ik](iw2, ib)).real(); + for (int ib = bands_start; ib < bands_end; ib++) { + Stru->Mkb_used(ik, ib) = 0.0; + for (int iw = 0; iw < Stru->nwfc2; iw++) { + for (int iw2 = 0; iw2 < Stru->nwfc2; iw2++) { + // Mk += (conj(Qtrial[ik](iw, ib)) * sinv(iw, iw2) * Qtrial[ik](iw2, ib)).real(); + if (iw <= iw2) { + Stru->Mkb_used(ik, ib) += + (conj(Stru->Qtrial[ik](iw, ib)) * + Stru->inverse_S[ik].get_inverse()(iw, iw2) // Peize Lin update 2015-12-05 + * Stru->Qtrial[ik](iw2, ib)) + .real(); + } else { + Stru->Mkb_used(ik, ib) += + (conj(Stru->Qtrial[ik](iw, ib)) * + conj(Stru->inverse_S[ik].get_inverse()(iw2, iw)) // Peize Lin update 2015-12-05 + * Stru->Qtrial[ik](iw2, ib)) + .real(); } } } - Stru->Mk[ik] += Stru->Mkb_used(ik,ib); - //ofs_running << "ik=" << ik << " ib=" << ib << " Mk=" << Stru->Mk[ik] << endl; + Stru->Mk[ik] += Stru->Mkb_used(ik, ib); + // ofs_running << "ik=" << ik << " ib=" << ib << " Mk=" << Stru->Mk[ik] << endl; } Stru->Mk[ik] /= (double)bands_number; - //cout << endl; - - // in fact this is caused by numerical unstability. - #ifdef _OPENMP - omp_set_lock(&unstable_lock); // Peize Lin add 2016-01-18 - #endif - //if (Stru->Mk[ik]*Stru->weight[ik] > upbound)//mohan fix bug 2010-06-14 - if (fill > Stru->spillage0 )//mohan refix bug 2010-06-18 +// cout << endl; + +// in fact this is caused by numerical unstability. +#ifdef _OPENMP + omp_set_lock(&unstable_lock); // Peize Lin add 2016-01-18 +#endif + // if (Stru->Mk[ik]*Stru->weight[ik] > upbound)//mohan fix bug 2010-06-14 + if (fill > Stru->spillage0) // mohan refix bug 2010-06-18 { ++unstable; - } - else if (Stru->Mk[ik] < 0.0) - { + } else if (Stru->Mk[ik] < 0.0) { ++unstable; - } - else - { + } else { fill += Stru->Mk[ik] * Stru->weight[ik]; } - #ifdef _OPENMP - omp_unset_lock(&unstable_lock); // Peize Lin add 2016-01-18 - #endif - }//end ik +#ifdef _OPENMP + omp_unset_lock(&unstable_lock); // Peize Lin add 2016-01-18 +#endif + } // end ik #ifdef __MPI -// Parallel_Reduce::reduce_int_all(unstable); - if (unstable>0) - { + // Parallel_Reduce::reduce_int_all(unstable); + if (unstable > 0) { ofs_running << "\n unstable=" << unstable; - //return Stru->spillage0; + // return Stru->spillage0; } Parallel_Reduce::reduce_double_allpool(fill); #endif spillage = Stru->spillage0 - fill; - - if (spillage < 0.0 || spillage > 1.0 || unstable) - { - -// Peize Lin test -for (int ik = 0; ik < Stru->nks ; ik++) -{ - //cout<<"ik:\t"<Strial[ik]); - cout_matrix( Stru->inverse_S[ik].get_inverse()); - for( size_t i=0; iStrial[ik].nr; ++i) - for( size_t j=0; jStrial[ik](i,j) = conj(Stru->Strial[ik](j,i)); - ComplexMatrix inverse_tmp(Stru->inverse_S[ik].get_inverse()); - for( size_t i=0; iStrial[ik] * inverse_tmp); -} - cout << "\n spillage0 = " << Stru->spillage0; - cout << "\n Type=" << this->wayc[ic].type - << " L=" << this->wayc[ic].L - << " N=" << this->wayc[ic].N; + if (spillage < 0.0 || spillage > 1.0 || unstable) { + + // Peize Lin test + for (int ik = 0; ik < Stru->nks; ik++) { + // cout<<"ik:\t"<Strial[ik]); + cout_matrix(Stru->inverse_S[ik].get_inverse()); + for (size_t i = 0; i < Stru->Strial[ik].nr; ++i) + for (size_t j = 0; j < i; ++j) + Stru->Strial[ik](i, j) = conj(Stru->Strial[ik](j, i)); + ComplexMatrix inverse_tmp(Stru->inverse_S[ik].get_inverse()); + for (size_t i = 0; i < inverse_tmp.nr; ++i) + for (size_t j = 0; j < i; ++j) + inverse_tmp(i, j) = conj(inverse_tmp(j, i)); + cout_matrix(Stru->Strial[ik] * inverse_tmp); + } + + cout << "\n spillage0 = " << Stru->spillage0; + cout << "\n Type=" << this->wayc[ic].type << " L=" << this->wayc[ic].L << " N=" << this->wayc[ic].N; cout << "\n bands_number = " << bands_number; - for (int ib=0; ibMkb_used(ik,ib) * Stru->weight[ik]/bands_number; + for (int ik = 0; ik < NKS; ik++) { + mm += Stru->Mkb_used(ik, ib) * Stru->weight[ik] / bands_number; } cout << "\n ib=" << ib << " new fill=" << mm; } double sum = 0.0; - for (int ik=0; ikMk[ik]; sum += Stru->Mk[ik] * Stru->weight[ik]; } @@ -877,39 +758,33 @@ for (int ik = 0; ik < Stru->nks ; ik++) return spillage; } - -void SpillageStep::newQ( const int &istr, const int &ic, const int &ie, const int &ik, - const double &c4_now ,const double &c4_old) -{ -// TITLE("SpillageStep","newQ"); +void SpillageStep::newQ(const int& istr, + const int& ic, + const int& ie, + const int& ik, + const double& c4_now, + const double& c4_old) { + // TITLE("SpillageStep","newQ"); const double delta = c4_now - c4_old; - for (int iw = 0; iw < nwfc2; iw++) - { + for (int iw = 0; iw < nwfc2; iw++) { const int jw = this->wayd[iw].iw00; - if ( this->wayd[iw].ic == ic) - { + if (this->wayd[iw].ic == ic) { //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - if ( !wayd[iw].average ) - { + if (!wayd[iw].average) { // the change of dQ= is due to // the change of Jlq(iw)=delta(Jlq(iw)) - for (int ib = 0; ib < this->data[istr].nbands; ib++) - { - this->data[istr].Qtrial[ik](iw, ib) += delta - * this->data[istr].Qin(ik, ib, jw, ie); + for (int ib = 0; ib < this->data[istr].nbands; ib++) { + this->data[istr].Qtrial[ik](iw, ib) += delta * this->data[istr].Qin(ik, ib, jw, ie); } - } - else // if use average orbital + } else // if use average orbital { const int L = wayd[iw].L; - for (int ib = 0; ib < this->data[istr].nbands; ib++) - { + for (int ib = 0; ib < this->data[istr].nbands; ib++) { std::complex avalue = std::complex(0.0, 0.0); - for (int m=0; m<2*L+1; m++) - { - avalue += this->data[istr].Qin(ik, ib, jw+m, ie); + for (int m = 0; m < 2 * L + 1; m++) { + avalue += this->data[istr].Qin(ik, ib, jw + m, ie); } - avalue /= (2*L+1); + avalue /= (2 * L + 1); this->data[istr].Qtrial[ik](iw, ib) += delta * avalue; } } @@ -919,12 +794,13 @@ void SpillageStep::newQ( const int &istr, const int &ic, const int &ie, const in return; } - -void SpillageStep::newS( - const int &istr, const int &ic, const int &ie, const int &ik, - const double &c4_now ,const double &c4_old) -{ -// TITLE("SpillageStep","newS"); +void SpillageStep::newS(const int& istr, + const int& ic, + const int& ie, + const int& ik, + const double& c4_now, + const double& c4_old) { + // TITLE("SpillageStep","newS"); // example c = c2, ie2 = ie //========================================================================================================== // iw0-s iw1p1 iw2p2 iw3p3 iw4s @@ -967,8 +843,7 @@ void SpillageStep::newS( //================================================= // search in all wavefunction ( type, i, l, m, n ) //================================================= - for (int iw = 0; iw < this->data[istr].nwfc2; iw++) - { + for (int iw = 0; iw < this->data[istr].nwfc2; iw++) { const int jw = this->wayd[iw].iw00; const int ic1 = this->wayd[iw].ic; const int T1 = this->wayd[iw].type; @@ -979,125 +854,95 @@ void SpillageStep::newS( //============================================= // search in all other eigenvalues (ic1 != ic). //============================================= - for (int ie1 = 0; ie1 < this->data[istr].ne; ie1++) - { + for (int ie1 = 0; ie1 < this->data[istr].ne; ie1++) { // update for the 'ic' row - if ( ie1 != ie || ic1 !=ic ) - { - for (int iw2 = iw; iw2 < this->data[istr].nwfc2; iw2++) - { + if (ie1 != ie || ic1 != ic) { + for (int iw2 = iw; iw2 < this->data[istr].nwfc2; iw2++) { const int kw = this->wayd[iw2].iw00; - if (this->wayd[iw2].ic == ic) - { + if (this->wayd[iw2].ic == ic) { // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // case 1 - if ( !wayd[iw].average && !wayd[iw2].average) - { - this->data[istr].Strial[ik](iw, iw2) += - (c4_now * input.Coef.C4( T1, L1, N1, ie1 ) - - c4_old * input.Coef.C4_old( T1, L1, N1, ie1 ) ) - * input.QS_data[istr].Sq1q2[ik](jw, kw, ie1, ie); - } - else // case 2 + if (!wayd[iw].average && !wayd[iw2].average) { + this->data[istr].Strial[ik](iw, iw2) += (c4_now * input.Coef.C4(T1, L1, N1, ie1) - + c4_old * input.Coef.C4_old(T1, L1, N1, ie1)) * + input.QS_data[istr].Sq1q2[ik](jw, kw, ie1, ie); + } else // case 2 { const int L2 = this->wayd[iw2].L; std::complex avalue = std::complex(0.0, 0.0); // case 2.1 - if ( wayd[iw].average && !wayd[iw2].average) - { - for (int m1=0; m1<2*L1+1; m1++) - { - avalue += input.QS_data[istr].Sq1q2[ik](jw+m1, kw, ie1, ie); + if (wayd[iw].average && !wayd[iw2].average) { + for (int m1 = 0; m1 < 2 * L1 + 1; m1++) { + avalue += input.QS_data[istr].Sq1q2[ik](jw + m1, kw, ie1, ie); } - avalue /= (2*L1+1); + avalue /= (2 * L1 + 1); } // case 2.2 - if ( !wayd[iw].average && wayd[iw2].average) - { - for (int m2=0; m2<2*L2+1; m2++) - { - avalue += input.QS_data[istr].Sq1q2[ik](jw, kw+m2, ie1, ie); + if (!wayd[iw].average && wayd[iw2].average) { + for (int m2 = 0; m2 < 2 * L2 + 1; m2++) { + avalue += input.QS_data[istr].Sq1q2[ik](jw, kw + m2, ie1, ie); } - avalue /= (2*L2+1); + avalue /= (2 * L2 + 1); } // case 2.3 - if ( wayd[iw].average && wayd[iw2].average) - { - for (int m1=0; m1<2*L1+1; m1++) - { - for (int m2=0; m2<2*L2+1; m2++) - { - avalue += input.QS_data[istr].Sq1q2[ik](jw+m1, kw+m2, ie1, ie); + if (wayd[iw].average && wayd[iw2].average) { + for (int m1 = 0; m1 < 2 * L1 + 1; m1++) { + for (int m2 = 0; m2 < 2 * L2 + 1; m2++) { + avalue += input.QS_data[istr].Sq1q2[ik](jw + m1, kw + m2, ie1, ie); } } - avalue /= ( (2*L1+1)*(2*L2+1) ); + avalue /= ((2 * L1 + 1) * (2 * L2 + 1)); } - this->data[istr].Strial[ik](iw, iw2) += - (c4_now * input.Coef.C4( T1, L1, N1, ie1 ) - - c4_old * input.Coef.C4_old( T1, L1, N1, ie1 ) ) - * avalue; + this->data[istr].Strial[ik](iw, iw2) += (c4_now * input.Coef.C4(T1, L1, N1, ie1) - + c4_old * input.Coef.C4_old(T1, L1, N1, ie1)) * + avalue; } // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> } } - } - else - { - for (int iw2 = iw; iw2 < this->data[istr].nwfc2; iw2++) - { + } else { + for (int iw2 = iw; iw2 < this->data[istr].nwfc2; iw2++) { const int ic2 = this->wayd[iw2].ic; const int kw = this->wayd[iw2].iw00; const int T2 = this->wayd[iw2].type; const int L2 = this->wayd[iw2].L; const int N2 = this->wayd[iw2].N; - for (int ie2 = 0; ie2 < this->data[istr].ne; ie2++) - { + for (int ie2 = 0; ie2 < this->data[istr].ne; ie2++) { // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - if ( !wayd[iw].average && !wayd[iw2].average) - { - this->data[istr].Strial[ik](iw, iw2) += - (c4_now * input.Coef.C4( T2, L2, N2, ie2 ) - - c4_old * input.Coef.C4_old( T2, L2, N2, ie2 ) ) - * input.QS_data[istr].Sq1q2[ik](jw, kw, ie, ie2); - } - else // case 2 + if (!wayd[iw].average && !wayd[iw2].average) { + this->data[istr].Strial[ik](iw, iw2) += (c4_now * input.Coef.C4(T2, L2, N2, ie2) - + c4_old * input.Coef.C4_old(T2, L2, N2, ie2)) * + input.QS_data[istr].Sq1q2[ik](jw, kw, ie, ie2); + } else // case 2 { const int L2 = this->wayd[iw2].L; std::complex avalue = std::complex(0.0, 0.0); // case 2.1 - if ( wayd[iw].average && !wayd[iw2].average) - { - for (int m1=0; m1<2*L1+1; m1++) - { - avalue += input.QS_data[istr].Sq1q2[ik](jw+m1, kw, ie, ie2); + if (wayd[iw].average && !wayd[iw2].average) { + for (int m1 = 0; m1 < 2 * L1 + 1; m1++) { + avalue += input.QS_data[istr].Sq1q2[ik](jw + m1, kw, ie, ie2); } - avalue /= (2*L1+1); + avalue /= (2 * L1 + 1); } // case 2.2 - if ( !wayd[iw].average && wayd[iw2].average) - { - for (int m2=0; m2<2*L2+1; m2++) - { - avalue += input.QS_data[istr].Sq1q2[ik](jw, kw+m2, ie, ie2); + if (!wayd[iw].average && wayd[iw2].average) { + for (int m2 = 0; m2 < 2 * L2 + 1; m2++) { + avalue += input.QS_data[istr].Sq1q2[ik](jw, kw + m2, ie, ie2); } - avalue /= (2*L2+1); + avalue /= (2 * L2 + 1); } // case 2.3 - if ( wayd[iw].average && wayd[iw2].average) - { - for (int m1=0; m1<2*L1+1; m1++) - { - for (int m2=0; m2<2*L2+1; m2++) - { - avalue += input.QS_data[istr].Sq1q2[ik](jw+m1, kw+m2, ie, ie2); + if (wayd[iw].average && wayd[iw2].average) { + for (int m1 = 0; m1 < 2 * L1 + 1; m1++) { + for (int m2 = 0; m2 < 2 * L2 + 1; m2++) { + avalue += input.QS_data[istr].Sq1q2[ik](jw + m1, kw + m2, ie, ie2); } } - avalue /= ( (2*L1+1)*(2*L2+1) ); + avalue /= ((2 * L1 + 1) * (2 * L2 + 1)); } - this->data[istr].Strial[ik](iw, iw2) += - (c4_now * input.Coef.C4( T2, L2, N2, ie2 ) - - c4_old * input.Coef.C4_old( T2, L2, N2, ie2 ) ) - * avalue; + this->data[istr].Strial[ik](iw, iw2) += (c4_now * input.Coef.C4(T2, L2, N2, ie2) - + c4_old * input.Coef.C4_old(T2, L2, N2, ie2)) * + avalue; } // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> } @@ -1110,17 +955,12 @@ void SpillageStep::newS( return; } - - -void SpillageStep::updateQS( const int &istr ) -{ -// if(test==1)TITLE("SpillageStep","updateQS"); - for (int ik=0; ik< data[istr].nks; ik++) - { +void SpillageStep::updateQS(const int& istr) { + // if(test==1)TITLE("SpillageStep","updateQS"); + for (int ik = 0; ik < data[istr].nks; ik++) { data[istr].Qoverlap[ik] = data[istr].Qtrial[ik]; data[istr].Soverlap[ik] = data[istr].Strial[ik]; - data[istr].inverse_S[ik].update(); // Peize Lin update 2015-12-05 - } + data[istr].inverse_S[ik].update(); // Peize Lin update 2015-12-05 + } return; } - diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageStep.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageStep.h index 6b3afcc8467..1c0ef639fd8 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageStep.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageStep.h @@ -9,25 +9,25 @@ // of each orbital. struct Way2Data // dimension : nwfc2 { - int type; - int i; // atom index - int L; - int N; - int m; // mohan add 2010-06-16 + int type; + int i; // atom index + int L; + int N; + int m; // mohan add 2010-06-16 - int iw0; // to label , which not include 'N', but not used now, - int iw00; // to - int ic; + int iw0; // to label , which not include 'N', but not used now, + int iw00; // to + int ic; - bool average; // mohan add 2009-07-12 + bool average; // mohan add 2009-07-12 }; struct Way2c4 // dimension : nchi { - int type; - int L; - int N; - char spd; //mohan add 2010-04-17, the orbital type. + int type; + int L; + int N; + char spd; // mohan add 2010-04-17, the orbital type. }; // (1) It's a memeber of MultiZeta. @@ -36,43 +36,39 @@ struct Way2c4 // dimension : nchi // (4) It also defines the main routine to calculate the spillage value. // (5) Also the update of Q and S matrix using complicated index. // (6) It also contains four calss: Type_Information; Step_Data; Way2c4; Way2Data; -class SpillageStep -{ - public: - SpillageStep(); - ~SpillageStep(); - - Type_Information *info; // dimension : type - Step_Data *data; - Way2c4 *wayc; - Way2Data *wayd; +class SpillageStep { + public: + SpillageStep(); + ~SpillageStep(); - void set_info(const int &ntype_in); - void set_nwfc(void); - void set_iw00(void); - void set_nchi(void); + Type_Information* info; // dimension : type + Step_Data* data; + Way2c4* wayc; + Way2Data* wayd; - // allocate data for current level. - void allocate_data( const int &istep); + void set_info(const int& ntype_in); + void set_nwfc(void); + void set_iw00(void); + void set_nchi(void); - void init_QS_matrix( const int &is); - double get_spillage( const int &is, const int &ic, const int &ie); - void updateQS( const int &is ); + // allocate data for current level. + void allocate_data(const int& istep); - int ntype; - int nchi; // total radial wave functions(T,L,N); - int nwfc2; - int ne; - int ilevel; + void init_QS_matrix(const int& is); + double get_spillage(const int& is, const int& ic, const int& ie); + void updateQS(const int& is); - private: + int ntype; + int nchi; // total radial wave functions(T,L,N); + int nwfc2; + int ne; + int ilevel; - void newQ( const int &is, const int &ic, const int &ie, const int &ik, - const double &c4_now, const double &c4_old); - void newS( const int &is, const int &ic, const int &ie, const int &ik, - const double &c4_now ,const double &c4_old); + private: + void newQ(const int& is, const int& ic, const int& ie, const int& ik, const double& c4_now, const double& c4_old); + void newS(const int& is, const int& ic, const int& ie, const int& ik, const double& c4_now, const double& c4_old); - int test; - int nwfc; + int test; + int nwfc; }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageValue.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageValue.cpp index 78e7146b6ab..ac7ceccb5d3 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageValue.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageValue.cpp @@ -1,139 +1,112 @@ #include "SpillageValue.h" #include "tools.h" -SpillageValue::SpillageValue() -{ - dim = 0; - value = new double[1]; - value_old = new double[1]; +SpillageValue::SpillageValue() { + dim = 0; + value = new double[1]; + value_old = new double[1]; } -SpillageValue::~SpillageValue() -{ - delete[] value; - delete[] value_old; +SpillageValue::~SpillageValue() { + delete[] value; + delete[] value_old; } -void SpillageValue::allocate( const int &dim_in ) -{ - this->dim = dim_in; - assert( dim < 100); - assert( dim > 0); - - delete[] value; - delete[] value_old; - value = new double[dim]; - value_old = new double[dim]; +void SpillageValue::allocate(const int& dim_in) { + this->dim = dim_in; + assert(dim < 100); + assert(dim > 0); - // assume max step < 100 - const int max_levels = 100; - value_each_level.create(dim, max_levels); - - this->reset(); + delete[] value; + delete[] value_old; + value = new double[dim]; + value_old = new double[dim]; - return; + // assume max step < 100 + const int max_levels = 100; + value_each_level.create(dim, max_levels); + + this->reset(); + + return; } -void SpillageValue::reset(void) -{ - for(int i=0; ivalue; - } - else - { - v = this->value_old; - } - - double mv=0.0; - // case 1: // get the largest spillage value. - if( abs(SCHEME_VALUE)==1) - { - for(int i=0; ivalue; + } else { + v = this->value_old; + } + + double mv = 0.0; + // case 1: // get the largest spillage value. + if (abs(SCHEME_VALUE) == 1) { + for (int i = 0; i < dim; i++) { + mv = std::max(mv, v[i]); + } + return mv; + } + // case 2: // get average spillage value. + else if (abs(SCHEME_VALUE) == 2) { + for (int i = 0; i < dim; i++) { + mv += v[i] / dim; + } + return mv; + } + // case 3: // mixture of case 1 and 2 + else if (abs(SCHEME_VALUE) == 3) { + double average = 0.0; + for (int i = 0; i < dim; i++) { + average += v[i] / dim; + } - double max_diverse = 0.0; - double avg_diverse = 0.0; - for(int i=0; ivalue_each_level(i ,ilevel) = value_old[i]; - } - return; +void SpillageValue::save_level(const int& ilevel) { + // dim stands for number of structures. + for (int i = 0; i < dim; i++) { + this->value_each_level(i, ilevel) = value_old[i]; + } + return; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageValue.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageValue.h index b0827a60f01..4a5e91a6195 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageValue.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/SpillageValue.h @@ -4,52 +4,49 @@ #include "common.h" -class SpillageValue -{ - friend class Read_INPUT; - - friend class MultiZeta; - // in multizeta, 'value_old' are calculated. - - friend class Metropolis; - // in metropolis, 'value' are set. - - friend class Out_Orbital; - // in OurOrbital, 'value each level' are used. - - public: - - // 1: get new spillage value. - // 0: get old spillage value. - double cal_defined_value( bool get_new_flag); - - void update_value(); - - void out(); - - void save_level( const int &ilevel); - - private: - - // spillage value for each structure. - double *value; - - // the previous spillage value for each structure. - double *value_old; - - // spillage for all structures. - matrix value_each_level; - - // dimension is the number of structures. - // eg. 5 different dimers. - int dim; - - void allocate( const int &dim_in ); - - void reset(); - - SpillageValue(); - ~SpillageValue(); +class SpillageValue { + friend class Read_INPUT; + + friend class MultiZeta; + // in multizeta, 'value_old' are calculated. + + friend class Metropolis; + // in metropolis, 'value' are set. + + friend class Out_Orbital; + // in OurOrbital, 'value each level' are used. + + public: + // 1: get new spillage value. + // 0: get old spillage value. + double cal_defined_value(bool get_new_flag); + + void update_value(); + + void out(); + + void save_level(const int& ilevel); + + private: + // spillage value for each structure. + double* value; + + // the previous spillage value for each structure. + double* value_old; + + // spillage for all structures. + matrix value_each_level; + + // dimension is the number of structures. + // eg. 5 different dimers. + int dim; + + void allocate(const int& dim_in); + + void reset(); + + SpillageValue(); + ~SpillageValue(); }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Step_Data.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Step_Data.cpp index 224f67ab796..a4d97409527 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Step_Data.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Step_Data.cpp @@ -1,103 +1,92 @@ #include "Step_Data.h" #include "../src_tools/complexmatrix_inline.h" -Step_Data::Step_Data() -{ -// TITLE("Step_Data","Step_Data"); - Qoverlap = new ComplexMatrix[1]; - Soverlap = new ComplexMatrix[1]; - Qtrial = new ComplexMatrix[1]; - Strial = new ComplexMatrix[1]; - weight = new double[1]; - Sinv = new ComplexMatrix[1]; - inverse_S = new Inverse_Matrix_S[1]; - Mk = new double[1]; - test = 0; +Step_Data::Step_Data() { + // TITLE("Step_Data","Step_Data"); + Qoverlap = new ComplexMatrix[1]; + Soverlap = new ComplexMatrix[1]; + Qtrial = new ComplexMatrix[1]; + Strial = new ComplexMatrix[1]; + weight = new double[1]; + Sinv = new ComplexMatrix[1]; + inverse_S = new Inverse_Matrix_S[1]; + Mk = new double[1]; + test = 0; } -Step_Data::~Step_Data() -{ -// TITLE("Step_Data","~Step_Data"); - delete[] Qoverlap; - delete[] Soverlap; - delete[] Qtrial; - delete[] Strial; - delete[] weight; - delete[] Sinv; - delete[] inverse_S; - delete[] Mk; +Step_Data::~Step_Data() { + // TITLE("Step_Data","~Step_Data"); + delete[] Qoverlap; + delete[] Soverlap; + delete[] Qtrial; + delete[] Strial; + delete[] weight; + delete[] Sinv; + delete[] inverse_S; + delete[] Mk; } -void Step_Data::init( - const int &nks_in, - const double* weight_in, - const int &nbands_in, - const int &ne_in, - const int &nwfc_in, - const int &nwfc2_in, - const int &nwfc_all_in) -{ - if(test==1)TITLE("Step_Data","init"); - this->nks = nks_in; - assert(nks > 0); - - delete[] Mk; //mohan add 2010-05-02 - this->Mk = new double[nks]; - ZEROS( Mk, nks ); - - delete[] weight; - this->weight = new double[nks]; - for(int ik=0; iknbands = nbands_in; - - assert(nbands > 0); - this->Mkb.create(nks, nbands);//mohan add 2010-05-02 - this->Mkb_used.create(nks, nbands); - this->Mkb.zero_out(); - this->Mkb_used.zero_out(); - - this->ne = ne_in; - this->nwfc = nwfc_in; - this->nwfc2 = nwfc2_in; - this->nwfc_all = nwfc_all_in; - - - if(test==1) - { - cout << "\n" << setw(10) << "nwfc" - << setw(10) << "nwfc2" - << setw(10) << "nwfc_all"; - - cout << "\n" << setw(10) << nwfc - << setw(10) << nwfc2 - << setw(10) << nwfc_all; - } - - this->allocate(); - - return; +void Step_Data::init(const int& nks_in, + const double* weight_in, + const int& nbands_in, + const int& ne_in, + const int& nwfc_in, + const int& nwfc2_in, + const int& nwfc_all_in) { + if (test == 1) + TITLE("Step_Data", "init"); + this->nks = nks_in; + assert(nks > 0); + + delete[] Mk; // mohan add 2010-05-02 + this->Mk = new double[nks]; + ZEROS(Mk, nks); + + delete[] weight; + this->weight = new double[nks]; + for (int ik = 0; ik < nks; ik++) { + weight[ik] = weight_in[ik]; + } + this->nbands = nbands_in; + + assert(nbands > 0); + this->Mkb.create(nks, nbands); // mohan add 2010-05-02 + this->Mkb_used.create(nks, nbands); + this->Mkb.zero_out(); + this->Mkb_used.zero_out(); + + this->ne = ne_in; + this->nwfc = nwfc_in; + this->nwfc2 = nwfc2_in; + this->nwfc_all = nwfc_all_in; + + if (test == 1) { + cout << "\n" << setw(10) << "nwfc" << setw(10) << "nwfc2" << setw(10) << "nwfc_all"; + + cout << "\n" << setw(10) << nwfc << setw(10) << nwfc2 << setw(10) << nwfc_all; + } + + this->allocate(); + + return; } -void Step_Data::allocate() -{ +void Step_Data::allocate() { this->Qin.create(nks, nbands, nwfc_all, ne); return; } // be called in Multi_Zeta.cpp -void Step_Data::initQS(void) -{ - if(test==1) TITLE("Step_Data","initQS"); - assert(nks > 0); - assert(nbands > 0); - assert(nwfc > 0); // nwfc is for , - assert(ne > 0); - - delete[] Qtrial; - delete[] Strial; +void Step_Data::initQS(void) { + if (test == 1) + TITLE("Step_Data", "initQS"); + assert(nks > 0); + assert(nbands > 0); + assert(nwfc > 0); // nwfc is for , + assert(ne > 0); + + delete[] Qtrial; + delete[] Strial; delete[] Qoverlap; delete[] Soverlap; delete[] Sinv; @@ -110,18 +99,14 @@ void Step_Data::initQS(void) this->Sinv = new ComplexMatrix[nks]; this->inverse_S = new Inverse_Matrix_S[nks]; - for(int ik=0; ik=-1); - delete[] n; - delete[] nbase; - delete[] fa; - n = new int[lmax+1]; - nbase = new int[lmax+1]; - fa = new string[lmax+1]; - for(int i=0; i= -1); + delete[] n; + delete[] nbase; + delete[] fa; + n = new int[lmax + 1]; + nbase = new int[lmax + 1]; + fa = new string[lmax + 1]; + for (int i = 0; i < lmax + 1; i++) { + n[i] = nbase[i] = 0; + } + return; } -void Type_Information::cal_nmax() -{ - this->nmax = 0; - for(int l=0; lnmax = std::max( nmax, n[l]+nbase[l] ); - } -// cout << "\n nmax = " << nmax; - return; +void Type_Information::cal_nmax() { + this->nmax = 0; + for (int l = 0; l < lmax + 1; l++) { + this->nmax = std::max(nmax, n[l] + nbase[l]); + } + // cout << "\n nmax = " << nmax; + return; } -void Type_Information::cal_nw(void) -{ - TITLE("Type_Information","cal_nw"); - // where is this lmax from ? - // in Multi_Zeta, - // read in from file directly - // for each level and each type. +void Type_Information::cal_nw(void) { + TITLE("Type_Information", "cal_nw"); + // where is this lmax from ? + // in Multi_Zeta, + // read in from file directly + // for each level and each type. - // be called in SpillageStep. + // be called in SpillageStep. - // nw2: number of total local orbitals. - // (ia, l, n, m) - // Including multi-zeta orbitals, - // which are made up from same Jl(q). + // nw2: number of total local orbitals. + // (ia, l, n, m) + // Including multi-zeta orbitals, + // which are made up from same Jl(q). this->nw2 = 0; - for(int l=0; l 1 - // f orbitals, 7 ==> 1 - } - //cout << "\n nw = " << nw; + for (int l = 0; l < lmax + 1; l++) { + if (fa[l] == "f") { + nw2 += (2 * l + 1) * n[l] * na; + } else if (fa[l] == "a") { + nw2 += 1 * na; // 1 means average orbital used, + // for example, d orbitals 5 ==> 1 + // f orbitals, 7 ==> 1 + } + // cout << "\n nw = " << nw; } - // nw: number of overlap we must save. - // doesn't consider n[l], - // the only condition is n[l] > 0 in this atom species. - this->nw = 0; - for(int l=0; l0) - { - nw += (2*l+1)*na; - } - } + // nw: number of overlap we must save. + // doesn't consider n[l], + // the only condition is n[l] > 0 in this atom species. + this->nw = 0; + for (int l = 0; l < lmax + 1; l++) { + // warning : in different step, n[l] value may be different. + if (n[l] > 0) { + nw += (2 * l + 1) * na; + } + } - cout << " cal_nw::nw = " << nw; - cout << " cal_nw::nw2 = " << nw2 << endl; + cout << " cal_nw::nw = " << nw; + cout << " cal_nw::nw2 = " << nw2 << endl; return; } - - diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Type_Information.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Type_Information.h index 1a9e0d38f6e..ea2da3d687f 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/Type_Information.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/Type_Information.h @@ -3,39 +3,38 @@ #include "common.h" // Information of a particular type -class Type_Information -{ - public: +class Type_Information { + public: Type_Information(); ~Type_Information(); - int id;// index of element periodic table. + int id; // index of element periodic table. - int na;// number of atoms of this type. + int na; // number of atoms of this type. - string *fa;// mohan add 2009-07-12 - // f: full orbtial used. - // a: average orbital used. + string* fa; // mohan add 2009-07-12 + // f: full orbtial used. + // a: average orbital used. - string state; // mohan add 2009-08-27, new/skip - // state: new, start Metropolis calculation in this step. - // state: skip, skip this Metropolis calculation, - // used only in case RESTART=TRUE; - - int lmax;// lmax used. + string state; // mohan add 2009-08-27, new/skip + // state: new, start Metropolis calculation in this step. + // state: skip, skip this Metropolis calculation, + // used only in case RESTART=TRUE; - int *n;// number of radial function for each L. + int lmax; // lmax used. - int *nbase;// number of radial function of each L, sum up all the steps information before! + int* n; // number of radial function for each L. - int nmax; + int* nbase; // number of radial function of each L, sum up all the steps information before! + + int nmax; int nw; - int nw2; + int nw2; - void init();// allocate n, nbase, fa; + void init(); // allocate n, nbase, fa; void cal_nw(); - void cal_nmax(); + void cal_nmax(); }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/common.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/common.cpp index 3ec4fd9da4d..bba7557882b 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/common.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/common.cpp @@ -1,115 +1,105 @@ #include "common.h" -void PRINTCM(const string &s, const ComplexMatrix &m) -{ +void PRINTCM(const string& s, const ComplexMatrix& m) { const int b1 = m.nr; const int b2 = m.nc; - cout << "\n" << s << " " << b1 << " " << b2 ; - - if (b1*b2 == 0) return; - - cout << "\n norm : "; - for (int i = 0;i < b1;i++) - { - for (int j = 0;j < b2;j++) - { - if (j % 8 == 0) cout << "\n "; - double norm = ( conj( m(i, j) ) * m(i, j) ).real(); - if( abs(norm) > 1.0e-9) cout<< setw(12) << norm; - else cout< 1.0e-9) + cout << setw(12) << norm; + else + cout << setw(12) << "0"; } } - /* - cout << "\n real part : "; - for (int i = 0;i < b1;i++) + /* + cout << "\n real part : "; + for (int i = 0;i < b1;i++) { for (int j = 0;j < b2;j++) { if (j % 8 == 0) cout << "\n "; - double n = ( m(i, j) ).real(); - if( abs(n) > 1.0e-9) cout<< setw(12) << n; - else cout< 1.0e-9) cout<< setw(12) << n; + else cout< 1.0e-9) cout<< setw(12) << n; - else cout< 1.0e-9) cout<< setw(12) << n; + else cout<> SearchName; - if( SearchName == TargetName) - { + if (SearchName == TargetName) { find = true; -// cout << " Find the block:" << TargetName << endl; + // cout << " Find the block:" << TargetName << endl; break; } } - if (!find && quit) - { + if (!find && quit) { cout << "\n Can't find : " << TargetName; exit(0); } return find; } -void SCAN_END(ifstream &ifs, const string &TargetName) -{ +void SCAN_END(ifstream& ifs, const string& TargetName) { string SearchName; ifs >> SearchName; - if( SearchName != TargetName) - { - cout<<"\n"<<"In SCAN_END, can't find: "<> ok; - } -void QUIT(void) -{ +void QUIT(void) { timer::finish(); #ifdef __MPI MPI_Finalize(); @@ -117,27 +107,23 @@ void QUIT(void) exit(0); } -void TITLE(const string &class_name,const string &function_name) -{ -// ofs_running<<"\n\n ==> "< "< "< " << class_name << "::" << function_name << endl; + cout << " -------------------------------------" << endl; return; } -void TITLE(ofstream &ofs, const string &class_name,const string &function_name) -{ - return; - cout<<"\n -------------------------------------" << endl; - cout<<" ==> "< " << class_name << "::" << function_name << endl; + cout << " -------------------------------------" << endl; - ofs <<" -------------------------------------" << endl; - ofs <<" ==> "< " << class_name << "::" << function_name << endl; + ofs << " -------------------------------------" << endl; return; } - - diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/common.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/common.h index a573be54621..6b869bdeea6 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/common.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/common.h @@ -1,6 +1,5 @@ #ifndef COMMON_H #define COMMON_H -using namespace std; #include #include @@ -26,7 +25,7 @@ using namespace std; #include "../src_tools/complexarray.h" #include "../src_tools/lapack_connector.h" #include "../src_tools/Random.h" -#include "../src_tools/timer.h"// added 2009-4-17 +#include "../src_tools/timer.h" // added 2009-4-17 #include "../src_tools/inverse_matrix.h" #ifdef __MPI @@ -34,67 +33,58 @@ using namespace std; #endif template -static void READ_VALUE(ifstream &ifs, T &v) -{ +static void READ_VALUE(std::ifstream& ifs, T& v) { ifs >> v; ifs.ignore(150, '\n'); return; } - -bool SCAN_BEGIN(ifstream &ifs, const string &TargetName, const bool restart=1, const bool quit=true); -void SCAN_END(ifstream &ifs, const string &TargetName); -void TITLE(const string &class_name,const string &function_name); -void TITLE(ofstream &ofs, const string &class_name,const string &function_name); -void PRINTCM(const string &s, const ComplexMatrix &m); +bool SCAN_BEGIN(std::ifstream& ifs, const std::string& TargetName, const bool restart = 1, const bool quit = true); +void SCAN_END(std::ifstream& ifs, const std::string& TargetName); +void TITLE(const std::string& class_name, const std::string& function_name); +void TITLE(std::ofstream& ofs, const std::string& class_name, const std::string& function_name); +void PRINTCM(const std::string& s, const ComplexMatrix& m); //========================================================== // GLOBAL FUNCTION : // NAME : ZEROS // set elements of u as zero which u is 1_d complex array //========================================================== -template -void ZEROS(complex *u,const int n) -{ - assert(n!=0); - assert(u!=0); - for(int i=0;i(0.0,0.0); +template +void ZEROS(std::complex* u, const int n) { + assert(n != 0); + assert(u != 0); + for (int i = 0; i < n; i++) { + u[i] = std::complex(0.0, 0.0); } return; } -template -void ZEROS(T *u,const int n) -{ - assert(n>=0); - for(int i=0;i +void ZEROS(T* u, const int n) { + assert(n >= 0); + for (int i = 0; i < n; i++) { u[i] = 0; } } -void WARNING_QUIT(const string &file,const string &description); -void BLOCK_HERE( const string &description ); +void WARNING_QUIT(const std::string& file, const std::string& description); +void BLOCK_HERE(const std::string& description); void QUIT(); // mohan add 2010-06-12 template -void OUT(ofstream &ofs,const string &name,const T &a) -{ - stringstream name2; - name2 << "[" << name << "]"; - ofs<< " " << setw(40) << name2.str() << " = " << a < -void OUT(ofstream &ofs,const string &name,const T &x, const T &y, const T &z) -{ - stringstream name2; - name2 << "[" << name << "]"; - ofs<< " " << setw(40) <", 1, 0)) { + READ_VALUE(ifs, BANDS_CONTROL); + if (BANDS_CONTROL) { + READ_VALUE(ifs, BANDS_START); + assert(BANDS_START > 0); + BANDS_START -= 1; + // because the band index start from 0; + READ_VALUE(ifs, BANDS_END); + // BANDS_END need not -=1; + } + + ofs_running << " ATTENTION! YOU SELECT THE BANDS: " << endl; + ofs_running << " BANDS_START=" << BANDS_START + 1 << " BANDS_END=" << BANDS_END << endl; + } + + // mohan add 2009-08-26 + if (SCAN_BEGIN(ifs, "", 1, 0)) { + READ_VALUE(ifs, BLOCK_NE); + assert(BLOCK_NE >= 0); - if( ifs ) - { - // mohan add 2010-05-01 - if ( SCAN_BEGIN(ifs,"",1,0) ) - { - READ_VALUE( ifs, BANDS_CONTROL); - if (BANDS_CONTROL) - { - READ_VALUE(ifs, BANDS_START); - assert(BANDS_START > 0); - BANDS_START -= 1; - // because the band index start from 0; - READ_VALUE(ifs, BANDS_END); - // BANDS_END need not -=1; - } - - ofs_running << " ATTENTION! YOU SELECT THE BANDS: " << endl; - ofs_running << " BANDS_START=" << BANDS_START+1 << " BANDS_END=" << BANDS_END << endl; - } - - // mohan add 2009-08-26 - if ( SCAN_BEGIN(ifs,"",1,0) ) - { - READ_VALUE( ifs, BLOCK_NE); - assert(BLOCK_NE>=0); - - READ_VALUE( ifs, BLOCK_NE_MIN); - assert(BLOCK_NE >= BLOCK_NE_MIN); - // static_cast( sqrt( 2.0 * ecut )* rcut/3.1415926535897932 ); - - ofs_running << " ATTENTION! YOU SELECT BLOCK_NE=" << BLOCK_NE << endl; - ofs_running << " ALSO BLOCK_NE_MIN=" << BLOCK_NE_MIN << endl; - } - - // mohan add 2009-08-31 - if ( SCAN_BEGIN(ifs,"",1,0) ) - { - double block_ne_energy; - double rcut_in; - READ_VALUE( ifs, block_ne_energy); - READ_VALUE( ifs, rcut_in ); - BLOCK_NE = static_cast( sqrt( 2.0 * block_ne_energy )* rcut_in/3.1415926535897932 ); - assert(BLOCK_NE >= 0); - - ofs_running << "\n Attential! Now, input BLOCK_NE parameter be replaced!" << endl; - ofs_running << "\n New BLOCK_NE = " << BLOCK_NE - << " energy_cut = " << block_ne_energy - << " rcut_in = " << rcut_in << endl; - } - - // mohan add 2009-08-28 - // 1: max spillage value. - // 2: average spillage value. - // 3: add kapa value. - if ( SCAN_BEGIN(ifs,"",1,0) ) - { - READ_VALUE( ifs, SCHEME_VALUE ); - assert(abs(SCHEME_VALUE)>0); - assert(abs(SCHEME_VALUE)<4); - } - - if ( SCAN_BEGIN(ifs,"",1,0) ) - { - READ_VALUE( ifs, NKSTOT ); - assert(NKSTOT>0); + READ_VALUE(ifs, BLOCK_NE_MIN); + assert(BLOCK_NE >= BLOCK_NE_MIN); + // static_cast( sqrt( 2.0 * ecut )* rcut/3.1415926535897932 ); + + ofs_running << " ATTENTION! YOU SELECT BLOCK_NE=" << BLOCK_NE << endl; + ofs_running << " ALSO BLOCK_NE_MIN=" << BLOCK_NE_MIN << endl; + } + + // mohan add 2009-08-31 + if (SCAN_BEGIN(ifs, "", 1, 0)) { + double block_ne_energy; + double rcut_in; + READ_VALUE(ifs, block_ne_energy); + READ_VALUE(ifs, rcut_in); + BLOCK_NE = static_cast(sqrt(2.0 * block_ne_energy) * rcut_in / 3.1415926535897932); + assert(BLOCK_NE >= 0); + + ofs_running << "\n Attential! Now, input BLOCK_NE parameter be replaced!" << endl; + ofs_running << "\n New BLOCK_NE = " << BLOCK_NE << " energy_cut = " << block_ne_energy + << " rcut_in = " << rcut_in << endl; + } + + // mohan add 2009-08-28 + // 1: max spillage value. + // 2: average spillage value. + // 3: add kapa value. + if (SCAN_BEGIN(ifs, "", 1, 0)) { + READ_VALUE(ifs, SCHEME_VALUE); + assert(abs(SCHEME_VALUE) > 0); + assert(abs(SCHEME_VALUE) < 4); + } + + if (SCAN_BEGIN(ifs, "", 1, 0)) { + READ_VALUE(ifs, NKSTOT); + assert(NKSTOT > 0); #ifdef __MPI - READ_VALUE( ifs, KPAR ); - assert(KPAR>0); -#endif - } - - }// end ifs - - else if( ifs2 ) - { - if ( SCAN_BEGIN(ifs2,"",1,0) ) - { - READ_VALUE( ifs2, WFC_FILE); - } - - if ( SCAN_BEGIN(ifs2,"",1,0) ) - { - READ_VALUE( ifs2, SMOOTH); - assert(SMOOTH == 0 || SMOOTH == 1); - READ_VALUE( ifs2, SIGMA); - assert(SIGMA >= 0.0); - READ_VALUE( ifs2, ECUT_JLQ); - assert(ECUT_JLQ > 0 && ECUT_JLQ < 1000); - // mohan set the boundaries) - READ_VALUE( ifs2, RCUT); - assert(RCUT > 0 && RCUT < 15); - READ_VALUE( ifs2, TOLERENCE); - assert(TOLERENCE> 0.0); - } - - if ( SCAN_BEGIN(ifs2,"",1,0) ) - { - READ_VALUE( ifs2, NKSTOT ); - assert(NKSTOT>0); + READ_VALUE(ifs, KPAR); + assert(KPAR > 0); +#endif + } + + } // end ifs + + else if (ifs2) { + if (SCAN_BEGIN(ifs2, "", 1, 0)) { + READ_VALUE(ifs2, WFC_FILE); + } + + if (SCAN_BEGIN(ifs2, "", 1, 0)) { + READ_VALUE(ifs2, SMOOTH); + assert(SMOOTH == 0 || SMOOTH == 1); + READ_VALUE(ifs2, SIGMA); + assert(SIGMA >= 0.0); + READ_VALUE(ifs2, ECUT_JLQ); + assert(ECUT_JLQ > 0 && ECUT_JLQ < 1000); + // mohan set the boundaries) + READ_VALUE(ifs2, RCUT); + assert(RCUT > 0 && RCUT < 15); + READ_VALUE(ifs2, TOLERENCE); + assert(TOLERENCE > 0.0); + } + + if (SCAN_BEGIN(ifs2, "", 1, 0)) { + READ_VALUE(ifs2, NKSTOT); + assert(NKSTOT > 0); #ifdef __MPI - READ_VALUE( ifs2, KPAR ); - assert(KPAR>0); + READ_VALUE(ifs2, KPAR); + assert(KPAR > 0); #endif } - }// end ifs2 + } // end ifs2 } // end my rank0. //------------------------------------------------ - // second part + // second part //------------------------------------------------ - // 2.1 - if( ifs ) - { - if (MY_RANK==0) - { - this->read_PW_QS_1(); - } - } - else if ( ifs2 ) - { - this->read_WFC(); - } - - // 2.2 - // bcast NKSTOT. - // bcast the global information. - // need to first bcast KPAR. - this->bcast(); - - // set the parallel information - // about pool. - Pkpoints.init(); - - // init the k point information. - Pkpoints.kinfo(NKSTOT); - - // calculate the local number of k points. + // 2.1 + if (ifs) { + if (MY_RANK == 0) { + this->read_PW_QS_1(); + } + } else if (ifs2) { + this->read_WFC(); + } + + // 2.2 + // bcast NKSTOT. + // bcast the global information. + // need to first bcast KPAR. + this->bcast(); + + // set the parallel information + // about pool. + Pkpoints.init(); + + // init the k point information. + Pkpoints.kinfo(NKSTOT); + + // calculate the local number of k points. #ifdef __MPI - NKS = Pkpoints.nks_pool[MY_POOL]; + NKS = Pkpoints.nks_pool[MY_POOL]; #else - NKS = NKSTOT; + NKS = NKSTOT; #endif - OUT(ofs_running,"NKS",NKS); + OUT(ofs_running, "NKS", NKS); - // 2.3 - if( ifs ) - { - this->read_PW_QS_2(); - } - else if( ifs2 ) - { - this->read_WFC_2(); - USEPW = 1; - } + // 2.3 + if (ifs) { + this->read_PW_QS_2(); + } else if (ifs2) { + this->read_WFC_2(); + USEPW = 1; + } return; } -void Read_INPUT::bcast(void) -{ +void Read_INPUT::bcast(void) { #ifdef __MPI - Parallel_Common::bcast_bool( BANDS_CONTROL ); - Parallel_Common::bcast_int( BANDS_START ); - Parallel_Common::bcast_int( BANDS_END ); + Parallel_Common::bcast_bool(BANDS_CONTROL); + Parallel_Common::bcast_int(BANDS_START); + Parallel_Common::bcast_int(BANDS_END); - Parallel_Common::bcast_int( BLOCK_NE ); - Parallel_Common::bcast_int( BLOCK_NE_MIN ); + Parallel_Common::bcast_int(BLOCK_NE); + Parallel_Common::bcast_int(BLOCK_NE_MIN); - Parallel_Common::bcast_int( SCHEME_VALUE ); - Parallel_Common::bcast_int( KPAR ); + Parallel_Common::bcast_int(SCHEME_VALUE); + Parallel_Common::bcast_int(KPAR); - Parallel_Common::bcast_int( CALSPI ); - Parallel_Common::bcast_bool( RESTART ); - Parallel_Common::bcast_bool( this->output ); - Parallel_Common::bcast_int( STRNUM ); + Parallel_Common::bcast_int(CALSPI); + Parallel_Common::bcast_bool(RESTART); + Parallel_Common::bcast_bool(this->output); + Parallel_Common::bcast_int(STRNUM); - OUT(ofs_running,"STRNUM",STRNUM); + OUT(ofs_running, "STRNUM", STRNUM); - if (MY_RANK!=0) - { + if (MY_RANK != 0) { delete[] qsfile; qsfile = new string[STRNUM]; } - for (int i=0; iSV.allocate( STRNUM ); + this->SV.allocate(STRNUM); delete[] this->QS_data; - this->QS_data = new ReadData[ STRNUM ]; + this->QS_data = new ReadData[STRNUM]; - for (int i=0; iQS_data[i].OverlapQandS( qsfile[i].c_str() ); - //this->QS_data[in].OverlapSinv( sinv_file.c_str() ); // not used + this->QS_data[i].OverlapQandS(qsfile[i].c_str()); + // this->QS_data[in].OverlapSinv( sinv_file.c_str() ); // not used } return; } -void Read_INPUT::read_PW_QS_1(void) -{ - TITLE(ofs_running, "Read_INPUT","read_PW_QS_1"); +void Read_INPUT::read_PW_QS_1(void) { + TITLE(ofs_running, "Read_INPUT", "read_PW_QS_1"); - if ( SCAN_BEGIN(ifs,"") ) - { + if (SCAN_BEGIN(ifs, "")) { // <1> calculate spillage or not. - READ_VALUE( ifs, CALSPI ); + READ_VALUE(ifs, CALSPI); // <1.5> restart from file or not. // mohan add this function 2009-08-27 - READ_VALUE( ifs, RESTART); + READ_VALUE(ifs, RESTART); // <2> output file or not. - READ_VALUE( ifs, this->output ); + READ_VALUE(ifs, this->output); // <3> number of structures. - READ_VALUE( ifs, STRNUM ); - OUT(ofs_running,"STRNUM",STRNUM); - if (STRNUM<=0) - { - WARNING_QUIT("Read_INPUT::read_PW_QS_1","STRNUM<=0"); + READ_VALUE(ifs, STRNUM); + OUT(ofs_running, "STRNUM", STRNUM); + if (STRNUM <= 0) { + WARNING_QUIT("Read_INPUT::read_PW_QS_1", "STRNUM<=0"); } delete[] qsfile; this->qsfile = new string[STRNUM]; // <4> read in each file. - for (int in=0; in< STRNUM; in++) - { + for (int in = 0; in < STRNUM; in++) { READ_VALUE(ifs, qsfile[in]); ifstream check(qsfile[in].c_str()); - if (!check) - { + if (!check) { ofs_running << qsfile[in] << endl; - WARNING_QUIT("Read_INPUT","the file is not exist!"); - } - else - { - OUT(ofs_running,"FILE",qsfile[in]); - static bool already_read = false; - if (!already_read) - { - check >> LAT0; - OUT(ofs_running,"LAT0",LAT0); - check >> LATVEC.e11 >> LATVEC.e12 >> LATVEC.e13; - check >> LATVEC.e21 >> LATVEC.e22 >> LATVEC.e23; - check >> LATVEC.e31 >> LATVEC.e32 >> LATVEC.e33; - OUT(ofs_running,"a1",LATVEC.e11,LATVEC.e12,LATVEC.e13); - OUT(ofs_running,"a2",LATVEC.e21,LATVEC.e22,LATVEC.e23); - OUT(ofs_running,"a3",LATVEC.e31,LATVEC.e32,LATVEC.e33); - READ_VALUE(check, NTYPE); - OUT(ofs_running,"NTYPE",NTYPE); - assert( NTYPE > 0 ); - NA = new int[NTYPE]; - LABEL = new string[NTYPE]; - CARPOSX = new double*[NTYPE]; - CARPOSY = new double*[NTYPE]; - CARPOSZ = new double*[NTYPE]; - for(int it=0; it> CARPOSX[it][ia] >> CARPOSY[it][ia] >> CARPOSZ[it][ia]; - OUT(ofs_running,"POS",CARPOSX[it][ia],CARPOSY[it][ia],CARPOSZ[it][ia]); - } - } - - READ_VALUE(check, ECUT); - READ_VALUE(check, ECUT_JLQ); - READ_VALUE(check, RCUT); - READ_VALUE(check, SMOOTH); - READ_VALUE(check, SIGMA); - - READ_VALUE(check, TOLERENCE); - READ_VALUE(check, LMAXALL); - READ_VALUE(check, NKSTOT); - READ_VALUE(check, NBANDS); - READ_VALUE(check, NWFCALL); - READ_VALUE(check, NE); - - OUT(ofs_running,"ECUT(Ry)",ECUT); - OUT(ofs_running,"ECUT_JLQ(Ry)",ECUT_JLQ); - OUT(ofs_running,"RCUT(Bohr)",RCUT); - OUT(ofs_running,"SMOOTH",SMOOTH); - OUT(ofs_running,"SIGMA",SIGMA); - OUT(ofs_running,"TOLERENCE",TOLERENCE); - OUT(ofs_running,"LMAXALL",LMAXALL); - OUT(ofs_running,"NKSTOT",NKSTOT); - OUT(ofs_running,"NBANDS",NBANDS); - OUT(ofs_running,"NWFCALL",NWFCALL); - OUT(ofs_running,"NE",NE); - - if(SMOOTH) assert(SIGMA!=0.0); - - already_read = true; - }//only read once. + WARNING_QUIT("Read_INPUT", "the file is not exist!"); + } else { + OUT(ofs_running, "FILE", qsfile[in]); + static bool already_read = false; + if (!already_read) { + check >> LAT0; + OUT(ofs_running, "LAT0", LAT0); + check >> LATVEC.e11 >> LATVEC.e12 >> LATVEC.e13; + check >> LATVEC.e21 >> LATVEC.e22 >> LATVEC.e23; + check >> LATVEC.e31 >> LATVEC.e32 >> LATVEC.e33; + OUT(ofs_running, "a1", LATVEC.e11, LATVEC.e12, LATVEC.e13); + OUT(ofs_running, "a2", LATVEC.e21, LATVEC.e22, LATVEC.e23); + OUT(ofs_running, "a3", LATVEC.e31, LATVEC.e32, LATVEC.e33); + READ_VALUE(check, NTYPE); + OUT(ofs_running, "NTYPE", NTYPE); + assert(NTYPE > 0); + NA = new int[NTYPE]; + LABEL = new string[NTYPE]; + CARPOSX = new double*[NTYPE]; + CARPOSY = new double*[NTYPE]; + CARPOSZ = new double*[NTYPE]; + for (int it = 0; it < NTYPE; it++) { + READ_VALUE(check, LABEL[it]); + READ_VALUE(check, NA[it]); + OUT(ofs_running, "LABEL", LABEL[it]); + OUT(ofs_running, "NA", NA[it]); + CARPOSX[it] = new double[NA[it]]; + CARPOSY[it] = new double[NA[it]]; + CARPOSZ[it] = new double[NA[it]]; + for (int ia = 0; ia < NA[it]; ia++) { + check >> CARPOSX[it][ia] >> CARPOSY[it][ia] >> CARPOSZ[it][ia]; + OUT(ofs_running, "POS", CARPOSX[it][ia], CARPOSY[it][ia], CARPOSZ[it][ia]); + } + } + + READ_VALUE(check, ECUT); + READ_VALUE(check, ECUT_JLQ); + READ_VALUE(check, RCUT); + READ_VALUE(check, SMOOTH); + READ_VALUE(check, SIGMA); + + READ_VALUE(check, TOLERENCE); + READ_VALUE(check, LMAXALL); + READ_VALUE(check, NKSTOT); + READ_VALUE(check, NBANDS); + READ_VALUE(check, NWFCALL); + READ_VALUE(check, NE); + + OUT(ofs_running, "ECUT(Ry)", ECUT); + OUT(ofs_running, "ECUT_JLQ(Ry)", ECUT_JLQ); + OUT(ofs_running, "RCUT(Bohr)", RCUT); + OUT(ofs_running, "SMOOTH", SMOOTH); + OUT(ofs_running, "SIGMA", SIGMA); + OUT(ofs_running, "TOLERENCE", TOLERENCE); + OUT(ofs_running, "LMAXALL", LMAXALL); + OUT(ofs_running, "NKSTOT", NKSTOT); + OUT(ofs_running, "NBANDS", NBANDS); + OUT(ofs_running, "NWFCALL", NWFCALL); + OUT(ofs_running, "NE", NE); + + if (SMOOTH) + assert(SIGMA != 0.0); + + already_read = true; + } // only read once. check.close(); } } @@ -436,79 +393,69 @@ void Read_INPUT::read_PW_QS_1(void) return; } -void Read_INPUT::read_WFC(void) -{ - TITLE("Read_INPUT","read_WFC"); - - ifstream ifswfc( WFC_FILE.c_str() ); - - if(!ifswfc) - { - cout << " Can't find wfc file : " << WFC_FILE << endl; - WARNING_QUIT("Read_INPUT::read_WFC","Can't find wavefunctions file."); - } - else - { - cout << " Find file: " << WFC_FILE << endl; - } - - if(MY_RANK==0) - { - - ifswfc >> LAT0; - cout << "\n LAT0 = " << LAT0; - ifswfc >> LATVEC.e11 >> LATVEC.e12 >> LATVEC.e13; - ifswfc >> LATVEC.e21 >> LATVEC.e22 >> LATVEC.e23; - ifswfc >> LATVEC.e31 >> LATVEC.e32 >> LATVEC.e33; - cout << "\n a1 = " << LATVEC.e11 << " " << LATVEC.e12 << " " << LATVEC.e13; - cout << "\n a2 = " << LATVEC.e21 << " " << LATVEC.e22 << " " << LATVEC.e23; - cout << "\n a3 = " << LATVEC.e31 << " " << LATVEC.e32 << " " << LATVEC.e33; - READ_VALUE(ifswfc, NTYPE); - cout << "\n NTYPE = " << NTYPE << endl; - assert( NTYPE > 0 ); - NA = new int[NTYPE]; - LABEL = new string[NTYPE]; - CARPOSX = new double*[NTYPE]; - CARPOSY = new double*[NTYPE]; - CARPOSZ = new double*[NTYPE]; - for(int it=0; it> LAT0; + cout << "\n LAT0 = " << LAT0; + ifswfc >> LATVEC.e11 >> LATVEC.e12 >> LATVEC.e13; + ifswfc >> LATVEC.e21 >> LATVEC.e22 >> LATVEC.e23; + ifswfc >> LATVEC.e31 >> LATVEC.e32 >> LATVEC.e33; + cout << "\n a1 = " << LATVEC.e11 << " " << LATVEC.e12 << " " << LATVEC.e13; + cout << "\n a2 = " << LATVEC.e21 << " " << LATVEC.e22 << " " << LATVEC.e23; + cout << "\n a3 = " << LATVEC.e31 << " " << LATVEC.e32 << " " << LATVEC.e33; + READ_VALUE(ifswfc, NTYPE); + cout << "\n NTYPE = " << NTYPE << endl; + assert(NTYPE > 0); + NA = new int[NTYPE]; + LABEL = new string[NTYPE]; + CARPOSX = new double*[NTYPE]; + CARPOSY = new double*[NTYPE]; + CARPOSZ = new double*[NTYPE]; + for (int it = 0; it < NTYPE; it++) { + READ_VALUE(ifswfc, LABEL[it]); + READ_VALUE(ifswfc, NA[it]); + cout << "\n LABEL = " << LABEL[it]; + cout << "\n NA=" << NA[it]; + CARPOSX[it] = new double[NA[it]]; + CARPOSY[it] = new double[NA[it]]; + CARPOSZ[it] = new double[NA[it]]; + for (int ia = 0; ia < NA[it]; ia++) { + ifswfc >> CARPOSX[it][ia] >> CARPOSY[it][ia] >> CARPOSZ[it][ia]; + cout << "\n " << CARPOSX[it][ia] << " " << CARPOSY[it][ia] << " " << CARPOSZ[it][ia]; + } + } + + READ_VALUE(ifswfc, ECUT); + READ_VALUE(ifswfc, NKSTOT); + READ_VALUE(ifswfc, NBANDS); + + cout << "\n ECUT = " << ECUT; + cout << "\n ECUT_JLQ = " << ECUT_JLQ; + cout << "\n RCUT = " << RCUT; + cout << "\n SMOOTH = " << SMOOTH; + cout << "\n SIGMA = " << SIGMA; + cout << "\n TOLERENCE = " << TOLERENCE; + cout << "\n NKSTOT = " << NKSTOT; + cout << "\n NBANDs = " << NBANDS; + } + + ifswfc.close(); + return; } +void Read_INPUT::read_WFC_2(void) { + TITLE("Read_INPUT", "read_WFC_2"); + QUIT(); +} diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/read_INPUT.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/read_INPUT.h index 001334396d6..b56d22f5347 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/read_INPUT.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/read_INPUT.h @@ -7,42 +7,40 @@ #include "SpillageValue.h" // read information from file : INPUT -class Read_INPUT -{ - public: - Read_INPUT(); - ~Read_INPUT(); +class Read_INPUT { + public: + Read_INPUT(); + ~Read_INPUT(); - ReadData* QS_data; - Coefficients Coef; - SpillageValue SV; + ReadData* QS_data; + Coefficients Coef; + SpillageValue SV; - ifstream ifs; - ifstream ifs2; - bool cal_sp; - bool output; + ifstream ifs; + ifstream ifs2; + bool cal_sp; + bool output; - // get this value from Multi_Zeta.cpp - int nlevel; + // get this value from Multi_Zeta.cpp + int nlevel; - void init(void); + void init(void); - void read_test(void); - void read_plot_c4(void); -// void read_cal_c4(void); - void read_start_c4(const int &step); + void read_test(void); + void read_plot_c4(void); + // void read_cal_c4(void); + void read_start_c4(const int& step); - private: - int test; + private: + int test; - void bcast(void); - void read_PW_QS_1(void); - void read_PW_QS_2(void); - void read_WFC(void); - void read_WFC_2(void); - - string *qsfile; + void bcast(void); + void read_PW_QS_1(void); + void read_PW_QS_2(void); + void read_WFC(void); + void read_WFC_2(void); + string* qsfile; }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/tools.cpp b/tools/SIAB/SimulatedAnnealing/source/src_spillage/tools.cpp index 19098635486..374ed33751c 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/tools.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/tools.cpp @@ -1,6 +1,6 @@ #include "tools.h" -//plane wave , mohan add 2010-06-14 +// plane wave , mohan add 2010-06-14 PW_Basis PW; MultiZeta mz; Read_INPUT input; @@ -25,11 +25,11 @@ int NE = -1; // global information int STRNUM = -1; int NTYPE = -1; -string *LABEL; -int *NA; -double **CARPOSX; -double **CARPOSY; -double **CARPOSZ; +string* LABEL; +int* NA; +double** CARPOSX; +double** CARPOSY; +double** CARPOSZ; Matrix3 LATVEC; // plane wave information @@ -37,15 +37,15 @@ bool USEPW = true; double LAT0 = -1.0; // k points -double *CARKX; -double *CARKY; -double *CARKZ; +double* CARKX; +double* CARKY; +double* CARKZ; // orbital + energy cutoff double ECUT = -1.0; double ECUT_JLQ = -1.0; double RCUT = -1.0; -bool SMOOTH = false; +bool SMOOTH = false; double SIGMA = -0.1; double TOLERENCE = 1.0e-12; int LMAXALL = -1; @@ -54,9 +54,9 @@ int NMAXUSED = -1; int NCHIUSED = -1; // band information -bool BANDS_CONTROL=false; // mohan add 2010-05-02 -int BANDS_START=0; -int BANDS_END=0; // needed to be checked carefully if not read in. +bool BANDS_CONTROL = false; // mohan add 2010-05-02 +int BANDS_START = 0; +int BANDS_END = 0; // needed to be checked carefully if not read in. // other global information int CALSPI = 0; // mohan 2010-06-17 @@ -71,45 +71,38 @@ double ACCEPTANCE_HIGH = 0.6; double ACCEPTANCE_LOW = 0.3; double KINETIC_MAX = 30.0; // (unit?????) -double KINETIC_DR = 0.01; // -int OPTIMIZE_METHOD = 1; // 1: Kin 2: Ecut +double KINETIC_DR = 0.01; // +int OPTIMIZE_METHOD = 1; // 1: Kin 2: Ecut // constant const double PI = 3.1415926535897; const double TWO_PI = 2.0 * PI; const double FOUR_PI = 4.0 * PI; -const double SQRT_INVERSE_FOUR_PI = sqrt(1.0/FOUR_PI); +const double SQRT_INVERSE_FOUR_PI = sqrt(1.0 / FOUR_PI); const std::complex IMAG_UNIT = std::complex(0, 1.0); -const std::complex NEG_IMAG_UNIT = std::complex(0,-1.0); +const std::complex NEG_IMAG_UNIT = std::complex(0, -1.0); const double PI_HALF = PI / 2.0; const double SQRT2 = 1.41421356237309504880; // read wavefunction string WFC_FILE = "WAVEFUNC.dat"; -void DESTROY(void) -{ - if(NTYPE>0) - { - delete[] LABEL; - delete[] NA; - for(int i=0; i0) - { - delete[] CARKX; - delete[] CARKY; - delete[] CARKZ; - } +void DESTROY(void) { + if (NTYPE > 0) { + delete[] LABEL; + delete[] NA; + for (int i = 0; i < NTYPE; i++) { + delete[] CARPOSX[i]; + delete[] CARPOSY[i]; + delete[] CARPOSZ[i]; + } + delete[] CARPOSX; + delete[] CARPOSY; + delete[] CARPOSZ; + } + if (NKS > 0) { + delete[] CARKX; + delete[] CARKY; + delete[] CARKZ; + } } - - - diff --git a/tools/SIAB/SimulatedAnnealing/source/src_spillage/tools.h b/tools/SIAB/SimulatedAnnealing/source/src_spillage/tools.h index 21486a12ae0..5ed542ad65a 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_spillage/tools.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_spillage/tools.h @@ -6,7 +6,7 @@ #include "MultiZeta.h" #include "read_INPUT.h" #include "../src_parallel/parallel_kpoints.h" // add 2010-06-12 -//plane wave , mohan add 2010-06-14 +// plane wave , mohan add 2010-06-14 extern PW_Basis PW; extern MultiZeta mz; extern Read_INPUT input; @@ -31,11 +31,11 @@ extern int NE; // global information extern int STRNUM; extern int NTYPE; -extern string *LABEL; -extern int *NA; -extern double **CARPOSX; -extern double **CARPOSY; -extern double **CARPOSZ; +extern string* LABEL; +extern int* NA; +extern double** CARPOSX; +extern double** CARPOSY; +extern double** CARPOSZ; extern Matrix3 LATVEC; // plane wave information @@ -43,11 +43,11 @@ extern bool USEPW; extern double LAT0; // k points -extern double *CARKX; -extern double *CARKY; -extern double *CARKZ; +extern double* CARKX; +extern double* CARKY; +extern double* CARKZ; -//orbital + energy cutoff +// orbital + energy cutoff extern double ECUT; extern double ECUT_JLQ; extern double RCUT; @@ -61,12 +61,12 @@ extern int NCHIUSED; // band information extern bool BANDS_CONTROL; -extern int BANDS_START;//mohan add 2010-05-02 +extern int BANDS_START; // mohan add 2010-05-02 extern int BANDS_END; // other global information -extern int CALSPI; // mohan 2010-06-17 -extern int BLOCK_NE; // if ie < BLOCK_NE, we use this Jlq(ie), mohan add 2009-08-26 +extern int CALSPI; // mohan 2010-06-17 +extern int BLOCK_NE; // if ie < BLOCK_NE, we use this Jlq(ie), mohan add 2009-08-26 extern int BLOCK_NE_MIN; // mohan add 2009-08-27 extern bool RESTART; extern int TEST1; @@ -76,16 +76,16 @@ extern int ACCEPTANCE_STEPS; // mohan add 2009-10-31 extern double ACCEPTANCE_HIGH; extern double ACCEPTANCE_LOW; -extern double KINETIC_MAX; // mohan add 2009-10-31 -extern double KINETIC_DR; // mohan add 2010-04-12 -extern int OPTIMIZE_METHOD;// mohan add 2010-04-14 +extern double KINETIC_MAX; // mohan add 2009-10-31 +extern double KINETIC_DR; // mohan add 2010-04-12 +extern int OPTIMIZE_METHOD; // mohan add 2010-04-14 // constant -extern const double PI; // mohan add 2010-04-16 +extern const double PI; // mohan add 2010-04-16 extern const double TWO_PI; // mohan add 2010-06-14 extern const double FOUR_PI; extern const std::complex IMAG_UNIT; -extern const std::complex NEG_IMAG_UNIT;//mohan add 2010-06-14 +extern const std::complex NEG_IMAG_UNIT; // mohan add 2010-06-14 extern const double SQRT_INVERSE_FOUR_PI; extern const double PI_HALF; extern const double SQRT2; diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth.h index 272874c5b3c..d71b5388219 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth.h @@ -1,156 +1,158 @@ #ifndef GRAM_SCHMIDT_ORTH_H #define GRAM_SCHMIDT_ORTH_H -#include -#include +#include +#include using std::exception; -class GS_Orth_Coordinate: public exception{}; - -template -class Gram_Schmidt_Orth -{ -public: - - ~Gram_Schmidt_Orth(); - Func_Type **orth(); - -private: - int coordinate; // 0:cartesian, 1:sphere - size_t func_num; - size_t variable_num; - Func_Type **func{nullptr}; - R_Type *r{nullptr}; - R_Type *r_2{nullptr}; - R_Type *rab{nullptr}; - -private: - bool finish_init{false}; - -public: - - size_t get_coordinate() const { return coordinate; } - Gram_Schmidt_Orth &set_coordinate(size_t coordinate_in) - { - if( 0 != coordinate_in && 1 != coordinate_in) { throw GS_Orth_Coordinate();} - coordinate = coordinate_in; - return *this; - } - - size_t get_func_num() const { return func_num; } - Gram_Schmidt_Orth &set_func_num(size_t func_num_in){ func_num = func_num_in; return *this; } - - size_t get_variable_num() const { return variable_num; } - Gram_Schmidt_Orth &set_variable_num(size_t variable_num_in){ variable_num = variable_num_in; return *this; } - - Func_Type **get_func() const { return func; } - Gram_Schmidt_Orth &set_func(Func_Type **func_in){ func = func_in; return *this; } - - R_Type *get_r() const { return r; } - Gram_Schmidt_Orth &set_r(R_Type *r_in){ r = r_in; return *this; } - - R_Type *get_r_2() const { return r_2; } - - R_Type *get_rab() const { return rab; } - Gram_Schmidt_Orth &set_rab_element(const R_Type &rab_element_in) - { - if(NULL==rab) - rab = new R_Type [variable_num]; - for( size_t i(0); i +class Gram_Schmidt_Orth { + public: + ~Gram_Schmidt_Orth(); + Func_Type** orth(); + + private: + int coordinate; // 0:cartesian, 1:sphere + size_t func_num; + size_t variable_num; + Func_Type** func{nullptr}; + R_Type* r{nullptr}; + R_Type* r_2{nullptr}; + R_Type* rab{nullptr}; + + private: + bool finish_init{false}; + + public: + size_t get_coordinate() const { return coordinate; } + Gram_Schmidt_Orth& set_coordinate(size_t coordinate_in) { + if (0 != coordinate_in && 1 != coordinate_in) { + throw GS_Orth_Coordinate(); + } + coordinate = coordinate_in; + return *this; + } + + size_t get_func_num() const { return func_num; } + Gram_Schmidt_Orth& set_func_num(size_t func_num_in) { + func_num = func_num_in; + return *this; + } + + size_t get_variable_num() const { return variable_num; } + Gram_Schmidt_Orth& set_variable_num(size_t variable_num_in) { + variable_num = variable_num_in; + return *this; + } + + Func_Type** get_func() const { return func; } + Gram_Schmidt_Orth& set_func(Func_Type** func_in) { + func = func_in; + return *this; + } + + R_Type* get_r() const { return r; } + Gram_Schmidt_Orth& set_r(R_Type* r_in) { + r = r_in; + return *this; + } + + R_Type* get_r_2() const { return r_2; } + + R_Type* get_rab() const { return rab; } + Gram_Schmidt_Orth& set_rab_element(const R_Type& rab_element_in) { + if (NULL == rab) + rab = new R_Type[variable_num]; + for (size_t i(0); i < variable_num; ++i) + rab[i] = rab_element_in; + return *this; + } + + private: + void init(); + Func_Type cal_norm(Func_Type* func_in); }; #include "mathzone.h" #include "lapack_connector.h" -template -void Gram_Schmidt_Orth::init() -{ - if(this->finish_init) return; - if(nullptr == this->r_2) - { - this->r_2 = new R_Type[variable_num]; - Mathzone::Pointwise_Product( this->variable_num, this->r, this->r, this->r_2); - } - if(nullptr == rab) - { - this->rab = new R_Type[variable_num]; - this->rab[0] = 0.0; - for( size_t ir(1); irrab[ir] = this->r[ir] - this->r[ir-1]; - } - } - this->finish_init = true; - return; +template +void Gram_Schmidt_Orth::init() { + if (this->finish_init) + return; + if (nullptr == this->r_2) { + this->r_2 = new R_Type[variable_num]; + Mathzone::Pointwise_Product(this->variable_num, this->r, this->r, this->r_2); + } + if (nullptr == rab) { + this->rab = new R_Type[variable_num]; + this->rab[0] = 0.0; + for (size_t ir(1); ir < variable_num; ++ir) { + this->rab[ir] = this->r[ir] - this->r[ir - 1]; + } + } + this->finish_init = true; + return; } -template -Gram_Schmidt_Orth::~Gram_Schmidt_Orth() -{ - delete[]rab; - delete[]r_2; +template +Gram_Schmidt_Orth::~Gram_Schmidt_Orth() { + delete[] rab; + delete[] r_2; } -template -Func_Type **Gram_Schmidt_Orth::orth() -{ - init(); - - // Schmidt: hn to en - // e1 = h1 / ||h1|| - // gn = hn - \sum{i=1 to n-1}(hn,ei)ei - // en = gn / ||gn|| - - for( size_t if1(0); if1variable_num]; - Mathzone::Pointwise_Product( this->variable_num, this->func[if1], this->func[if2], mul_func); - const Func_Type in_product = cal_norm(mul_func); - delete[]mul_func; mul_func=nullptr; - - // hn -(hn,ei)ei - LapackConnector::daxpy( this->variable_num, -in_product, this->func[if2], 1, this->func[if1], 1); - } - - // ||gn|| - Func_Type *func_2 = new Func_Type[this->variable_num]; - Mathzone::Pointwise_Product( this->variable_num, this->func[if1], this->func[if1], func_2); - const Func_Type norm = sqrt(cal_norm(func_2)); - delete[]func_2; func_2=nullptr; - - // en = gn / ||gn|| - LapackConnector::dscal( this->variable_num, 1.0/norm, this->func[if1], 1); - } - return func; +template +Func_Type** Gram_Schmidt_Orth::orth() { + init(); + + // Schmidt: hn to en + // e1 = h1 / ||h1|| + // gn = hn - \sum{i=1 to n-1}(hn,ei)ei + // en = gn / ||gn|| + + for (size_t if1(0); if1 < func_num; ++if1) { + for (size_t if2(0); if2 < if1; ++if2) { + // (hn,ei) + Func_Type* mul_func = new Func_Type[this->variable_num]; + Mathzone::Pointwise_Product(this->variable_num, this->func[if1], this->func[if2], mul_func); + const Func_Type in_product = cal_norm(mul_func); + delete[] mul_func; + mul_func = nullptr; + + // hn -(hn,ei)ei + LapackConnector::daxpy(this->variable_num, -in_product, this->func[if2], 1, this->func[if1], 1); + } + + // ||gn|| + Func_Type* func_2 = new Func_Type[this->variable_num]; + Mathzone::Pointwise_Product(this->variable_num, this->func[if1], this->func[if1], func_2); + const Func_Type norm = sqrt(cal_norm(func_2)); + delete[] func_2; + func_2 = nullptr; + + // en = gn / ||gn|| + LapackConnector::dscal(this->variable_num, 1.0 / norm, this->func[if1], 1); + } + return func; } -template -Func_Type Gram_Schmidt_Orth::cal_norm(Func_Type *func_in) -{ - Func_Type norm(0.0); - switch(coordinate) - { - case 0: - Mathzone::Simpson_Integral( this->variable_num, func_in, this->rab, norm); - break; - case 1: - Func_Type *tmp_func = new Func_Type[this->variable_num]; - Mathzone::Pointwise_Product( this->variable_num, func_in, this->r_2, tmp_func); - Mathzone::Simpson_Integral( this->variable_num, tmp_func, this->rab, norm); - delete[]tmp_func; tmp_func=nullptr; - break; - } - return norm; +template +Func_Type Gram_Schmidt_Orth::cal_norm(Func_Type* func_in) { + Func_Type norm(0.0); + switch (coordinate) { + case 0: + Mathzone::Simpson_Integral(this->variable_num, func_in, this->rab, norm); + break; + case 1: + Func_Type* tmp_func = new Func_Type[this->variable_num]; + Mathzone::Pointwise_Product(this->variable_num, func_in, this->r_2, tmp_func); + Mathzone::Simpson_Integral(this->variable_num, tmp_func, this->rab, norm); + delete[] tmp_func; + tmp_func = nullptr; + break; + } + return norm; } #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth_bak.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth_bak.cpp index a1a58a47f90..4e61ec9d72f 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth_bak.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth_bak.cpp @@ -2,82 +2,76 @@ #include "mathzone.h" #include "lapack_connector.h" -void Gram_Schmidt_Orth::init() -{ - if(this->finish_init) return; - if(nullptr == this->r_2) - { - this->r_2 = new double[variable_num]; - Mathzone::Pointwise_Product( this->variable_num, this->r, this->r, this->r_2); - } - if(nullptr == rab) - { - this->rab = new double[variable_num]; - this->rab[0] = 0.0; - for( size_t ir(1); irrab[ir] = this->r[ir] - this->r[ir-1]; - } - } - this->finish_init = true; - return; +void Gram_Schmidt_Orth::init() { + if (this->finish_init) + return; + if (nullptr == this->r_2) { + this->r_2 = new double[variable_num]; + Mathzone::Pointwise_Product(this->variable_num, this->r, this->r, this->r_2); + } + if (nullptr == rab) { + this->rab = new double[variable_num]; + this->rab[0] = 0.0; + for (size_t ir(1); ir < variable_num; ++ir) { + this->rab[ir] = this->r[ir] - this->r[ir - 1]; + } + } + this->finish_init = true; + return; } -Gram_Schmidt_Orth::~Gram_Schmidt_Orth() -{ - delete[]rab; - delete[]r_2; +Gram_Schmidt_Orth::~Gram_Schmidt_Orth() { + delete[] rab; + delete[] r_2; } -double **Gram_Schmidt_Orth::orth() -{ - init(); +double** Gram_Schmidt_Orth::orth() { + init(); - // Schmidt: hn to en - // e1 = h1 / ||h1|| - // gn = hn - \sum{i=1 to n-1}(hn,ei)ei - // en = gn / ||gn|| + // Schmidt: hn to en + // e1 = h1 / ||h1|| + // gn = hn - \sum{i=1 to n-1}(hn,ei)ei + // en = gn / ||gn|| - for( size_t if1(0); if1variable_num]; - Mathzone::Pointwise_Product( this->variable_num, this->func[if1], this->func[if2], mul_func); - const double in_product = cal_norm(mul_func); - delete[]mul_func; mul_func=nullptr; + for (size_t if1(0); if1 < func_num; ++if1) { + for (size_t if2(0); if2 < if1; ++if2) { + // (hn,ei) + double* mul_func = new double[this->variable_num]; + Mathzone::Pointwise_Product(this->variable_num, this->func[if1], this->func[if2], mul_func); + const double in_product = cal_norm(mul_func); + delete[] mul_func; + mul_func = nullptr; - // hn -(hn,ei)ei - daxpy( this->variable_num, -in_product, this->func[if2], 1, this->func[if1], 1); - } - - // ||gn|| - double *func_2 = new double[this->variable_num]; - Mathzone::Pointwise_Product( this->variable_num, this->func[if1], this->func[if1], func_2); - const double norm = sqrt(cal_norm(func_2)); - delete[]func_2; func_2=nullptr; - - // en = gn / ||gn|| - dscal( this->variable_num, 1.0/norm, this->func[if1], 1); - } - return func; + // hn -(hn,ei)ei + daxpy(this->variable_num, -in_product, this->func[if2], 1, this->func[if1], 1); + } + + // ||gn|| + double* func_2 = new double[this->variable_num]; + Mathzone::Pointwise_Product(this->variable_num, this->func[if1], this->func[if1], func_2); + const double norm = sqrt(cal_norm(func_2)); + delete[] func_2; + func_2 = nullptr; + + // en = gn / ||gn|| + dscal(this->variable_num, 1.0 / norm, this->func[if1], 1); + } + return func; } -double Gram_Schmidt_Orth::cal_norm(double *func_in) -{ - double norm(0.0); - switch(coordinate) - { - case 0: - Mathzone::Simpson_Integral( this->variable_num, func_in, this->rab, norm); - break; - case 1: - double *tmp_func = new double[this->variable_num]; - Mathzone::Pointwise_Product( this->variable_num, func_in, this->r_2, tmp_func); - Mathzone::Simpson_Integral( this->variable_num, tmp_func, this->rab, norm); - delete[]tmp_func; tmp_func=nullptr; - break; - } - return norm; +double Gram_Schmidt_Orth::cal_norm(double* func_in) { + double norm(0.0); + switch (coordinate) { + case 0: + Mathzone::Simpson_Integral(this->variable_num, func_in, this->rab, norm); + break; + case 1: + double* tmp_func = new double[this->variable_num]; + Mathzone::Pointwise_Product(this->variable_num, func_in, this->r_2, tmp_func); + Mathzone::Simpson_Integral(this->variable_num, tmp_func, this->rab, norm); + delete[] tmp_func; + tmp_func = nullptr; + break; + } + return norm; } \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth_bak.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth_bak.h index 18551a8c82c..fb5d0115bca 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth_bak.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/Gram_Schmidt_Orth_bak.h @@ -1,69 +1,77 @@ #ifndef GRAM_SCHMIDT_ORTH_H #define GRAM_SCHMIDT_ORTH_H -#include -#include +#include +#include using std::exception; -class GS_Orth_Coordinate: public exception{}; +class GS_Orth_Coordinate : public exception {}; -class Gram_Schmidt_Orth -{ -public: +class Gram_Schmidt_Orth { + public: + ~Gram_Schmidt_Orth(); + double** orth(); - ~Gram_Schmidt_Orth(); - double **orth(); - -private: - int coordinate; // 0:cartesian, 1:sphere - size_t func_num; - size_t variable_num; - double **func{nullptr}; - double *r{nullptr}; - double *r_2{nullptr}; - double *rab{nullptr}; + private: + int coordinate; // 0:cartesian, 1:sphere + size_t func_num; + size_t variable_num; + double** func{nullptr}; + double* r{nullptr}; + double* r_2{nullptr}; + double* rab{nullptr}; -private: - bool finish_init{false}; - -public: + private: + bool finish_init{false}; - size_t get_coordinate() const { return coordinate; } - Gram_Schmidt_Orth &set_coordinate(size_t coordinate_in) - { - if( 0 != coordinate_in && 1 != coordinate_in) { throw GS_Orth_Coordinate();} - coordinate = coordinate_in; - return *this; - } + public: + size_t get_coordinate() const { return coordinate; } + Gram_Schmidt_Orth& set_coordinate(size_t coordinate_in) { + if (0 != coordinate_in && 1 != coordinate_in) { + throw GS_Orth_Coordinate(); + } + coordinate = coordinate_in; + return *this; + } - size_t get_func_num() const { return func_num; } - Gram_Schmidt_Orth &set_func_num(size_t func_num_in){ func_num = func_num_in; return *this; } + size_t get_func_num() const { return func_num; } + Gram_Schmidt_Orth& set_func_num(size_t func_num_in) { + func_num = func_num_in; + return *this; + } - size_t get_variable_num() const { return variable_num; } - Gram_Schmidt_Orth &set_variable_num(size_t variable_num_in){ variable_num = variable_num_in; return *this; } + size_t get_variable_num() const { return variable_num; } + Gram_Schmidt_Orth& set_variable_num(size_t variable_num_in) { + variable_num = variable_num_in; + return *this; + } - double **get_func() const { return func; } - Gram_Schmidt_Orth &set_func(double **func_in){ func = func_in; return *this; } + double** get_func() const { return func; } + Gram_Schmidt_Orth& set_func(double** func_in) { + func = func_in; + return *this; + } - double *get_r() const { return r; } - Gram_Schmidt_Orth &set_r(double *r_in){ r = r_in; return *this; } + double* get_r() const { return r; } + Gram_Schmidt_Orth& set_r(double* r_in) { + r = r_in; + return *this; + } - double *get_r_2() const { return r_2; } + double* get_r_2() const { return r_2; } - double *get_rab() const { return rab; } - Gram_Schmidt_Orth &set_rab_element(const double &rab_element_in) - { - if(NULL==rab) - rab = new double [variable_num]; - for( size_t i(0); i #include -class Random -{ - public: - Random(); - ~Random(); - - static void between0and1( double *v, const int &num ) - { - assert( v!= NULL); - assert( num > 1); - for(int i=0; i( std::rand() ) / RAND_MAX; - } - } - - static double betweenMinus2and2(void) - { - return 2.0*betweenMinus1and1(); - } - - static double betweenMinus1and1(void) - { - int a = std::rand() % 2; - if(a==0) return between0and1(); - else if(a==1) return betweenMinus1and0(); - } - - static double between0and1(void) - { - return static_cast( std::rand() )/RAND_MAX; - } - - static double betweenMinus1and0(void) - { - return -static_cast( std::rand() )/RAND_MAX; - } - +class Random { + public: + Random(); + ~Random(); + + static void between0and1(double* v, const int& num) { + assert(v != NULL); + assert(num > 1); + for (int i = 0; i < num; i++) { + v[i] = static_cast(std::rand()) / RAND_MAX; + } + } + + static double betweenMinus2and2(void) { return 2.0 * betweenMinus1and1(); } + + static double betweenMinus1and1(void) { + int a = std::rand() % 2; + if (a == 0) + return between0and1(); + else if (a == 1) + return betweenMinus1and0(); + } + + static double between0and1(void) { return static_cast(std::rand()) / RAND_MAX; } + + static double betweenMinus1and0(void) { return -static_cast(std::rand()) / RAND_MAX; } }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/Simulated_Annealing.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/Simulated_Annealing.cpp index 14d48ea16cc..b0e2f73b210 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/Simulated_Annealing.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/Simulated_Annealing.cpp @@ -2,88 +2,100 @@ #include "mathzone.h" #include "Random.h" -void Simulated_Annealing::cal_all_temperature(void) -{ - preprocess_all_temperature(); - for( size_t itemperature(0); itemperature != this->temperature_num; ++itemperature) - { - cal_each_temperature(itemperature); - if(quit_loop_all_temperature()){ break; } - update_temperature(itemperature); - } - reprocess_all_temperature(); - return; +void Simulated_Annealing::cal_all_temperature(void) { + preprocess_all_temperature(); + for (size_t itemperature(0); itemperature != this->temperature_num; ++itemperature) { + cal_each_temperature(itemperature); + if (quit_loop_all_temperature()) { + break; + } + update_temperature(itemperature); + } + reprocess_all_temperature(); + return; } -void Simulated_Annealing::cal_each_temperature( size_t itemperature) -{ - preprocess_each_temperature(itemperature); - for( size_t istep(0); istep != this->step_num; ++istep) - { - cal_each_step(itemperature, istep); - if(quit_loop_each_temperature(itemperature)){ break; } - } - reprocess_each_temperature(itemperature); - return; +void Simulated_Annealing::cal_each_temperature(size_t itemperature) { + preprocess_each_temperature(itemperature); + for (size_t istep(0); istep != this->step_num; ++istep) { + cal_each_step(itemperature, istep); + if (quit_loop_each_temperature(itemperature)) { + break; + } + } + reprocess_each_temperature(itemperature); + return; } -void Simulated_Annealing::cal_each_step( size_t itemperature, size_t istep) -{ - preprocess_each_step(itemperature, istep); - move_variable(itemperature, istep); - double new_function; - bool accept_flag(false), reject_flag(false); - judge_accept_reject(new_function, itemperature, istep, accept_flag, reject_flag); - process_accept_reject(new_function, itemperature, istep, accept_flag, reject_flag); - reprocess_each_step(itemperature, istep); - return; +void Simulated_Annealing::cal_each_step(size_t itemperature, size_t istep) { + preprocess_each_step(itemperature, istep); + move_variable(itemperature, istep); + double new_function; + bool accept_flag(false), reject_flag(false); + judge_accept_reject(new_function, itemperature, istep, accept_flag, reject_flag); + process_accept_reject(new_function, itemperature, istep, accept_flag, reject_flag); + reprocess_each_step(itemperature, istep); + return; } -void Simulated_Annealing::judge_accept_reject( double &new_function, size_t itemperature, size_t istep, bool &accept_flag, bool &reject_flag) -{ - if(must_accept_before(new_function, itemperature, istep)) { accept_flag = true; } - else if(must_reject_before(new_function, itemperature, istep)) { reject_flag = true; } - if(accept_flag || reject_flag){ return; } - else - { - new_function = cal_new_function(itemperature, istep); - if(must_accept_after(new_function, itemperature, istep)) { accept_flag = true; } - else if(must_reject_after(new_function, itemperature, istep)) { reject_flag = true; } - } +void Simulated_Annealing::judge_accept_reject(double& new_function, + size_t itemperature, + size_t istep, + bool& accept_flag, + bool& reject_flag) { + if (must_accept_before(new_function, itemperature, istep)) { + accept_flag = true; + } else if (must_reject_before(new_function, itemperature, istep)) { + reject_flag = true; + } + if (accept_flag || reject_flag) { + return; + } else { + new_function = cal_new_function(itemperature, istep); + if (must_accept_after(new_function, itemperature, istep)) { + accept_flag = true; + } else if (must_reject_after(new_function, itemperature, istep)) { + reject_flag = true; + } + } - if(accept_flag) - { - if(reject_flag) { throw Accept_Reject_Conflict(); } - else { return; } - } - else if(reject_flag) { return; } - else - { - if(new_function<=old_function) { accept_flag = true; } - else - { - const double p = Mathzone::Boltzmann_dist(new_function - old_function, this->temperature); - const double r = Random::between0and1(); - if (r < p) { accept_flag = true; } - else { reject_flag = true; } - } - } + if (accept_flag) { + if (reject_flag) { + throw Accept_Reject_Conflict(); + } else { + return; + } + } else if (reject_flag) { + return; + } else { + if (new_function <= old_function) { + accept_flag = true; + } else { + const double p = Mathzone::Boltzmann_dist(new_function - old_function, this->temperature); + const double r = Random::between0and1(); + if (r < p) { + accept_flag = true; + } else { + reject_flag = true; + } + } + } } -void Simulated_Annealing::process_accept_reject( double &new_function, size_t itemperature, size_t istep, bool &accept_flag, bool &reject_flag) -{ - // accept and reject may conflict without checking before - if(accept_flag) - { - accept_process( new_function, itemperature, istep); - } - if(reject_flag) - { - reject_process( new_function, itemperature, istep); - } +void Simulated_Annealing::process_accept_reject(double& new_function, + size_t itemperature, + size_t istep, + bool& accept_flag, + bool& reject_flag) { + // accept and reject may conflict without checking before + if (accept_flag) { + accept_process(new_function, itemperature, istep); + } + if (reject_flag) { + reject_process(new_function, itemperature, istep); + } } -void Simulated_Annealing::accept_process( double new_function, size_t itemperature, size_t istep) -{ - this->old_function = new_function; +void Simulated_Annealing::accept_process(double new_function, size_t itemperature, size_t istep) { + this->old_function = new_function; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/Simulated_Annealing.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/Simulated_Annealing.h index 5e8c1f017a1..fa3a47ad2fa 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/Simulated_Annealing.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/Simulated_Annealing.h @@ -1,56 +1,71 @@ #ifndef SIMULATED_ANNEALING_H #define SIMULATED_ANNEALING_H -#include -#include +#include +#include using std::exception; -class Accept_Reject_Conflict: public exception{}; - -class Simulated_Annealing -{ - public: - - virtual void cal_all_temperature(void); - virtual void cal_each_temperature( size_t itemperature); - virtual void cal_each_step( size_t itemperature, size_t istep); - virtual void judge_accept_reject( double &new_function, size_t itemperature, size_t istep, bool &accept_flag, bool &reject_flag); - virtual void process_accept_reject( double &new_function, size_t itemperature, size_t istep, bool &accept_flag, bool &reject_flag); - virtual void accept_process( double new_function, size_t itemperature, size_t istep); - - virtual void move_variable(size_t itemperature, size_t istep)=0; - virtual double cal_new_function(size_t itemperature, size_t istep)=0; - - virtual void preprocess_all_temperature(){} - virtual bool quit_loop_all_temperature(){return false;} - virtual void update_temperature(size_t itemperature){} - virtual void reprocess_all_temperature(){} - - virtual void preprocess_each_temperature(size_t itemperature){} - virtual bool quit_loop_each_temperature(size_t itemperature){return false;} - virtual void reprocess_each_temperature(size_t itemperature){} - - virtual void preprocess_each_step(size_t itemperature, size_t istep){} - virtual void reprocess_each_step(size_t itemperature, size_t iste){} - - virtual bool must_accept_before(double new_function, size_t itemperature, size_t istep){return false;} - virtual bool must_reject_before(double new_function, size_t itemperature, size_t istep){return false;} - virtual bool must_accept_after(double new_function, size_t itemperature, size_t istep){return false;} - virtual bool must_reject_after(double new_function, size_t itemperature, size_t istep){return false;} - - virtual void reject_process(double new_function, size_t itemperature, size_t istep){} - - protected: - size_t temperature_num; - size_t step_num; - double temperature; - double old_function; - - public: - Simulated_Annealing &set_temperature_num(size_t temperature_num_in){temperature_num = temperature_num_in; return *this;} - Simulated_Annealing &set_step_num(size_t step_num_in){step_num = step_num_in; return *this;} - Simulated_Annealing &set_temperature(double temperature_in){temperature = temperature_in; return *this;} - Simulated_Annealing &set_old_function(double old_function_in){old_function = old_function_in; return *this;} +class Accept_Reject_Conflict : public exception {}; + +class Simulated_Annealing { + public: + virtual void cal_all_temperature(void); + virtual void cal_each_temperature(size_t itemperature); + virtual void cal_each_step(size_t itemperature, size_t istep); + virtual void + judge_accept_reject(double& new_function, size_t itemperature, size_t istep, bool& accept_flag, bool& reject_flag); + virtual void process_accept_reject(double& new_function, + size_t itemperature, + size_t istep, + bool& accept_flag, + bool& reject_flag); + virtual void accept_process(double new_function, size_t itemperature, size_t istep); + + virtual void move_variable(size_t itemperature, size_t istep) = 0; + virtual double cal_new_function(size_t itemperature, size_t istep) = 0; + + virtual void preprocess_all_temperature() {} + virtual bool quit_loop_all_temperature() { return false; } + virtual void update_temperature(size_t itemperature) {} + virtual void reprocess_all_temperature() {} + + virtual void preprocess_each_temperature(size_t itemperature) {} + virtual bool quit_loop_each_temperature(size_t itemperature) { return false; } + virtual void reprocess_each_temperature(size_t itemperature) {} + + virtual void preprocess_each_step(size_t itemperature, size_t istep) {} + virtual void reprocess_each_step(size_t itemperature, size_t iste) {} + + virtual bool must_accept_before(double new_function, size_t itemperature, size_t istep) { return false; } + virtual bool must_reject_before(double new_function, size_t itemperature, size_t istep) { return false; } + virtual bool must_accept_after(double new_function, size_t itemperature, size_t istep) { return false; } + virtual bool must_reject_after(double new_function, size_t itemperature, size_t istep) { return false; } + + virtual void reject_process(double new_function, size_t itemperature, size_t istep) {} + + protected: + size_t temperature_num; + size_t step_num; + double temperature; + double old_function; + + public: + Simulated_Annealing& set_temperature_num(size_t temperature_num_in) { + temperature_num = temperature_num_in; + return *this; + } + Simulated_Annealing& set_step_num(size_t step_num_in) { + step_num = step_num_in; + return *this; + } + Simulated_Annealing& set_temperature(double temperature_in) { + temperature = temperature_in; + return *this; + } + Simulated_Annealing& set_old_function(double old_function_in) { + old_function = old_function_in; + return *this; + } }; #endif \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/complexarray.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/complexarray.cpp index 22519a92c40..202fe03cc50 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/complexarray.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/complexarray.cpp @@ -7,46 +7,43 @@ int ComplexArray::arrayCount = 0; -void ComplexArrayAlloc() -{ - cout << "\n Allocation error for ComplexArray " << endl; - exit(0); +void ComplexArrayAlloc() { + cout << "\n Allocation error for ComplexArray " << endl; + exit(0); } -ComplexArray::ComplexArray(const int d1,const int d2,const int d3) -{ - dim = 3; - bound1 = (d1 <= 0) ? 1 : d1; - bound2 = (d2 <= 0) ? 1 : d2; - bound3 = (d3 <= 0) ? 1 : d3; - bound4 = 0; +ComplexArray::ComplexArray(const int d1, const int d2, const int d3) { + dim = 3; + bound1 = (d1 <= 0) ? 1 : d1; + bound2 = (d2 <= 0) ? 1 : d2; + bound3 = (d3 <= 0) ? 1 : d3; + bound4 = 0; - set_new_handler(ComplexArrayAlloc); + set_new_handler(ComplexArrayAlloc); - size = bound1 * bound2 * bound3 ; //* sizeof(float); + size = bound1 * bound2 * bound3; //* sizeof(float); - ptr = new std::complex[size](); - assert(ptr != 0); + ptr = new std::complex[size](); + assert(ptr != 0); - ++arrayCount; + ++arrayCount; } -ComplexArray::ComplexArray(const int d1,const int d2,const int d3,const int d4) -{ - dim = 4; - bound1 = (d1 <= 0) ? 1 : d1; - bound2 = (d2 <= 0) ? 1 : d2; - bound3 = (d3 <= 0) ? 1 : d3; - bound4 = (d4 <= 0) ? 1 : d4; +ComplexArray::ComplexArray(const int d1, const int d2, const int d3, const int d4) { + dim = 4; + bound1 = (d1 <= 0) ? 1 : d1; + bound2 = (d2 <= 0) ? 1 : d2; + bound3 = (d3 <= 0) ? 1 : d3; + bound4 = (d4 <= 0) ? 1 : d4; - set_new_handler(ComplexArrayAlloc); + set_new_handler(ComplexArrayAlloc); - size = bound1 * bound2 * bound3 * bound4 ; //* sizeof(float); + size = bound1 * bound2 * bound3 * bound4; //* sizeof(float); - ptr = new std::complex[size](); - assert(ptr != 0); + ptr = new std::complex[size](); + assert(ptr != 0); - ++arrayCount; + ++arrayCount; } //******************************** @@ -54,61 +51,55 @@ ComplexArray::ComplexArray(const int d1,const int d2,const int d3,const int d4) // Destructor for class ComplexArray // //******************************** -ComplexArray ::~ComplexArray() -{ - freemem(); -} +ComplexArray ::~ComplexArray() { freemem(); } -void ComplexArray::freemem() -{ - delete [] ptr; - ptr = NULL; +void ComplexArray::freemem() { + delete[] ptr; + ptr = NULL; } -void ComplexArray::create(const int d1,const int d2,const int d3,const int d4) -{ - size = d1 * d2 * d3 * d4; - assert(size>0); +void ComplexArray::create(const int d1, const int d2, const int d3, const int d4) { + size = d1 * d2 * d3 * d4; + assert(size > 0); - dim = 4; + dim = 4; - bound1 = d1; - bound2 = d2; - bound3 = d3; - bound4 = d4; + bound1 = d1; + bound2 = d2; + bound3 = d3; + bound4 = d4; - delete [] ptr; - ptr = new std::complex[size](); - assert(ptr != 0); + delete[] ptr; + ptr = new std::complex[size](); + assert(ptr != 0); } -void ComplexArray::create(const int d1,const int d2,const int d3) -{ - size = d1 * d2 * d3; - assert(size>0); +void ComplexArray::create(const int d1, const int d2, const int d3) { + size = d1 * d2 * d3; + assert(size > 0); - dim = 3; + dim = 3; - bound1 = d1; - bound2 = d2; - bound3 = d3; - bound4 = 1; + bound1 = d1; + bound2 = d2; + bound3 = d3; + bound4 = 1; - delete [] ptr; - ptr = new std::complex[size](); - assert(ptr != 0); + delete[] ptr; + ptr = new std::complex[size](); + assert(ptr != 0); } -const ComplexArray &ComplexArray::operator=(const ComplexArray &right) -{ - for (int i = 0;i < size;i++) ptr[i] = right.ptr[i]; - return *this;// enables x = y = z; +const ComplexArray& ComplexArray::operator=(const ComplexArray& right) { + for (int i = 0; i < size; i++) + ptr[i] = right.ptr[i]; + return *this; // enables x = y = z; } -const ComplexArray &ComplexArray::operator=(const std::complex &right) -{ - for (int i = 0;i < size;i++) ptr[i] = right; - return *this;// enables x = y = z; +const ComplexArray& ComplexArray::operator=(const std::complex& right) { + for (int i = 0; i < size; i++) + ptr[i] = right; + return *this; // enables x = y = z; } //******************************************************** @@ -117,25 +108,21 @@ const ComplexArray &ComplexArray::operator=(const std::complex &right) // const reference return create an cvakue // //******************************************************** -const std::complex &ComplexArray::operator() -(const int ind1,const int ind2,const int ind3)const -{ - const int ind = (ind1 * bound2 + ind2) * bound3 + ind3 ; - return ptr[ind]; +const std::complex& ComplexArray::operator()(const int ind1, const int ind2, const int ind3) const { + const int ind = (ind1 * bound2 + ind2) * bound3 + ind3; + return ptr[ind]; } - //******************************************************** // // overloaded subscript operator for const real Array // const reference return creates an cvakue // //******************************************************** -const std::complex &ComplexArray::operator() -(const int ind1,const int ind2,const int ind3,const int ind4)const -{ - const int ind = ((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4; - return ptr[ind]; +const std::complex& +ComplexArray::operator()(const int ind1, const int ind2, const int ind3, const int ind4) const { + const int ind = ((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4; + return ptr[ind]; } //******************************************************** @@ -144,10 +131,9 @@ const std::complex &ComplexArray::operator() // const reference return creates an lvakue // //******************************************************** -complex &ComplexArray::operator()(const int ind1,const int ind2,const int ind3) -{ - const int ind = (ind1 * bound2 + ind2) * bound3 + ind3; - return ptr[ind]; // reference return +complex& ComplexArray::operator()(const int ind1, const int ind2, const int ind3) { + const int ind = (ind1 * bound2 + ind2) * bound3 + ind3; + return ptr[ind]; // reference return } //******************************************************** @@ -156,10 +142,9 @@ complex &ComplexArray::operator()(const int ind1,const int ind2,const in // const reference return creates an lvakue // //******************************************************** -complex &ComplexArray::operator()(const int ind1,const int ind2,const int ind3,const int ind4) -{ - const int ind = ((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4; - return ptr[ind];// reference return +complex& ComplexArray::operator()(const int ind1, const int ind2, const int ind3, const int ind4) { + const int ind = ((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4; + return ptr[ind]; // reference return } //**************************** @@ -167,9 +152,10 @@ complex &ComplexArray::operator()(const int ind1,const int ind2,const in // zeroes out the whole array // //**************************** -void ComplexArray::zero_out(void) -{ - if (size <= 0) return; - for (int i = 0;i < size; i++) ptr[i] = 0; - return; +void ComplexArray::zero_out(void) { + if (size <= 0) + return; + for (int i = 0; i < size; i++) + ptr[i] = 0; + return; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/complexarray.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/complexarray.h index 6506fce530d..5e99f37bab0 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/complexarray.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/complexarray.h @@ -10,59 +10,49 @@ #include #include -using namespace std; +class ComplexArray { + public: + std::complex* ptr; -class ComplexArray -{ -public: - complex *ptr; + ComplexArray(const int d1 = 1, const int d2 = 1, const int d3 = 1); + ComplexArray(const int d1, const int d2, const int d3, const int d4); + ~ComplexArray(); - ComplexArray(const int d1 = 1 ,const int d2 = 1,const int d3 = 1); - ComplexArray(const int d1, const int d2,const int d3,const int d4); - ~ComplexArray(); + void create(const int d1, const int d2, const int d3); + void create(const int d1, const int d2, const int d3, const int d4); - void create(const int d1,const int d2,const int d3); - void create(const int d1,const int d2,const int d3,const int d4); + const ComplexArray& operator=(const ComplexArray& right); + const ComplexArray& operator=(const std::complex& right); - const ComplexArray &operator=(const ComplexArray &right); - const ComplexArray &operator=(const std::complex &right); + std::complex& operator()(const int d1, const int d2, const int d3); + std::complex& operator()(const int d1, const int d2, const int d3, const int d4); - complex &operator()(const int d1,const int d2,const int d3); - complex &operator()(const int d1,const int d2,const int d3,const int d4); + const std::complex& operator()(const int d1, const int d2, const int d3) const; + const std::complex& operator()(const int d1, const int d2, const int d3, const int d4) const; - const std::complex &operator()(const int d1,const int d2,const int d3)const; - const std::complex &operator()(const int d1,const int d2,const int d3,const int d4)const; + void zero_out(void); - void zero_out(void); + int getSize() const { return size; } - int getSize() const - { return size;} + int getDim() const { return dim; } - int getDim() const - { return dim;} + int getBound1() const { return bound1; } - int getBound1() const - { return bound1;} + int getBound2() const { return bound2; } - int getBound2() const - { return bound2;} + int getBound3() const { return bound3; } - int getBound3() const - { return bound3;} + int getBound4() const { return bound4; } - int getBound4() const - { return bound4;} + int getArrayCount(void) { return arrayCount; } - int getArrayCount(void) - { return arrayCount;} + private: + int size; + int dim; + int bound1, bound2, bound3, bound4; + static int arrayCount; -private: - int size; - int dim; - int bound1, bound2, bound3, bound4; - static int arrayCount; - - void freemem(); + void freemem(); }; -#endif // ComplexArray class +#endif // ComplexArray class diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/complexmatrix.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/complexmatrix.h index 9d75a910af2..15af190be18 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/complexmatrix.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/complexmatrix.h @@ -6,115 +6,108 @@ #define COMPLEXMATRIX_H #include -using namespace std; - -class ComplexMatrix -{ - -public: - - complex *c; - int nr; - int nc; - int size; - - //============== - // Constructors - //============== - inline ComplexMatrix(const int nrows = 1,const int ncols = 1); - - //=================== - // Copy constructor - //================== - inline ComplexMatrix(const ComplexMatrix &m1); - inline ~ComplexMatrix(); - - //============ - // Operators - //============ - complex &operator()(const int i,const int j) - { - return c[nc * i + j];//mohan modify in-line 2007-10-1 - } - const std::complex &operator()(const int i,const int j)const - { - return c[nc * i + j];//mohan modify in-line 2007-10-13 - } - - friend ComplexMatrix operator+(const ComplexMatrix &m1, const ComplexMatrix &m2); - friend ComplexMatrix operator-(const ComplexMatrix &m1, const ComplexMatrix &m2); - friend ComplexMatrix operator*(const ComplexMatrix &m1, const ComplexMatrix &m2); - friend ComplexMatrix multiply_special(const char Symmetry, const char Side, const char Uplo, const ComplexMatrix &m1, const ComplexMatrix &m2); - friend ComplexMatrix operator*(const std::complex &s, const ComplexMatrix &m); - friend ComplexMatrix operator*(const ComplexMatrix &m, const std::complex &s); - friend ComplexMatrix operator*(const double &s, const ComplexMatrix &m); - friend ComplexMatrix operator*(const ComplexMatrix &m, const double &s); - inline ComplexMatrix& operator=(const ComplexMatrix &m); - inline ComplexMatrix& operator*=(const std::complex &s); - inline ComplexMatrix& operator+=(const ComplexMatrix &m); - inline ComplexMatrix& operator-=(const ComplexMatrix &m); - - inline ComplexMatrix &add(const ComplexMatrix &m1, const ComplexMatrix &m2); - inline ComplexMatrix &minus(const ComplexMatrix &m1, const ComplexMatrix &m2); - inline ComplexMatrix &multiply(const ComplexMatrix &m1, const ComplexMatrix &m2); - inline ComplexMatrix &multiply_special(const char Symmetry, const char Side, const char Uplo, const ComplexMatrix &m1, const ComplexMatrix &m2); - - //================== - // member function: - //================== - inline void create(const int nrow,const int ncol); - inline void zero_out(void); - static int& getMCount(void){return mCount;} - inline void set_as_identity_matrix(void); -private: - - static int mCount; - inline void freemem(void);//mohan add 2007-11-20 - inline void init(const int nrows,const int ncols); + +class ComplexMatrix { + + public: + std::complex* c; + int nr; + int nc; + int size; + + //============== + // Constructors + //============== + inline ComplexMatrix(const int nrows = 1, const int ncols = 1); + + //=================== + // Copy constructor + //================== + inline ComplexMatrix(const ComplexMatrix& m1); + inline ~ComplexMatrix(); + + //============ + // Operators + //============ + std::complex& operator()(const int i, const int j) { + return c[nc * i + j]; // mohan modify in-line 2007-10-1 + } + const std::complex& operator()(const int i, const int j) const { + return c[nc * i + j]; // mohan modify in-line 2007-10-13 + } + + friend ComplexMatrix operator+(const ComplexMatrix& m1, const ComplexMatrix& m2); + friend ComplexMatrix operator-(const ComplexMatrix& m1, const ComplexMatrix& m2); + friend ComplexMatrix operator*(const ComplexMatrix& m1, const ComplexMatrix& m2); + friend ComplexMatrix multiply_special(const char Symmetry, + const char Side, + const char Uplo, + const ComplexMatrix& m1, + const ComplexMatrix& m2); + friend ComplexMatrix operator*(const std::complex& s, const ComplexMatrix& m); + friend ComplexMatrix operator*(const ComplexMatrix& m, const std::complex& s); + friend ComplexMatrix operator*(const double& s, const ComplexMatrix& m); + friend ComplexMatrix operator*(const ComplexMatrix& m, const double& s); + inline ComplexMatrix& operator=(const ComplexMatrix& m); + inline ComplexMatrix& operator*=(const std::complex& s); + inline ComplexMatrix& operator+=(const ComplexMatrix& m); + inline ComplexMatrix& operator-=(const ComplexMatrix& m); + + inline ComplexMatrix& add(const ComplexMatrix& m1, const ComplexMatrix& m2); + inline ComplexMatrix& minus(const ComplexMatrix& m1, const ComplexMatrix& m2); + inline ComplexMatrix& multiply(const ComplexMatrix& m1, const ComplexMatrix& m2); + inline ComplexMatrix& multiply_special(const char Symmetry, + const char Side, + const char Uplo, + const ComplexMatrix& m1, + const ComplexMatrix& m2); + + //================== + // member function: + //================== + inline void create(const int nrow, const int ncol); + inline void zero_out(void); + static int& getMCount(void) { return mCount; } + inline void set_as_identity_matrix(void); + + private: + static int mCount; + inline void freemem(void); // mohan add 2007-11-20 + inline void init(const int nrows, const int ncols); }; -inline std::complex trace(const ComplexMatrix &m); +inline std::complex trace(const ComplexMatrix& m); // mohan add 2008-7-1 -inline double abs2_row(const ComplexMatrix &m,const int ir); +inline double abs2_row(const ComplexMatrix& m, const int ir); // mohan add 2008-7-1 -inline double abs2_column(const ComplexMatrix &m,const int ic); -inline double abs2(const ComplexMatrix &m); -inline double abs2(const int nmat, ComplexMatrix **m); -inline double abs2_triangle_matrix( const char Uplo, ComplexMatrix &m); - -inline ComplexMatrix transpose(const ComplexMatrix &m, const bool &conjugate); - -inline void scale_accumulate( - const std::complex &s, - const ComplexMatrix &min, - ComplexMatrix &mout); - -inline void scale_accumulate( - const int &nmat, - const std::complex &s, - ComplexMatrix **min, - ComplexMatrix **mout); - -inline void scaled_sum( - const std::complex &s1, - const ComplexMatrix &m1, - const std::complex &s2, - const ComplexMatrix &m2, - ComplexMatrix &mout); - -inline void scaled_sum( - const int &nmat, - const std::complex &s1, - ComplexMatrix **m1, - const std::complex &s2, - ComplexMatrix **m2, - ComplexMatrix **mout); - -inline ComplexMatrix multiply_special( - const char Symmetry, - const char Side, - const char Uplo, - const ComplexMatrix &m1, - const ComplexMatrix &m2); - +inline double abs2_column(const ComplexMatrix& m, const int ic); +inline double abs2(const ComplexMatrix& m); +inline double abs2(const int nmat, ComplexMatrix** m); +inline double abs2_triangle_matrix(const char Uplo, ComplexMatrix& m); + +inline ComplexMatrix transpose(const ComplexMatrix& m, const bool& conjugate); + +inline void scale_accumulate(const std::complex& s, const ComplexMatrix& min, ComplexMatrix& mout); + +inline void scale_accumulate(const int& nmat, const std::complex& s, ComplexMatrix** min, ComplexMatrix** mout); + +inline void scaled_sum(const std::complex& s1, + const ComplexMatrix& m1, + const std::complex& s2, + const ComplexMatrix& m2, + ComplexMatrix& mout); + +inline void scaled_sum(const int& nmat, + const std::complex& s1, + ComplexMatrix** m1, + const std::complex& s2, + ComplexMatrix** m2, + ComplexMatrix** mout); + +inline ComplexMatrix multiply_special(const char Symmetry, + const char Side, + const char Uplo, + const ComplexMatrix& m1, + const ComplexMatrix& m2); + #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/complexmatrix_inline.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/complexmatrix_inline.h index e4698810a89..4f4fdb41b3b 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/complexmatrix_inline.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/complexmatrix_inline.h @@ -17,461 +17,385 @@ #include "complexarray.h" // constructor with sizes -inline ComplexMatrix::ComplexMatrix(int nrows, int ncols) -{ - this->init(nrows, ncols); - ++mCount; +inline ComplexMatrix::ComplexMatrix(int nrows, int ncols) { + this->init(nrows, ncols); + ++mCount; } // zero out the ComplexMatrix -inline void ComplexMatrix::zero_out(void) -{ -// for (int i=0; i(0.0,0.0); - memset ( c, 0, size*sizeof(complex) ); // Peize Lin update 2015-12-08 +inline void ComplexMatrix::zero_out(void) { + // for (int i=0; i(0.0,0.0); + memset(c, 0, size * sizeof(complex)); // Peize Lin update 2015-12-08 } /* void need_more_memory() { - cout << "\n Sorry to crash... but the running need more momory! Exit." << endl; - exit(0); + cout << "\n Sorry to crash... but the running need more momory! Exit." << endl; + exit(0); } */ -inline void ComplexMatrix::init(const int nrows,const int ncols) -{ - this->nr = nrows; - this->nc = ncols; - this->size = nr * nc; -// std::set_new_handler( need_more_memory ); - this->c = new std::complex[size]; - assert(c != 0); - this->zero_out(); -}//mohan the principle:as simple as possible:modify inline 2007-10-13 +inline void ComplexMatrix::init(const int nrows, const int ncols) { + this->nr = nrows; + this->nc = ncols; + this->size = nr * nc; + // std::set_new_handler( need_more_memory ); + this->c = new std::complex[size]; + assert(c != 0); + this->zero_out(); +} // mohan the principle:as simple as possible:modify inline 2007-10-13 // Copy constructor -inline ComplexMatrix::ComplexMatrix(const ComplexMatrix &m1) -{ - this->init(m1.nr, m1.nc); - ++mCount; - for(int i=0; isize; i++) c[i] = m1.c[i]; +inline ComplexMatrix::ComplexMatrix(const ComplexMatrix& m1) { + this->init(m1.nr, m1.nc); + ++mCount; + for (int i = 0; i < this->size; i++) + c[i] = m1.c[i]; } // deconstructor -inline ComplexMatrix::~ComplexMatrix() -{ - this->freemem(); -} +inline ComplexMatrix::~ComplexMatrix() { this->freemem(); } // Free up memory for ComplexMatrix -inline void ComplexMatrix::freemem(void) -{ - delete[] c; - c = NULL; +inline void ComplexMatrix::freemem(void) { + delete[] c; + c = NULL; } // reallocate memory for Complex Matrix -inline void ComplexMatrix::create(const int nrow,const int ncol) -{ - // because c has been 'new' in init function. - delete[] c; - this->init(nrow, ncol); - return; -} - -inline void ComplexMatrix::set_as_identity_matrix() -{ -/* for(int i=0; i(1.0, 0.0); - else c[nc * i + j] = std::complex(0.0, 0.0); - } - } -*/ - // Peize Lin update 2015-12-08 - zero_out(); - const int nrc_min = min(nr,nc); - for( int i=0; i(1.0,0.0); - } - return; -} - -// Adding matrices, as a friend -inline ComplexMatrix operator+(const ComplexMatrix &m1, const ComplexMatrix &m2) -{ - ComplexMatrix tm(m1); - tm+=m2; - return tm; -} - -// Subtracting matrices, as a friend -inline ComplexMatrix operator-(const ComplexMatrix &m1, const ComplexMatrix &m2) -{ - ComplexMatrix tm(m1); - tm-=m2; - return tm; +inline void ComplexMatrix::create(const int nrow, const int ncol) { + // because c has been 'new' in init function. + delete[] c; + this->init(nrow, ncol); + return; +} + +inline void ComplexMatrix::set_as_identity_matrix() { + /* for(int i=0; i(1.0, 0.0); + else c[nc * i + j] = std::complex(0.0, 0.0); + } + } + */ + // Peize Lin update 2015-12-08 + zero_out(); + const int nrc_min = min(nr, nc); + for (int i = 0; i < nrc_min; ++i) { + c[nc * i + i] = std::complex(1.0, 0.0); + } + return; +} + +// Adding matrices, as a friend +inline ComplexMatrix operator+(const ComplexMatrix& m1, const ComplexMatrix& m2) { + ComplexMatrix tm(m1); + tm += m2; + return tm; +} + +// Subtracting matrices, as a friend +inline ComplexMatrix operator-(const ComplexMatrix& m1, const ComplexMatrix& m2) { + ComplexMatrix tm(m1); + tm -= m2; + return tm; } // Multiplying matrices, as a friend // mprod = m1 * m2 -inline ComplexMatrix operator*(const ComplexMatrix &m1, const ComplexMatrix &m2) -{ - assert(m1.nc == m2.nr); - ComplexMatrix mprod(m1.nr, m2.nc); - -/* - complex z; - for (int i = 0;i < m1.nr;i++) - { - for (int j = 0;j < m2.nc;j++) - { - z = std::complex(0,0); - for (int k = 0;k < m1.nc;k++) - { - z += m1(i, k) * m2(k, j); - } - mprod(i, j) = z; - } - } -*/ - // Peize Lin update 2015-12-07 - LapackConnector::zgemm('N', 'N', - m1.nr, m2.nc, m1.nc, - 1.0, m1.c, m1.nc, m2.c, m2.nc, - 0.0, mprod.c, mprod.nc); - return mprod; +inline ComplexMatrix operator*(const ComplexMatrix& m1, const ComplexMatrix& m2) { + assert(m1.nc == m2.nr); + ComplexMatrix mprod(m1.nr, m2.nc); + + /* + complex z; + for (int i = 0;i < m1.nr;i++) + { + for (int j = 0;j < m2.nc;j++) + { + z = std::complex(0,0); + for (int k = 0;k < m1.nc;k++) + { + z += m1(i, k) * m2(k, j); + } + mprod(i, j) = z; + } + } + */ + // Peize Lin update 2015-12-07 + LapackConnector::zgemm('N', 'N', m1.nr, m2.nc, m1.nc, 1.0, m1.c, m1.nc, m2.c, m2.nc, 0.0, mprod.c, mprod.nc); + return mprod; } // Peize Lin add 2015-12-08 // m1^T=m1('T') or m1^H=m1('H') // mprod=m1*m2('L'eft) or mprod=m2*m1('R'ight) // m1 stored in 'U'pper or 'L'ower -inline ComplexMatrix multiply_special(const char Symmetry, const char Side, const char Uplo, const ComplexMatrix &m1, const ComplexMatrix &m2) -{ - assert(m1.nr == m1.nc); - assert(m1.nc == m2.nr); - ComplexMatrix mprod(m1.nr, m2.nc); - if('T'==Symmetry) - { - LapackConnector::zsymm(Side, Uplo, - m1.nr, m2.nc, - 1.0, m1.c, m1.nc, m2.c, m2.nc, - 0.0, mprod.c, mprod.nc); - } - else if('H'==Symmetry) - { - LapackConnector::zhemm(Side, Uplo, - m1.nr, m2.nc, - 1.0, m1.c, m1.nc, m2.c, m2.nc, - 0.0, mprod.c, mprod.nc); - } - else - { - throw invalid_argument("Symmetry must be 'T' or 'H'"); - } - return mprod; +inline ComplexMatrix multiply_special(const char Symmetry, + const char Side, + const char Uplo, + const ComplexMatrix& m1, + const ComplexMatrix& m2) { + assert(m1.nr == m1.nc); + assert(m1.nc == m2.nr); + ComplexMatrix mprod(m1.nr, m2.nc); + if ('T' == Symmetry) { + LapackConnector::zsymm(Side, Uplo, m1.nr, m2.nc, 1.0, m1.c, m1.nc, m2.c, m2.nc, 0.0, mprod.c, mprod.nc); + } else if ('H' == Symmetry) { + LapackConnector::zhemm(Side, Uplo, m1.nr, m2.nc, 1.0, m1.c, m1.nc, m2.c, m2.nc, 0.0, mprod.c, mprod.nc); + } else { + throw invalid_argument("Symmetry must be 'T' or 'H'"); + } + return mprod; } // Scale a ComplexMatrix -inline ComplexMatrix operator*(const std::complex &c,const ComplexMatrix &m) -{ - ComplexMatrix sm(m); - for (int i=0 ;i& c, const ComplexMatrix& m) { + ComplexMatrix sm(m); + for (int i = 0; i < m.size; i++) + sm.c[i] *= c; + return sm; } // ComplexMatrix scalar -inline ComplexMatrix operator*(const ComplexMatrix &m,const std::complex &c) -{ - ComplexMatrix sm(m); - for (int i = 0;i < m.size;i++) sm.c[i] *= c; - return sm; +inline ComplexMatrix operator*(const ComplexMatrix& m, const std::complex& c) { + ComplexMatrix sm(m); + for (int i = 0; i < m.size; i++) + sm.c[i] *= c; + return sm; } -inline ComplexMatrix operator*(const double &r,const ComplexMatrix &m) -{ - ComplexMatrix sm(m); - for(int i=0; ic[i] = m1.c[i] + m2.c[i]; - return *this; +inline ComplexMatrix& ComplexMatrix::add(const ComplexMatrix& m1, const ComplexMatrix& m2) { + for (int i = 0; i < size; ++i) + this->c[i] = m1.c[i] + m2.c[i]; + return *this; } -inline ComplexMatrix &ComplexMatrix::minus(const ComplexMatrix &m1, const ComplexMatrix &m2) -{ - for(int i=0; ic[i] = m1.c[i] - m2.c[i]; - return *this; +inline ComplexMatrix& ComplexMatrix::minus(const ComplexMatrix& m1, const ComplexMatrix& m2) { + for (int i = 0; i < size; ++i) + this->c[i] = m1.c[i] - m2.c[i]; + return *this; } - -inline ComplexMatrix &ComplexMatrix::multiply(const ComplexMatrix &m1, const ComplexMatrix &m2) -{ - LapackConnector::zgemm('N', 'N', - m1.nr, m2.nc, m1.nc, - 1.0, m1.c, m1.nc, m2.c, m2.nc, - 0.0, this->c, this->nc); - return *this; + +inline ComplexMatrix& ComplexMatrix::multiply(const ComplexMatrix& m1, const ComplexMatrix& m2) { + LapackConnector::zgemm('N', 'N', m1.nr, m2.nc, m1.nc, 1.0, m1.c, m1.nc, m2.c, m2.nc, 0.0, this->c, this->nc); + return *this; } - + // Peize Lin add 2015-12-08 // m1^T=m1('T') or m1^H=m1('H') // mprod=m1*m2('L'eft) or mprod=m2*m1('R'ight) -// m1 stored in 'U'pper or 'L'ower -inline ComplexMatrix &ComplexMatrix::multiply_special(const char Symmetry, const char Side, const char Uplo, const ComplexMatrix &m1, const ComplexMatrix &m2) -{ - if('T'==Symmetry) - { - LapackConnector::zsymm(Side, Uplo, - m1.nr, m2.nc, - 1.0, m1.c, m1.nc, m2.c, m2.nc, - 0.0, this->c, this->nc); - } - else if('H'==Symmetry) - { - LapackConnector::zhemm(Side, Uplo, - m1.nr, m2.nc, - 1.0, m1.c, m1.nc, m2.c, m2.nc, - 0.0, this->c, this->nc); - } - else - { - throw invalid_argument("Symmetry must be 'T' or 'H'"); - } - return *this; -} - -inline ComplexMatrix& ComplexMatrix::operator=(const ComplexMatrix &m) -{ - if(m.nr!=this->nr || m.nc!=this->nc) - { - cout << "\n row/col number can't match in ComplexMatrix '=' operator\n"; - cout << " this nr = " << this->nr; - cout << " this nc = " << this->nc; - cout << " in nr = " << m.nr; - cout << " in nc = " << m.nc; - exit(0); - } -/* else { - this->create(m.nr, m.nc); - } */ // why ? - -// for(int i=0;isize;i++) c[i] = m.c[i]; - memcpy ( c, m.c, this->size * sizeof(complex) ); // Peize Lin update 2015-12-08 - return *this; -} - -inline ComplexMatrix& ComplexMatrix::operator*=(const std::complex &s) -{ - for (int i = 0;i < this->size;i++) c[i] *= s; - return *this; +// m1 stored in 'U'pper or 'L'ower +inline ComplexMatrix& ComplexMatrix::multiply_special(const char Symmetry, + const char Side, + const char Uplo, + const ComplexMatrix& m1, + const ComplexMatrix& m2) { + if ('T' == Symmetry) { + LapackConnector::zsymm(Side, Uplo, m1.nr, m2.nc, 1.0, m1.c, m1.nc, m2.c, m2.nc, 0.0, this->c, this->nc); + } else if ('H' == Symmetry) { + LapackConnector::zhemm(Side, Uplo, m1.nr, m2.nc, 1.0, m1.c, m1.nc, m2.c, m2.nc, 0.0, this->c, this->nc); + } else { + throw invalid_argument("Symmetry must be 'T' or 'H'"); + } + return *this; +} + +inline ComplexMatrix& ComplexMatrix::operator=(const ComplexMatrix& m) { + if (m.nr != this->nr || m.nc != this->nc) { + cout << "\n row/col number can't match in ComplexMatrix '=' operator\n"; + cout << " this nr = " << this->nr; + cout << " this nc = " << this->nc; + cout << " in nr = " << m.nr; + cout << " in nc = " << m.nc; + exit(0); + } + /* else { + this->create(m.nr, m.nc); + } */ // why ? + + // for(int i=0;isize;i++) c[i] = m.c[i]; + memcpy(c, m.c, this->size * sizeof(complex)); // Peize Lin update 2015-12-08 + return *this; +} + +inline ComplexMatrix& ComplexMatrix::operator*=(const std::complex& s) { + for (int i = 0; i < this->size; i++) + c[i] *= s; + return *this; } // Accumulate to a ComplexMatrix in place -inline ComplexMatrix& ComplexMatrix::operator+=(const ComplexMatrix &m) -{ - for(int i=0; ic[i] += m.c[i]; - return *this; +inline ComplexMatrix& ComplexMatrix::operator+=(const ComplexMatrix& m) { + for (int i = 0; i < size; i++) + this->c[i] += m.c[i]; + return *this; } // decumulate to a ComplexMatrix in place -inline ComplexMatrix& ComplexMatrix::operator-=(const ComplexMatrix &m) -{ - for(int i=0; ic[i] -= m.c[i]; - return *this; +inline ComplexMatrix& ComplexMatrix::operator-=(const ComplexMatrix& m) { + for (int i = 0; i < size; i++) + this->c[i] -= m.c[i]; + return *this; } // Returns trace of ComplexMatrix -inline std::complex trace(const ComplexMatrix &m) -{ - complex tr=complex(0,0); - assert(m.nr == m.nc); - for (int i=0; i trace(const ComplexMatrix& m) { + complex tr = complex(0, 0); + assert(m.nr == m.nc); + for (int i = 0; i < m.nr; i++) + tr += m(i, i); + return tr; } // Do mout += s*min -inline void scale_accumulate(const std::complex &s, - const ComplexMatrix &min, - ComplexMatrix &mout) -{ - assert(min.nr == mout.nr); - assert(min.nc == mout.nc); - for (int j=0; j& s, const ComplexMatrix& min, ComplexMatrix& mout) { + assert(min.nr == mout.nr); + assert(min.nc == mout.nc); + for (int j = 0; j < min.size; j++) { + mout.c[j] += s * min.c[j]; + } + return; } // Do mout[i] += s*min[i] -inline void scale_accumulate(const int &nmat, - const std::complex &s, - ComplexMatrix **min, - ComplexMatrix **mout) -{ - assert(nmat>=0); - for (int i=0; i& s, ComplexMatrix** min, ComplexMatrix** mout) { + assert(nmat >= 0); + for (int i = 0; i < nmat; i++) { + scale_accumulate(s, *min[i], *mout[i]); + } + return; } // Do mout = s1*m1 + s2*m2 -inline void scaled_sum(const std::complex &s1, - const ComplexMatrix &m1, - const std::complex &s2, - const ComplexMatrix &m2, - ComplexMatrix &mout) -{ - assert(m1.nr == m2.nr); - assert(m1.nr == mout.nr); - assert(m1.nc == m2.nc); - assert(m1.nc == mout.nc); - - for(int i=0; i& s1, + const ComplexMatrix& m1, + const std::complex& s2, + const ComplexMatrix& m2, + ComplexMatrix& mout) { + assert(m1.nr == m2.nr); + assert(m1.nr == mout.nr); + assert(m1.nc == m2.nc); + assert(m1.nc == mout.nc); + + for (int i = 0; i < m1.size; i++) { + mout.c[i] = s1 * m1.c[i] + s2 * m2.c[i]; + } + return; } // Does mout[i] = s1*m1[i] + s2*m2[i] -inline void scaled_sum(const int &nmat, - const std::complex &s1, - ComplexMatrix **m1, - const std::complex &s2, - ComplexMatrix **m2, - ComplexMatrix **mout) -{ - assert(nmat>0); - for(int i=0; i z; - for(int ic=0;ic z; - for(int ir=0;ir& s1, + ComplexMatrix** m1, + const std::complex& s2, + ComplexMatrix** m2, + ComplexMatrix** mout) { + assert(nmat > 0); + for (int i = 0; i < nmat; i++) { + scaled_sum(s1, *m1[i], s2, *m2[i], *mout[i]); + } + return; +} + +inline double abs2_row(const ComplexMatrix& m, const int ir) { + double r = 0.0; + complex z; + for (int ic = 0; ic < m.nc; ic++) { + z = m.c[m.nc * ir + ic]; + r += z.real() * z.real() + z.imag() * z.imag(); + } + return r; +} + +inline double abs2_column(const ComplexMatrix& m, const int ic) { + double r = 0.0; + complex z; + for (int ir = 0; ir < m.nr; ir++) { + z = m.c[m.nc * ir + ic]; + r += z.real() * z.real() + z.imag() * z.imag(); + } + return r; } // returns absolute square magnitude of sum of all ComplexMatrix elements -inline double abs2(const ComplexMatrix &m) -{ - double r=0.0; - complex z; - - for (int i = 0;i < m.size;i++) - { - z = m.c[i]; - r += z.real() * z.real() + z.imag() * z.imag(); - } - return r; -} +inline double abs2(const ComplexMatrix& m) { + double r = 0.0; + complex z; -// Same for an array of matrices -inline double abs2(const int nmat, ComplexMatrix **m) -{ - double r = 0.0; - for (int i = 0;i < nmat;i++) - { - r += abs2(*m[i]); - } - return r; + for (int i = 0; i < m.size; i++) { + z = m.c[i]; + r += z.real() * z.real() + z.imag() * z.imag(); + } + return r; } -inline double abs2_triangle_matrix( const char Uplo, ComplexMatrix &m) -{ - double r(0.0); - complex z; - - if('U'==Uplo) - { - for (int i=0; i z; + + if ('U' == Uplo) { + for (int i = 0; i < m.nr; ++i) { + for (int j = i + 1; j < m.nc; ++j) { + z = m(i, j); + r += z.real() * z.real() + z.imag() * z.imag(); + } + } + } else if ('L' == Uplo) { + for (int i = 0; i < m.nr; ++i) { + for (int j = 0; j < i; ++j) { + z = m(i, j); + r += z.real() * z.real() + z.imag() * z.imag(); + } + } + } else { + throw invalid_argument("Uplo must be 'U' or 'L'"); + } +} + +inline ComplexMatrix transpose(const ComplexMatrix& m, const bool& conjugate) { + ComplexMatrix tm(m.nc, m.nr); + if (conjugate) { + for (int i = 0; i < m.nr; i++) { + for (int j = 0; j < m.nc; j++) { + tm(j, i) = conj(m(i, j)); + } + } + } else { + for (int i = 0; i < m.nr; i++) { + for (int j = 0; j < m.nc; j++) { + tm(j, i) = m(i, j); + } + } + } + return tm; } #endif \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/intarray.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/intarray.cpp index 0f8cbf486cf..647d8c1a966 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/intarray.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/intarray.cpp @@ -6,207 +6,236 @@ int IntArray::arrayCount = 0; -void IntArrayAlloc() -{ - cout << "\n Allocation error for IntArray " << endl; - exit(0); -} - -IntArray::IntArray(const int d1,const int d2) -{ - dim = 2; - bound1 = (d1 <= 0) ? 1 : d1; - bound2 = (d2 <= 0) ? 1 : d2; - bound3 = bound4 = 0; - size = bound1 * bound2; - ptr = new int[size]; - assert( ptr != 0); - ++arrayCount; -} - -IntArray::IntArray(const int d1,const int d2,const int d3) -{ - dim = 3; - bound1 = (d1 <= 0) ? 1 : d1; - bound2 = (d2 <= 0) ? 1 : d2; - bound3 = (d3 <= 0) ? 1 : d3; - bound4 = 0; - set_new_handler(IntArrayAlloc); - size = bound1 * bound2 * bound3 ; //* sizeof(float); - ptr = new int[size]();assert(ptr != 0); - zero_out(); - ++arrayCount; -} - -IntArray::IntArray(const int d1,const int d2,const int d3,const int d4) -{ - dim = 4; - bound1 = (d1 <= 0) ? 1 : d1; - bound2 = (d2 <= 0) ? 1 : d2; - bound3 = (d3 <= 0) ? 1 : d3; - bound4 = (d4 <= 0) ? 1 : d4; - set_new_handler(IntArrayAlloc); - size = bound1 * bound2 * bound3 * bound4 ; //* sizeof(float); - ptr = new int[size]();assert(ptr != 0); - zero_out(); - ++arrayCount; -} - -IntArray::IntArray(const int d1,const int d2,const int d3, - const int d4,const int d5) -{ - dim = 5; - bound1 = (d1 <= 0) ? 1 : d1; - bound2 = (d2 <= 0) ? 1 : d2; - bound3 = (d3 <= 0) ? 1 : d3; - bound4 = (d4 <= 0) ? 1 : d4; - bound5 = (d5 <= 0) ? 1 : d5; - set_new_handler(IntArrayAlloc); - size = bound1 * bound2 * bound3 * bound4 * bound5; - ptr = new int[size]();assert(ptr != 0); - zero_out(); - ++arrayCount; -} - -IntArray::IntArray(const int d1,const int d2,const int d3, - const int d4,const int d5,const int d6) -{ - dim = 6; - bound1 = (d1 <= 0) ? 1 : d1; - bound2 = (d2 <= 0) ? 1 : d2; - bound3 = (d3 <= 0) ? 1 : d3; - bound4 = (d4 <= 0) ? 1 : d4; - bound5 = (d5 <= 0) ? 1 : d5; - bound6 = (d6 <= 0) ? 1 : d6; - set_new_handler(IntArrayAlloc); - size = bound1 * bound2 * bound3 * bound4 * bound5 * bound6; - ptr = new int[size]();assert(ptr != 0); - zero_out(); - ++arrayCount; +void IntArrayAlloc() { + cout << "\n Allocation error for IntArray " << endl; + exit(0); } -//******************************** -// Destructor for class IntArray -//******************************** -IntArray ::~IntArray() -{ - freemem(); -} - -void IntArray::freemem() -{ - delete [] ptr; - ptr = NULL; -} - -void IntArray::create(const int d1,const int d2,const int d3,const int d4,const int d5,const int d6) -{ - size = d1 * d2 * d3 * d4 * d5 * d6;assert(size>0); - dim = 6; - bound1 = d1;bound2 = d2;bound3 = d3;bound4 = d4;bound5 = d5;bound6 = d6; - delete[] ptr; ptr = new int[size]; - assert(ptr != 0);zero_out(); -} - -void IntArray::create(const int d1,const int d2,const int d3,const int d4,const int d5) -{ - size = d1 * d2 * d3 * d4 * d5;assert(size>0); - dim = 5; - bound1 = d1;bound2 = d2;bound3 = d3;bound4 = d4;bound5 = d5; - delete[] ptr; ptr = new int[size]; - assert(ptr != 0);zero_out(); +IntArray::IntArray(const int d1, const int d2) { + dim = 2; + bound1 = (d1 <= 0) ? 1 : d1; + bound2 = (d2 <= 0) ? 1 : d2; + bound3 = bound4 = 0; + size = bound1 * bound2; + ptr = new int[size]; + assert(ptr != 0); + ++arrayCount; } -void IntArray::create(const int d1,const int d2,const int d3,const int d4) -{ - size = d1 * d2 * d3 * d4;assert(size>0); - dim = 4; - bound1 = d1;bound2 = d2;bound3 = d3;bound4 = d4; - delete[] ptr; ptr = new int[size]; - assert(ptr != 0);zero_out(); +IntArray::IntArray(const int d1, const int d2, const int d3) { + dim = 3; + bound1 = (d1 <= 0) ? 1 : d1; + bound2 = (d2 <= 0) ? 1 : d2; + bound3 = (d3 <= 0) ? 1 : d3; + bound4 = 0; + set_new_handler(IntArrayAlloc); + size = bound1 * bound2 * bound3; //* sizeof(float); + ptr = new int[size](); + assert(ptr != 0); + zero_out(); + ++arrayCount; } -void IntArray::create(const int d1,const int d2,const int d3) -{ - size = d1 * d2 * d3;assert(size>0); - dim = 3; - bound1 = d1;bound2 = d2;bound3 = d3;bound4 = 1; - delete [] ptr;ptr = new int[size]; - assert(ptr != 0);zero_out(); +IntArray::IntArray(const int d1, const int d2, const int d3, const int d4) { + dim = 4; + bound1 = (d1 <= 0) ? 1 : d1; + bound2 = (d2 <= 0) ? 1 : d2; + bound3 = (d3 <= 0) ? 1 : d3; + bound4 = (d4 <= 0) ? 1 : d4; + set_new_handler(IntArrayAlloc); + size = bound1 * bound2 * bound3 * bound4; //* sizeof(float); + ptr = new int[size](); + assert(ptr != 0); + zero_out(); + ++arrayCount; } -void IntArray::create(const int d1, const int d2) -{ - size = d1 * d2;assert(size>0); - dim = 2; - bound1 = d1;bound2 = d2;bound3 = bound4 = 1; - delete[] ptr;ptr = new int[size]; - assert(ptr !=0 );zero_out(); +IntArray::IntArray(const int d1, const int d2, const int d3, const int d4, const int d5) { + dim = 5; + bound1 = (d1 <= 0) ? 1 : d1; + bound2 = (d2 <= 0) ? 1 : d2; + bound3 = (d3 <= 0) ? 1 : d3; + bound4 = (d4 <= 0) ? 1 : d4; + bound5 = (d5 <= 0) ? 1 : d5; + set_new_handler(IntArrayAlloc); + size = bound1 * bound2 * bound3 * bound4 * bound5; + ptr = new int[size](); + assert(ptr != 0); + zero_out(); + ++arrayCount; } -const IntArray &IntArray::operator=(const IntArray &right) -{ - for (int i = 0;i < size;i++) ptr[i] = right.ptr[i]; - return *this;// enables x = y = z; +IntArray::IntArray(const int d1, const int d2, const int d3, const int d4, const int d5, const int d6) { + dim = 6; + bound1 = (d1 <= 0) ? 1 : d1; + bound2 = (d2 <= 0) ? 1 : d2; + bound3 = (d3 <= 0) ? 1 : d3; + bound4 = (d4 <= 0) ? 1 : d4; + bound5 = (d5 <= 0) ? 1 : d5; + bound6 = (d6 <= 0) ? 1 : d6; + set_new_handler(IntArrayAlloc); + size = bound1 * bound2 * bound3 * bound4 * bound5 * bound6; + ptr = new int[size](); + assert(ptr != 0); + zero_out(); + ++arrayCount; } -const IntArray &IntArray::operator=(const int &value) -{ - for (int i = 0;i < size;i++) ptr[i] = value; - return *this;// enables x = y = z; +//******************************** +// Destructor for class IntArray +//******************************** +IntArray ::~IntArray() { freemem(); } + +void IntArray::freemem() { + delete[] ptr; + ptr = NULL; +} + +void IntArray::create(const int d1, const int d2, const int d3, const int d4, const int d5, const int d6) { + size = d1 * d2 * d3 * d4 * d5 * d6; + assert(size > 0); + dim = 6; + bound1 = d1; + bound2 = d2; + bound3 = d3; + bound4 = d4; + bound5 = d5; + bound6 = d6; + delete[] ptr; + ptr = new int[size]; + assert(ptr != 0); + zero_out(); +} + +void IntArray::create(const int d1, const int d2, const int d3, const int d4, const int d5) { + size = d1 * d2 * d3 * d4 * d5; + assert(size > 0); + dim = 5; + bound1 = d1; + bound2 = d2; + bound3 = d3; + bound4 = d4; + bound5 = d5; + delete[] ptr; + ptr = new int[size]; + assert(ptr != 0); + zero_out(); +} + +void IntArray::create(const int d1, const int d2, const int d3, const int d4) { + size = d1 * d2 * d3 * d4; + assert(size > 0); + dim = 4; + bound1 = d1; + bound2 = d2; + bound3 = d3; + bound4 = d4; + delete[] ptr; + ptr = new int[size]; + assert(ptr != 0); + zero_out(); +} + +void IntArray::create(const int d1, const int d2, const int d3) { + size = d1 * d2 * d3; + assert(size > 0); + dim = 3; + bound1 = d1; + bound2 = d2; + bound3 = d3; + bound4 = 1; + delete[] ptr; + ptr = new int[size]; + assert(ptr != 0); + zero_out(); +} + +void IntArray::create(const int d1, const int d2) { + size = d1 * d2; + assert(size > 0); + dim = 2; + bound1 = d1; + bound2 = d2; + bound3 = bound4 = 1; + delete[] ptr; + ptr = new int[size]; + assert(ptr != 0); + zero_out(); +} + +const IntArray& IntArray::operator=(const IntArray& right) { + for (int i = 0; i < size; i++) + ptr[i] = right.ptr[i]; + return *this; // enables x = y = z; +} + +const IntArray& IntArray::operator=(const int& value) { + for (int i = 0; i < size; i++) + ptr[i] = value; + return *this; // enables x = y = z; } //******************************************************** // overloaded subscript operator for const Int Array // const reference return create an cvakue //******************************************************** -const int &IntArray::operator() -(const int ind1,const int ind2)const -{return ptr[ ind1 * bound2 + ind2 ];} +const int& IntArray::operator()(const int ind1, const int ind2) const { return ptr[ind1 * bound2 + ind2]; } -const int &IntArray::operator() -(const int ind1,const int ind2,const int ind3)const -{return ptr[ (ind1 * bound2 + ind2) * bound3 + ind3 ];} +const int& IntArray::operator()(const int ind1, const int ind2, const int ind3) const { + return ptr[(ind1 * bound2 + ind2) * bound3 + ind3]; +} -const int &IntArray::operator() -(const int ind1,const int ind2,const int ind3,const int ind4)const -{return ptr[ ((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4 ];} +const int& IntArray::operator()(const int ind1, const int ind2, const int ind3, const int ind4) const { + return ptr[((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4]; +} -const int &IntArray::operator() -(const int ind1,const int ind2,const int ind3,const int ind4,const int ind5)const -{return ptr[ (((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4) * bound5 + ind5 ];} +const int& IntArray::operator()(const int ind1, const int ind2, const int ind3, const int ind4, const int ind5) const { + return ptr[(((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4) * bound5 + ind5]; +} -const int &IntArray::operator() -(const int ind1,const int ind2,const int ind3,const int ind4,const int ind5,const int ind6)const -{return ptr[ ((((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4) * bound5 + ind5) * bound6 + ind6 ];} +const int& IntArray::operator()(const int ind1, + const int ind2, + const int ind3, + const int ind4, + const int ind5, + const int ind6) const { + return ptr[((((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4) * bound5 + ind5) * bound6 + ind6]; +} //******************************************************** // overloaded subscript operator for non-const Int Array // const reference return creates an lvakue //******************************************************** -int &IntArray::operator()(const int ind1,const int ind2) -{return ptr[ind1 * bound2 + ind2];} +int& IntArray::operator()(const int ind1, const int ind2) { return ptr[ind1 * bound2 + ind2]; } -int &IntArray::operator()(const int ind1,const int ind2,const int ind3) -{return ptr[ (ind1 * bound2 + ind2) * bound3 + ind3 ];} +int& IntArray::operator()(const int ind1, const int ind2, const int ind3) { + return ptr[(ind1 * bound2 + ind2) * bound3 + ind3]; +} -int &IntArray::operator()(const int ind1,const int ind2,const int ind3,const int ind4) -{return ptr[ ((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4 ];} +int& IntArray::operator()(const int ind1, const int ind2, const int ind3, const int ind4) { + return ptr[((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4]; +} -int &IntArray::operator() -(const int ind1,const int ind2,const int ind3,const int ind4,const int ind5) -{return ptr[ (((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4) * bound5 + ind5 ];} +int& IntArray::operator()(const int ind1, const int ind2, const int ind3, const int ind4, const int ind5) { + return ptr[(((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4) * bound5 + ind5]; +} -int &IntArray::operator() -(const int ind1,const int ind2,const int ind3,const int ind4,const int ind5,const int ind6) -{return ptr[ ((((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4) * bound5 + ind5) * bound6 + ind6 ];} +int& IntArray::operator()(const int ind1, + const int ind2, + const int ind3, + const int ind4, + const int ind5, + const int ind6) { + return ptr[((((ind1 * bound2 + ind2) * bound3 + ind3) * bound4 + ind4) * bound5 + ind5) * bound6 + ind6]; +} //**************************** // zeroes out the whole array //**************************** -void IntArray::zero_out(void) -{ - if (size <= 0) return; - for (int i = 0;i < size; i++) ptr[i] = 0; - return; +void IntArray::zero_out(void) { + if (size <= 0) + return; + for (int i = 0; i < size; i++) + ptr[i] = 0; + return; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/intarray.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/intarray.h index 3318578da1a..1266a57a3e7 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/intarray.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/intarray.h @@ -10,63 +10,59 @@ #include #include -using namespace std; +class IntArray { + public: + int* ptr; -class IntArray -{ -public: - int *ptr; + // Constructors for different dimesnions + IntArray(const int d1 = 1, const int d2 = 1); + IntArray(const int d1, const int d2, const int d3); + IntArray(const int d1, const int d2, const int d3, const int d4); + IntArray(const int d1, const int d2, const int d3, const int d4, const int d5); + IntArray(const int d1, const int d2, const int d3, const int d4, const int d5, const int d6); - // Constructors for different dimesnions - IntArray(const int d1 = 1, const int d2 = 1); - IntArray(const int d1, const int d2,const int d3); - IntArray(const int d1, const int d2,const int d3,const int d4); - IntArray(const int d1, const int d2,const int d3,const int d4,const int d5); - IntArray(const int d1, const int d2,const int d3,const int d4,const int d5,const int d6); + ~IntArray(); - ~IntArray(); + void create(const int d1, const int d2); + void create(const int d1, const int d2, const int d3); + void create(const int d1, const int d2, const int d3, const int d4); + void create(const int d1, const int d2, const int d3, const int d4, const int d5); + void create(const int d1, const int d2, const int d3, const int d4, const int d5, const int d6); - void create(const int d1, const int d2); - void create(const int d1, const int d2, const int d3); - void create(const int d1, const int d2, const int d3, const int d4); - void create(const int d1, const int d2, const int d3, const int d4, const int d5); - void create(const int d1, const int d2, const int d3, const int d4, const int d5, const int d6); + const IntArray& operator=(const IntArray& right); + const IntArray& operator=(const int& right); - const IntArray &operator=(const IntArray &right); - const IntArray &operator=(const int &right); + int& operator()(const int d1, const int d2); + int& operator()(const int d1, const int d2, const int d3); + int& operator()(const int d1, const int d2, const int d3, const int d4); + int& operator()(const int d1, const int d2, const int d3, const int d4, const int d5); + int& operator()(const int d1, const int d2, const int d3, const int d4, const int d5, const int d6); - int &operator()(const int d1, const int d2); - int &operator()(const int d1, const int d2, const int d3); - int &operator()(const int d1, const int d2, const int d3,const int d4); - int &operator()(const int d1, const int d2, const int d3, const int d4, const int d5); - int &operator()(const int d1, const int d2, const int d3, const int d4, const int d5, const int d6); + const int& operator()(const int d1, const int d2) const; + const int& operator()(const int d1, const int d2, const int d3) const; + const int& operator()(const int d1, const int d2, const int d3, const int d4) const; + const int& operator()(const int d1, const int d2, const int d3, const int d4, const int d5) const; + const int& operator()(const int d1, const int d2, const int d3, const int d4, const int d5, const int d6) const; - const int &operator()(const int d1,const int d2)const; - const int &operator()(const int d1,const int d2,const int d3)const; - const int &operator()(const int d1,const int d2,const int d3,const int d4)const; - const int &operator()(const int d1,const int d2,const int d3,const int d4, const int d5)const; - const int &operator()(const int d1,const int d2,const int d3,const int d4, const int d5, const int d6)const; + void zero_out(void); - void zero_out(void); + int getSize() const { return size; } + int getDim() const { return dim; } + int getBound1() const { return bound1; } + int getBound2() const { return bound2; } + int getBound3() const { return bound3; } + int getBound4() const { return bound4; } + int getBound5() const { return bound5; } + int getBound6() const { return bound6; } - int getSize() const{ return size;} - int getDim() const{ return dim;} - int getBound1() const{ return bound1;} - int getBound2() const{ return bound2;} - int getBound3() const{ return bound3;} - int getBound4() const { return bound4;} - int getBound5() const { return bound5;} - int getBound6() const { return bound6;} + int getArrayCount(void) { return arrayCount; } - int getArrayCount(void) - { return arrayCount;} - -private: - int size; - int dim; - int bound1, bound2, bound3, bound4, bound5, bound6; - static int arrayCount; - void freemem(); + private: + int size; + int dim; + int bound1, bound2, bound3, bound4, bound5, bound6; + static int arrayCount; + void freemem(); }; -#endif // IntArray class +#endif // IntArray class diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix.cpp index ab9c73f635f..8fcaf3faa17 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix.cpp @@ -2,61 +2,53 @@ #include "../src_spillage/Inverse_Matrix_S.h" #include "complexmatrix_inline.h" -Inverse_Matrix::Inverse_Matrix(){} -Inverse_Matrix::~Inverse_Matrix(){} -void Inverse_Matrix::init(const int &dim_in) -{ +Inverse_Matrix::Inverse_Matrix() {} +Inverse_Matrix::~Inverse_Matrix() {} +void Inverse_Matrix::init(const int& dim_in) { this->dim = dim_in; this->e = new double[dim]; - this->lwork = 2*dim; + this->lwork = 2 * dim; this->work2 = new std::complex[lwork]; - this->rwork = new double[3*dim-2]; + this->rwork = new double[3 * dim - 2]; this->info = 0; this->A.create(dim, dim); this->EA.create(dim, dim); return; } -void Inverse_Matrix::using_zheev( const ComplexMatrix &Sin, ComplexMatrix &Sout) -{ - timer::tick("Inverse","using_zheev"); +void Inverse_Matrix::using_zheev(const ComplexMatrix& Sin, ComplexMatrix& Sout) { + timer::tick("Inverse", "using_zheev"); this->A = Sin; - //LapackConnector::zhegv( 1, 'V', 'U', nwan , A , nwan , B , nwan , e, work2 , 80 , rwork , &info ); + // LapackConnector::zhegv( 1, 'V', 'U', nwan , A , nwan , B , nwan , e, work2 , 80 , rwork , &info ); LapackConnector::zheev('V', 'U', dim, this->A, dim, e, work2, lwork, rwork, &info); - for(int i=0; iA(j,i) ) / e[i] ; + for (int i = 0; i < dim; i++) { + for (int j = 0; j < dim; j++) { + EA(i, j) = conj(this->A(j, i)) / e[i]; } } Sout = this->A * this->EA; - timer::tick("Inverse","using_zheev"); + timer::tick("Inverse", "using_zheev"); return; } -void Inverse_Matrix::using_zpotrf( const ComplexMatrix &Sin) -{ -// timer::tick("Inverse","using_zpotrf"); +void Inverse_Matrix::using_zpotrf(const ComplexMatrix& Sin) { + // timer::tick("Inverse","using_zpotrf"); - for(int i=0; i *work2; + std::complex* work2; double* rwork; int info; diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate.cpp index 448b818233e..726ef881755 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate.cpp @@ -1,6 +1,2 @@ #include "inverse_matrix_iterate.h" #include "inverse_matrix_iterate_inline.h" - - - - diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate.h index 19ef02ee38d..fa27a7f70c5 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate.h @@ -3,53 +3,74 @@ #include "complexmatrix.h" -#include -#include -#include +#include +#include +#include // input A, X_0 // cal A_I // iterate: X_{n+1} = X_n (2I - A*X_n ) - -class Inverse_Matrix_Iterate -{ - public: - inline void init(size_t dim_in); - inline Inverse_Matrix_Iterate &set_X0(const ComplexMatrix &X0_in); - Inverse_Matrix_Iterate &set_A(ComplexMatrix &A_in) { this->A_ptr=&A_in; return *this;}; - inline const ComplexMatrix &cal_inverse(); - const ComplexMatrix &get_inverse() { return *this->inverse_ptr; } - - private: - inline void iterate(const ComplexMatrix &old_X, ComplexMatrix &new_X); - - private: - ComplexMatrix *A_ptr = NULL; - ComplexMatrix X_store_1; - ComplexMatrix X_store_2; - const ComplexMatrix *X0_ptr = NULL; - const ComplexMatrix *inverse_ptr = NULL; - ComplexMatrix identity; - ComplexMatrix matrix_tmp_1; - ComplexMatrix matrix_tmp_2; - ComplexMatrix X0_tmp; - size_t iterate_num{20}; - double tolerate_error2{1E-20}; - double fluctrate_error2{0.0}; - double last_error2{std::numeric_limits::max()}; - struct Matrix_Info{ size_t dim; char symmetry{NULL}; char uplo{NULL};} matrix_info; - - public: - Inverse_Matrix_Iterate &set_iterate_num(size_t iterate_num_in) { this->iterate_num=iterate_num_in; return *this;} - Inverse_Matrix_Iterate &set_tolerate_error(double tolerate_error_in) { this->tolerate_error2=tolerate_error_in*tolerate_error_in; return *this;} - Inverse_Matrix_Iterate &set_fluctrate_error(double fluctrate_error_in) { this->fluctrate_error2=fluctrate_error_in*fluctrate_error_in; return *this;} - Inverse_Matrix_Iterate &set_symmetric_info(char symmetry_in, char uplo_in) { this->matrix_info.symmetry = symmetry_in; this->matrix_info.uplo = uplo_in; return *this;} - - private: - class Little_Error: public exception {}; - public: - class Unstable: public exception {}; - private: + +class Inverse_Matrix_Iterate { + public: + inline void init(size_t dim_in); + inline Inverse_Matrix_Iterate& set_X0(const ComplexMatrix& X0_in); + Inverse_Matrix_Iterate& set_A(ComplexMatrix& A_in) { + this->A_ptr = &A_in; + return *this; + }; + inline const ComplexMatrix& cal_inverse(); + const ComplexMatrix& get_inverse() { return *this->inverse_ptr; } + + private: + inline void iterate(const ComplexMatrix& old_X, ComplexMatrix& new_X); + + private: + ComplexMatrix* A_ptr = NULL; + ComplexMatrix X_store_1; + ComplexMatrix X_store_2; + const ComplexMatrix* X0_ptr = NULL; + const ComplexMatrix* inverse_ptr = NULL; + ComplexMatrix identity; + ComplexMatrix matrix_tmp_1; + ComplexMatrix matrix_tmp_2; + ComplexMatrix X0_tmp; + size_t iterate_num{20}; + double tolerate_error2{1E-20}; + double fluctrate_error2{0.0}; + double last_error2{std::numeric_limits::max()}; + struct Matrix_Info { + size_t dim; + char symmetry{NULL}; + char uplo{NULL}; + } matrix_info; + + public: + Inverse_Matrix_Iterate& set_iterate_num(size_t iterate_num_in) { + this->iterate_num = iterate_num_in; + return *this; + } + Inverse_Matrix_Iterate& set_tolerate_error(double tolerate_error_in) { + this->tolerate_error2 = tolerate_error_in * tolerate_error_in; + return *this; + } + Inverse_Matrix_Iterate& set_fluctrate_error(double fluctrate_error_in) { + this->fluctrate_error2 = fluctrate_error_in * fluctrate_error_in; + return *this; + } + Inverse_Matrix_Iterate& set_symmetric_info(char symmetry_in, char uplo_in) { + this->matrix_info.symmetry = symmetry_in; + this->matrix_info.uplo = uplo_in; + return *this; + } + + private: + class Little_Error : public exception {}; + + public: + class Unstable : public exception {}; + + private: }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate_bak.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate_bak.cpp index 6ba253892b7..9624abc9ea7 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate_bak.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate_bak.cpp @@ -1,80 +1,75 @@ #include "inverse_matrix_iterate.h" -void Inverse_Matrix_Iterate::init(size_t dim_in) -{ - this->matrix_info.dim = dim_in; - this->X_store_1.create(dim_in,dim_in); - this->X_store_2.create(dim_in,dim_in); - - this->X0_tmp.create(dim_in,dim_in); - this->identity.create(dim_in,dim_in); - this->identity.set_as_identity_matrix(); - this->error_matrix.create(dim_in,dim_in); +void Inverse_Matrix_Iterate::init(size_t dim_in) { + this->matrix_info.dim = dim_in; + this->X_store_1.create(dim_in, dim_in); + this->X_store_2.create(dim_in, dim_in); + + this->X0_tmp.create(dim_in, dim_in); + this->identity.create(dim_in, dim_in); + this->identity.set_as_identity_matrix(); + this->error_matrix.create(dim_in, dim_in); } -Inverse_Matrix_Iterate &Inverse_Matrix_Iterate::set_X0(const ComplexMatrix &X0_in) -{ - if( &X0_in == &this->X_store_1 ) // without this will cause a bug when istep==1 - { - this->X0_ptr = &this->X0_tmp; - this->X0_tmp = X0_in; - } - else - { - this->X0_ptr = &X0_in; - } - return *this; +Inverse_Matrix_Iterate& Inverse_Matrix_Iterate::set_X0(const ComplexMatrix& X0_in) { + if (&X0_in == &this->X_store_1) // without this will cause a bug when istep==1 + { + this->X0_ptr = &this->X0_tmp; + this->X0_tmp = X0_in; + } else { + this->X0_ptr = &X0_in; + } + return *this; } -void Inverse_Matrix_Iterate::iterate(const ComplexMatrix &old_X, ComplexMatrix &new_X) -{ - // I - A * X_n - if(this->matrix_info.symmetry) - { this->error_matrix = this->identity - multiply_special(this->matrix_info.symmetry, 'L', this->matrix_info.uplo, *(this->A_ptr), old_X); } - else - { this->error_matrix = this->identity - *(this->A_ptr) * old_X; } - - const double error_norm(sqrt(abs2(this->error_matrix))); - if ( error_norm < this->tolerate_error) - { - this->inverse_ptr = &old_X; - throw Little_Error(); - } - else if ( error_norm > this->last_error + this->fluctrate_error) - { throw Unstable(); } - else { this->last_error = error_norm; } - - // X_{n+1} = X_n (I + (I-A*X_n) ) = X_n ( 2I - A*X_n ) - for( size_t i(0); imatrix_info.dim; ++i) { this->error_matrix(i,i) += 1.0; } - new_X = old_X * this->error_matrix; -// new_X = old_X * (this->identity + this->error_matrix); +void Inverse_Matrix_Iterate::iterate(const ComplexMatrix& old_X, ComplexMatrix& new_X) { + // I - A * X_n + if (this->matrix_info.symmetry) { + this->error_matrix = + this->identity - + multiply_special(this->matrix_info.symmetry, 'L', this->matrix_info.uplo, *(this->A_ptr), old_X); + } else { + this->error_matrix = this->identity - *(this->A_ptr) * old_X; + } + + const double error_norm(sqrt(abs2(this->error_matrix))); + if (error_norm < this->tolerate_error) { + this->inverse_ptr = &old_X; + throw Little_Error(); + } else if (error_norm > this->last_error + this->fluctrate_error) { + throw Unstable(); + } else { + this->last_error = error_norm; + } + + // X_{n+1} = X_n (I + (I-A*X_n) ) = X_n ( 2I - A*X_n ) + for (size_t i(0); i < this->matrix_info.dim; ++i) { + this->error_matrix(i, i) += 1.0; + } + new_X = old_X * this->error_matrix; + // new_X = old_X * (this->identity + this->error_matrix); - this->inverse_ptr = &new_X; + this->inverse_ptr = &new_X; } -const ComplexMatrix &Inverse_Matrix_Iterate::cal_inverse() -{ - try - { - this->inverse_ptr = this->X0_ptr; - this->last_error = std::numeric_limits::max(); - if(this->iterate_num >= 1) - { - iterate( *this->X0_ptr, this->X_store_1 ); - } - for( size_t istep(2); istep<=this->iterate_num; ++istep) - { - if( istep&1 ) // istep odd, X_store_2 -> X_store_1 - { - iterate( this->X_store_2, this->X_store_1 ); - } - else // istep even, X_store_1 -> X_store_2 - { - iterate( this->X_store_1, this->X_store_2); - } - } - } - catch(const Little_Error &e){} +const ComplexMatrix& Inverse_Matrix_Iterate::cal_inverse() { + try { + this->inverse_ptr = this->X0_ptr; + this->last_error = std::numeric_limits::max(); + if (this->iterate_num >= 1) { + iterate(*this->X0_ptr, this->X_store_1); + } + for (size_t istep(2); istep <= this->iterate_num; ++istep) { + if (istep & 1) // istep odd, X_store_2 -> X_store_1 + { + iterate(this->X_store_2, this->X_store_1); + } else // istep even, X_store_1 -> X_store_2 + { + iterate(this->X_store_1, this->X_store_2); + } + } + } catch (const Little_Error& e) { + } - return get_inverse(); + return get_inverse(); } \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate_inline.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate_inline.h index 6f7457d2cfc..79188157d3b 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate_inline.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_iterate_inline.h @@ -5,83 +5,81 @@ #include "complexmatrix.h" #include "complexmatrix_inline.h" -inline void Inverse_Matrix_Iterate::init(size_t dim_in) -{ - this->matrix_info.dim = dim_in; - this->X_store_1.create(dim_in,dim_in); - this->X_store_2.create(dim_in,dim_in); - - this->X0_tmp.create(dim_in,dim_in); - this->identity.create(dim_in,dim_in); - this->identity.set_as_identity_matrix(); - this->matrix_tmp_1.create(dim_in,dim_in); - this->matrix_tmp_2.create(dim_in,dim_in); +inline void Inverse_Matrix_Iterate::init(size_t dim_in) { + this->matrix_info.dim = dim_in; + this->X_store_1.create(dim_in, dim_in); + this->X_store_2.create(dim_in, dim_in); + + this->X0_tmp.create(dim_in, dim_in); + this->identity.create(dim_in, dim_in); + this->identity.set_as_identity_matrix(); + this->matrix_tmp_1.create(dim_in, dim_in); + this->matrix_tmp_2.create(dim_in, dim_in); } -inline Inverse_Matrix_Iterate &Inverse_Matrix_Iterate::set_X0(const ComplexMatrix &X0_in) -{ - if( &X0_in == &this->X_store_1 ) // without this will cause a bug when istep==1 - { - this->X0_ptr = &this->X0_tmp; - this->X0_tmp = X0_in; - } - else - { - this->X0_ptr = &X0_in; - } - return *this; +inline Inverse_Matrix_Iterate& Inverse_Matrix_Iterate::set_X0(const ComplexMatrix& X0_in) { + if (&X0_in == &this->X_store_1) // without this will cause a bug when istep==1 + { + this->X0_ptr = &this->X0_tmp; + this->X0_tmp = X0_in; + } else { + this->X0_ptr = &X0_in; + } + return *this; } -inline void Inverse_Matrix_Iterate::iterate(const ComplexMatrix &old_X, ComplexMatrix &new_X) -{ - // I - A * X_n - if(this->matrix_info.symmetry) - { this->matrix_tmp_1.minus( this->identity, this->matrix_tmp_2.multiply_special(this->matrix_info.symmetry, 'L', this->matrix_info.uplo, *(this->A_ptr), old_X) ); } - else - { this->matrix_tmp_1.minus( this->identity, this->matrix_tmp_2.multiply(*(this->A_ptr), old_X ) ); } - - const double error_norm2(abs2(this->matrix_tmp_1)); - if ( error_norm2 < this->tolerate_error2) - { - this->inverse_ptr = &old_X; - throw Little_Error(); - } - else if ( error_norm2 > this->last_error2 + this->fluctrate_error2) - { throw Unstable(); } - else { this->last_error2 = error_norm2; } - - // X_{n+1} = X_n (I + (I-A*X_n) ) = X_n ( 2I - A*X_n ) - for( size_t i(0); imatrix_info.dim; ++i) { this->matrix_tmp_1(i,i) += 1.0; } - new_X.multiply(old_X, this->matrix_tmp_1); -// new_X = old_X * (this->identity + this->matrix_tmp_1); +inline void Inverse_Matrix_Iterate::iterate(const ComplexMatrix& old_X, ComplexMatrix& new_X) { + // I - A * X_n + if (this->matrix_info.symmetry) { + this->matrix_tmp_1.minus(this->identity, + this->matrix_tmp_2.multiply_special(this->matrix_info.symmetry, + 'L', + this->matrix_info.uplo, + *(this->A_ptr), + old_X)); + } else { + this->matrix_tmp_1.minus(this->identity, this->matrix_tmp_2.multiply(*(this->A_ptr), old_X)); + } + + const double error_norm2(abs2(this->matrix_tmp_1)); + if (error_norm2 < this->tolerate_error2) { + this->inverse_ptr = &old_X; + throw Little_Error(); + } else if (error_norm2 > this->last_error2 + this->fluctrate_error2) { + throw Unstable(); + } else { + this->last_error2 = error_norm2; + } + + // X_{n+1} = X_n (I + (I-A*X_n) ) = X_n ( 2I - A*X_n ) + for (size_t i(0); i < this->matrix_info.dim; ++i) { + this->matrix_tmp_1(i, i) += 1.0; + } + new_X.multiply(old_X, this->matrix_tmp_1); + // new_X = old_X * (this->identity + this->matrix_tmp_1); - this->inverse_ptr = &new_X; + this->inverse_ptr = &new_X; } -inline const ComplexMatrix &Inverse_Matrix_Iterate::cal_inverse() -{ - try - { - this->inverse_ptr = this->X0_ptr; - this->last_error2 = std::numeric_limits::max(); - if(this->iterate_num >= 1) - { - iterate( *this->X0_ptr, this->X_store_1 ); - } - for( size_t istep(2); istep<=this->iterate_num; ++istep) - { - if( istep&1 ) // istep odd, X_store_2 -> X_store_1 - { - iterate( this->X_store_2, this->X_store_1 ); - } - else // istep even, X_store_1 -> X_store_2 - { - iterate( this->X_store_1, this->X_store_2); - } - } - } - catch(const Little_Error &e){} +inline const ComplexMatrix& Inverse_Matrix_Iterate::cal_inverse() { + try { + this->inverse_ptr = this->X0_ptr; + this->last_error2 = std::numeric_limits::max(); + if (this->iterate_num >= 1) { + iterate(*this->X0_ptr, this->X_store_1); + } + for (size_t istep(2); istep <= this->iterate_num; ++istep) { + if (istep & 1) // istep odd, X_store_2 -> X_store_1 + { + iterate(this->X_store_2, this->X_store_1); + } else // istep even, X_store_1 -> X_store_2 + { + iterate(this->X_store_1, this->X_store_2); + } + } + } catch (const Little_Error& e) { + } - return get_inverse(); + return get_inverse(); } #endif \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_perturbe.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_perturbe.cpp index 8726ccd7aae..9dc0146cb2b 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_perturbe.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_perturbe.cpp @@ -1,27 +1,28 @@ #include "inverse_matrix_perturbe.h" -#include -ComplexMatrix &Inverse_Matrix_Perturbe::cal_inverse() -{ -//std::cout<<"@"; - this->I = *this->A_inverse; - const ComplexMatrix b_a_inverse(*this->B * *this->A_inverse); - ComplexMatrix add_item(*this->A_inverse); - for(size_t i(1); i<=iterate_num; ++i) - { - add_item = add_item * b_a_inverse; - if(plus_minus_state==2) { this->I += add_item; } - else if(plus_minus_state==1) - { - if((i&1) == 0) { this->I += add_item; } - else { this->I -= add_item; } - } - else { throw invalid_argument("set plus_minus_state"); } - } - return this->I; +#include +ComplexMatrix& Inverse_Matrix_Perturbe::cal_inverse() { + // std::cout<<"@"; + this->I = *this->A_inverse; + const ComplexMatrix b_a_inverse(*this->B * *this->A_inverse); + ComplexMatrix add_item(*this->A_inverse); + for (size_t i(1); i <= iterate_num; ++i) { + add_item = add_item * b_a_inverse; + if (plus_minus_state == 2) { + this->I += add_item; + } else if (plus_minus_state == 1) { + if ((i & 1) == 0) { + this->I += add_item; + } else { + this->I -= add_item; + } + } else { + throw invalid_argument("set plus_minus_state"); + } + } + return this->I; } -void Inverse_Matrix_Perturbe::init(const int &dim) -{ +void Inverse_Matrix_Perturbe::init(const int& dim) { this->I.create(dim, dim); return; } \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_perturbe.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_perturbe.h index 5a461edbdf3..5655296bc50 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_perturbe.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/inverse_matrix_perturbe.h @@ -7,29 +7,40 @@ // cal (A+-B).inverse() // (A-B)^{-1} = A^{-1} + A^{-1}*B*A^{-1} + A^{-1}*B*A^{-1}*B*A^{-1} + ... -class Inverse_Matrix_Perturbe -{ - public: - void init(const int &dim); - ComplexMatrix &cal_inverse(); - ComplexMatrix &get_I() { return I; } - - private: - const ComplexMatrix *A_inverse{nullptr}; - const ComplexMatrix *B{nullptr}; - ComplexMatrix I; - size_t iterate_num; - int plus_minus_state{0}; // 1 plus, 2 minus - - public: - const ComplexMatrix *get_A_inverse() { return A_inverse; } - Inverse_Matrix_Perturbe &set_A_inverse(ComplexMatrix *A_inverse_in) { A_inverse = A_inverse_in; return *this;} - const ComplexMatrix *get_B() { return B; } - Inverse_Matrix_Perturbe &set_B(ComplexMatrix *B_in) { B = B_in; return *this;} - const size_t &get_iterate_num() { return iterate_num; } - Inverse_Matrix_Perturbe &set_iterate_num(size_t iterate_num_in) { iterate_num = iterate_num_in; return *this;} - const int &get_plus_minus_state() { return plus_minus_state; } - Inverse_Matrix_Perturbe &set_plus_minus_state(int plus_minus_state_in) { plus_minus_state = plus_minus_state_in; return *this;} +class Inverse_Matrix_Perturbe { + public: + void init(const int& dim); + ComplexMatrix& cal_inverse(); + ComplexMatrix& get_I() { return I; } + + private: + const ComplexMatrix* A_inverse{nullptr}; + const ComplexMatrix* B{nullptr}; + ComplexMatrix I; + size_t iterate_num; + int plus_minus_state{0}; // 1 plus, 2 minus + + public: + const ComplexMatrix* get_A_inverse() { return A_inverse; } + Inverse_Matrix_Perturbe& set_A_inverse(ComplexMatrix* A_inverse_in) { + A_inverse = A_inverse_in; + return *this; + } + const ComplexMatrix* get_B() { return B; } + Inverse_Matrix_Perturbe& set_B(ComplexMatrix* B_in) { + B = B_in; + return *this; + } + const size_t& get_iterate_num() { return iterate_num; } + Inverse_Matrix_Perturbe& set_iterate_num(size_t iterate_num_in) { + iterate_num = iterate_num_in; + return *this; + } + const int& get_plus_minus_state() { return plus_minus_state; } + Inverse_Matrix_Perturbe& set_plus_minus_state(int plus_minus_state_in) { + plus_minus_state = plus_minus_state_in; + return *this; + } }; #endif \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/lapack_connector.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/lapack_connector.h index 91eafad567f..31cb8fd8449 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/lapack_connector.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/lapack_connector.h @@ -4,11 +4,11 @@ // File: LapackConnector.hpp // Author: sltk // Comment: LapackConnector provide the connector to the fortran Lapack routine. -// Warning: +// Warning: // Start time: 2007-03-08 // Last modified: 2008-08-12 ywcui : add zhegvx -// 2008-08-13 mohan : find bug,test. -// 2008-09-03 mohan : Add zgesv +// 2008-08-13 mohan : find bug,test. +// 2008-09-03 mohan : Add zgesv // ============================================================================= #ifndef LAPACKCONNECTOR_HPP @@ -16,471 +16,453 @@ #include -//#include +// #include #include #include -using namespace std; #include "complexmatrix.h" - -extern "C" -{ - - void zpotrf_( const char* uplo, - const int* n, - const std::complex *A, - const int* lda, - const int* infp); - - void zpotri_( const char* uplo, - const int* n, - const std::complex *A, - const int* lda, - const int* infp); - - //======================================================================= - //ZGESV computes the solution to a complex system of linear equations - // A * X = B, - // where A is an N-by-N matrix and X and B are N-by-NRHS matrices. - // - // The LU decomposition with partial pivoting and row interchanges is - // used to factor A as - // A = P * L * U, - // where P is a permutation matrix, L is unit lower triangular, and U is - // upper triangular. The factored form of A is then used to solve the - // system of equations A * X = B. - // - // A = LDA * N - // B = LDB * NRHS (exit X = B) - //======================================================================== - void zgesv_(const int* n, - const int* nrhs, - const std::complex *A, - const int *lda, - const int *ipiv, - const std::complex *B, - const int* ldb, - int* info - ); - - /*zhegv computes all the eigenvalues, and optionally, the eigenvectors - of a complex generalized Hermitian-definite eigenproblem, of the form - A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. - Here A and B are assumed to be Hermitian and B is also - positive definite. - */ - - /*zhegvx computes selected eigenvalues, and optionally, eigenvectors - of a complex generalized Hermitian-definite eigenproblem, of the form - A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. Here A and - B are assumed to be Hermitian and B is also positive definite. - Eigenvalues and eigenvectors can be selected by specifying either a - range of values or a range of indices for the desired eigenvalues. - */ - - void zhegv_(const int* itype, - const char* jobz, - const char* uplo, - const int* n, - std::complex* a, - const int* lda, - std::complex* b, - const int* ldb, - double* w, - std::complex* work, - int* lwork, - double* rwork, - int* info ); - - void zheev_(const char* jobz, - const char* uplo, - const int* n, - complex *a, - const int* lda, - double* w, - complex* work, - const int* lwork, - double* rwork, - int* info ); - - //=================================================================================== - // zhegvx : - // itype : 1: A*x = (lambda)*B*x - // 2: A*B*x = (lambda)*x - // 3: B*A*x = (lambda)*x - // jobz : 'N': Compute eigenvalues only - // 'V': Compute eigenvalues and eigenvectors. - // range : 'A': all eigenvalues will be found. - // 'V': all eigenvalues in the half-open interval (VL,VU] will be found. - // 'I': the IL-th through IU-th eigenvalues will be found. - // uplo : 'U': Upper triangles of A and B are stored - // 'L': Lower triangles of A and B are stored - // N : The order of the matrices A and B. N >= 0. - // A : (input/output) COMPLEX*16 array, dimension (LDA, N) - // On entry, the Hermitian matrix A. If UPLO = 'U', the leading - // N-by-N upper triangular part of A contains the upper triangular - // part of the matrix A. If UPLO = 'L', the leading N-by-N lower - // triangular part of A contains the lower triangular part of the - // matrix A. - // LDA : The leading dimension of the array A. LDA >= max(1,N). - // LDB : On entry, the Hermitian matrix B. If UPLO = 'U', the leading - // N-by-N upper triangular part of B contains the upper triangular - // part of the matrix B. If UPLO = 'L', the leading N-by-N lower - // triangular part of B contains the lower triangular part of the - // matrix B. - // vl,vu : the lower and upper bounds of the interval to be searched for - // eigenvalues. VL < VU. Not referenced if RANGE = 'A' or 'I'. - // il,iu : the indices (in ascending order) of the smallest and largest - // eigenvalues to be returned. 1 <= IL <= IU <= N, if N > 0; - // IL = 1 and IU = 0 if N = 0. Not referenced if RANGE = 'A' or 'V'. - // abstol : The absolute error tolerance for the eigenvalues - // m : The total number of eigenvalues found ,0 <= M <= N. If RANGE - // = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. - // w : The first M elements contain the selected eigenvalues in - // ascending order - // z : If JOBZ = 'N', then Z is not referenced. If JOBZ = 'V', then - // if INFO = 0, the first M columns of Z contain the orthonormal - // eigenvectors of the matrix A corresponding to the selected - // eigenvalues, with the i-th column of Z holding the eigenvector - // associated with W(i). The eigenvectors are normalized as fol- - // lows: if ITYPE = 1 or 2, Z**T*B*Z = I; if ITYPE = 3, - // Z**T*inv(B)*Z = I. - // If an eigenvector fails to converge, then that column of Z - // contains the latest approximation to the eigenvector, and the - // index of the eigenvector is returned in IFAIL. Note: the user - // must ensure that at least max(1,M) columns are supplied in the - // array Z; if RANGE = 'V', the exact value of M is not known in - // advance and an upper bound must be used - // LDZ : The leading dimension of the array Z. LDZ >= 1, and if JOBZ = - // 'V', LDZ >= max(1,N). - // work : On exit, if INFO = 0, WORK(1) returns the optimal LWORK. - // lwork : LWORK >= max(1,2*N). For optimal efficiency, LWORK >= (NB+1)*N, - // where NB is the blocksize for ZHETRD returned by ILAENV. - // rwork : dimension (7*N) - // iwork : dimension (5*N) - // info : = 0: successful exit - // < 0: if INFO = -i, the i-th argument had an illegal value - // > 0: ZPOTRF or ZHEEVX returned an error code: - //=================================================================================== - - /* - void zhegvx_(const int* itype, - const char* jobz, - const char* range, - const char* uplo, - const int* N, - std::complex *A, - const int* LDA, - std::complex *B, - const int* LDB, - const double* vl, - const double* vu, - const int* il, - const int* iu, - const double* abstol, - const int* m, - double* w, - std::complex *z, - const int *LDZ, - std::complex *work, - const int* lwork, - double* rwork, - int* iwork, - int* ifail, - int* info - ); - */ - - - // Peize Lin add 2015-11-20 - void daxpy_(int *N, double *alpha, double *X, int *incX, double *Y, int *incY); - void dscal_(int *N, double *alpha, double *X, int *incX); - - // Peize Lin add 2015-12-07 - void zgemm_(const char *TransA, const char *TransB, - const int *M, const int *N, const int *K, - const double *alpha, const void *A, const int *lda, const void *B, const int *ldb, - const double *beta, void *C, const int *ldc); - void zsymm_(const char *Side, const char *Uplo, - const int *M, const int *N, - const double *alpha, const void *A, const int *lda, const void *B, const int *ldb, - const double *beta, void *C, const int *ldc); - void zhemm_(const char *Side, const char *Uplo, - const int *M, const int *N, - const double *alpha, const void *A, const int *lda, const void *B, const int *ldb, - const double *beta, void *C, const int *ldc); - +extern "C" { + +void zpotrf_(const char* uplo, const int* n, const std::complex* A, const int* lda, const int* infp); + +void zpotri_(const char* uplo, const int* n, const std::complex* A, const int* lda, const int* infp); + +//======================================================================= +// ZGESV computes the solution to a complex system of linear equations +// A * X = B, +// where A is an N-by-N matrix and X and B are N-by-NRHS matrices. +// +// The LU decomposition with partial pivoting and row interchanges is +// used to factor A as +// A = P * L * U, +// where P is a permutation matrix, L is unit lower triangular, and U is +// upper triangular. The factored form of A is then used to solve the +// system of equations A * X = B. +// +// A = LDA * N +// B = LDB * NRHS (exit X = B) +//======================================================================== +void zgesv_(const int* n, + const int* nrhs, + const std::complex* A, + const int* lda, + const int* ipiv, + const std::complex* B, + const int* ldb, + int* info); + +/*zhegv computes all the eigenvalues, and optionally, the eigenvectors + of a complex generalized Hermitian-definite eigenproblem, of the form + A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. + Here A and B are assumed to be Hermitian and B is also + positive definite. +*/ + +/*zhegvx computes selected eigenvalues, and optionally, eigenvectors + of a complex generalized Hermitian-definite eigenproblem, of the form + A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. Here A and + B are assumed to be Hermitian and B is also positive definite. + Eigenvalues and eigenvectors can be selected by specifying either a + range of values or a range of indices for the desired eigenvalues. +*/ + +void zhegv_(const int* itype, + const char* jobz, + const char* uplo, + const int* n, + std::complex* a, + const int* lda, + std::complex* b, + const int* ldb, + double* w, + std::complex* work, + int* lwork, + double* rwork, + int* info); + +void zheev_(const char* jobz, + const char* uplo, + const int* n, + std::complex* a, + const int* lda, + double* w, + std::complex* work, + const int* lwork, + double* rwork, + int* info); + +//=================================================================================== +// zhegvx : +// itype : 1: A*x = (lambda)*B*x +// 2: A*B*x = (lambda)*x +// 3: B*A*x = (lambda)*x +// jobz : 'N': Compute eigenvalues only +// 'V': Compute eigenvalues and eigenvectors. +// range : 'A': all eigenvalues will be found. +// 'V': all eigenvalues in the half-open interval (VL,VU] will be found. +// 'I': the IL-th through IU-th eigenvalues will be found. +// uplo : 'U': Upper triangles of A and B are stored +// 'L': Lower triangles of A and B are stored +// N : The order of the matrices A and B. N >= 0. +// A : (input/output) COMPLEX*16 array, dimension (LDA, N) +// On entry, the Hermitian matrix A. If UPLO = 'U', the leading +// N-by-N upper triangular part of A contains the upper triangular +// part of the matrix A. If UPLO = 'L', the leading N-by-N lower +// triangular part of A contains the lower triangular part of the +// matrix A. +// LDA : The leading dimension of the array A. LDA >= max(1,N). +// LDB : On entry, the Hermitian matrix B. If UPLO = 'U', the leading +// N-by-N upper triangular part of B contains the upper triangular +// part of the matrix B. If UPLO = 'L', the leading N-by-N lower +// triangular part of B contains the lower triangular part of the +// matrix B. +// vl,vu : the lower and upper bounds of the interval to be searched for +// eigenvalues. VL < VU. Not referenced if RANGE = 'A' or 'I'. +// il,iu : the indices (in ascending order) of the smallest and largest +// eigenvalues to be returned. 1 <= IL <= IU <= N, if N > 0; +// IL = 1 and IU = 0 if N = 0. Not referenced if RANGE = 'A' or 'V'. +// abstol : The absolute error tolerance for the eigenvalues +// m : The total number of eigenvalues found ,0 <= M <= N. If RANGE +// = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. +// w : The first M elements contain the selected eigenvalues in +// ascending order +// z : If JOBZ = 'N', then Z is not referenced. If JOBZ = 'V', then +// if INFO = 0, the first M columns of Z contain the orthonormal +// eigenvectors of the matrix A corresponding to the selected +// eigenvalues, with the i-th column of Z holding the eigenvector +// associated with W(i). The eigenvectors are normalized as fol- +// lows: if ITYPE = 1 or 2, Z**T*B*Z = I; if ITYPE = 3, +// Z**T*inv(B)*Z = I. +// If an eigenvector fails to converge, then that column of Z +// contains the latest approximation to the eigenvector, and the +// index of the eigenvector is returned in IFAIL. Note: the user +// must ensure that at least max(1,M) columns are supplied in the +// array Z; if RANGE = 'V', the exact value of M is not known in +// advance and an upper bound must be used +// LDZ : The leading dimension of the array Z. LDZ >= 1, and if JOBZ = +// 'V', LDZ >= max(1,N). +// work : On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +// lwork : LWORK >= max(1,2*N). For optimal efficiency, LWORK >= (NB+1)*N, +// where NB is the blocksize for ZHETRD returned by ILAENV. +// rwork : dimension (7*N) +// iwork : dimension (5*N) +// info : = 0: successful exit +// < 0: if INFO = -i, the i-th argument had an illegal value +// > 0: ZPOTRF or ZHEEVX returned an error code: +//=================================================================================== + +/* +void zhegvx_(const int* itype, + const char* jobz, + const char* range, + const char* uplo, + const int* N, + std::complex *A, + const int* LDA, + std::complex *B, + const int* LDB, + const double* vl, + const double* vu, + const int* il, + const int* iu, + const double* abstol, + const int* m, + double* w, + std::complex *z, + const int *LDZ, + std::complex *work, + const int* lwork, + double* rwork, + int* iwork, + int* ifail, + int* info + ); +*/ + +// Peize Lin add 2015-11-20 +void daxpy_(int* N, double* alpha, double* X, int* incX, double* Y, int* incY); +void dscal_(int* N, double* alpha, double* X, int* incX); + +// Peize Lin add 2015-12-07 +void zgemm_(const char* TransA, + const char* TransB, + const int* M, + const int* N, + const int* K, + const double* alpha, + const void* A, + const int* lda, + const void* B, + const int* ldb, + const double* beta, + void* C, + const int* ldc); +void zsymm_(const char* Side, + const char* Uplo, + const int* M, + const int* N, + const double* alpha, + const void* A, + const int* lda, + const void* B, + const int* ldb, + const double* beta, + void* C, + const int* ldc); +void zhemm_(const char* Side, + const char* Uplo, + const int* M, + const int* N, + const double* alpha, + const void* A, + const int* lda, + const void* B, + const int* ldb, + const double* beta, + void* C, + const int* ldc); }; // Class LapackConnector provide the connector to fortran lapack routine. // The entire function in this class are static and inline function. -// Usage example: LapackConnector::functionname(parameter list). -class LapackConnector -{ -private: - // Transpose the complex matrix to the fortran-form real-complex array. - static inline - complex* transpose(const ComplexMatrix& a, const int n, const int lda) - { - complex* aux = new std::complex[lda*n]; - for(int i = 0; i < n; ++i) - { for(int j = 0; j < lda; ++j) - { - aux[i*lda+j] = a(j,i); // aux[i*lda+j] means aux[i][j] in semantic, not in syntax! - } - } - return aux; - } - - // Transpose the fortran-form real-complex array to the complex matrix. - static inline - void transpose(const std::complex* aux, ComplexMatrix& a, const int n, const int lda) - { - for(int i = 0; i < n; ++i) - { for(int j = 0; j < lda; ++j) - { - a(j, i) = aux[i*lda+j]; // aux[i*lda+j] means aux[i][j] in semantic, not in syntax! - } - } - } - - static inline - char change_side(const char &side) - { - switch(side) - { - case 'L': return 'R'; - case 'R': return 'L'; - default: throw invalid_argument("Side must be 'L' or 'R'"); - } - } - - static inline - char change_uplo(const char &uplo) - { - switch(uplo) - { - case 'U': return 'L'; - case 'L': return 'U'; - default: throw invalid_argument("Uplo must be 'U' or 'L'"); - } - } - - - -public: - static inline - void zgesv (const int n, - const int nrhs, - ComplexMatrix &A, - const int lda, - const int *ipiv, - complex *B, - const int ldb, - int* info - ) - { - complex *aux = LapackConnector::transpose(A, n, lda); - - zgesv_(&n, &nrhs, aux, &lda, ipiv, B, &ldb, info); - - LapackConnector::transpose(aux, A, n, lda); - } - - static inline - void zpotrf(char uplo, - int n, - ComplexMatrix &a, - const int lda, - int& info) - { -/* complex *aux = LapackConnector::transpose(a, n, lda); - zpotrf_( &uplo, &n, aux, &lda, &info); - LapackConnector::transpose(aux, a, n, lda); - delete[] aux; -*/ // Peize Lin update 2015-12-27 - const char uplo_changed(change_uplo(uplo)); - zpotrf_( &uplo_changed, &n, a.c, &lda, &info); - } - - static inline - void zpotri(char uplo, - int n, - ComplexMatrix &a, - const int lda, - int& info) - { -/* complex *aux = LapackConnector::transpose(a, n, lda); - zpotri_( &uplo, &n, aux, &lda, &info); - LapackConnector::transpose(aux, a, n, lda); - delete[] aux; -*/ // Peize Lin update 2015-12-27 - const char uplo_changed(change_uplo(uplo)); - zpotri_( &uplo_changed, &n, a.c, &lda, &info); - } - - - // wrap function of fortran lapack routine zhegv. - static inline - void zhegv( const int itype, - const char jobz, - const char uplo, - const int n, - ComplexMatrix& a, - const int lda, - ComplexMatrix& b, - const int ldb, - double* w, - std::complex* work, - int lwork, - double* rwork, - int& info ) - { // Transpose the complex matrix to the fortran-form real-complex array. - complex* aux = LapackConnector::transpose(a, n, lda); - complex* bux = LapackConnector::transpose(b, n, ldb); - - // call the fortran routine - zhegv_(&itype, &jobz, &uplo, &n, aux, &lda, bux, &ldb, w, work, &lwork, rwork, &info); - - // Transpose the fortran-form real-complex array to the complex matrix. - LapackConnector::transpose(aux, a, n, lda); - LapackConnector::transpose(bux, b, n, ldb); - - // free the memory. - delete[] aux; - delete[] bux; - } - - // wrap function of fortran lapack routine zheev. - static inline - void zheev( const char jobz, - const char uplo, - const int n, - ComplexMatrix& a, - const int lda, - double* w, - complex< double >* work, - const int lwork, - double* rwork, - int* info ) - { // Transpose the complex matrix to the fortran-form real-complex array. - complex *aux = LapackConnector::transpose(a, n, lda); - - // call the fortran routine - zheev_(&jobz, &uplo, &n, aux, &lda, w, work, &lwork, rwork, info); - - // Transpose the fortran-form real-complex array to the complex matrix. - LapackConnector::transpose(aux, a, n, lda); - - // free the memory. - delete[] aux; - } - - // wrap function of fortran lapack routine zheev. - static inline - void zhegvx( const int itype, - const char jobz, - const char range, - const char uplo, - const int n, - ComplexMatrix& a, - const int lda, - ComplexMatrix& b, - const int ldb, - const double vl, - const double vu, - const int il, - const int iu, - const double abstol, - const int m, - double* w, - ComplexMatrix& z, - const int ldz, - std::complex* work, - const int lwork, - double* rwork, - int* iwork, - int* ifail, - int& info) - { - // Transpose the complex matrix to the fortran-form real-complex array. - complex* aux = LapackConnector::transpose(a, n, lda); - complex* bux = LapackConnector::transpose(b, n, ldb); - complex* zux = LapackConnector::transpose(z, n, ldz); - - // call the fortran routine -// zhegvx_(&itype, &jobz, &range, &uplo, &n, aux, &lda, bux, &ldb, &vl, -// &vu, &il,&iu, &abstol, &m, w, zux, &ldz, work, &lwork, rwork, iwork, ifail, &info); - - // Transpose the fortran-form real-complex array to the complex matrix - LapackConnector::transpose(zux, z, n, ldz); - - // free the memory. - delete[] aux; - delete[] bux; - delete[] zux; - - } - - - // Peize Lin add 2015-11-20 - static inline - void daxpy( int N, double alpha, double *X, int incX, double *Y, int incY) - { - daxpy_(&N, &alpha, X, &incX, Y, &incY); - } - - static inline - void dscal( int N, double alpha, double *X, int incX) - { - dscal_(&N, &alpha, X, &incX); - } - - // Peize Lin add 2015-12-07 - // multiply two matrix. C=A*B - static inline - void zgemm(const char TransA, const char TransB, - const int M, const int N, const int K, - const double alpha, const void *A, const int lda, const void *B, const int ldb, - const double beta, void *C, const int ldc) - { - zgemm_(&TransA, &TransB, - &N, &M, &K, - &alpha, B, &ldb, A, &lda, - &beta, C, &ldc); - } - - // multiply two matrix. C=A*B('L'eft) or C=B*A('R'ight). A^T=A, stored in 'U'pper or 'L'ower - static inline - void zsymm(const char side, const char uplo, - const int M, const int N, - const double alpha, const void *A, const int lda, const void *B, const int ldb, - const double beta, void *C, const int ldc) - { - const char &side_changed(change_side(side)); - const char &uplo_changed(change_uplo(uplo)); - zsymm_(&side_changed, &uplo_changed, - &N, &M, - &alpha, A, &lda, B, &ldb, - &beta, C, &ldc); - } - - // multiply two matrix. C=A*B('L'eft) or C=B*A('R'ight). A^H=A, stored in 'U'pper or 'L'ower - static inline - void zhemm(const char side, const char uplo, - const int M, const int N, - const double alpha, const void *A, const int lda, const void *B, const int ldb, - const double beta, void *C, const int ldc) - { - const char &side_changed(change_side(side)); - const char &uplo_changed(change_uplo(uplo)); - zhemm_(&side_changed, &uplo_changed, - &N, &M, - &alpha, A, &lda, B, &ldb, - &beta, C, &ldc); - } +// Usage example: LapackConnector::functionname(parameter list). +class LapackConnector { + private: + // Transpose the complex matrix to the fortran-form real-complex array. + static inline std::complex* transpose(const ComplexMatrix& a, const int n, const int lda) { + std::complex* aux = new std::complex[lda * n]; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < lda; ++j) { + aux[i * lda + j] = a(j, i); // aux[i*lda+j] means aux[i][j] in semantic, not in syntax! + } + } + return aux; + } + + // Transpose the fortran-form real-complex array to the complex matrix. + static inline void transpose(const std::complex* aux, ComplexMatrix& a, const int n, const int lda) { + for (int i = 0; i < n; ++i) { + for (int j = 0; j < lda; ++j) { + a(j, i) = aux[i * lda + j]; // aux[i*lda+j] means aux[i][j] in semantic, not in syntax! + } + } + } + + static inline char change_side(const char& side) { + switch (side) { + case 'L': + return 'R'; + case 'R': + return 'L'; + default: + throw invalid_argument("Side must be 'L' or 'R'"); + } + } + + static inline char change_uplo(const char& uplo) { + switch (uplo) { + case 'U': + return 'L'; + case 'L': + return 'U'; + default: + throw invalid_argument("Uplo must be 'U' or 'L'"); + } + } + + public: + static inline void zgesv(const int n, + const int nrhs, + ComplexMatrix& A, + const int lda, + const int* ipiv, + std::complex* B, + const int ldb, + int* info) { + std::complex* aux = LapackConnector::transpose(A, n, lda); + + zgesv_(&n, &nrhs, aux, &lda, ipiv, B, &ldb, info); + + LapackConnector::transpose(aux, A, n, lda); + } + + static inline void zpotrf(char uplo, int n, ComplexMatrix& a, const int lda, int& info) { + /* std::complex *aux = LapackConnector::transpose(a, n, lda); + zpotrf_( &uplo, &n, aux, &lda, &info); + LapackConnector::transpose(aux, a, n, lda); + delete[] aux; + */ // Peize Lin update 2015-12-27 + const char uplo_changed(change_uplo(uplo)); + zpotrf_(&uplo_changed, &n, a.c, &lda, &info); + } + + static inline void zpotri(char uplo, int n, ComplexMatrix& a, const int lda, int& info) { + /* std::complex *aux = LapackConnector::transpose(a, n, lda); + zpotri_( &uplo, &n, aux, &lda, &info); + LapackConnector::transpose(aux, a, n, lda); + delete[] aux; + */ // Peize Lin update 2015-12-27 + const char uplo_changed(change_uplo(uplo)); + zpotri_(&uplo_changed, &n, a.c, &lda, &info); + } + + // wrap function of fortran lapack routine zhegv. + static inline void zhegv(const int itype, + const char jobz, + const char uplo, + const int n, + ComplexMatrix& a, + const int lda, + ComplexMatrix& b, + const int ldb, + double* w, + std::complex* work, + int lwork, + double* rwork, + int& info) { // Transpose the complex matrix to the fortran-form real-complex array. + std::complex* aux = LapackConnector::transpose(a, n, lda); + std::complex* bux = LapackConnector::transpose(b, n, ldb); + + // call the fortran routine + zhegv_(&itype, &jobz, &uplo, &n, aux, &lda, bux, &ldb, w, work, &lwork, rwork, &info); + + // Transpose the fortran-form real-complex array to the complex matrix. + LapackConnector::transpose(aux, a, n, lda); + LapackConnector::transpose(bux, b, n, ldb); + + // free the memory. + delete[] aux; + delete[] bux; + } + + // wrap function of fortran lapack routine zheev. + static inline void zheev(const char jobz, + const char uplo, + const int n, + ComplexMatrix& a, + const int lda, + double* w, + std::complex* work, + const int lwork, + double* rwork, + int* info) { // Transpose the complex matrix to the fortran-form real-complex array. + std::complex* aux = LapackConnector::transpose(a, n, lda); + + // call the fortran routine + zheev_(&jobz, &uplo, &n, aux, &lda, w, work, &lwork, rwork, info); + + // Transpose the fortran-form real-complex array to the complex matrix. + LapackConnector::transpose(aux, a, n, lda); + + // free the memory. + delete[] aux; + } + + // wrap function of fortran lapack routine zheev. + static inline void zhegvx(const int itype, + const char jobz, + const char range, + const char uplo, + const int n, + ComplexMatrix& a, + const int lda, + ComplexMatrix& b, + const int ldb, + const double vl, + const double vu, + const int il, + const int iu, + const double abstol, + const int m, + double* w, + ComplexMatrix& z, + const int ldz, + std::complex* work, + const int lwork, + double* rwork, + int* iwork, + int* ifail, + int& info) { + // Transpose the complex matrix to the fortran-form real-complex array. + std::complex* aux = LapackConnector::transpose(a, n, lda); + std::complex* bux = LapackConnector::transpose(b, n, ldb); + std::complex* zux = LapackConnector::transpose(z, n, ldz); + + // call the fortran routine + // zhegvx_(&itype, &jobz, &range, &uplo, &n, aux, &lda, bux, &ldb, &vl, + // &vu, &il,&iu, &abstol, &m, w, zux, &ldz, work, &lwork, rwork, iwork, ifail, &info); + + // Transpose the fortran-form real-complex array to the complex matrix + LapackConnector::transpose(zux, z, n, ldz); + + // free the memory. + delete[] aux; + delete[] bux; + delete[] zux; + } + + // Peize Lin add 2015-11-20 + static inline void daxpy(int N, double alpha, double* X, int incX, double* Y, int incY) { + daxpy_(&N, &alpha, X, &incX, Y, &incY); + } + + static inline void dscal(int N, double alpha, double* X, int incX) { dscal_(&N, &alpha, X, &incX); } + + // Peize Lin add 2015-12-07 + // multiply two matrix. C=A*B + static inline void zgemm(const char TransA, + const char TransB, + const int M, + const int N, + const int K, + const double alpha, + const void* A, + const int lda, + const void* B, + const int ldb, + const double beta, + void* C, + const int ldc) { + zgemm_(&TransA, &TransB, &N, &M, &K, &alpha, B, &ldb, A, &lda, &beta, C, &ldc); + } + + // multiply two matrix. C=A*B('L'eft) or C=B*A('R'ight). A^T=A, stored in 'U'pper or 'L'ower + static inline void zsymm(const char side, + const char uplo, + const int M, + const int N, + const double alpha, + const void* A, + const int lda, + const void* B, + const int ldb, + const double beta, + void* C, + const int ldc) { + const char& side_changed(change_side(side)); + const char& uplo_changed(change_uplo(uplo)); + zsymm_(&side_changed, &uplo_changed, &N, &M, &alpha, A, &lda, B, &ldb, &beta, C, &ldc); + } + + // multiply two matrix. C=A*B('L'eft) or C=B*A('R'ight). A^H=A, stored in 'U'pper or 'L'ower + static inline void zhemm(const char side, + const char uplo, + const int M, + const int N, + const double alpha, + const void* A, + const int lda, + const void* B, + const int ldb, + const double beta, + void* C, + const int ldc) { + const char& side_changed(change_side(side)); + const char& uplo_changed(change_uplo(uplo)); + zhemm_(&side_changed, &uplo_changed, &N, &M, &alpha, A, &lda, B, &ldb, &beta, C, &ldc); + } }; -#endif // LAPACKCONNECTOR_HPP +#endif // LAPACKCONNECTOR_HPP diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/mathzone.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/mathzone.cpp index a42bbbae093..411d6441118 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/mathzone.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/mathzone.cpp @@ -1,35 +1,26 @@ #include "mathzone.h" - double Mathzone::PI = 3.14159265; -Mathzone::Mathzone() -{ -} - -Mathzone::~Mathzone() -{ -} +Mathzone::Mathzone() {} -double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rjp, double *ryp) -{ - const int XMIN = 2; - const double FPMIN = 1.0e-30; - const double EPS = 1.0e-10; - const int MAXIT = 10000; +Mathzone::~Mathzone() {} - int i, isign, l, nl; - double a, b, br, bi, c, cr, ci, d, del, del1, den, di, dlr, dli, dr, e, f, fact, fact2, - fact3, ff, gam, gam1, gam2, gammi, gampl, h, p, pimu, pimu2, q, r, rjl, - rjl1, rjmu, rjp1, rjpl, rjtemp, ry1, rymu, rymup, rytemp, sum, sum1, - temp, w, x2, xi, xi2; +double Mathzone::BESSJY(double x, double xnu, double* rj, double* ry, double* rjp, double* ryp) { + const int XMIN = 2; + const double FPMIN = 1.0e-30; + const double EPS = 1.0e-10; + const int MAXIT = 10000; - if (x <= 0.0 || xnu < 0.0) - { -// WARNING_QUIT("Mathzone::BESSJY","bad arguments"); - exit(0); - } + int i, isign, l, nl; + double a, b, br, bi, c, cr, ci, d, del, del1, den, di, dlr, dli, dr, e, f, fact, fact2, fact3, ff, gam, gam1, gam2, + gammi, gampl, h, p, pimu, pimu2, q, r, rjl, rjl1, rjmu, rjp1, rjpl, rjtemp, ry1, rymu, rymup, rytemp, sum, sum1, + temp, w, x2, xi, xi2; + if (x <= 0.0 || xnu < 0.0) { + // WARNING_QUIT("Mathzone::BESSJY","bad arguments"); + exit(0); + } nl = (x < XMIN ? (int)(xnu + 0.5) : IMAX(0, (int)(xnu - x + 1.5))); const double xmu = xnu - nl; @@ -39,24 +30,26 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj w = xi2 / PI; isign = 1; h = xnu * xi; - if (h < FPMIN) h = FPMIN; + if (h < FPMIN) + h = FPMIN; b = xi2 * xnu; d = 0.0; c = h; - - for (i = 1;i <= MAXIT;i++) - { + + for (i = 1; i <= MAXIT; i++) { b += xi2; d = b - d; - if (fabs(d) < FPMIN) d = FPMIN; + if (fabs(d) < FPMIN) + d = FPMIN; c = b - 1.0 / c; - if (fabs(c) < FPMIN) c = FPMIN; + if (fabs(c) < FPMIN) + c = FPMIN; d = 1.0 / d; @@ -64,12 +57,15 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj h = del * h; - if (d < 0.0) isign = -isign; + if (d < 0.0) + isign = -isign; - if (fabs(del - 1.0) < EPS) break; + if (fabs(del - 1.0) < EPS) + break; } - if (i > MAXIT) cout << "x too large in bessjy; try asymptotic expansion" << endl; + if (i > MAXIT) + cout << "x too large in bessjy; try asymptotic expansion" << endl; rjl = isign * FPMIN; @@ -81,27 +77,26 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj fact = xnu * xi; - for (l = nl;l >= 1;l--) - { + for (l = nl; l >= 1; l--) { rjtemp = fact * rjl + rjpl; fact -= xi; rjpl = fact * rjtemp - rjl; rjl = rjtemp; } - if (rjl == 0.0) rjl = EPS; + if (rjl == 0.0) + rjl = EPS; f = rjpl / rjl; - if (x < XMIN) - { + if (x < XMIN) { x2 = 0.5 * x; pimu = PI * xmu; fact = (fabs(pimu) < EPS ? 1.0 : pimu / sin(pimu)); d = -log(x2); e = xmu * d; fact2 = (fabs(e) < EPS ? 1.0 : sinh(e) / e); - // call BESCHB + // call BESCHB BESCHB(xmu, &gam1, &gam2, &gampl, &gammi); ff = 2.0 / PI * fact * (gam1 * cosh(e) + gam2 * fact2 * d); e = exp(e); @@ -115,8 +110,7 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj sum = ff + r * q; sum1 = p; - for (i = 1;i <= MAXIT;i++) - { + for (i = 1; i <= MAXIT; i++) { ff = (i * ff + p + q) / (i * i - xmu2); c *= (d / i); p /= (i - xmu); @@ -126,10 +120,12 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj del1 = c * p - i * del; sum1 += del1; - if (fabs(del) < (1.0 + fabs(sum))*EPS) break; + if (fabs(del) < (1.0 + fabs(sum)) * EPS) + break; } - if (i > MAXIT) cout << "bessy series failed to converge"; + if (i > MAXIT) + cout << "bessy series failed to converge"; rymu = -sum; @@ -140,8 +136,7 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj rjmu = w / (rymup - f * rymu); } - else - { + else { a = 0.25 - xmu2; p = -0.5 * xi; q = 1.0; @@ -159,14 +154,14 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj q = p * dli + q * dlr; p = temp; - for (i = 2;i <= MAXIT;i++) - { + for (i = 2; i <= MAXIT; i++) { a += 2 * (i - 1); bi += 2.0; dr = a * dr + br; di = a * di + bi; - if (fabs(dr) + fabs(di) < FPMIN) dr = FPMIN; + if (fabs(dr) + fabs(di) < FPMIN) + dr = FPMIN; fact = a / (cr * cr + ci * ci); @@ -174,7 +169,8 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj ci = bi - ci * fact; - if (fabs(cr) + fabs(ci) < FPMIN) cr = FPMIN; + if (fabs(cr) + fabs(ci) < FPMIN) + cr = FPMIN; den = dr * dr + di * di; @@ -192,17 +188,21 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj p = temp; - if (fabs(dlr - 1.0) + fabs(dli) < EPS) break; + if (fabs(dlr - 1.0) + fabs(dli) < EPS) + break; } - if (i > MAXIT) cout << "cf2 failed in bessjy"; + if (i > MAXIT) + cout << "cf2 failed in bessjy"; gam = (p - f) / q; rjmu = sqrt(w / ((p - f) * gam + q)); - if(rjl >=0 ) rjmu = fabs(rjmu); - else rjmu = -fabs(rjmu); + if (rjl >= 0) + rjmu = fabs(rjmu); + else + rjmu = -fabs(rjmu); rymu = rjmu * gam; @@ -216,8 +216,7 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj *rj = rjl1 * fact; *rjp = rjp1 * fact; - for (i = 1;i <= nl;i++) - { + for (i = 1; i <= nl; i++) { rytemp = (xmu + i) * xi2 * ry1 - rymu; rymu = ry1; ry1 = rytemp; @@ -228,415 +227,331 @@ double Mathzone::BESSJY(double x, double xnu, double *rj, double *ry, double *rj *ryp = xnu * xi * rymu - ry1; } -int Mathzone::IMAX(int a, int b) -{ - if (a > b) return a; - else return b; +int Mathzone::IMAX(int a, int b) { + if (a > b) + return a; + else + return b; } -void Mathzone::BESCHB(double x, double *gam1, double *gam2, double *gampl, double *gammi) -{ - const int NUSE1 = 7; - const int NUSE2 = 8; +void Mathzone::BESCHB(double x, double* gam1, double* gam2, double* gampl, double* gammi) { + const int NUSE1 = 7; + const int NUSE2 = 8; double xx; - static double c1[] = { -1.142022680371168e0, 6.5165112670737e-3, - 3.087090173086e-4, -3.4706269649e-6, - 6.9437664e-9, 3.67795e-11, -1.356e-13 - }; - static double c2[] = { 1.843740587300905e0, -7.68528408447867e-2, - 1.2719271366546e-3, -4.9717367042e-6, -3.31261198e-8, - 2.423096e-10, -1.702e-13, -1.49e-15 - }; - xx = 8.0 * x * x - 1.0; //Multiply x by 2 to make range be .1 to 1,and then apply transformation for evaluating even Chebyshev series. + static double c1[] = {-1.142022680371168e0, + 6.5165112670737e-3, + 3.087090173086e-4, + -3.4706269649e-6, + 6.9437664e-9, + 3.67795e-11, + -1.356e-13}; + static double c2[] = {1.843740587300905e0, + -7.68528408447867e-2, + 1.2719271366546e-3, + -4.9717367042e-6, + -3.31261198e-8, + 2.423096e-10, + -1.702e-13, + -1.49e-15}; + xx = 8.0 * x * x - 1.0; // Multiply x by 2 to make range be .1 to 1,and then apply transformation for evaluating + // even Chebyshev series. *gam1 = CHEBEV(-1.0, 1.0, c1, NUSE1, xx); *gam2 = CHEBEV(-1.0, 1.0, c2, NUSE2, xx); *gampl = *gam2 - x * (*gam1); *gammi = *gam2 + x * (*gam1); } -double Mathzone::CHEBEV(double a, double b, double c[], int m, double x) -{ +double Mathzone::CHEBEV(double a, double b, double c[], int m, double x) { double d = 0.0, dd = 0.0, sv, y, y2; int j; - if ((x - a)*(x - b) > 0.0) cout << "x not in range in routine chebev" << endl; + if ((x - a) * (x - b) > 0.0) + cout << "x not in range in routine chebev" << endl; y2 = 2.0 * (y = (2.0 * x - a - b) / (b - a)); - for (j = m - 1;j >= 1;j--) - { + for (j = m - 1; j >= 1; j--) { sv = d; d = y2 * d - dd + c[j]; dd = sv; } - return y*d - dd + 0.5*c[0]; + return y * d - dd + 0.5 * c[0]; } +double Mathzone::Spherical_Bessel_7(const int n, const double& x) { + if (x == 0) { + if (n != 0) + return 0; + if (n == 0) + return 1; + } + double order, rj, rjp, ry, ryp; -double Mathzone::Spherical_Bessel_7(const int n, const double &x) -{ - if(x==0) - { - if(n!=0) return 0; - if(n==0) return 1; - } - double order, rj, rjp, ry, ryp; - - if (n < 0 || x <= 0.0) - { - exit(0); -// WARNING_QUIT("Mathzone::Spherical_Bessel_7","bad arguments in sphbes"); - } + if (n < 0 || x <= 0.0) { + exit(0); + // WARNING_QUIT("Mathzone::Spherical_Bessel_7","bad arguments in sphbes"); + } - order = n + 0.5; + order = n + 0.5; - // call BESSSJY - BESSJY(x, order, &rj, &ry, &rjp, &ryp); + // call BESSSJY + BESSJY(x, order, &rj, &ry, &rjp, &ryp); - const double RTPIO2=1.2533141; // mohan remian question: here is INT???????????? + const double RTPIO2 = 1.2533141; // mohan remian question: here is INT???????????? - const double factor = RTPIO2 / sqrt(x); + const double factor = RTPIO2 / sqrt(x); - return factor*rj; + return factor * rj; } +void Mathzone::Spherical_Bessel_Roots(const int& num, + const int& l, + const double& epsilon, + double* eigenvalue, + const double& rcut) { + // TITLE("Mathzone","Spherical_Bessel_Roots"); + // if(num<=0) WARNING_QUIT("Mathzone::Spherical_Bessel_Roots","num<=0"); + + const double max = + 2 * PI + (num + (l + 0.5) / 2 + 0.75) * PI / 2 + + sqrt((num + (l + 0.5) / 2 + 0.75) * (num + (l + 0.5) / 2 + 0.75) * PI * PI / 4 - (l + 0.5) * (l + 0.5) / 2); + + // magic number !! + // only need to > 1 + const int msh = 10 * num; + // cout<<"\n msh = "<(msh); -void Mathzone::Spherical_Bessel_Roots -( - const int &num, - const int &l, - const double &epsilon, - double* eigenvalue, - const double &rcut -) -{ -// TITLE("Mathzone","Spherical_Bessel_Roots"); -// if(num<=0) WARNING_QUIT("Mathzone::Spherical_Bessel_Roots","num<=0"); - - const double max = 2*PI + (num + (l+0.5)/2 + 0.75)*PI/2 + - sqrt((num + (l+0.5)/2+0.75)*(num + (l+0.5)/2+0.75)*PI*PI/4-(l+0.5)*(l+0.5)/2); - - // magic number !! - // only need to > 1 - const int msh = 10 * num; -// cout<<"\n msh = "<(msh); - -// cout<<"\n delta = "<=7) - { - for(int ir=0; ir 1.0e-8) - { - ir0 = 0;//mohan modify 2007-10-13 - } - else - { - if (l == -1) - { - cout << "\n sph_bes, j_{-1}(0) ?//?"; - } - else if (l == 0) - { - jl [0] = 1.0;//mohan modify 2007-10-13 - } - else - { - jl [0] = 0.0;//mohan modify 2007-10-13 - } - ir0 = 1;//mohan modify 2007-10-13 - } - if (l == - 1) - { - for (ir = ir0;ir < msh; ir++) - { - x1 = q * r[ir]; - jl [ir] = cos(x1) / x1; - } - } - else if (l == 0) - { - for (ir = ir0;ir < msh;ir++) - { - x1 = q * r[ir]; - jl [ir] = sin(x1) / x1; - } - } - else if (l == 1) - { - for (ir = ir0;ir < msh;ir++) - { - x1 = q * r[ir]; - const double sinx = sin(x1); - const double cosx = cos(x1); - jl [ir] = (sinx / x1 - cosx) / x1; - } - } - else if (l == 2) - { - for (ir = ir0;ir < msh;ir++) - { - const double x1 = q * r[ir]; - const double sinx = sin(x1); - const double cosx = cos(x1); - jl [ir] = ((3.0 / x1 - x1) * sinx - - 3.0 * cosx) / (x1 * x1); - } - } - else if (l == 3) - { - for (ir = ir0;ir < msh;ir++) - { - x1 = q * r[ir]; - jl [ir] = (sin(x1) * (15.0 / x1 - 6.0 * x1) + - cos(x1) * (x1 * x1 - 15.0)) / pow(x1, 3);//mohan modify 2007-10-13 - } - } - else if (l == 4) - { - for (ir = ir0;ir < msh;ir++) - { - const double x1 = q * r[ir]; - const double x2 = x1 * x1; - const double x3 = x1 * x2; - const double x4 = x1 * x3; - const double x5 = x1 * x4; - jl [ir] = (sin(x1) * (105.0 - 45.0 * x2 + x4) + - cos(x1) * (10.0 * x3 - 105.0 * x1)) / x5; // mohan modify 2007-10-13 - } - } - else if (l == 5) - { - for (ir = ir0;ir < msh;ir++) - { - x1 = q * r[ir]; - - if (x1 < 0.14) - { - jl[ir] = 0;//mohan add 2007-10-15 - } - else - { - double cx1 = cos(x1); - double sx1 = sin(x1); - jl [ir] = (-cx1 - - (945.0 * cx1) / pow(x1, 4) + - (105.0 * cx1) / (x1 * x1) + - (945.0 * sx1) / pow(x1, 5) - - (420.0 * sx1) / pow(x1, 3) + - (15.0 * sx1) / x1) / x1; - - } - } - } - else if (l == 6) - { - for (ir = ir0;ir < msh;ir++) - { - x1 = q * r[ir]; - - if (x1 < 0.29) - { - jl[ir] = 0;//mohan add 2007-10-15 - } - else - { - double cx1 = cos(x1); - double sx1 = sin(x1); - jl [ir] = ((-10395.0 * cx1) / pow(x1, 5) + - (1260.0 * cx1) / pow(x1, 3) - - (21.0 * cx1) / x1 - sx1 + - (10395.0 * sx1) / pow(x1, 6) - - (4725.0 * sx1) / pow(x1, 4) + - (210.0 * sx1) / (x1 * x1)) / x1; - } - } - }//mohan modify 2007-11-20 reduce cos , sin , q*r[ir] times; - else - { - cout << "\n error in sph_bes, l out of {-1 ... 6},l = " << l ; - } - } -// printr1_d(ofs,"jl[] :",jl,msh); -// timer::tick("Mathzone","Spherical_Bessel"); - return; -} - -void Mathzone::Pointwise_Product -( - const size_t mesh, - const double * func1, - const double * func2, - double * mul_func -) -{ - for( size_t i(0); i= 7) { + for (int ir = 0; ir < msh; ir++) { + x1 = q * r[ir]; + jl[ir] = Spherical_Bessel_7(l, x1); + } + return; + } + + if (abs(q) < 1.0e-8) { + if (l == -1) { + cout << "\n sph_bes, j_{-1}(0) ????"; + } else if (l == 0) { + for (i = 0; i < msh; i++) { + jl[i] = 1.0; + } + } else { + for (i = 0; i < msh; i++) { + jl[i] = 0.0; + } + } + } else { + if (abs(q * r[0]) > 1.0e-8) { + ir0 = 0; // mohan modify 2007-10-13 + } else { + if (l == -1) { + cout << "\n sph_bes, j_{-1}(0) ?//?"; + } else if (l == 0) { + jl[0] = 1.0; // mohan modify 2007-10-13 + } else { + jl[0] = 0.0; // mohan modify 2007-10-13 + } + ir0 = 1; // mohan modify 2007-10-13 + } + if (l == -1) { + for (ir = ir0; ir < msh; ir++) { + x1 = q * r[ir]; + jl[ir] = cos(x1) / x1; + } + } else if (l == 0) { + for (ir = ir0; ir < msh; ir++) { + x1 = q * r[ir]; + jl[ir] = sin(x1) / x1; + } + } else if (l == 1) { + for (ir = ir0; ir < msh; ir++) { + x1 = q * r[ir]; + const double sinx = sin(x1); + const double cosx = cos(x1); + jl[ir] = (sinx / x1 - cosx) / x1; + } + } else if (l == 2) { + for (ir = ir0; ir < msh; ir++) { + const double x1 = q * r[ir]; + const double sinx = sin(x1); + const double cosx = cos(x1); + jl[ir] = ((3.0 / x1 - x1) * sinx - 3.0 * cosx) / (x1 * x1); + } + } else if (l == 3) { + for (ir = ir0; ir < msh; ir++) { + x1 = q * r[ir]; + jl[ir] = (sin(x1) * (15.0 / x1 - 6.0 * x1) + cos(x1) * (x1 * x1 - 15.0)) / + pow(x1, 3); // mohan modify 2007-10-13 + } + } else if (l == 4) { + for (ir = ir0; ir < msh; ir++) { + const double x1 = q * r[ir]; + const double x2 = x1 * x1; + const double x3 = x1 * x2; + const double x4 = x1 * x3; + const double x5 = x1 * x4; + jl[ir] = (sin(x1) * (105.0 - 45.0 * x2 + x4) + cos(x1) * (10.0 * x3 - 105.0 * x1)) / + x5; // mohan modify 2007-10-13 + } + } else if (l == 5) { + for (ir = ir0; ir < msh; ir++) { + x1 = q * r[ir]; + + if (x1 < 0.14) { + jl[ir] = 0; // mohan add 2007-10-15 + } else { + double cx1 = cos(x1); + double sx1 = sin(x1); + jl[ir] = (-cx1 - (945.0 * cx1) / pow(x1, 4) + (105.0 * cx1) / (x1 * x1) + + (945.0 * sx1) / pow(x1, 5) - (420.0 * sx1) / pow(x1, 3) + (15.0 * sx1) / x1) / + x1; + } + } + } else if (l == 6) { + for (ir = ir0; ir < msh; ir++) { + x1 = q * r[ir]; + + if (x1 < 0.29) { + jl[ir] = 0; // mohan add 2007-10-15 + } else { + double cx1 = cos(x1); + double sx1 = sin(x1); + jl[ir] = ((-10395.0 * cx1) / pow(x1, 5) + (1260.0 * cx1) / pow(x1, 3) - (21.0 * cx1) / x1 - sx1 + + (10395.0 * sx1) / pow(x1, 6) - (4725.0 * sx1) / pow(x1, 4) + (210.0 * sx1) / (x1 * x1)) / + x1; + } + } + } // mohan modify 2007-11-20 reduce cos , sin , q*r[ir] times; + else { + cout << "\n error in sph_bes, l out of {-1 ... 6},l = " << l; + } + } + // printr1_d(ofs,"jl[] :",jl,msh); + // timer::tick("Mathzone","Spherical_Bessel"); + return; +} + +void Mathzone::Pointwise_Product(const size_t mesh, const double* func1, const double* func2, double* mul_func) { + for (size_t i(0); i < mesh; ++i) { + mul_func[i] = func1[i] * func2[i]; + } + return; } -void Mathzone::Simpson_Integral -( - const int mesh, - const double *func, - const double *rab, - double &asum -) -{ - /* simpson's rule integration. On input: - ! mesh = mhe number of grid points (should be odd) - ! func(i)= function to be integrated - ! rab(i) = r(i) * dr(i)/di * di - ! For the logarithmic grid not including r=0 : - ! r(i) = r_0*exp((i-1)*dx) ==> rab(i)=r(i)*dx - ! For the logarithmic grid including r=0 : - ! r(i) = a(exp((i-1)*dx)-1) ==> rab(i)=(r(i)+a)*dx - ! Output in asum = \sum_i c_i f(i)*rab(i) = \int_0^\infty f(r) dr - ! where c_i are alternativaly 2/3, 4/3 except c_1 = c_mesh = 1/3 - */ - // simpson's rule integrator for function stored on the - // radial logarithmic mesh - // routine assumes that mesh is an odd number so run check - if (mesh % 2 == 0) - { - cout << "\n error in subroutine simpson "; - cout << "\n routine assumes mesh is odd but mesh = " - << mesh << endl; - return; - } - - asum = 0.00; - const double r12 = 1.00 / 12.00; - double f3 = func [0] * rab [0] * r12; - for (int i = 1;i < mesh;i += 2) - { - const double f1 = f3; - const double f2 = func [i] * rab [i] * r12; - f3 = func [i + 1] * rab [i + 1] * r12; - asum += 4.00 * f1 + 16.00 * f2 + 4.00 * f3; - } - return; -}// end subroutine simpson - -double Mathzone::Boltzmann_dist(const double &value, const double &t) -{ - static const double small = 1.0e-20; - assert(t > small); - assert(value > 0.0); -// cout << "\n value = " << value; -// cout << "\n Boltzmann_dist = " << exp( -value/t ); - return exp(-value / t); +void Mathzone::Simpson_Integral(const int mesh, const double* func, const double* rab, double& asum) { + /* simpson's rule integration. On input: + ! mesh = mhe number of grid points (should be odd) + ! func(i)= function to be integrated + ! rab(i) = r(i) * dr(i)/di * di + ! For the logarithmic grid not including r=0 : + ! r(i) = r_0*exp((i-1)*dx) ==> rab(i)=r(i)*dx + ! For the logarithmic grid including r=0 : + ! r(i) = a(exp((i-1)*dx)-1) ==> rab(i)=(r(i)+a)*dx + ! Output in asum = \sum_i c_i f(i)*rab(i) = \int_0^\infty f(r) dr + ! where c_i are alternativaly 2/3, 4/3 except c_1 = c_mesh = 1/3 + */ + // simpson's rule integrator for function stored on the + // radial logarithmic mesh + // routine assumes that mesh is an odd number so run check + if (mesh % 2 == 0) { + cout << "\n error in subroutine simpson "; + cout << "\n routine assumes mesh is odd but mesh = " << mesh << endl; + return; + } + + asum = 0.00; + const double r12 = 1.00 / 12.00; + double f3 = func[0] * rab[0] * r12; + for (int i = 1; i < mesh; i += 2) { + const double f1 = f3; + const double f2 = func[i] * rab[i] * r12; + f3 = func[i + 1] * rab[i + 1] * r12; + asum += 4.00 * f1 + 16.00 * f2 + 4.00 * f3; + } + return; +} // end subroutine simpson + +double Mathzone::Boltzmann_dist(const double& value, const double& t) { + static const double small = 1.0e-20; + assert(t > small); + assert(value > 0.0); + // cout << "\n value = " << value; + // cout << "\n Boltzmann_dist = " << exp( -value/t ); + return exp(-value / t); } \ No newline at end of file diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/mathzone.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/mathzone.h index a1e9b93f426..66546a82756 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/mathzone.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/mathzone.h @@ -10,60 +10,33 @@ #include #include -using namespace std; - -class Mathzone -{ -public: - - Mathzone(); - ~Mathzone(); - - //======================================================== - // Spherical Bessel - //======================================================== - static void Spherical_Bessel - ( - const int &msh, //number of grid points - const double *r,//radial grid - const double &q, // - const int &l, //angular momentum - double *jl //jl(1:msh) = j_l(q*r(i)),spherical bessel function - ); - static void Spherical_Bessel_Roots - ( - const int &num, - const int &l, - const double &epsilon, - double* eigenvalue, - const double &rcut - ); - static void Pointwise_Product( - const size_t mesh, - const double * func1, - const double * func2, - double * mul_func - ); - static void Simpson_Integral( - const int mesh, - const double *func, - const double *rab, - double &asum - ); - static double Boltzmann_dist( - const double &value, - const double &t - ); - static double PI; - -private: - static double Spherical_Bessel_7(const int n, const double &x); - static double BESSJY(double x, double xnu, double *rj, double *ry, double *rjp, double *ryp); - static void BESCHB(double x, double *gam1, double *gam2, double *gampl, double *gammi); - static double CHEBEV(double a, double b, double c[], int m, double x); - static int IMAX(int a, int b); - - +class Mathzone { + public: + Mathzone(); + ~Mathzone(); + + //======================================================== + // Spherical Bessel + //======================================================== + static void Spherical_Bessel(const int& msh, // number of grid points + const double* r, // radial grid + const double& q, // + const int& l, // angular momentum + double* jl // jl(1:msh) = j_l(q*r(i)),spherical bessel function + ); + static void + Spherical_Bessel_Roots(const int& num, const int& l, const double& epsilon, double* eigenvalue, const double& rcut); + static void Pointwise_Product(const size_t mesh, const double* func1, const double* func2, double* mul_func); + static void Simpson_Integral(const int mesh, const double* func, const double* rab, double& asum); + static double Boltzmann_dist(const double& value, const double& t); + static double PI; + + private: + static double Spherical_Bessel_7(const int n, const double& x); + static double BESSJY(double x, double xnu, double* rj, double* ry, double* rjp, double* ryp); + static void BESCHB(double x, double* gam1, double* gam2, double* gampl, double* gammi); + static double CHEBEV(double a, double b, double c[], int m, double x); + static int IMAX(int a, int b); }; #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix.cpp index 5b6df2600d5..5de35db2934 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix.cpp @@ -19,55 +19,49 @@ using namespace std; int matrix::mCount = 0; -void matrixAlloc() -{ - cout << "\n Allocation error for Matrix " << endl; - abort(); +void matrixAlloc() { + cout << "\n Allocation error for Matrix " << endl; + abort(); } -void matrix::init(const int nrows,const int ncols) -{ - nr = nrows; - nc = ncols; - c = NULL; -// hermetian = 0; - set_new_handler(matrixAlloc); +void matrix::init(const int nrows, const int ncols) { + nr = nrows; + nc = ncols; + c = NULL; + // hermetian = 0; + set_new_handler(matrixAlloc); - if(nr*nc == 0) c = NULL; - else - { - c = new double[nrows*ncols](); - this->zero_out(); - assert(c!=0);// terminate if memory not allocated - } + if (nr * nc == 0) + c = NULL; + else { + c = new double[nrows * ncols](); + this->zero_out(); + assert(c != 0); // terminate if memory not allocated + } - mCount++; + mCount++; } // Free up memory for matrix -void matrix::freemem(void) -{ - delete [] c; - c = NULL; +void matrix::freemem(void) { + delete[] c; + c = NULL; } // constructor with sizes -matrix::matrix(const int nrows,const int ncols) -{ - this->init(nrows, ncols); -} +matrix::matrix(const int nrows, const int ncols) { this->init(nrows, ncols); } //****************** // // Copy constructor // //****************** -matrix::matrix(const matrix &m1) -{ - init(m1.nr, m1.nc); - //hermetian = m1.hermetian; - // Copy over m1 contents - for (int i = 0; i < nr*nc; i++) c[i] = m1.c[i]; +matrix::matrix(const matrix& m1) { + init(m1.nr, m1.nc); + // hermetian = m1.hermetian; + // Copy over m1 contents + for (int i = 0; i < nr * nc; i++) + c[i] = m1.c[i]; } //************* @@ -75,149 +69,132 @@ matrix::matrix(const matrix &m1) // destructor // //************* -matrix::~matrix() -{ - this->freemem(); -} +matrix::~matrix() { this->freemem(); } //****************************** // reallocate memory for matrix //****************************** -void matrix::create(const int nrow,const int ncol) -{ - delete [] c; - nr = nrow; - nc = ncol; - c = new double[nrow * ncol](); - return; +void matrix::create(const int nrow, const int ncol) { + delete[] c; + nr = nrow; + nc = ncol; + c = new double[nrow * ncol](); + return; } /* Assignment: nonstandard in that it returns void. To make it standard, * replace void -> matrix and uncomment the return *this; */ -void matrix::operator=(const matrix & m1) -{ - for (int i = 0; i < nr*nc; i++) c[i] = m1.c[i]; +void matrix::operator=(const matrix& m1) { + for (int i = 0; i < nr * nc; i++) + c[i] = m1.c[i]; } /* Adding matrices, as a friend */ -matrix operator+(const matrix &m1, const matrix &m2) -{ - assert(m1.nr == m2.nr); - assert(m2.nc == m2.nc); +matrix operator+(const matrix& m1, const matrix& m2) { + assert(m1.nr == m2.nr); + assert(m2.nc == m2.nc); - matrix tm(m1); - for (int i = 0; i < m1.nr*m1.nc; i++) tm.c[i] += m2.c[i]; - return tm; + matrix tm(m1); + for (int i = 0; i < m1.nr * m1.nc; i++) + tm.c[i] += m2.c[i]; + return tm; } /* Subtracting matrices, as a friend */ -matrix operator-(const matrix &m1, const matrix &m2) -{ - assert(m1.nr == m2.nr); - assert(m2.nc == m2.nc); +matrix operator-(const matrix& m1, const matrix& m2) { + assert(m1.nr == m2.nr); + assert(m2.nc == m2.nc); - matrix tm(m1); - for(int i = 0; i < m1.nr*m1.nc; i++) tm.c[i] -= m2.c[i]; - return tm; + matrix tm(m1); + for (int i = 0; i < m1.nr * m1.nc; i++) + tm.c[i] -= m2.c[i]; + return tm; } //*************************************** // -// Multiplying matrices, as a friend +// Multiplying matrices, as a friend // // ************************************* -matrix operator*(const matrix &m1, const matrix &m2) -{ - assert(m1.nr == m2.nr); - assert(m2.nc == m2.nc); - - // allocate the result and zero it out - matrix mprod(m2.nr, m1.nc); - - mprod.zero_out(); - - // do the multiply and return - for (int i = 0;i < m2.nr;i++) - { - for (int j = 0;j < m1.nc;j++) - { - for (int k = 0;k < m2.nc;k++) - { - mprod(i, j) += m2(i, k) * m1(k, j); - } - } - } - - return mprod; +matrix operator*(const matrix& m1, const matrix& m2) { + assert(m1.nr == m2.nr); + assert(m2.nc == m2.nc); + + // allocate the result and zero it out + matrix mprod(m2.nr, m1.nc); + + mprod.zero_out(); + + // do the multiply and return + for (int i = 0; i < m2.nr; i++) { + for (int j = 0; j < m1.nc; j++) { + for (int k = 0; k < m2.nc; k++) { + mprod(i, j) += m2(i, k) * m1(k, j); + } + } + } + + return mprod; } /* Scale a matrix */ -matrix operator*(const double &s, const matrix &m) -{ - matrix sm(m); - for (int i = 0; i < m.nr*m.nc; i++) sm.c[i] *= s; - return sm; +matrix operator*(const double& s, const matrix& m) { + matrix sm(m); + for (int i = 0; i < m.nr * m.nc; i++) + sm.c[i] *= s; + return sm; } /* matrix * double */ -matrix operator*(const matrix &m,const double &s) -{ - matrix sm(m); - for (int i = 0; i < m.nr*m.nc; i++)sm.c[i] *= s; - return sm; +matrix operator*(const matrix& m, const double& s) { + matrix sm(m); + for (int i = 0; i < m.nr * m.nc; i++) + sm.c[i] *= s; + return sm; } /* Scale a matrix in place */ -void matrix::operator*=(const double &s) -{ - for (int i = 0; i < nc*nr; i++) c[i] *= s; +void matrix::operator*=(const double& s) { + for (int i = 0; i < nc * nr; i++) + c[i] *= s; } /* Accumulate to a matrix in place */ -void matrix::operator+=(const matrix & m) -{ - if (nr != m.nr || nc != m.nc) - { - cout << " void matrix::operator+=(const matrix &m) has size mismatch\n"; - abort(); - } - for (int i = 0; i < nc*nr; i++) c[i] += m.c[i]; +void matrix::operator+=(const matrix& m) { + if (nr != m.nr || nc != m.nc) { + cout << " void matrix::operator+=(const matrix &m) has size mismatch\n"; + abort(); + } + for (int i = 0; i < nc * nr; i++) + c[i] += m.c[i]; } - /* decumulate to a matrix in place */ -void matrix::operator-=(const matrix & m) -{ - if (nr != m.nr || nc != m.nc) - { - cout << "void matrix::operator-=(const matrix &m) has size mismatch\n"; - abort(); - } - for (int i = 0; i < nc*nr; i++) c[i] -= m.c[i]; +void matrix::operator-=(const matrix& m) { + if (nr != m.nr || nc != m.nc) { + cout << "void matrix::operator-=(const matrix &m) has size mismatch\n"; + abort(); + } + for (int i = 0; i < nc * nr; i++) + c[i] -= m.c[i]; } /* zero out the matrix */ -void matrix::zero_out(void) -{ - for(int i = 0; i < nr*nc; i++) - { - c[i] = 0.0; - } - return; -} - - -matrix transpose(matrix m) -{ - matrix tm(m.nc, m.nr); - - for (int i = 0;i < m.nr;i++) - { - for (int j = 0;j < m.nc;j++) - { - tm(j, i) = m(i, j); - } - } - return tm; +void matrix::zero_out(void) { + for (int i = 0; i < nr * nc; i++) { + c[i] = 0.0; + } + return; +} + +matrix transpose(matrix m) { + matrix tm(m.nc, m.nr); + + for (int i = 0; i < m.nr; i++) { + for (int j = 0; j < m.nc; j++) { + tm(j, i) = m(i, j); + } + } + return tm; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix.h index 5c3e896f555..4658720cf60 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix.h @@ -1,54 +1,51 @@ #ifndef MATRIX_H #define MATRIX_H -class matrix -{ - /* data */ -public: - double *c; /* Holds the data */ - int nr; - int nc; /* Number of rows and columns */ - int hermetian; - static int mCount; - - /* Constructors and destructor */ - matrix(const int nrows = 1,const int ncols = 1); - matrix(const matrix &m1); /* copy constructor */ - ~matrix(); - - void create(const int nrow,const int ncol); - void operator=(const matrix &m1); /* Nonstandard: returns void */ - - double &operator()(const int ir,const int ic) - { return c[nc*ir + ic]; }; - - const double &operator()(const int ir,const int ic)const - { return c[nc*ir + ic]; }; - -// inline double &operator()(int i,int j) const -// { return c[nc*i+j]; } - - friend matrix operator+(const matrix &m1, const matrix &m2); - friend matrix operator-(const matrix &m1, const matrix &m2); - friend matrix operator*(const matrix &m1, const matrix &m2); - friend matrix operator*(const double &s, const matrix &m); - friend matrix operator*(const matrix &m, const double &s); - void operator*=(const double &s); - void operator+=(const matrix &m); - void operator-=(const matrix &m); - - /* member function: */ - matrix Inverse(void); - - double det(void); - - /* Does the memory allocations of the constructor */ - void init(int nrows, int ncols); - - /* Free up memory */ - void freemem(void); - - /* zero out all the entries */ - void zero_out(void); +class matrix { + /* data */ + public: + double* c; /* Holds the data */ + int nr; + int nc; /* Number of rows and columns */ + int hermetian; + static int mCount; + + /* Constructors and destructor */ + matrix(const int nrows = 1, const int ncols = 1); + matrix(const matrix& m1); /* copy constructor */ + ~matrix(); + + void create(const int nrow, const int ncol); + void operator=(const matrix& m1); /* Nonstandard: returns void */ + + double& operator()(const int ir, const int ic) { return c[nc * ir + ic]; }; + + const double& operator()(const int ir, const int ic) const { return c[nc * ir + ic]; }; + + // inline double &operator()(int i,int j) const + // { return c[nc*i+j]; } + + friend matrix operator+(const matrix& m1, const matrix& m2); + friend matrix operator-(const matrix& m1, const matrix& m2); + friend matrix operator*(const matrix& m1, const matrix& m2); + friend matrix operator*(const double& s, const matrix& m); + friend matrix operator*(const matrix& m, const double& s); + void operator*=(const double& s); + void operator+=(const matrix& m); + void operator-=(const matrix& m); + + /* member function: */ + matrix Inverse(void); + + double det(void); + + /* Does the memory allocations of the constructor */ + void init(int nrows, int ncols); + + /* Free up memory */ + void freemem(void); + + /* zero out all the entries */ + void zero_out(void); }; matrix transpose(matrix m); diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix3.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix3.cpp index 67ccc3c8f45..75d7237df6a 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix3.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix3.cpp @@ -1,212 +1,222 @@ #include "matrix3.h" -Matrix3::Matrix3(const double &r11, const double &r12, const double &r13, - const double &r21, const double &r22, const double &r23, - const double &r31, const double &r32, const double &r33) -{ - e11 = r11;e12 = r12;e13 = r13; - e21 = r21;e22 = r22;e23 = r23; - e31 = r31;e32 = r32;e33 = r33; -} - -void Matrix3::Reset(void) -{ - e11 = 1;e12 = 0;e13 = 0; - e21 = 0;e22 = 1;e23 = 0; - e31 = 0;e32 = 0;e33 = 1; -} - -void Matrix3::Identity(void) -{ - e11 = 1;e12 = 0;e13 = 0; - e21 = 0;e22 = 1;e23 = 0; - e31 = 0;e32 = 0;e33 = 1; -} - -double Matrix3::Det(void) const -{ - return e11*e22*e33 - - e11*e32*e23 + - e21*e32*e13 - - e21*e12*e33 + - e31*e12*e23 - - e31*e22*e13; -} - -Matrix3 Matrix3::Transpose(void) const -{ - return Matrix3(e11, e21, e31, e12, e22, e32, e13, e23, e33); -} - -Matrix3 Matrix3::Inverse(void) const -{ - double d = this->Det(); - - if(d == 0)d = 1; - - return Matrix3((e22*e33 - e23*e32) / d, - -(e12*e33 - e13*e32) / d, - (e12*e23 - e13*e22) / d, - -(e21*e33 - e23*e31) / d, - (e11*e33 - e13*e31) / d, - -(e11*e23 - e13*e21) / d, - (e21*e32 - e22*e31) / d, - -(e11*e32 - e12*e31) / d, - (e11*e22 - e12*e21) / d); -} - -Matrix3& Matrix3::operator = (const Matrix3 &m) -{ - e11 = m.e11;e12 = m.e12;e13 = m.e13; - e21 = m.e21;e22 = m.e22;e23 = m.e23; - e31 = m.e31;e32 = m.e32;e33 = m.e33; - return *this; -} - -Matrix3& Matrix3::operator +=(const Matrix3 &m) -{ - e11 += m.e11;e12 += m.e12;e13 += m.e13; - e21 += m.e21;e22 += m.e22;e23 += m.e23; - e31 += m.e31;e32 += m.e32;e33 += m.e33; - return *this; -} - -Matrix3& Matrix3::operator -=(const Matrix3 &m) -{ - e11 -= m.e11;e12 -= m.e12;e13 -= m.e13; - e21 -= m.e21;e22 -= m.e22;e23 -= m.e23; - e31 -= m.e31;e32 -= m.e32;e33 -= m.e33; - return *this; -} - -Matrix3& Matrix3::operator *=(const double &s) -{ - e11 *= s;e12 *= s;e13 *= s; - e21 *= s;e22 *= s;e23 *= s; - e31 *= s;e32 *= s;e33 *= s; - return *this; -} - -Matrix3& Matrix3::operator /=(const double &s) -{ - e11 /= s;e12 /= s;e13 /= s; - e21 /= s;e22 /= s;e23 /= s; - e31 /= s;e32 /= s;e33 /= s; - return *this; -} - -//m1+m2 -Matrix3 operator +(const Matrix3 &m1, const Matrix3 &m2) -{ - return Matrix3(m1.e11 + m2.e11, - m1.e12 + m2.e12, - m1.e13 + m2.e13, - m1.e21 + m2.e21, - m1.e22 + m2.e22, - m1.e23 + m2.e23, - m1.e31 + m2.e31, - m1.e32 + m2.e32, - m1.e33 + m2.e33); -} - -//m1-m2 -Matrix3 operator -(const Matrix3 &m1, const Matrix3 &m2) -{ - return Matrix3(m1.e11 + m2.e11, - m1.e12 - m2.e12, - m1.e13 - m2.e13, - m1.e21 - m2.e21, - m1.e22 - m2.e22, - m1.e23 - m2.e23, - m1.e31 - m2.e31, - m1.e32 - m2.e32, - m1.e33 - m2.e33); -} - -//m/s -Matrix3 operator /(const Matrix3 &m, const double &s) -{ - return Matrix3(m.e11 / s, m.e12 / s, m.e13 / s, - m.e21 / s, m.e22 / s, m.e23 / s, - m.e31 / s, m.e32 / s, m.e33 / s); -} - -//m1*m2 -Matrix3 operator *(const Matrix3 &m1, const Matrix3 &m2) -{ - return Matrix3(m1.e11*m2.e11 + m1.e12*m2.e21 + m1.e13*m2.e31, - m1.e11*m2.e12 + m1.e12*m2.e22 + m1.e13*m2.e32, - m1.e11*m2.e13 + m1.e12*m2.e23 + m1.e13*m2.e33, - m1.e21*m2.e11 + m1.e22*m2.e21 + m1.e23*m2.e31, - m1.e21*m2.e12 + m1.e22*m2.e22 + m1.e23*m2.e32, - m1.e21*m2.e13 + m1.e22*m2.e23 + m1.e23*m2.e33, - m1.e31*m2.e11 + m1.e32*m2.e21 + m1.e33*m2.e31, - m1.e31*m2.e12 + m1.e32*m2.e22 + m1.e33*m2.e32, - m1.e31*m2.e13 + m1.e32*m2.e23 + m1.e33*m2.e33); -} - -//m*s -Matrix3 operator *(const Matrix3 &m,const double &s) -{ - return Matrix3(m.e11*s, m.e12*s, m.e13*s, - m.e21*s, m.e22*s, m.e23*s, - m.e31*s, m.e32*s, m.e33*s); -} - -//s*m -Matrix3 operator *(const double &s, const Matrix3 &m) -{ - return Matrix3(m.e11*s, m.e12*s, m.e13*s, - m.e21*s, m.e22*s, m.e23*s, - m.e31*s, m.e32*s, m.e33*s); -} - -//m*u -Vector3 operator *(const Matrix3 &m, const Vector3 &u) -{ - return Vector3(m.e11*u.x + m.e12*u.y + m.e13*u.z, - m.e21*u.x + m.e22*u.y + m.e23*u.z, - m.e31*u.x + m.e32*u.y + m.e33*u.z); -} - -//u*m -Vector3 operator *(const Vector3 &u, const Matrix3 &m) -{ - return Vector3(u.x*m.e11 + u.y*m.e21 + u.z*m.e31, - u.x*m.e12 + u.y*m.e22 + u.z*m.e32, - u.x*m.e13 + u.y*m.e23 + u.z*m.e33); +Matrix3::Matrix3(const double& r11, + const double& r12, + const double& r13, + const double& r21, + const double& r22, + const double& r23, + const double& r31, + const double& r32, + const double& r33) { + e11 = r11; + e12 = r12; + e13 = r13; + e21 = r21; + e22 = r22; + e23 = r23; + e31 = r31; + e32 = r32; + e33 = r33; +} + +void Matrix3::Reset(void) { + e11 = 1; + e12 = 0; + e13 = 0; + e21 = 0; + e22 = 1; + e23 = 0; + e31 = 0; + e32 = 0; + e33 = 1; +} + +void Matrix3::Identity(void) { + e11 = 1; + e12 = 0; + e13 = 0; + e21 = 0; + e22 = 1; + e23 = 0; + e31 = 0; + e32 = 0; + e33 = 1; +} + +double Matrix3::Det(void) const { + return e11 * e22 * e33 - e11 * e32 * e23 + e21 * e32 * e13 - e21 * e12 * e33 + e31 * e12 * e23 - e31 * e22 * e13; +} + +Matrix3 Matrix3::Transpose(void) const { return Matrix3(e11, e21, e31, e12, e22, e32, e13, e23, e33); } + +Matrix3 Matrix3::Inverse(void) const { + double d = this->Det(); + + if (d == 0) + d = 1; + + return Matrix3((e22 * e33 - e23 * e32) / d, + -(e12 * e33 - e13 * e32) / d, + (e12 * e23 - e13 * e22) / d, + -(e21 * e33 - e23 * e31) / d, + (e11 * e33 - e13 * e31) / d, + -(e11 * e23 - e13 * e21) / d, + (e21 * e32 - e22 * e31) / d, + -(e11 * e32 - e12 * e31) / d, + (e11 * e22 - e12 * e21) / d); +} + +Matrix3& Matrix3::operator=(const Matrix3& m) { + e11 = m.e11; + e12 = m.e12; + e13 = m.e13; + e21 = m.e21; + e22 = m.e22; + e23 = m.e23; + e31 = m.e31; + e32 = m.e32; + e33 = m.e33; + return *this; +} + +Matrix3& Matrix3::operator+=(const Matrix3& m) { + e11 += m.e11; + e12 += m.e12; + e13 += m.e13; + e21 += m.e21; + e22 += m.e22; + e23 += m.e23; + e31 += m.e31; + e32 += m.e32; + e33 += m.e33; + return *this; +} + +Matrix3& Matrix3::operator-=(const Matrix3& m) { + e11 -= m.e11; + e12 -= m.e12; + e13 -= m.e13; + e21 -= m.e21; + e22 -= m.e22; + e23 -= m.e23; + e31 -= m.e31; + e32 -= m.e32; + e33 -= m.e33; + return *this; +} + +Matrix3& Matrix3::operator*=(const double& s) { + e11 *= s; + e12 *= s; + e13 *= s; + e21 *= s; + e22 *= s; + e23 *= s; + e31 *= s; + e32 *= s; + e33 *= s; + return *this; +} + +Matrix3& Matrix3::operator/=(const double& s) { + e11 /= s; + e12 /= s; + e13 /= s; + e21 /= s; + e22 /= s; + e23 /= s; + e31 /= s; + e32 /= s; + e33 /= s; + return *this; +} + +// m1+m2 +Matrix3 operator+(const Matrix3& m1, const Matrix3& m2) { + return Matrix3(m1.e11 + m2.e11, + m1.e12 + m2.e12, + m1.e13 + m2.e13, + m1.e21 + m2.e21, + m1.e22 + m2.e22, + m1.e23 + m2.e23, + m1.e31 + m2.e31, + m1.e32 + m2.e32, + m1.e33 + m2.e33); +} + +// m1-m2 +Matrix3 operator-(const Matrix3& m1, const Matrix3& m2) { + return Matrix3(m1.e11 + m2.e11, + m1.e12 - m2.e12, + m1.e13 - m2.e13, + m1.e21 - m2.e21, + m1.e22 - m2.e22, + m1.e23 - m2.e23, + m1.e31 - m2.e31, + m1.e32 - m2.e32, + m1.e33 - m2.e33); +} + +// m/s +Matrix3 operator/(const Matrix3& m, const double& s) { + return Matrix3(m.e11 / s, m.e12 / s, m.e13 / s, m.e21 / s, m.e22 / s, m.e23 / s, m.e31 / s, m.e32 / s, m.e33 / s); +} + +// m1*m2 +Matrix3 operator*(const Matrix3& m1, const Matrix3& m2) { + return Matrix3(m1.e11 * m2.e11 + m1.e12 * m2.e21 + m1.e13 * m2.e31, + m1.e11 * m2.e12 + m1.e12 * m2.e22 + m1.e13 * m2.e32, + m1.e11 * m2.e13 + m1.e12 * m2.e23 + m1.e13 * m2.e33, + m1.e21 * m2.e11 + m1.e22 * m2.e21 + m1.e23 * m2.e31, + m1.e21 * m2.e12 + m1.e22 * m2.e22 + m1.e23 * m2.e32, + m1.e21 * m2.e13 + m1.e22 * m2.e23 + m1.e23 * m2.e33, + m1.e31 * m2.e11 + m1.e32 * m2.e21 + m1.e33 * m2.e31, + m1.e31 * m2.e12 + m1.e32 * m2.e22 + m1.e33 * m2.e32, + m1.e31 * m2.e13 + m1.e32 * m2.e23 + m1.e33 * m2.e33); +} + +// m*s +Matrix3 operator*(const Matrix3& m, const double& s) { + return Matrix3(m.e11 * s, m.e12 * s, m.e13 * s, m.e21 * s, m.e22 * s, m.e23 * s, m.e31 * s, m.e32 * s, m.e33 * s); +} + +// s*m +Matrix3 operator*(const double& s, const Matrix3& m) { + return Matrix3(m.e11 * s, m.e12 * s, m.e13 * s, m.e21 * s, m.e22 * s, m.e23 * s, m.e31 * s, m.e32 * s, m.e33 * s); +} + +// m*u +Vector3 operator*(const Matrix3& m, const Vector3& u) { + return Vector3(m.e11 * u.x + m.e12 * u.y + m.e13 * u.z, + m.e21 * u.x + m.e22 * u.y + m.e23 * u.z, + m.e31 * u.x + m.e32 * u.y + m.e33 * u.z); +} + +// u*m +Vector3 operator*(const Vector3& u, const Matrix3& m) { + return Vector3(u.x * m.e11 + u.y * m.e21 + u.z * m.e31, + u.x * m.e12 + u.y * m.e22 + u.z * m.e32, + u.x * m.e13 + u.y * m.e23 + u.z * m.e33); } - // whether m1==m2 -bool operator==(const Matrix3 &m1, const Matrix3 &m2) -{ - if(m1.e11 == m2.e11 && - m1.e12 == m2.e12 && - m1.e13 == m2.e13 && - m1.e21 == m2.e21 && - m1.e22 == m2.e22 && - m1.e23 == m2.e23 && - m1.e31 == m2.e31 && - m1.e32 == m2.e32 && - m1.e33 == m2.e33) - { - return true; - } - return false; -} - -//whether m1 != m2 -bool operator!=(const Matrix3 &m1, const Matrix3 &m2) -{ - return !(m1 == m2); //!= defined in terms of operator == +bool operator==(const Matrix3& m1, const Matrix3& m2) { + if (m1.e11 == m2.e11 && m1.e12 == m2.e12 && m1.e13 == m2.e13 && m1.e21 == m2.e21 && m1.e22 == m2.e22 && + m1.e23 == m2.e23 && m1.e31 == m2.e31 && m1.e32 == m2.e32 && m1.e33 == m2.e33) { + return true; + } + return false; } +// whether m1 != m2 +bool operator!=(const Matrix3& m1, const Matrix3& m2) { + return !(m1 == m2); //!= defined in terms of operator == +} -void Matrix3::print(void)const -{ - cout << e11 << setw(15) << e12 << setw(15) << e13 << endl ; - cout << e21 << setw(15) << e22 << setw(15) << e23 << endl ; - cout << e31 << setw(15) << e32 << setw(15) << e33 << endl ; - return; +void Matrix3::print(void) const { + cout << e11 << setw(15) << e12 << setw(15) << e13 << endl; + cout << e21 << setw(15) << e22 << setw(15) << e23 << endl; + cout << e31 << setw(15) << e32 << setw(15) << e33 << endl; + return; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix3.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix3.h index 024f19870d7..09e54e0f061 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix3.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/matrix3.h @@ -11,44 +11,48 @@ #include "vector3.h" -class Matrix3 -{ - /* data */ -public: - // element eij:i_column,j_row - double e11, e12, e13, e21, e22, e23, e31, e32, e33; - - /* Constructors and destructor */ - Matrix3(const double &r11 = 1,const double &r12 = 0,const double &r13 = 0, - const double &r21 = 0,const double &r22 = 1,const double &r23 = 0, - const double &r31 = 0,const double &r32 = 0,const double &r33 = 1); - - void Reset(void); - void Identity(void); - double Det(void) const ; - Matrix3 Transpose(void) const ; - Matrix3 Inverse(void) const ; - - Matrix3& operator=(const Matrix3 &m); - Matrix3& operator+=(const Matrix3 &m); - Matrix3& operator-=(const Matrix3 &m); - Matrix3& operator*=(const double &s); - Matrix3& operator/=(const double &s); - - void print(void)const; +class Matrix3 { + /* data */ + public: + // element eij:i_column,j_row + double e11, e12, e13, e21, e22, e23, e31, e32, e33; + + /* Constructors and destructor */ + Matrix3(const double& r11 = 1, + const double& r12 = 0, + const double& r13 = 0, + const double& r21 = 0, + const double& r22 = 1, + const double& r23 = 0, + const double& r31 = 0, + const double& r32 = 0, + const double& r33 = 1); + + void Reset(void); + void Identity(void); + double Det(void) const; + Matrix3 Transpose(void) const; + Matrix3 Inverse(void) const; + + Matrix3& operator=(const Matrix3& m); + Matrix3& operator+=(const Matrix3& m); + Matrix3& operator-=(const Matrix3& m); + Matrix3& operator*=(const double& s); + Matrix3& operator/=(const double& s); + + void print(void) const; }; -Matrix3 operator +(const Matrix3 &m1, const Matrix3 &m2); //m1+m2 -Matrix3 operator -(const Matrix3 &m1, const Matrix3 &m2); //m1-m2 -Matrix3 operator /(const Matrix3 &m,const double &s); //m/s -Matrix3 operator *(const Matrix3 &m1,const Matrix3 &m2); //m1*m2 -Matrix3 operator *(const Matrix3 &m,const double &s); //m*s -Matrix3 operator *(double &s, const Matrix3 &m); //s*m -Vector3 operator *(const Matrix3 &m, const Vector3 &u); //m*u -Vector3 operator *(const Vector3 &u, const Matrix3 &m); //u*m +Matrix3 operator+(const Matrix3& m1, const Matrix3& m2); // m1+m2 +Matrix3 operator-(const Matrix3& m1, const Matrix3& m2); // m1-m2 +Matrix3 operator/(const Matrix3& m, const double& s); // m/s +Matrix3 operator*(const Matrix3& m1, const Matrix3& m2); // m1*m2 +Matrix3 operator*(const Matrix3& m, const double& s); // m*s +Matrix3 operator*(double& s, const Matrix3& m); // s*m +Vector3 operator*(const Matrix3& m, const Vector3& u); // m*u +Vector3 operator*(const Vector3& u, const Matrix3& m); // u*m -bool operator ==(const Matrix3 &m1, const Matrix3 &m2); //whether m1 == m2 -bool operator !=(const Matrix3 &m1, const Matrix3 &m2); //whethor m1 != m2 +bool operator==(const Matrix3& m1, const Matrix3& m2); // whether m1 == m2 +bool operator!=(const Matrix3& m1, const Matrix3& m2); // whethor m1 != m2 #endif // MATRIX3_H - diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/realarray.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/realarray.cpp index 86c17471dbe..2951f7c93c6 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/realarray.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/realarray.cpp @@ -7,48 +7,47 @@ int realArray::arrayCount = 0; -void realArrayAlloc() -{ - cout << "\n Allocation error for realArray " << endl; - exit(0); +void realArrayAlloc() { + cout << "\n Allocation error for realArray " << endl; + exit(0); } -realArray::realArray(const int d1,const int d2,const int d3) -{ - dim = 3; - bound1 = (d1 <= 0) ? 1 : d1; - bound2 = (d2 <= 0) ? 1 : d2; - bound3 = (d3 <= 0) ? 1 : d3; - bound4 = 0; +realArray::realArray(const int d1, const int d2, const int d3) { + dim = 3; + bound1 = (d1 <= 0) ? 1 : d1; + bound2 = (d2 <= 0) ? 1 : d2; + bound3 = (d3 <= 0) ? 1 : d3; + bound4 = 0; - set_new_handler(realArrayAlloc); + set_new_handler(realArrayAlloc); - size = bound1 * bound2 * bound3 ; //* sizeof(float); + size = bound1 * bound2 * bound3; //* sizeof(float); - ptr = new double[size](); - assert(ptr != 0); - for(int i=0; i0); +void realArray::create(const int d1, const int d2, const int d3, const int d4) { + size = d1 * d2 * d3 * d4; + assert(size > 0); - dim = 4; + dim = 4; - bound1 = d1; - bound2 = d2; - bound3 = d3; - bound4 = d4; + bound1 = d1; + bound2 = d2; + bound3 = d3; + bound4 = d4; - delete [] ptr; - ptr = new double[size](); - assert(ptr != 0); - for(int i=0; i0); +void realArray::create(const int d1, const int d2, const int d3) { + size = d1 * d2 * d3; + assert(size > 0); - dim = 3; + dim = 3; - bound1 = d1; - bound2 = d2; - bound3 = d3; - bound4 = 1; + bound1 = d1; + bound2 = d2; + bound3 = d3; + bound4 = 1; - delete [] ptr; - ptr = new double[size](); - assert(ptr != 0); - for(int i=0; i #include -using namespace std; +class realArray { + public: + double* ptr; -class realArray -{ -public: - double *ptr; + realArray(const int d1 = 1, const int d2 = 1, const int d3 = 1); + realArray(const int d1, const int d2, const int d3, const int d4); + ~realArray(); - realArray(const int d1 = 1 ,const int d2 = 1,const int d3 = 1); - realArray(const int d1, const int d2,const int d3,const int d4); - ~realArray(); + void create(const int d1, const int d2, const int d3); + void create(const int d1, const int d2, const int d3, const int d4); - void create(const int d1,const int d2,const int d3); - void create(const int d1,const int d2,const int d3,const int d4); + const realArray& operator=(const realArray& right); + const realArray& operator=(const double& right); - const realArray &operator=(const realArray &right); - const realArray &operator=(const double &right); + double& operator()(const int d1, const int d2, const int d3); + double& operator()(const int d1, const int d2, const int d3, const int d4); - double &operator()(const int d1,const int d2,const int d3); - double &operator()(const int d1,const int d2,const int d3,const int d4); + const double& operator()(const int d1, const int d2, const int d3) const; + const double& operator()(const int d1, const int d2, const int d3, const int d4) const; - const double &operator()(const int d1,const int d2,const int d3)const; - const double &operator()(const int d1,const int d2,const int d3,const int d4)const; + void zero_out(void); - void zero_out(void); + int getSize() const { return size; } - int getSize() const - { return size;} + int getDim() const { return dim; } - int getDim() const - { return dim;} + int getBound1() const { return bound1; } - int getBound1() const - { return bound1;} + int getBound2() const { return bound2; } - int getBound2() const - { return bound2;} + int getBound3() const { return bound3; } - int getBound3() const - { return bound3;} + int getBound4() const { return bound4; } - int getBound4() const - { return bound4;} + int getArrayCount(void) { return arrayCount; } - int getArrayCount(void) - { return arrayCount;} + private: + int size; + int dim; + int bound1, bound2, bound3, bound4; + static int arrayCount; -private: - int size; - int dim; - int bound1, bound2, bound3, bound4; - static int arrayCount; - - void freemem(); + void freemem(); }; //************************************************** // set elements of a as zeros which a is 1_d array. //************************************************** -template -void zeros(T *u,const int n) -{ - assert(n>0); - for (int i = 0;i < n;i++) u[i] = 0; +template +void zeros(T* u, const int n) { + assert(n > 0); + for (int i = 0; i < n; i++) + u[i] = 0; } -#endif // realArray class +#endif // realArray class diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/timer.cpp b/tools/SIAB/SimulatedAnnealing/source/src_tools/timer.cpp index ec1660d9ce3..f2128bf4eff 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/timer.cpp +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/timer.cpp @@ -7,7 +7,7 @@ using namespace std; //---------------------------------------------------------- -// EXPLAIN : +// EXPLAIN : //---------------------------------------------------------- bool timer::disabled = false; int timer::n_clock = 100; @@ -18,227 +18,192 @@ double* timer::cpu_start; string* timer::name; string* timer::class_name; int* timer::calls; -bool timer::delete_flag=false; - -timer::timer() -{ -}; - -timer::~timer() -{ -}; - -void timer::finish() -{ - timer::tick("","total"); - print_all(); - if(delete_flag) - { - delete[] cpu_second; - delete[] cpu_start; - delete[] name; - delete[] class_name; - delete[] calls; - } +bool timer::delete_flag = false; + +timer::timer(){}; + +timer::~timer(){}; + +void timer::finish() { + timer::tick("", "total"); + print_all(); + if (delete_flag) { + delete[] cpu_second; + delete[] cpu_start; + delete[] name; + delete[] class_name; + delete[] calls; + } } //---------------------------------------------------------- // //---------------------------------------------------------- -void timer::start(void) -{ - cpu_second = new double[n_clock](); - cpu_start = new double[n_clock](); - name = new string[n_clock](); - class_name = new string[n_clock](); - calls = new int[n_clock](); - delete_flag = true; - - for (int i = 0; i < n_clock; i++) - { - cpu_start[i] = (double)start_flag; - name[i]= "\0"; - class_name[i]= "\0"; - calls[i] = 0; - } - - // first init ,then we can use tick - timer::tick("","total"); - return; +void timer::start(void) { + cpu_second = new double[n_clock](); + cpu_start = new double[n_clock](); + name = new string[n_clock](); + class_name = new string[n_clock](); + calls = new int[n_clock](); + delete_flag = true; + + for (int i = 0; i < n_clock; i++) { + cpu_start[i] = (double)start_flag; + name[i] = "\0"; + class_name[i] = "\0"; + calls[i] = 0; + } + + // first init ,then we can use tick + timer::tick("", "total"); + return; } -double timer::cpu_time(void) -{ - clock_t t1 = 0; -//---------------------------------------------------------- -// EXPLAIN : here static is important !! -// only first call can let t0 = 0,clock begin -// when enter this function second time , t0 > 0 -//---------------------------------------------------------- - static clock_t t0 = 0; - if (t0 == 0) - { - t0 = clock(); - } - t1 = clock() - t0; - - if(t1 < 0) return 0; // mohan add, abandon the cross point time 2^32 ~ -2^32 . - else return (double)t1/CLOCKS_PER_SEC; +double timer::cpu_time(void) { + clock_t t1 = 0; + //---------------------------------------------------------- + // EXPLAIN : here static is important !! + // only first call can let t0 = 0,clock begin + // when enter this function second time , t0 > 0 + //---------------------------------------------------------- + static clock_t t0 = 0; + if (t0 == 0) { + t0 = clock(); + } + t1 = clock() - t0; + + if (t1 < 0) + return 0; // mohan add, abandon the cross point time 2^32 ~ -2^32 . + else + return (double)t1 / CLOCKS_PER_SEC; } -void timer::tick(const string &tagc,const string &tag) -{ -//---------------------------------------------------------- -// EXPLAIN : if timer is disabled , return -//---------------------------------------------------------- - if (disabled) - { - return; - } - - int find_clock=0;//counter -//---------------------------------------------------------- -// EXPLAIN : find if the tag has been used -//---------------------------------------------------------- - for(find_clock=0; find_clock= n_clock) - { - cout << "\nError! Too many timer!"; - return; - } - -//---------------------------------------------------------- -// CALL MEMBER FUNCTION : -// NAME : cpu_time -// -// EXPLAIN : start_flag is minus 1, -// so if cpu_start == start_flag,means a new clock counting -// begin, hence we record the start time of this clock -// counting , if cpu_start != start_flag, means it's -// the end of this counting, so we add the time during -// this two 'time point' to the clock time storage. -//---------------------------------------------------------- - if (cpu_start[find_clock] == start_flag ) - { - cpu_start[find_clock] = cpu_time(); - calls[find_clock]++; - } - else - { - cpu_second[find_clock] += cpu_time() - cpu_start[find_clock]; - cpu_start[find_clock] = start_flag; - } - return; +void timer::tick(const string& tagc, const string& tag) { + //---------------------------------------------------------- + // EXPLAIN : if timer is disabled , return + //---------------------------------------------------------- + if (disabled) { + return; + } + + int find_clock = 0; // counter + //---------------------------------------------------------- + // EXPLAIN : find if the tag has been used + //---------------------------------------------------------- + for (find_clock = 0; find_clock < n_now; find_clock++) { + if (tag == name[find_clock] && tagc == class_name[find_clock]) { + break; + } + } + + //---------------------------------------------------------- + // EXPLAIN : if it's a new tag; add a new tag to list; + // add this new tag to name list; + //---------------------------------------------------------- + if (find_clock == n_now) { + n_now++; + name[find_clock] = tag; + class_name[find_clock] = tagc; + } + + //---------------------------------------------------------- + // EXPLAIN : if exceed the the uplimits of list + //---------------------------------------------------------- + if (n_now >= n_clock) { + cout << "\nError! Too many timer!"; + return; + } + + //---------------------------------------------------------- + // CALL MEMBER FUNCTION : + // NAME : cpu_time + // + // EXPLAIN : start_flag is minus 1, + // so if cpu_start == start_flag,means a new clock counting + // begin, hence we record the start time of this clock + // counting , if cpu_start != start_flag, means it's + // the end of this counting, so we add the time during + // this two 'time point' to the clock time storage. + //---------------------------------------------------------- + if (cpu_start[find_clock] == start_flag) { + cpu_start[find_clock] = cpu_time(); + calls[find_clock]++; + } else { + cpu_second[find_clock] += cpu_time() - cpu_start[find_clock]; + cpu_start[find_clock] = start_flag; + } + return; } - - -void timer::enable(void) -{ - disabled = false; - return; +void timer::enable(void) { + disabled = false; + return; } -void timer::disable(void) -{ - disabled = true; - return; +void timer::disable(void) { + disabled = true; + return; } -double timer::print(const string &tag) -{ - int index = 0; - for(int i=0; i 1s , set small = 10^6 - - cout<<"\n--------- CLASS NAME--------------- NAME ----- TIME(sec) -- CALLS ----- AVG ----- PER%"; - bool *print_flag = new bool[n_clock]; - for(int i=0; i 1s , set small = 10^6 + + cout << "\n--------- CLASS NAME--------------- NAME ----- TIME(sec) -- CALLS ----- AVG ----- PER%"; + bool* print_flag = new bool[n_clock]; + for (int i = 0; i < n_clock; i++) + print_flag[i] = false; + + for (int i = 0; i < n_clock; i++) { + int k = 0; + double tmp = -1.0; + for (int j = 0; j < n_clock; j++) { + if (print_flag[j]) { + continue; + } + if (tmp < cpu_second[j]) { + k = j; + // cout << "\n k = " << k; + tmp = cpu_second[j]; + } + } + print_flag[k] = true; + + if ((cpu_second[k] >= 0 && cpu_second[k] < small) || (cpu_second[k] <= 0 && cpu_second[k] > -small)) { + continue; + } + const long double spend_time = cpu_second[k]; + const double average_spend_time = spend_time / calls[k]; + + cout << "\n" + << setw(20) << class_name[k] << setw(20) << name[k] << setw(15) << spend_time << setw(10) << calls[k] + << setw(10) << setprecision(2) << average_spend_time << setw(10) << spend_time / cpu_second[0] * 100 + << "%"; + } + cout << "\n--------------------------------------------------------------------------------------" << endl; + delete[] print_flag; + return; } diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/timer.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/timer.h index 826e56ca28c..661db52aa92 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/timer.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/timer.h @@ -10,70 +10,65 @@ #include #include #include -using namespace std; //========================================================== // CLASS : // NAME : timer(calculate time) //========================================================== -class timer -{ - timer(); - ~timer(); +class timer { + timer(); + ~timer(); - public: -//========================================================== -// MEMBER FUNCTIONS : -// NAME : tick(use twice at a time) -// NAME : start -// NAME : finish -// NAME : enable -// NAME : disable -// NAME : print -// NAME : print_all -//========================================================== - static void tick(const string &class_name_in,const string &name_in); - - static void start(); - static void finish(); + public: + //========================================================== + // MEMBER FUNCTIONS : + // NAME : tick(use twice at a time) + // NAME : start + // NAME : finish + // NAME : enable + // NAME : disable + // NAME : print + // NAME : print_all + //========================================================== + static void tick(const std::string& class_name_in, const std::string& name_in); - static void enable(); - static void disable(); + static void start(); + static void finish(); - static void print_all(); - static long double print_until_now(); - static double print(const string &name_in); + static void enable(); + static void disable(); - private: + static void print_all(); + static long double print_until_now(); + static double print(const std::string& name_in); -//========================================================== -// MEMBER VARIABLES : -// NAME : disabled(if disabled , timer can't work) -// NAME : n_clock(uplimit number of clock numbers) -// NAME : n_now(the index of clocks) -// NAME : start_flag -// NAME : cpu_start -// NAME : cput_second(record cpu time) -// NAME : name(record clock name) -// NAME : class_name(record another name for clock) -//========================================================== - static bool disabled; - static int n_clock; - static int n_now; - static int start_flag; - static double *cpu_start; - static double *cpu_second; - static string *name; - static string *class_name; - static int *calls; - -//========================================================== -// MEMBER FUNCTIONS : -// NAME : cpu_time(calculate time) -//========================================================== - static double cpu_time(); - static bool delete_flag; + private: + //========================================================== + // MEMBER VARIABLES : + // NAME : disabled(if disabled , timer can't work) + // NAME : n_clock(uplimit number of clock numbers) + // NAME : n_now(the index of clocks) + // NAME : start_flag + // NAME : cpu_start + // NAME : cput_second(record cpu time) + // NAME : name(record clock name) + // NAME : class_name(record another name for clock) + //========================================================== + static bool disabled; + static int n_clock; + static int n_now; + static int start_flag; + static double* cpu_start; + static double* cpu_second; + static std::string* name; + static std::string* class_name; + static int* calls; + //========================================================== + // MEMBER FUNCTIONS : + // NAME : cpu_time(calculate time) + //========================================================== + static double cpu_time(); + static bool delete_flag; }; #endif - diff --git a/tools/SIAB/SimulatedAnnealing/source/src_tools/vector3.h b/tools/SIAB/SimulatedAnnealing/source/src_tools/vector3.h index 945f117855f..f27d2b49e93 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_tools/vector3.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_tools/vector3.h @@ -11,227 +11,212 @@ #include #include #include -using namespace std; template -class Vector3 -{ -public: - T x; - T y; - T z; - Vector3(const T &x1 = 0,const T &y1 = 0,const T &z1 = 0); +class Vector3 { + public: + T x; + T y; + T z; + Vector3(const T& x1 = 0, const T& y1 = 0, const T& z1 = 0); - Vector3& operator=(const Vector3 &u); - Vector3& operator+=(const Vector3 &u); - Vector3& operator-=(const Vector3 &u); - Vector3& operator*=(const Vector3 &u); - Vector3& operator*=(const T &s); - Vector3& operator/=(const Vector3 &u); - Vector3& operator/=(const T &s); + Vector3& operator=(const Vector3& u); + Vector3& operator+=(const Vector3& u); + Vector3& operator-=(const Vector3& u); + Vector3& operator*=(const Vector3& u); + Vector3& operator*=(const T& s); + Vector3& operator/=(const Vector3& u); + Vector3& operator/=(const T& s); - void set(const T &x1, const T &y1,const T &z1); + void set(const T& x1, const T& y1, const T& z1); - inline T norm(void) const - { return sqrt(x*x + y*y + z*z); } + inline T norm(void) const { return std::sqrt(x * x + y * y + z * z); } - T norm2(void)const; - void normalize(void); - void reverse(void); + T norm2(void) const; + void normalize(void); + void reverse(void); - // mohan add 2009-11-29 - void print(void)const ; + // mohan add 2009-11-29 + void print(void) const; }; template -Vector3 operator+(const Vector3 &u,const Vector3 &v); +Vector3 operator+(const Vector3& u, const Vector3& v); template -Vector3 operator-(const Vector3 &u,const Vector3 &v); +Vector3 operator-(const Vector3& u, const Vector3& v); // | i j k | // | ux uy uz | // | vx vy vz | -//u.v=(uy*vz-uz*vy)i+(-ux*vz+uz*vx)j+(ux*vy-uy*vx)k +// u.v=(uy*vz-uz*vy)i+(-ux*vz+uz*vx)j+(ux*vy-uy*vx)k template -Vector3 operator^(const Vector3 &u,const Vector3 &v); -//u.v=(ux*vx)+(uy*vy)+(uz*vz) +Vector3 operator^(const Vector3& u, const Vector3& v); +// u.v=(ux*vx)+(uy*vy)+(uz*vz) template -T operator*(const Vector3 &u,const Vector3 &v); +T operator*(const Vector3& u, const Vector3& v); template -Vector3 operator*(const T &s,const Vector3 &u); +Vector3 operator*(const T& s, const Vector3& u); template -Vector3 operator/(const Vector3 &u,const T &s); +Vector3 operator/(const Vector3& u, const T& s); template -Vector3 cross(const Vector3 &u,const Vector3 &v); -//u.v=(ux*vx)+(uy*vy)+(uz*vz) +Vector3 cross(const Vector3& u, const Vector3& v); +// u.v=(ux*vx)+(uy*vy)+(uz*vz) template -T dot(const Vector3 &u,const Vector3 &v); -//template -//T TripleSalarProduct(Vector3 u, Vector3 v, Vector3 w); +T dot(const Vector3& u, const Vector3& v); +// template +// T TripleSalarProduct(Vector3 u, Vector3 v, Vector3 w); //========================================================== // Define Constructor //========================================================== template -Vector3::Vector3(const T &x1,const T &y1, const T &z1) -:x(x1),y(y1),z(z1) -{} +Vector3::Vector3(const T& x1, const T& y1, const T& z1) : x(x1), y(y1), z(z1) {} template -void Vector3::set(const T &x1,const T &y1,const T &z1) -{ - x = x1; y = y1; z = z1; +void Vector3::set(const T& x1, const T& y1, const T& z1) { + x = x1; + y = y1; + z = z1; } template -T Vector3::norm2(void)const -{ - return x*x + y*y + z*z; +T Vector3::norm2(void) const { + return x * x + y * y + z * z; } -//|v| = sqrt(x*x+y*y+z*z)=1 +//|v| = std::sqrt(x*x+y*y+z*z)=1 template -void Vector3::normalize(void) -{ - T m = sqrt(x*x + y*y + z*z); - x /= m;y /= m;z /= m; +void Vector3::normalize(void) { + T m = std::sqrt(x * x + y * y + z * z); + x /= m; + y /= m; + z /= m; } template -void Vector3::reverse(void) -{ - x = -x;y = -y;z = -z; +void Vector3::reverse(void) { + x = -x; + y = -y; + z = -z; } template -Vector3& Vector3::operator=(const Vector3 &u) -{ - x = u.x;y = u.y;z = u.z; - return *this; +Vector3& Vector3::operator=(const Vector3& u) { + x = u.x; + y = u.y; + z = u.z; + return *this; } template -Vector3& Vector3::operator+=(const Vector3 &u) -{ - x += u.x;y += u.y;z += u.z; - return *this; +Vector3& Vector3::operator+=(const Vector3& u) { + x += u.x; + y += u.y; + z += u.z; + return *this; } template -Vector3& Vector3::operator-=(const Vector3 &u) -{ - x -= u.x;y -= u.y;z -= u.z; - return *this; +Vector3& Vector3::operator-=(const Vector3& u) { + x -= u.x; + y -= u.y; + z -= u.z; + return *this; } template -Vector3& Vector3::operator*=(const T &s) -{ - x *= s;y *= s;z *= s; - return *this; +Vector3& Vector3::operator*=(const T& s) { + x *= s; + y *= s; + z *= s; + return *this; } template -Vector3& Vector3::operator/=(const T &s) -{ - x /= s;y /= s;z /= s; - return *this; +Vector3& Vector3::operator/=(const T& s) { + x /= s; + y /= s; + z /= s; + return *this; } template -Vector3 operator+(const Vector3 &u,const Vector3 &v) -{ - return Vector3(u.x + v.x, u.y + v.y, u.z + v.z); +Vector3 operator+(const Vector3& u, const Vector3& v) { + return Vector3(u.x + v.x, u.y + v.y, u.z + v.z); } template -Vector3 operator-(const Vector3 &u,const Vector3 &v) -{ - return Vector3(u.x - v.x, u.y - v.y, u.z - v.z); +Vector3 operator-(const Vector3& u, const Vector3& v) { + return Vector3(u.x - v.x, u.y - v.y, u.z - v.z); } -// u.v=(uy*vz-uz*vy)i+(-ux*vz+uz*vx)j+(ux*vy-uy*vzx)k +// u.v=(uy*vz-uz*vy)i+(-ux*vz+uz*vx)j+(ux*vy-uy*vzx)k template -Vector3 operator^(const Vector3 &u,const Vector3 &v) -{ - return Vector3 (u.y * v.z - u.z * v.y, - -u.x * v.z + u.z * v.x, - u.x * v.y - u.y * v.x); +Vector3 operator^(const Vector3& u, const Vector3& v) { + return Vector3(u.y * v.z - u.z * v.y, -u.x * v.z + u.z * v.x, u.x * v.y - u.y * v.x); } -//u.v=(ux*vx)+(uy*vy)+(uz*vz) +// u.v=(ux*vx)+(uy*vy)+(uz*vz) template -T operator*(const Vector3 &u,const Vector3 &v) -{ - return (u.x * v.x + u.y * v.y + u.z * v.z); +T operator*(const Vector3& u, const Vector3& v) { + return (u.x * v.x + u.y * v.y + u.z * v.z); } -template // mohan add 2009-5-10 -Vector3 operator*(const Vector3 &u, const T &s) -{ - return Vector3(u.x * s, u.y * s, u.z * s); +template // mohan add 2009-5-10 +Vector3 operator*(const Vector3& u, const T& s) { + return Vector3(u.x * s, u.y * s, u.z * s); } template -Vector3 operator*(const T &s,const Vector3 &u) -{ - return Vector3(u.x * s, u.y * s, u.z * s); +Vector3 operator*(const T& s, const Vector3& u) { + return Vector3(u.x * s, u.y * s, u.z * s); } template -Vector3 operator /(const Vector3 &u,const T &s) -{ - return Vector3(u.x / s, u.y / s, u.z / s); +Vector3 operator/(const Vector3& u, const T& s) { + return Vector3(u.x / s, u.y / s, u.z / s); } -// u.v=(uy*vz-uz*vy)i+(-ux*vz+uz*vx)j+(ux*vy-uy*vzx)k +// u.v=(uy*vz-uz*vy)i+(-ux*vz+uz*vx)j+(ux*vy-uy*vzx)k template -Vector3 cross(const Vector3 &u, const Vector3 &v) -{ - return Vector3 (u.y * v.z - u.z * v.y, - -u.x * v.z + u.z * v.x, - u.x * v.y - u.y * v.x); +Vector3 cross(const Vector3& u, const Vector3& v) { + return Vector3(u.y * v.z - u.z * v.y, -u.x * v.z + u.z * v.x, u.x * v.y - u.y * v.x); } template -T dot(const Vector3 &u,const Vector3 &v) -{ - return (u.x * v.x + u.y * v.y + u.z * v.z); +T dot(const Vector3& u, const Vector3& v) { + return (u.x * v.x + u.y * v.y + u.z * v.z); } -//whether u == v +// whether u == v template -bool operator ==(const Vector3 &u, const Vector3 &v) -{ - if(u.x == v.x && u.y == v.y && u.z == v.z) - { - return true; - } - return false; +bool operator==(const Vector3& u, const Vector3& v) { + if (u.x == v.x && u.y == v.y && u.z == v.z) { + return true; + } + return false; } -//whether m1 != m2 +// whether m1 != m2 template -bool operator !=(const Vector3 &u, const Vector3 &v) -{ +bool operator!=(const Vector3& u, const Vector3& v) { return !(u == v); } template -void Vector3::print(void)const -{ - cout.precision(5) ; - cout << "(" << setw(10) << x << "," << setw(10) << y << "," - << setw(10) << z << ")" << endl ; - return ; +void Vector3::print(void) const { + std::cout.precision(5); + std::cout << "(" << std::setw(10) << x << "," << std::setw(10) << y << "," << std::setw(10) << z << ")" + << std::endl; + return; } -//s = u.(v x w) -//template -//T TripleScalarProduct(Vector3 u, Vector3 v, Vector3 w) +// s = u.(v x w) +// template +// T TripleScalarProduct(Vector3 u, Vector3 v, Vector3 w) //{ -// return T((u.x * (v.y * w.z - v.z * w.y)) + -// (u.y * (-v.x * w.z + v.z * w.x)) + -// (u.z * (v.x * w.y - v.y * w.x))); -//} +// return T((u.x * (v.y * w.z - v.z * w.y)) + +// (u.y * (-v.x * w.z + v.z * w.x)) + +// (u.z * (v.x * w.y - v.y * w.x))); +// } #endif diff --git a/tools/SIAB/SimulatedAnnealing/source/src_unittest/src_tools/common_test.h b/tools/SIAB/SimulatedAnnealing/source/src_unittest/src_tools/common_test.h index 67e3c09bdab..954bb7e5c12 100644 --- a/tools/SIAB/SimulatedAnnealing/source/src_unittest/src_tools/common_test.h +++ b/tools/SIAB/SimulatedAnnealing/source/src_unittest/src_tools/common_test.h @@ -1,56 +1,49 @@ #ifndef COMMON_TEST #define COMMON_TEST -#include -#include -#include +#include +#include +#include using std::cout; using std::endl; -#include +#include extern double sum_t; // gettimeofday( &time_now, NULL); -inline double get_time(const timeval &begin, const timeval &end) -{ - return (double)(end.tv_sec-begin.tv_sec) + (double)(end.tv_usec-begin.tv_usec)/1000000.0; +inline double get_time(const timeval& begin, const timeval& end) { + return (double)(end.tv_sec - begin.tv_sec) + (double)(end.tv_usec - begin.tv_usec) / 1000000.0; } -inline void cout_matrix( const ComplexMatrix &matrix) -{ - cout<< std::setprecision(10)<< std::setiosflags(ios::fixed); - const size_t nr(matrix.nr), nc(matrix.nc); - for(size_t i(0); i -1 // if or not calculate the spillage. 1/0 -0 // restart from file or not. 1/0 -0 // if or not output the file. 1/0 -1 // number of structures. +1 // if or not calculate the spillage. 1/0 +0 // restart from file or not. 1/0 +0 // if or not output the file. 1/0 +1 // number of structures. /home/mohan/3_my_program/1_MCSP/GaAs.10.5.dat_haha -8 //number of kpoints. -1 //number of pools. +8 //number of kpoints. +1 //number of pools. @@ -16,49 +16,49 @@ -2 //1:max 2:average +2 //1:max 2:average -1.0e-9 // Init temparature for spillage -0.5 // Cooling rate -1 // Number of temperatures(spillage) -0 // Number of temperatures(kinetical) -100 // Number of steps per temparature -0.005 // Delta kappa -5 // Selectly output information -100 // Acceptance_steps -0.4 // Acceptance_high -0.2 // Acceptance_low -100 // Max kinetic energy(Rydberg). -0.01 // 'dr' for kinetic minimized. -1 // 1: Kin 2: Ecut +1.0e-9 // Init temparature for spillage +0.5 // Cooling rate +1 // Number of temperatures(spillage) +0 // Number of temperatures(kinetical) +100 // Number of steps per temparature +0.005 // Delta kappa +5 // Selectly output information +100 // Acceptance_steps +0.4 // Acceptance_high +0.2 // Acceptance_low +100 // Max kinetic energy(Rydberg). +0.01 // 'dr' for kinetic minimized. +1 // 1: Kin 2: Ecut -0 // to control the number of bands.(Yes1/No0) -3 // int, the start band index(>0). -4 // int, the ed band index(0). +4 // int, the ed band index( -2 // Number of levels. +2 // Number of levels. # label / na / skip / lmax / each L / 31 1 new 2 0 1 1 -33 1 new 2 0 1 1 +33 1 new 2 0 1 1 31 1 new 1 1 1 -33 1 new 1 1 1 +33 1 new 1 1 1 -0.005 //dr(a.u.) of uniform mesh. Attention!!dr will affect kinetic energy minmized largely. --6 //xmin -1 //zed, chosen as valence charge. -0.01 //dx -6.0 //xmax +0.005 //dr(a.u.) of uniform mesh. Attention!!dr will affect kinetic energy minmized largely. +-6 //xmin +1 //zed, chosen as valence charge. +0.01 //dx +6.0 //xmax @@ -71,9 +71,9 @@ -0 // 'yes' to do this. -14.0 // rcut, only useful for test program -0.01 // dr, for simpson integral -2 // test eigenvalue index -2 // lmax +0 // 'yes' to do this. +14.0 // rcut, only useful for test program +0.01 // dr, for simpson integral +2 // test eigenvalue index +2 // lmax diff --git a/tools/SIAB/SimulatedAnnealing/source/tests_s/INPUT b/tools/SIAB/SimulatedAnnealing/source/tests_s/INPUT index 3f6fb190e02..08e3e69e724 100644 --- a/tools/SIAB/SimulatedAnnealing/source/tests_s/INPUT +++ b/tools/SIAB/SimulatedAnnealing/source/tests_s/INPUT @@ -2,13 +2,13 @@ 1 // if or not calculate the spillage. 1/0 0 // restart or not. 1/0 1 // if or not output the file. 1/0 -1 // number of structures. +1 // number of structures. H-6-0.6.15.dat 1 //number of k points -1 // number of pools +1 // number of pools @@ -25,8 +25,8 @@ H-6-0.6.15.dat 2 // Number of temperatures(spillage) 500 // Number of steps per temparature -1.0e-2 // start temperature for kinetic energy -0.8 // Cooling rate +1.0e-2 // start temperature for kinetic energy +0.8 // Cooling rate 1 // Number of temperatures(kinetical) 100 // Number of steps per temparature diff --git a/tools/average_pot/aveElecStatPot.py b/tools/average_pot/aveElecStatPot.py index 60bc1804ac4..72e56a6e5dd 100644 --- a/tools/average_pot/aveElecStatPot.py +++ b/tools/average_pot/aveElecStatPot.py @@ -17,15 +17,15 @@ if os.path.isdir(dir_path) and dir_name.startswith("OUT."): input_file = os.path.join(dir_path, "ElecStaticPot.cube") output_file = os.path.join(dir_path, "ElecStaticPot_AVE") - output_png = os.path.join(dir_path, "ElecStaticPot-vs-Z.png") + output_png = os.path.join(dir_path, "ElecStaticPot-vs-Z.png") if os.path.exists(input_file): print(f"Processeding: {input_file}") break else: print(f"File does not exist: {input_file}") sys.exit() - -with open(input_file, 'r') as inpt: + +with open(input_file, "r") as inpt: temp = inpt.readlines() Ry_to_eV = 13.605698066819 @@ -40,7 +40,8 @@ z_Ang = np.arange(nz) * step_z nrow = nz // 6 -if nz % 6 != 0: nrow += 1 +if nz % 6 != 0: + nrow += 1 data_start = 6 + natom average = np.zeros(nz) @@ -57,27 +58,31 @@ average_eV = average * Ry_to_eV -with open(output_file, 'w') as output: +with open(output_file, "w") as output: output.write("Average electrostatic potential along z axis\n") for i in range(1, data_start): output.write(temp[i]) - + output.write("iz\t\t Average(Ry)\t\t z(Angstrom)\t\t Average(eV)\n") for iz in range(nz): - output.write("{:<7d}\t{:>16.9e}\t{:>16.9e}\t{:>16.9e}\n".format(iz, average[iz], z_Ang[iz], average_eV[iz])) + output.write( + "{:<7d}\t{:>16.9e}\t{:>16.9e}\t{:>16.9e}\n".format( + iz, average[iz], z_Ang[iz], average_eV[iz] + ) + ) z_values = z_Ang -interpolation_func = interp1d(z_values, average_eV, kind='cubic') +interpolation_func = interp1d(z_values, average_eV, kind="cubic") z_interpolated = np.linspace(z_values.min(), z_values.max(), nz * 5) average_interpolated = interpolation_func(z_interpolated) -plt.figure(figsize=(4.5, 8)) +plt.figure(figsize=(4.5, 8)) plt.plot(average_interpolated, z_interpolated) -plt.xlabel('Average Electrostatic Potential (eV)') -plt.ylabel('Z axis (Angstrom)') -plt.title('Average Electrostatic Potential along Z') +plt.xlabel("Average Electrostatic Potential (eV)") +plt.ylabel("Z axis (Angstrom)") +plt.title("Average Electrostatic Potential along Z") plt.grid(True) plt.savefig(output_png, dpi=300) diff --git a/tools/generate_orbital.sh b/tools/generate_orbital.sh deleted file mode 120000 index 40e6684d85a..00000000000 --- a/tools/generate_orbital.sh +++ /dev/null @@ -1 +0,0 @@ -SIAB/Generate_Orbital_AllInOne.sh \ No newline at end of file diff --git a/tools/generate_orbital.sh b/tools/generate_orbital.sh new file mode 100755 index 00000000000..35ecc9401aa --- /dev/null +++ b/tools/generate_orbital.sh @@ -0,0 +1,1251 @@ +#!/bin/bash +# author mohan +# edit by Pengfei Li 2013-6-4 +# maintained by WenShuai Zhang (since 2016-11-30) with changelog: +# 1. fix bugs when reading "ORBITAL_INPUT" for lines begin with "#" or " ". +# 2. add support for generating orbital with multi different types of structures together, +# such as dimer STRU & tetramer STRU and so on. +# 3. add support for opt_orb_pytorch_dpsi generator + +args=$@ +if [ "$args" == "--help" -o "$args" == "-h" ] ; then + echo " Usage: ./ThisScript.sh " + echo " Example: ./generate_orbital.sh ORBITAL_INPUT_MixSTRU " + echo " If no , This script will use the default name for input file: ORBITAL_INPUT " + echo " " + exit +elif [ ! -z $1 ] && [ -f $1 ] ; then + InputFile=$1 +elif [ -f 'ORBITAL_INPUT' ] ; then + echo " Can't find specified input file, use default: ORBITAL_INPUT " + InputFile="ORBITAL_INPUT" +else + echo " Can't find specified input file or default file: ORBITAL_INPUT" + echo " see help by '-h' " + echo " " + exit +fi +if [ -z $InputFile ]; then + echo " Can't find input file" + exit; +fi +# +echo " " +echo " ********************************************************* " +echo " * * " +echo " * Start to Generate Orbital for LCAO * " +echo " * * " +echo " ********************************************************* " + +function completelyNewCalc(){ + echo " " + echo " Completely New SIA Calculation ... " + mkdir -p Old + if ( test -f "ORBITAL_RESULTS.txt" ); then + echo " Move Old Orbital files: ORBITAL_RESULTS.txt to Old/" + mv "ORBITAL_RESULTS.txt" Old/ + echo " Move Old INPUT files: INPUT to Old/" + mv "INPUT" Old/ + fi +} + +time_start=`date +%s` +#----------------------------------------------------------------- +# +# (0.0) fixed parameters +# +#----------------------------------------------------------------- +mass=1 #not used yet. +lat0=20 #in a.u + + +echo " InputFile = $InputFile" +#----------------------------------------------------------------- +# (0.0) get EXE_mpi +#----------------------------------------------------------------- +EXE_mpi=`grep -E "^\s*EXE_mpi" $InputFile | awk -F "EXE_mpi" '{print $2}' ` +EXE_mpi=`echo $EXE_mpi` +if [ -z "$EXE_mpi" ]; then + cpu_num=8 + hostfpath="myhosts" + #hostfpath="/home/nic/wszhang/eclipse_project/mesia_dft/delta_test/delta_dft/cifs2deltaDFT/myhosts" + grep slots $hostfpath > /dev/null + if [ $? = 0 ] ; then # has "slots" in file: $hostfpath + cpu_num=`cat $hostfpath |cut -d "=" -f 2-3|awk '{sum += $1};END {print sum}'` + else + cpu_num=`cat $hostfpath |wc -l` + fi + echo " cpu_num = $cpu_num" + echo " hostfpath = $hostfpath" + EXE_mpi="mpirun -np $cpu_num -hostfile ../$hostfpath " +fi +echo " EXE_mpi = $EXE_mpi " +Host_List=( `$EXE_mpi hostname 2>/dev/null` ) +Host1_List=( `echo ${Host_List[@]} | grep -o "$Host_List"` ) +Host1_NCore=${#Host1_List[@]} +echo " Host1_NCore = $Host1_NCore" +if [ $Host1_NCore -lt 1 ]; then + echo " error at getting Host1_NCore, program exiting ... " + exit 1 +fi + + +#----------------------------------------------------------------- +# (0.1) input parameters +#----------------------------------------------------------------- + +# (0.1.1) get exe +EXE_pw=`grep -E "^\s*EXE_pw" $InputFile | awk -F "EXE_pw" '{print $0}' | awk '{print $2}'` +echo " EXE_pw = $EXE_pw " + +# (0.1.2)get SIA +EXE_orbital=`grep -E "^\s*EXE_orbital" $InputFile | awk -F "EXE_orbital" '{print $0}' | awk '{print $2}'` +chmod +x "$EXE_orbital" + + +# (0.1.3)get the targets element and id +targets=`grep -E "^\s*targets" $InputFile | awk -F "targets" '{print $0}' | awk '{print $2}'` +echo " targets = $targets" + + + +#----------------------------------------------------------------- +# (1) big cicle, cicle of targets +#----------------------------------------------------------------- +for name in $targets; +do + +#echo "name=$name" +element=`echo "$name" | awk -F "_" '{print $2}'` +#echo "element=$element" +id=`echo "$name" | awk -F "_" '{print $1}'` +#echo "id=$id" + +# (0.1.6)get the pseudo_dir +Pseudo_dir=`grep -E "^\s*Pseudo_dir" $InputFile | awk -F "Pseudo_dir" '{print $0}' | awk '{print $2}'` +echo " Pseudo_dir = $Pseudo_dir " + +# (0.1.12) get the ecut +ecut=`grep -E "^\s*Ecut" $InputFile | awk -F "Ecut" '{print $0}' | awk '{print $2}'` +echo " ecut = $ecut" + +# (0.1.13) get the info about rcut,pseudo +#info_r=`grep -E "^\s*Rcut" $InputFile | awk -F "Rcut" '{print $0}' | awk '{print $2}'` +#rcut_number=`echo "$info_r" | awk '// {print NF}'` +info_r=( `grep -E "^\s*Rcut" $InputFile | awk -F "Rcut|#" '{print $2 }'` ) +rcut_number=${#info_r[@]} +echo " rcut_number = $rcut_number, info_r = ( ${info_r[@]} )" + +# (0.1.14) get the pseudopotential +pseudofile=`grep -E "^\s*Pseudo " $InputFile | awk -F "Pseudo " '{print $0}' | awk '{print $2}'` +echo " Pseudo = $pseudofile" + +# (0.1.15) get the smearing +smearing_sigma=`grep -E "^\s*smearing_sigma " $InputFile | awk -F "smearing_sigma " '{print $0}' | awk '{print $2}'` +echo " smearing_sigma = $smearing_sigma" + + +# +# (0.1.7)get maxL S P D +maxL=`grep -E "^\s*maxL" $InputFile | awk -F "maxL" '{print $0}' | awk '{print $2}'` + +#if ( test $maxL = 0 ) // mohan's scheme +#then +#S_MIN=1 +#P_MIN=" " +#D_MIN=" " +#elif ( test $maxL = 1 ) +#then +#S_MIN=1 +#P_MIN=1 +#D_MIN=" " +#else +#S_MIN=1 +#P_MIN=1 +#D_MIN=1 +#fi + + +# (0.x.x) check info (include Level) for each STRU +nSTRU=`grep -E "^\s*BLSTRU" $InputFile | wc -l` +#nSTRU=`grep -o "^\s*ListSTRU\s*[^#]*" W/ORBITAL_INPUT_DZP |wc -w |awk '{print $1-1}'` +if [[ "$nSTRU" == "0" ]] ; then + nSTRU=`grep -E "^\s*Dis" $InputFile | wc -l` + if [ "$nSTRU" != "1" ]; then + echo "error: input file has more than one line for Dis argument, please use the BLSTRU* " + fi +fi +echo " nSTRU = $nSTRU" +# +LevelBegin[0]=0 +EndLevel[0]=0 +SkipSTRU[0]=0 +RestartSTRU[0]=0 +ListSTRU[0]=" " +for((iSTRU=1;iSTRU<=$nSTRU;iSTRU++)) +do + ListSTRU[iSTRU]=`grep -E "^\s*ListSTRU " $InputFile |awk -F "ListSTRU" '{print $0}' \\ + |awk -v iSTRU=$iSTRU '{print $(iSTRU+1) }'` + ListSTRU[iSTRU]=${ListSTRU[iSTRU]:-dimer} + echo " STRU[$iSTRU] = ${ListSTRU[iSTRU]}" + + + BLSTRU[iSTRU]=`grep -E "^\s*BLSTRU$iSTRU" $InputFile | awk -F "BLSTRU$iSTRU" '{print $2}'` + if [[ -z "${BLSTRU[iSTRU]}" ]] && [[ "$iSTRU=1" ]] ; then + BLSTRU[iSTRU]=`grep -E "^\s*Dis" $InputFile | awk -F "Dis" '{print $2}'` + fi + BL_number[iSTRU]=`echo "${BLSTRU[iSTRU]}" | awk '// {print NF}'` + # (0.1.11) calculate the number of different dimers or trimers. + #BLSTRU=`grep "Dis1" $InputFile | awk -F "Dis1" '{print $2}'` + #BL_number=`echo "$BLSTRU" | awk '// {print NF}'` + echo " BL_number[$iSTRU] = ${BL_number[iSTRU]}" + echo " BLSTRU[$iSTRU] =" ${BLSTRU[iSTRU]} " :Bond Length for each STRU" + + EndLevel[iSTRU]=`grep -E "^\s*Level" $InputFile |awk -F "Level" '{print $0}' \\ + |awk -v iSTRU=$iSTRU '{print $(iSTRU+1) }'` + echo " EndLevel[$iSTRU] = ${EndLevel[iSTRU]}" + BeginLevel[iSTRU]=`grep -E "^\s*BeginLevel" $InputFile |awk -F "BeginLevel" '{print $0}' \\ + |awk -v iSTRU=$iSTRU '{print $(iSTRU+1) }'` + echo " BeginLevel[$iSTRU] = ${BeginLevel[iSTRU]:-auto/default}" + + # (0.1.4)get the nbands + nbands[iSTRU]=`grep -E "^\s*nbands" $InputFile | awk -F "nbands" '{print $0}' \\ + |awk -v iSTRU=$iSTRU '{print $(iSTRU+1) }'` + echo " nbands[$iSTRU] = ${nbands[iSTRU]}" + + # (0.1.5)get the ref_bands + ref_bands[iSTRU]=`grep -E "^\s*ref_bands" $InputFile | awk -F "$ref_bands" '{print $0}' \\ + |awk -v iSTRU=$iSTRU '{print $(iSTRU+1) }'` + echo " ref_bands[$iSTRU] = ${ref_bands[iSTRU]}" + + RestartSTRU[iSTRU]=`grep -E "^\s*RestartSTRU" $InputFile \\ + | awk -F "$RestartSTRU" '{print $0}' \\ + | awk -v iSTRU=$iSTRU '{print $(iSTRU+1) }'` + echo " RestartSTRU[$iSTRU] = ${RestartSTRU[iSTRU]:-auto/default}" + #if [ ! -n "${RestartSTRU[iSTRU]}" ]; then + # RestartSTRU[iSTRU]=0 + # echo " set RestartSTRU[$iSTRU]=0 " + #fi + + + SkipSTRU[iSTRU]=0 + if ( test -n "`grep -E "^\s*SkipSTRU" $InputFile`" ); then + SkipSTRU[iSTRU]=`grep -E "^\s*SkipSTRU" $InputFile \\ + | awk -F "$SkipSTRU" '{print $0}' \\ + | awk -v iSTRU=$iSTRU '{print $(iSTRU+1) }'` + fi + echo " SkipSTRU[$iSTRU] = ${SkipSTRU[iSTRU]}" + +done # first cicle of iSTRU +if [ "$nSTRU" == "1" ]; then + SkipSTRU[1]=0 +fi + +# (0.1.8)get the level +#Level=`grep "Level" $InputFile | awk -F "level" '{print $0}' | awk '{print $2}'` +#echo "__Level=$Level" + + +# (0.1.9)get every level`s lmax s p d f g +Llevels[1]=`grep -E "^\s*level1" $InputFile | awk -F "level1" '{print $2}'` +Llevels[2]=`grep -E "^\s*level2" $InputFile | awk -F "level2" '{print $2}'` +Llevels[3]=`grep -E "^\s*level3" $InputFile | awk -F "level3" '{print $2}'` +Llevels[4]=`grep -E "^\s*level4" $InputFile | awk -F "level4" '{print $2}'` +Llevels[5]=`grep -E "^\s*level5" $InputFile | awk -F "level5" '{print $2}'` +Llevels[6]=`grep -E "^\s*level6" $InputFile | awk -F "level6" '{print $2}'` +Llevels[7]=`grep -E "^\s*level7" $InputFile | awk -F "level7" '{print $2}'` +Llevels[8]=`grep -E "^\s*level8" $InputFile | awk -F "level8" '{print $2}'` +Llevels[9]=`grep -E "^\s*level9" $InputFile | awk -F "level9" '{print $2}'` + + +# (0.1.10)get some parameters for METROPOLIS +Start_tem_S_in=`grep -E "^\s*Start_tem_S" $InputFile \\ + | awk -F "Start_tem_S" '{print $0}' | awk '{print $2}'` +if ( test $Start_tem_S_in != " ") +then +Start_tem_S=$Start_tem_S_in +else +Start_tem_S=1.0e-4 #default +fi + + +Start_tem_K_in=`grep -E "^\s*Start_tem_K" $InputFile \\ + | awk -F "Start_tem_K" '{print $0}' | awk '{print $2}'` +if ( test $Start_tem_K_in != " " ) +then +Start_tem_K=$Start_tem_K_in +else +Start_tem_K=1.0e-2 #default +fi + +Step_S_in=`grep -E "^\s*Step_S" $InputFile \\ + | awk -F "Step_S" '{print $0}' | awk '{print $2}'` +if ( test $Step_S_in != " " ) +then +Step_S=$Step_S_in +else +Step_S=30 #default +fi + +Step_K_in=`grep -E "^\s*Step_K" $InputFile \\ + | awk -F "Step_K" '{print $0}' | awk '{print $2}'` +if ( test $Step_K_in != " ") +then +Step_K=$Step_K_in +else +Step_K=20 #default +fi + +Delta_kappa_in=`grep -E "^\s*Delta_kappa" $InputFile \\ + | awk -F "Delta_kappa" '{print $0}' | awk '{print $2}'` +Delta_kappa=$Delta_kappa_in +#echo " Delta_kappa=$Delta_kappa" + + + +# (1.1) output which element you want to calculate +echo " -------------------------------------------------------> $element" + +# (1.2) make the dir, the name is 'name' +if ( test -d $name ) +then + echo " The dir exist: $name" +else + echo " Make dir: $name" + mkdir $name +fi + +# (1.3) enter the name dir +cd $name + +## (1.4) another big cicle come: the rcut cicle. +count_r=1 +while [ $count_r -le $rcut_number ] +do + ### (1.4.1) + #rcut=`echo "$info_r" | awk '{print $'$count_r'}' ` + rcut=${info_r[count_r-1]} + echo " |run cicle: rcut=$rcut" + + + + ### (1.4.1.5) enter the third big cicle: iSTRU + echo " nSTRU = $nSTRU " + for((iSTRU=1;iSTRU<=$nSTRU;iSTRU++)) + do + if ( test ${SkipSTRU[iSTRU]} -eq 1 ); then + echo " |skip cicle: iSTRU=$iSTRU" + continue; + fi + echo " |run cicle: iSTRU=$iSTRU" + + + + ### (1.4.3) mkdir of rcut + test -d $rcut || mkdir $rcut + # (1.4.3.1) + cd $rcut + + iSTRULeft=`expr $iSTRU \- 1` + if [ "${BeginLevel[iSTRU]}" == "" ] ; then + BeginLevel[$iSTRU]=$((${EndLevel[iSTRULeft]}+1)) + echo -e "\n not found BeginLevel[$iSTRU], use: EndLevel[iSTRULeft]+1" + fi + echo -e "\n BeginLevel[iSTRU]=${BeginLevel[iSTRU]}, EndLevel[iSTRU]=${EndLevel[iSTRU]} " + + + + ### set if restart from previous SIA runs + ### if ( test SkipSTRU[`expr $iSTRU - 1`] -eq 1 ) ; then + #ifRestart=${RestartSTRU[$iSTRU]} + if [ "${RestartSTRU[$iSTRU]}" == "" ] ; then + if [ $iSTRU -gt 1 ] ; then + RestartSTRU[$iSTRU]=1 + else + RestartSTRU[$iSTRU]=0 + fi + fi + + + echo " RestartSTRU[$iSTRU] = ${RestartSTRU[$iSTRU]} " + if [ ${RestartSTRU[$iSTRU]} -eq 0 ] ; then + completelyNewCalc + else + if [ $iSTRU -gt 1 ]; then + + echo " " + echo " Current *.dat/*.txt ... will be considered previous calculation results of STRU${iSTRULeft} " + # + #if [ -f "ORBITAL_RESULTS.txt" ] ; then + # echo " Found file: ORBITAL_RESULTS.txt, continue ... " + #else + # echo " Can't find: ORBITAL_RESULTS.txt, exiting ... " + # exit + #fi + # + # + if [ ! -f "STRU${iSTRULeft}.ORBITAL_RESULTS.txt" ]; then + echo " Move Previous Orbital files and Rename as STRU${iSTRULeft}.*" + # + if ( test -f "ORBITAL_RESULTS.txt" ); then + mv "ORBITAL_RESULTS.txt" "STRU${iSTRULeft}.ORBITAL_RESULTS.txt" + fi + # + if ( test -f "INPUT" ); then + mv "INPUT" "STRU${iSTRULeft}.INPUT" + fi + # + if ( test -f "ORBITAL_${id}U.dat" ); then + mv "ORBITAL_${id}U.dat" "STRU${iSTRULeft}.ORBITAL_${id}U.dat" + fi + # + if ( test -f "ORBITAL_${id}L.dat" ); then + mv "ORBITAL_${id}L.dat" "STRU${iSTRULeft}.ORBITAL_${id}L.dat" + fi + # + if ( test -f "ORBITAL_ECUT.txt" ); then + mv "ORBITAL_ECUT.txt" "STRU${iSTRULeft}.ORBITAL_ECUT.txt" + fi + # + if ( test -f "ORBITAL_KINETIC.txt" ); then + mv "ORBITAL_KINETIC.txt" "STRU${iSTRULeft}.ORBITAL_KINETIC.txt" + fi + # + if ( test -f "ORBITAL_PLOTL.dat" ); then + mv "ORBITAL_PLOTL.dat" "STRU${iSTRULeft}.ORBITAL_PLOTL.dat" + fi + # + if ( test -f "ORBITAL_PLOTU.dat" ); then + mv "ORBITAL_PLOTU.dat" "STRU${iSTRULeft}.ORBITAL_PLOTU.dat" + fi + # + if ( test -f "ORBITAL_PLOTUK.dat" ); then + mv "ORBITAL_PLOTUK.dat" "STRU${iSTRULeft}.ORBITAL_PLOTUK.dat" + fi + # + if ( test -f "running_1.txt" ); then + mv "running_1.txt" "STRU${iSTRULeft}.running_1.txt" + fi + # + fi + # + if [ -f "STRU${iSTRULeft}.ORBITAL_RESULTS.txt" ] ; then + echo " Found file: STRU${iSTRULeft}.ORBITAL_RESULTS.txt, copy as ORBITAL_RESULTS.txt ... " + cp -ap "STRU${iSTRULeft}.ORBITAL_RESULTS.txt" "ORBITAL_RESULTS.txt" + else + echo " Not found file: STRU${iSTRULeft}.ORBITAL_RESULTS.txt, exiting ... " + exit + fi + else + echo " Current *.dat/*.txt ... will be considered previous calc. results of STRU${iSTRU} " + echo " Before SIA Calculation: mv ... & cp ... " + echo " Move: INPUT/*.dat/*.txt to Old/ " + mkdir -p Old + # + if ( test -f "INPUT" ); then + mv "INPUT" "Old/INPUT" + fi + if ( test -f "ORBITAL_${id}U.dat" ); then + mv "ORBITAL_${id}U.dat" "Old/ORBITAL_${id}U.dat" + fi + if ( test -f "ORBITAL_${id}L.dat" ); then + mv "ORBITAL_${id}L.dat" "Old/ORBITAL_${id}L.dat" + fi + if ( test -f "ORBITAL_ECUT.txt" ); then + mv "ORBITAL_ECUT.txt" "Old/ORBITAL_ECUT.txt" + fi + if ( test -f "ORBITAL_KINETIC.txt" ); then + mv "ORBITAL_KINETIC.txt" "Old/ORBITAL_KINETIC.txt" + fi + if ( test -f "ORBITAL_PLOTL.dat" ); then + mv "ORBITAL_PLOTL.dat" "Old/ORBITAL_PLOTL.dat" + fi + if ( test -f "ORBITAL_PLOTU.dat" ); then + mv "ORBITAL_PLOTU.dat" "Old/ORBITAL_PLOTU.dat" + fi + if ( test -f "ORBITAL_PLOTUK.dat" ); then + mv "ORBITAL_PLOTUK.dat" "Old/ORBITAL_PLOTUK.dat" + fi + if ( test -f "running_1.txt" ); then + mv "running_1.txt" "Old/running_1.txt" + fi + # + echo " Copy ORBITAL_RESULTS.txt to Old/ " + if ( test -f "ORBITAL_RESULTS.txt" ); then + cp -avp "ORBITAL_RESULTS.txt" "Old/ORBITAL_RESULTS.txt" + fi + # + echo " Start (SIA) Calculation:" + fi + echo " " + echo " Restart from Previous Result: ORBITAL_RESULTS.txt " + if [ -f "ORBITAL_RESULTS.txt" ] ; then + echo " Found file: ORBITAL_RESULTS.txt " + else + echo " Not found file: ORBITAL_RESULTS.txt, exiting ... " + exit + fi + fi # which:: if [ ${RestartSTRU[$iSTRU]} -eq 0 ] ; then + echo " " + + + + ### (1.4.3.5) exit the rcut dir + cd .. + + + + #### (1.4.2) enter the forth big cicle : Bond Length. + count=1 + while [ $count -le ${BL_number[iSTRU]} ] + do + + # (1.4.2.0) calculate the Bond Length for iSTRU + BL=`echo "${BLSTRU[iSTRU]}" | awk '{print $'$count'}' ` + dis1=$(echo "scale=5;$BL * 0.86603 "|bc) + dis2=$(echo "scale=5;$BL * 0.5 "|bc) + dis3=$(echo "scale=5;$BL * 0.81649 "|bc) + dis4=$(echo "scale=5;$BL * 0.28867 "|bc) + echo " |run cicle: BL=$BL" + +if [ "${ListSTRU[iSTRU]}" == "dimer" ]; then +na=2 +cat > $name.stru << EOF +ATOMIC_SPECIES +$element $mass $pseudofile +LATTICE_CONSTANT +$lat0 // add lattice constant(a.u.) +LATTICE_VECTORS +1 0 0 +0 1 0 +0 0 1 +ATOMIC_POSITIONS +Cartesian_angstrom //Cartesian or Direct coordinate. +$element //Element Label +0.0 //starting magnetism +2 //number of atoms +0.0 0.0 0.0 0 0 0 // crystal coor. +0.0 0.0 $BL 0 0 0 +EOF + +elif [ "${ListSTRU[iSTRU]}" == "trimer" ]; then +na=3 +cat > $name.stru << EOF +ATOMIC_SPECIES +$element $mass $pseudofile +LATTICE_CONSTANT +$lat0 // add lattice constant(a.u.) +LATTICE_VECTORS +1 0 0 +0 1 0 +0 0 1 +ATOMIC_POSITIONS +Cartesian_angstrom //Cartesian or Direct coordinate. +$element //Element Label +0.0 //starting magnetism +3 //number of atoms +0.0 0.0 0.0 0 0 0 // crystal coor. +0.0 0.0 $BL 0 0 0 +0.0 $dis1 $dis2 0 0 0 +EOF + +elif [ "${ListSTRU[iSTRU]}" == "tetramer" ]; then +na=4 +cat > $name.stru << EOF +ATOMIC_SPECIES +$element $mass $pseudofile +LATTICE_CONSTANT +$lat0 // add lattice constant(a.u.) +LATTICE_VECTORS +1 0 0 +0 1 0 +0 0 1 +ATOMIC_POSITIONS +Cartesian_angstrom //Cartesian or Direct coordinate. +$element //Element Label +0.0 //starting magnetism +4 //number of atoms +0.0 0.0 0.0 0 0 0 // crystal coor. +0.0 0.0 $BL 0 0 0 +0.0 $dis1 $dis2 0 0 0 +$dis3 $dis4 $dis2 0 0 0 +EOF + +fi +echo " na=$na" + + +# (1.4.2.2) get KPOINTS +cat > KPOINTS << EOF +K_POINTS +0 +Gamma +1 1 1 0 0 0 +EOF + +# (1.4.2.3) get INPUTw +cat > INPUTw << EOF +WANNIER_PARAMETERS +rcut 10 +out_spillage 2 +spillage_outdir OUT.$element-$rcut-$BL +EOF + + +# (1.4.2.4) get INPUTs +# cat > INPUTs << EOF +# INPUT_ORBITAL_INFORMATION +# +# 1 // smooth or not +# 0.1 // smearing_sigma +# $ecut // energy cutoff for spherical bessel functions(Ry) +# $rcut // cutoff of wavefunctions(a.u.) +# 1.0e-12 // tolerence +# +# EOF + + +# (1.4.2.5) get INPUT +cat > INPUT << EOF +INPUT_PARAMETERS +suffix $element-$rcut-$BL +stru_file $name.stru +pseudo_dir $Pseudo_dir +kpoint_file KPOINTS +calculation scf +ntype 1 +nspin 1 +lmaxmax $maxL +bessel_nao_rcut $rcut + +symmetry 0 +nbands ${nbands[iSTRU]} + +ecutwfc $ecut +scf_thr 1e-7 // about iteration +scf_nmax 1500 + +smearing_method gauss +smearing_sigma $smearing_sigma + +mixing_type pulay // about charge mixing +mixing_beta 0.4 +mixing_ndim 8 +printe 1 +EOF + +let count++ + + echo " pwd:" + pwd + if [ ${RestartSTRU[$iSTRU]} -eq 2 ]; then # grep -E "^\s*RestartSTRU" ../$InputFile > /dev/null 2>&1 ; then + echo " Skip_Calculation: $EXE_mpi $EXE_pw" + else + # (1.4.2.6) + #test -e ../node_openmpi && cp ../node_openmpi . + #------------- + #on Dirac + #------------- + #/opt/openmpi/bin/mpirun -np $cpu_number -machinefile node_openmpi $exe + #------------- + #on Einstein + #------------- + #mpiexec -np $cpu_num -machinefile node_openmpi $EXE_pw + #mpiexec -np $1 -machinefile $EXE_pw + + #exit + #mpiexec -n 12 -machinefile $PBS_NODEFILE $EXE_pw >> Log.txt + #mpirun -np $cpu_num $EXE_pw + #mpirun -hostfile "../$hostfpath" $EXE_pw + #mpirun -np $cpu_num -hostfile "../$hostfpath" $EXE_pw + + echo " $EXE_mpi $EXE_pw " + $EXE_mpi $EXE_pw + + #mv test.0.dat OUT.$element-$rcut-$BL/orb_matrix.0.dat + #mv test.1.dat OUT.$element-$rcut-$BL/orb_matrix.1.dat + #echo " Skip_Calculation: $EXE_mpi $EXE_pw" + fi + echo "" + + + + #### end cicle (1.4.2): Bond Length + done + + + + # (1.4.3.1) + cd $rcut + + + + ###if [ "${EXE_orbital##*.}" != "py" ]; + if [ "${EXE_orbital:0-3:3}" != ".py" ]; + then + echo -e " Using Simulated Annealing Method \n" + + ### (1.4.3.2) prepare for the INPUT file +cat > INPUT << EOF + +1 // if or not calculate the spillage. 1/0 +$(( ${RestartSTRU[$iSTRU]} > 0 )) // restart or not. 1/0 +1 // if or not output the file. 1/0 +${BL_number[iSTRU]} // number of structures. +EOF + +# (1.4.3.3) input the file names +count_files=1 +while [ $count_files -le ${BL_number[iSTRU]} ] +do + BL=`echo "${BLSTRU[iSTRU]}" | awk '{print $'$count_files'}' ` + cat >> INPUT << EOF +../OUT.$element-$rcut-$BL/orb_matrix.0.dat +EOF + let count_files++ +done + +cat >> INPUT << EOF + + + +1 //number of k points +1 // number of pools + + + +100 + + + +2 + + + +$Start_tem_S // Start temparature for spillage +0.8 // Cooling rate +$Step_S // Number of temperatures(spillage) +600 // Number of steps per temparature + +$Start_tem_K // start temperature for kinetic energy +0.8 // Cooling rate +$Step_K // Number of temperatures(kinetical) +600 // Number of steps per temparature + +$Delta_kappa // Delta kappa +50 // Selectly output information + +100 // Acceptance_steps +0.4 // Acceptance_high +0.2 // Acceptance_low + +100 // Max kinetic energy(Rydberg). +0.01 // 'dr' for kinetic minimized. +1 // 1: Kin 2: Ecut + + + + +1 // to control the number of bands.(Yes1/No0) +1 // int, the start band index(>0). +${ref_bands[$iSTRU]} // int, the ed band index( + +EOF + +cat >> INPUT << EOF + +${EndLevel[$iSTRU]} // Number of levels. +label / na / skip / lmax / each L / +EOF + + +for((i=1;i<=${EndLevel[iSTRU]};i++)) +do + if [ $i -ge ${BeginLevel[iSTRU]} -a $i -le ${EndLevel[iSTRU]} ] + then + leveltype="new " + else + leveltype="skip" + fi +#echo "leveltype=$leveltype" +cat >> INPUT << EOF +$id $na $leveltype ${Llevels[i]} +EOF +done + + +cat >> INPUT << EOF + +EOF + +cat >> INPUT << EOF + +0.01 //dr(a.u.) of uniform mesh. Attention!!dr will affect kinetic energy minmized largely. +-6 //xmin +1 //zed, chosen as valence charge. +0.01 //dx +6.0 //xmax + + + +0 +2 +./FILE/Si-S.ORBITAL +0 +./FILE/Si-P.ORBITAL +1 + + + +0 // 'yes' to do this. +14.0 // rcut, only useful for test program +0.01 // dr, for simpson integral +2 // test eigenvalue index +2 // lmax + + +EOF + + + + + + + + + + + + + + + elif [ "${EXE_orbital:0-12:12}" == "dpsi/main.py" ]; then # begin from if [ "${EXE_orbital:0-3:3}" != ".py" ]; + echo -e " Using PyTorch Gradient Method V2 (include dpsi) \n" + + ### len(dis[info["input"]["element"]]), + ### (1.4.3.2) prepare INPUT file in json for PyTorch program + +cat > INPUT << EOF +{ + "file_list": + { + "origin": + [ +EOF + +count_files=1 +while [ $count_files -lt ${BL_number[iSTRU]} ] +do + BL=`echo "${BLSTRU[iSTRU]}" | awk '{print $'$count_files'}' ` + cat >> INPUT << EOF + "../OUT.$element-$rcut-$BL/orb_matrix.0.dat", +EOF + let count_files++ +done +BL=`echo "${BLSTRU[iSTRU]}" | awk '{print $'$count_files'}' ` +cat >> INPUT << EOF + "../OUT.$element-$rcut-$BL/orb_matrix.0.dat" + ], + "linear": + [ + [ +EOF + +count_files=1 +while [ $count_files -lt ${BL_number[iSTRU]} ] +do + BL=`echo "${BLSTRU[iSTRU]}" | awk '{print $'$count_files'}' ` + cat >> INPUT << EOF + "../OUT.$element-$rcut-$BL/orb_matrix.1.dat", +EOF + let count_files++ +done +BL=`echo "${BLSTRU[iSTRU]}" | awk '{print $'$count_files'}' ` +cat >> INPUT << EOF + "../OUT.$element-$rcut-$BL/orb_matrix.1.dat" + ] + ] +EOF + +cat >> INPUT << EOF + + }, + "info": + { + "Nt_all": [ + "$element" + ], + "Nu": { + "$element": [ +EOF + + +if [ ${RestartSTRU[$iSTRU]} -ge 1 ] ; then + lr_value=0.0001 +else + lr_value=0.01 +fi +echo " iSTRULeft: $iSTRULeft, iSTRU: $iSTRU " +echo " BeginLevel[STRUs]: (${BeginLevel[@]}) " +echo " EndLevel[STRUs]: (${EndLevel[@]}) " +#if [ $ifRestart -eq 0 ] ; then +# C_init_from_file="false" +#elif [ $ifRestart -eq 1 ] ; then +# C_init_from_file="true" +#fi + + +LValueMax=0 +for LValue in {0..4} ; +do + numL[$LValue]=0 +done + +for((i=1;i<=${EndLevel[iSTRU]};i++)) +do + #if [ $i -le ${EndLevel[iSTRULeft]} ]; + #then + # C_init_from_file="true" + # #echo " Level:$i, C_init_from_file = " $C_init_from_file + #fi + + Llevels_i=( ${Llevels[i]} ) + for LValue in {0..4} ; + do + nAdd=${Llevels_i[$LValue+1]} + #echo " nAdd = $nAdd" + if [ "$nAdd" != "" ]; then + numL[$LValue]=$(( ${numL[$LValue]} + $nAdd )) + + if [ $LValueMax -lt $LValue ]; then + LValueMax=$LValue + fi + fi + done +done +echo " numL = ${numL[@]}, LValueMax = $LValueMax " + +for((LValue=0; LValue<${LValueMax}; LValue++)) +do + cat >> INPUT << EOF + ${numL[$LValue]}, +EOF +done + + cat >> INPUT << EOF + ${numL[$LValueMax]} + ] + }, + "Rcut": { + "$element": $rcut + }, + "dr": { + "$element": 0.01 + }, + "Ecut": { + "$element": $ecut + }, + "lr": $lr_value, + "cal_T": true, + "cal_smooth": true + }, + "weight": + { + "stru": [ +EOF + +for((i_BL=1; i_BL<${BL_number[iSTRU]}; i_BL++)) +do + cat >> INPUT << EOF + 1, +EOF +done + cat >> INPUT << EOF + 1 + ], +EOF + + +if [ 2 -ge 1 ] ; then + cat >> INPUT << EOF + "bands_range": [ +EOF +for((i_BL=1; i_BL<${BL_number[iSTRU]}; i_BL++)) +do + cat >> INPUT << EOF + `printf %.0f ${ref_bands[iSTRU]}`, +EOF +done + cat >> INPUT << EOF + `printf %.0f ${ref_bands[iSTRU]}` + ] +EOF +else + cat >> INPUT << EOF + "bands_file": [ + ] +EOF +fi + + + cat >> INPUT << EOF + }, + "C_init_info": + { +EOF +C_init_file="ORBITAL_RESULTS.txt" +if [ ${RestartSTRU[$iSTRU]} -ge 1 ] ; then ## [ "$C_init_from_file" == "true" ]; then + cat >> INPUT << EOF + "init_from_file": true, + "C_init_file" : "$C_init_file", + "opt_C_read" : false +EOF + echo -e " init_from_file : true, \n C_init_file : $C_init_file, \n opt_C_read: false\n" +elif [ ${RestartSTRU[$iSTRU]} -eq 0 ] ; then + cat >> INPUT << EOF + "init_from_file": false +EOF + echo -e " init_from_file : false \n " +else + exit +fi + + cat >> INPUT << EOF + }, + "V_info": + { + "same_band": true, + "init_from_file": true + } +} +EOF + + +export OMP_NUM_THREADS=$Host1_NCore +echo " Set OMP_NUM_THREADS = $OMP_NUM_THREADS " +echo " Python2 Version: " `which python2` +echo " Python3 Version: " `which python3` +echo "" + + + + + + + + + + + + + + + else # begin from: if [ "${EXE_orbital:0-3:3}" != ".py" ]; + echo -e " Using Previous PyTorch Gradient Method \n" + + ### len(dis[info["input"]["element"]]), + ### (1.4.3.2) prepare INPUT file in json for PyTorch program + +cat > INPUT << EOF +{ + "file_list": [ +EOF + +count_files=1 +while [ $count_files -lt ${BL_number[iSTRU]} ] +do + BL=`echo "${BLSTRU[iSTRU]}" | awk '{print $'$count_files'}' ` + cat >> INPUT << EOF + "../OUT.$element-$rcut-$BL/orb_matrix.0.dat", +EOF + let count_files++ +done + BL=`echo "${BLSTRU[iSTRU]}" | awk '{print $'$count_files'}' ` +cat >> INPUT << EOF + "../OUT.$element-$rcut-$BL/orb_matrix.0.dat" + ], + "info": { + "Nt_all": [ + "$element" + ], + "Nu": { + "$element": [ +EOF + + +echo " iSTRULeft: $iSTRULeft, iSTRU: $iSTRU " +echo " BeginLevel[STRUs]: (${BeginLevel[@]}) " +echo " EndLevel[STRUs]: (${EndLevel[@]}) " +#if [ $ifRestart -eq 0 ] ; then +# C_init_from_file="false" +#elif [ $ifRestart -eq 1 ] ; then +# C_init_from_file="true" +#fi + +LValueMax=0 +for LValue in {0..4} ; +do + numL[$LValue]=0 +done + +for((i=1;i<=${EndLevel[iSTRU]};i++)) +do + #if [ $i -le ${EndLevel[iSTRULeft]} ]; + #then + # C_init_from_file="true" + # #echo " Level:$i, C_init_from_file = " $C_init_from_file + #fi + + Llevels_i=( ${Llevels[i]} ) + for LValue in {0..4} ; + do + nAdd=${Llevels_i[$LValue+1]} + #echo " nAdd = $nAdd" + if [ "$nAdd" != "" ]; then + numL[$LValue]=$(( ${numL[$LValue]} + $nAdd )) + + if [ $LValueMax -lt $LValue ]; then + LValueMax=$LValue + fi + fi + done +done +echo " numL = ${numL[@]}, LValueMax = $LValueMax " + + +for((LValue=0; LValue<${LValueMax}; LValue++)) +do + cat >> INPUT << EOF + ${numL[$LValue]}, +EOF +done + cat >> INPUT << EOF + ${numL[$LValueMax]} + ] + }, + "Nb_true": [ +EOF + +for((i_BL=1; i_BL<${BL_number[iSTRU]}; i_BL++)) +do + cat >> INPUT << EOF + ${ref_bands[iSTRU]}, +EOF +done + cat >> INPUT << EOF + ${ref_bands[iSTRU]} + ], + "weight": [ +EOF + +for((i_BL=1; i_BL<${BL_number[iSTRU]}; i_BL++)) +do + cat >> INPUT << EOF + 1, +EOF +done +if [ ${RestartSTRU[$iSTRU]} -ge 1 ] ; then + lr_value=0.0001 +else + lr_value=0.01 +fi + cat >> INPUT << EOF + 1 + ], + "Rcut": { + "$element": $rcut + }, + "dr": { + "$element": 0.01 + }, + "Ecut": { + "$element": $ecut + }, + "lr": $lr_value, + "cal_T": false, + "cal_smooth": true + }, + "C_init_info": { +EOF + +C_init_file="ORBITAL_RESULTS.txt" +if [ ${RestartSTRU[$iSTRU]} -ge 1 ] ; then ## [ "$C_init_from_file" == "true" ]; then + cat >> INPUT << EOF + "init_from_file": true, + "C_init_file" : "$C_init_file" +EOF + echo -e " init_from_file : true \n C_init_file : $C_init_file \n " +elif [ ${RestartSTRU[$iSTRU]} -eq 0 ] ; then + cat >> INPUT << EOF + "init_from_file": false +EOF + echo -e " init_from_file : false \n " +else + exit +fi + + cat >> INPUT << EOF + }, + "V_info": { + "same_band": true, + "init_from_file": false + } +} +EOF + + + +export OMP_NUM_THREADS=$Host1_NCore +echo " Set OMP_NUM_THREADS = $OMP_NUM_THREADS " +echo " Python2 Version: " `which python2` +echo " Python3 Version: " `which python3` +echo "" + + fi # begin from: if [ "${EXE_orbital:0-3:3}" != ".py" ]; + #cat INPUT + + + + #mpiexec -n 1 -machinefile $PBS_NODEFILE $EXE_orbital >> Log.txt + echo " Run $EXE_orbital" + echo "" + $EXE_orbital + #mpirun -np cpu_num $EXE_orbital + + + + if [ "${EXE_orbital:0-3:3}" == ".py" ]; then + echo "" + unset OMP_NUM_THREADS + echo " unset OMP_NUM_THREADS " + #... + #echo " Back to Python2: " `which python2` + #echo " Back to Python3: " `which python3` + sleep 1 + fi + + #exit + + ### (1.4.3.5) exit the rcut dir + cd .. + ### end cicle (1.4.1.5): iSTRU + done + + + +let count_r++ +## end cicle (1.4): rcut +done + + + +# (1.5) exit the name dir. +cd .. +done +# end cicle (1): targets + +time_end=`date +%s` +time_passed=$(($time_end - $time_start)) +echo -e " Total Time: $time_passed \n" + diff --git a/tools/molden/molden.py b/tools/molden/molden.py index 10745c04992..0cb46669a82 100644 --- a/tools/molden/molden.py +++ b/tools/molden/molden.py @@ -39,6 +39,8 @@ S 1 1.00 0.102741 1.000000 """ + + class GTORadials: """ A general introduction to the Gaussian Type Orbitals (GTOs) can be found in the Wikipedia: @@ -49,8 +51,9 @@ class GTORadials: In following code will use the typical notation like: c for contraction coefficient, a for exponent, l for angular momentum, r for grid points. """ - NumericalRadials = None # list of the radial for each type. - # indexed by [it][l][ic][ig] to get (a, c) of primitive GTO, + + NumericalRadials = None # list of the radial for each type. + # indexed by [it][l][ic][ig] to get (a, c) of primitive GTO, # it: _ of type # l: angular momentum # ic: _ of contracted GTOs of one angular momentum @@ -74,13 +77,13 @@ def init_from_file(self, fgto): data = f.read() self.symbols, self.NumericalRadials = GTORadials._cgto_parse(data) - def register_cgto(self, a, c, l, elem = None, mode = 'a'): + def register_cgto(self, a, c, l, elem=None, mode="a"): """ add one CGTO to the GTORadials instance, for a given l """ - assert mode in ['a', 'w'], f"Invalid mode: {mode}" + assert mode in ["a", "w"], f"Invalid mode: {mode}" assert len(c) == len(a), f"Invalid basis: {c}, {a}" - + # find correct atom index it it = self.symbols.index(elem) if elem in self.symbols else None if it is None: @@ -89,34 +92,41 @@ def register_cgto(self, a, c, l, elem = None, mode = 'a'): self.NumericalRadials.append([]) if len(self.NumericalRadials[it]) <= l: # the case there is not enough l for present type - self.NumericalRadials[it] += [[] for i in range(l - len(self.NumericalRadials[it]) + 1)] - if mode == 'w': + self.NumericalRadials[it] += [ + [] for i in range(l - len(self.NumericalRadials[it]) + 1) + ] + if mode == "w": self.NumericalRadials[it][l] = [] # then append as a new CGTO, convert tuple[list[float], list[float]] to list[tuple[float, float]] self.NumericalRadials[it][l].append([(a_, c_) for a_, c_ in zip(a, c)]) - - def build(self, rgrid, normalize = True): + + def build(self, rgrid, normalize=True): """map all the radial functions for each l and cgto onto grid - + Args: rgrid: numpy array, the grid points normalize: bool, whether to normalize the GTOs - + Return: list of list of numpy arrays, the mapped radial functions, indexed by [it][l][ic][r] to get grid value """ import numpy as np + ntype = len(self.NumericalRadials) assert ntype == len(self.symbols) - out = [[] for i in range(ntype)] # the output, indexed by [it][l][ic][r] to get grid value + out = [ + [] for i in range(ntype) + ] # the output, indexed by [it][l][ic][r] to get grid value for it in range(ntype): lmax = len(self.NumericalRadials[it]) - 1 - out[it] = [[] for i in range(lmax+1)] - for l in range(lmax+1): - for i in range(len(self.NumericalRadials[it][l])): # for each CGTO + out[it] = [[] for i in range(lmax + 1)] + for l in range(lmax + 1): + for i in range(len(self.NumericalRadials[it][l])): # for each CGTO cgto = np.zeros_like(rgrid) # print(self.NumericalRadials[it][l][i]) - for a, c in self.NumericalRadials[it][l][i]: # for each primitive GTO + for a, c in self.NumericalRadials[it][l][ + i + ]: # for each primitive GTO cgto += GTORadials._build_gto(a, c, l, rgrid) if normalize: norm = np.sqrt(np.sum(cgto**2 * rgrid**2)) @@ -157,42 +167,62 @@ def _cgto_parse(data): """ import re import numpy as np - spectra = ["S", "P", "D", "F", "G", "H"] # no more... - data = [d.strip() for d in data.split("****")] # the separator of different elements - data = [d for d in data if d] # remove empty data + + spectra = ["S", "P", "D", "F", "G", "H"] # no more... + data = [ + d.strip() for d in data.split("****") + ] # the separator of different elements + data = [d for d in data if d] # remove empty data nelem = len(data) - out = [[[ # CGTO, because the number is still uncertain, leave as a list - ] for j in range(len(spectra))] for i in range(nelem)] + out = [ + [ + [] # CGTO, because the number is still uncertain, leave as a list + for j in range(len(spectra)) + ] + for i in range(nelem) + ] elems = [] - for d in data: # for each element... + for d in data: # for each element... # wash data - d = [l.strip() for l in d.split("\n") if not l.startswith("!")] # annotation from Basis Set Exchange - d = [l for l in d if l] # remove empty lines - - elem = None # should be read, if at last it is still None, abnormal case... - lmax = 0 # record lmax of the file read - - elempat = r"^([A-Z][a-z]?)\s+0$" # the starting line - cgtopat = r"^([A-Z]+)\s+(\d+)\s+(\d+\.\d+)$" # the header of one contracted GTOs - - switch = False # switch to read the data - i = 0 # the line number, for-loop is not used because we read CGTO-by-CGTO instead of line by line + d = [ + l.strip() for l in d.split("\n") if not l.startswith("!") + ] # annotation from Basis Set Exchange + d = [l for l in d if l] # remove empty lines + + elem = None # should be read, if at last it is still None, abnormal case... + lmax = 0 # record lmax of the file read + + elempat = r"^([A-Z][a-z]?)\s+0$" # the starting line + cgtopat = ( + r"^([A-Z]+)\s+(\d+)\s+(\d+\.\d+)$" # the header of one contracted GTOs + ) + + switch = False # switch to read the data + i = 0 # the line number, for-loop is not used because we read CGTO-by-CGTO instead of line by line while i < len(d): if re.match(elempat, d[i]): elem = re.match(elempat, d[i]).group(1) switch = True - elif re.match(cgtopat, d[i]) and switch: # a new CGTO + elif re.match(cgtopat, d[i]) and switch: # a new CGTO spec_, ngto, _ = re.match(cgtopat, d[i]).groups() - l_ = [spectra.index(s_) for s_ in spec_] # the angular momentum of this CGTO, for Pople basis - # it is possible to be not only one angular momentum - lmax = max(lmax, max(l_)) # refresh the maximal angular momentum for this atom type + l_ = [ + spectra.index(s_) for s_ in spec_ + ] # the angular momentum of this CGTO, for Pople basis + # it is possible to be not only one angular momentum + lmax = max( + lmax, max(l_) + ) # refresh the maximal angular momentum for this atom type ngto = int(ngto) # then read the coefficients and exponents by ngto lines: - ac_ = np.array([re.split(r"\s+", line) for line in d[i+1:i+1+ngto]]) + ac_ = np.array( + [re.split(r"\s+", line) for line in d[i + 1 : i + 1 + ngto]] + ) a_, c_ = ac_[:, 0], ac_[:, 1:] a_ = [float(a.upper().replace("D", "E")) for a in a_] - c_ = [[float(c.upper().replace("D", "E")) for c in ci] for ci in c_] # convert to float - for j, l__ in enumerate(l_): # save the GTOs read from the section + c_ = [ + [float(c.upper().replace("D", "E")) for c in ci] for ci in c_ + ] # convert to float + for j, l__ in enumerate(l_): # save the GTOs read from the section out[-1][l__].append([(a_[k], c_[k][j]) for k in range(ngto)]) i += ngto else: @@ -201,31 +231,34 @@ def _cgto_parse(data): assert elem is not None, "No symbol found in the file!" elems.append(elem) # clean the list up to lmax+1 - out[-1] = out[-1][:lmax+1] + out[-1] = out[-1][: lmax + 1] return elems, out def _build_gto(a, c, l, r): """build one GTO defined by coefficients c, exponents a, angular momentum l and map on - radial grid r""" + radial grid r""" import numpy as np + g = c * np.exp(-a * r**2) * r**l return g - + def __str__(self) -> str: """print the GTOs in the Gaussian format. Different CGTO are printed as different section.""" spectra = ["S", "P", "D", "F", "G", "H"] out = "" ntype = len(self.symbols) - for it in range(ntype): # for each type + for it in range(ntype): # for each type out += f"{self.symbols[it]:<2s} 0\n" NumericalRadial = self.NumericalRadials[it] for l in range(len(NumericalRadial)): if len(NumericalRadial[l]) == 0: continue - ncgto = len(NumericalRadial[l]) # number of contracted GTOs for this l + ncgto = len(NumericalRadial[l]) # number of contracted GTOs for this l for ic in range(ncgto): - ngto = len(NumericalRadial[l][ic]) # number of primitive GTOs for this l and ic + ngto = len( + NumericalRadial[l][ic] + ) # number of primitive GTOs for this l and ic out += f"{spectra[l]:<2s} {ngto:3d} {1:6.2f}\n" for ig in range(ngto): a, c = NumericalRadial[l][ic][ig] @@ -238,7 +271,7 @@ def molden_all(self) -> str: spectra = ["s", "p", "d", "f", "g", "h"] out = "[GTO]\n" ntype = len(self.symbols) - for it in range(ntype): # for each type + for it in range(ntype): # for each type out += f"{it:>8d}{'0':>8s}\n" NumericalRadial = self.NumericalRadials[it] for l in range(len(NumericalRadial)): @@ -250,24 +283,25 @@ def molden_all(self) -> str: out += f"{a:>62.3f} {c:>12.3f}\n" out += "\n" return out - + def molden(self, it, iat) -> str: spectra = ["s", "p", "d", "f", "g", "h"] out = f"{iat:>8d}{'0':>8s}\n" NumericalRadial = self.NumericalRadials[it] for l in range(len(NumericalRadial)): - for ic in range(len(NumericalRadial[l])): - ngto = len(NumericalRadial[l][ic]) - out += f"{spectra[l]:>25s}{ngto:>8d}{'1.00':>8s}\n" - for ig in range(ngto): - a, c = NumericalRadial[l][ic][ig] - out += f"{a:>62.3f} {c:>12.3f}\n" + for ic in range(len(NumericalRadial[l])): + ngto = len(NumericalRadial[l][ic]) + out += f"{spectra[l]:>25s}{ngto:>8d}{'1.00':>8s}\n" + for ig in range(ngto): + a, c = NumericalRadial[l][ic][ig] + out += f"{a:>62.3f} {c:>12.3f}\n" out += "\n" return out + def fit_radial_with_gto(nao, ngto, l, r, rel_r=2): """fit one radial function mapped on grid with GTOs - + Args: nao: numpy array, the radial function mapped on grid. ngto: int, the number of GTOs. @@ -277,6 +311,7 @@ def fit_radial_with_gto(nao, ngto, l, r, rel_r=2): from scipy.optimize import minimize from scipy.integrate import simpson import numpy as np + def f(a_and_c, nao=nao, ngto=ngto, l=l, r=r): """calculate the distance between the nao and superposition of GTOs of given angular momentum l on user defined grid points r""" @@ -293,24 +328,24 @@ def f(a_and_c, nao=nao, ngto=ngto, l=l, r=r): while r[0] < 1e-10: r = r[1:] dorb = dorb[1:] - return np.sum((dorb/r**l)**2) - + return np.sum((dorb / r**l) ** 2) + def gto_guess(nao, ngto, l, r, rel_r=2): """generate the initial guess for the coefficients and exponents of GTOs. The GTO has form like c * exp(-a * r^2) * r^l, where c is the coefficient, the l will push the maxima from r = 0 to positive value. On the other hand the standard Gaussian function is 1/sqrt(2*simga^2) * exp(-r^2/(2*sigma^2)), - , where the mu as taken to be zero. + , where the mu as taken to be zero. Therefore a = 1/(2*sigma^2), sigma = 1/sqrt(2*a). We set 3sigma = rmax, then the smallest a is guessed to be 9/(2*rmax^2), then the second smallest to be - a*rel_r, which means the sigma will be shrink by factor sqrt(rel_r), and so - on. c is set as the generalized cosine value between function to fit and the + a*rel_r, which means the sigma will be shrink by factor sqrt(rel_r), and so + on. c is set as the generalized cosine value between function to fit and the GTO with c = 1 and a setted. """ - amin = 3**2 / (2 * r[-1]**2) + amin = 3**2 / (2 * r[-1] ** 2) a_init = np.zeros(ngto) for i in range(ngto): - a_init[i] = amin * rel_r**(i + 1) + a_init[i] = amin * rel_r ** (i + 1) c_init = np.zeros(ngto) for i in range(ngto): model = GTORadials._build_gto(a_init[i], 1, l, r) @@ -319,42 +354,52 @@ def gto_guess(nao, ngto, l, r, rel_r=2): return np.concatenate((a_init, c_init)) init = gto_guess(nao, ngto, l, r, rel_r) - + # bounds for c and a - bounds = [(0, np.inf) for i in range(ngto)] + [(-np.inf, np.inf) for i in range(ngto)] - #res = basinhopping(f, init, niter=100, minimizer_kwargs={"method": "L-BFGS-B", "bounds": bounds}, disp=True) - res = minimize(f, init, bounds=bounds, method="L-BFGS-B", - options={"maxiter": 5000, "disp": False, "ftol": 1e-10, "gtol": 1e-10}) + bounds = [(0, np.inf) for i in range(ngto)] + [ + (-np.inf, np.inf) for i in range(ngto) + ] + # res = basinhopping(f, init, niter=100, minimizer_kwargs={"method": "L-BFGS-B", "bounds": bounds}, disp=True) + res = minimize( + f, + init, + bounds=bounds, + method="L-BFGS-B", + options={"maxiter": 5000, "disp": False, "ftol": 1e-10, "gtol": 1e-10}, + ) a, c = res.x[:ngto], res.x[ngto:] err = res.fun cgto = GTORadials() - cgto.register_cgto(a, c, l, 'w') + cgto.register_cgto(a, c, l, "w") out = cgto.build(r, False) norm_nao = simpson(nao**2 * r**2, x=r) - norm_gto = simpson(out[0][l][0]**2 * r**2, x=r) + norm_gto = simpson(out[0][l][0] ** 2 * r**2, x=r) factor = np.sqrt(norm_nao / norm_gto) print(f"NAO2GTO: Renormalize the CGTO from NAO2GTO method with factor {factor:.4f}") - c *= factor # renormalize the coefficients to make the norm of GTO equals to that of NAO + c *= factor # renormalize the coefficients to make the norm of GTO equals to that of NAO - print(f"""NAO2GTO: Angular momentum {l}, with {ngto} superposition to fit numerical atomic orbitals on given grid, + print( + f"""NAO2GTO: Angular momentum {l}, with {ngto} superposition to fit numerical atomic orbitals on given grid, Nonlinear fitting error: {err:.4e} Exponential and contraction coefficients of primitive GTOs in a.u.: -{"a":>10} {"c":>10}\n---------------------""") +{"a":>10} {"c":>10}\n---------------------""" + ) for i in range(ngto): print(f"{a[i]:10.6f} {c[i]:10.6f}") print(f"\nNAO2GTO: The fitted GTOs are saved in the CGTO instance.") return a, c + def read_nao(fpath): - ''' + """ Reads a numerical atomic orbital file of the ABACUS format. - + Parameters ---------- fpath : str Path to the orbital file. - + Returns ------- A dictionary containing the following key-value pairs: @@ -372,34 +417,45 @@ def read_nao(fpath): 'chi' : list of list of array of float A nested list of numerical radial functions organized as chi[l][zeta][ir]. - ''' + """ import re from itertools import accumulate import numpy as np - with open(fpath, 'r') as f: - data = list(filter(None, re.split('\t| |\n', f.read()))) + with open(fpath, "r") as f: + data = list(filter(None, re.split("\t| |\n", f.read()))) - elem = data[data.index('Element')+1] - ecut = float(data[data.index('Cutoff(Ry)')+1]) - rcut = float(data[data.index('Cutoff(a.u.)')+1]) - lmax = int(data[data.index('Lmax')+1]) + elem = data[data.index("Element") + 1] + ecut = float(data[data.index("Cutoff(Ry)") + 1]) + rcut = float(data[data.index("Cutoff(a.u.)") + 1]) + lmax = int(data[data.index("Lmax") + 1]) - spec_symbol = 'SPDFGHIKLMNOQRTUVWXYZ' - nzeta = [int(data[data.index(spec_symbol[l] + 'orbital-->') + 1]) for l in range(lmax+1)] + spec_symbol = "SPDFGHIKLMNOQRTUVWXYZ" + nzeta = [ + int(data[data.index(spec_symbol[l] + "orbital-->") + 1]) + for l in range(lmax + 1) + ] - nr = int(data[data.index('Mesh')+1]) - dr = float(data[data.index('dr')+1]) + nr = int(data[data.index("Mesh") + 1]) + dr = float(data[data.index("dr") + 1]) - delim = [i for i, x in enumerate(data) if x == 'Type'] + [len(data)] + delim = [i for i, x in enumerate(data) if x == "Type"] + [len(data)] nzeta_cumu = [0] + list(accumulate(nzeta)) - iorb = lambda l, zeta : nzeta_cumu[l] + zeta - chi = [[np.array(data[delim[iorb(l,zeta)]+6:delim[iorb(l,zeta)+1]], np.float64) - for zeta in range(nzeta[l]) ] for l in range(lmax+1)] + iorb = lambda l, zeta: nzeta_cumu[l] + zeta + chi = [ + [ + np.array( + data[delim[iorb(l, zeta)] + 6 : delim[iorb(l, zeta) + 1]], np.float64 + ) + for zeta in range(nzeta[l]) + ] + for l in range(lmax + 1) + ] + + return {"elem": elem, "ecut": ecut, "rcut": rcut, "nr": nr, "dr": dr, "chi": chi} - return {'elem': elem, 'ecut': ecut, 'rcut': rcut, 'nr': nr, 'dr': dr, 'chi': chi} -def convert_nao_to_gto(fnao, fgto = None, ngto: int = 7, rel_r: float = 2): +def convert_nao_to_gto(fnao, fgto=None, ngto: int = 7, rel_r: float = 2): """convert the numerical atomic orbitals to GTOs. Each chi (or say the zeta function) corresponds to a CGTO (contracted GTO), and the GTOs are fitted to the radial functions. Which also means during the SCF, the coefficient inside each CGTO is unchanged, while the @@ -415,22 +471,26 @@ def convert_nao_to_gto(fnao, fgto = None, ngto: int = 7, rel_r: float = 2): symbol = nao["elem"] # fit the radial functions with GTOs lmax = len(nao["chi"]) - 1 - for l in range(lmax+1): + for l in range(lmax + 1): nchi = len(nao["chi"][l]) for i in range(nchi): a, c = fit_radial_with_gto(nao["chi"][l][i], ngto, l, rgrid, rel_r) - gto.register_cgto(a, c, l, symbol, 'a') - + gto.register_cgto(a, c, l, symbol, "a") + # draw the fitted GTOs out = gto.build(rgrid) for it in range(len(out)): for l in range(len(out[it])): for ic in range(len(out[it][l])): - plt.plot(rgrid, out[it][l][ic], label=f"element {symbol}, l={l}, ic={ic}") + plt.plot( + rgrid, out[it][l][ic], label=f"element {symbol}, l={l}, ic={ic}" + ) plt.legend() - + fgto = os.path.basename(fnao).replace(".orb", "") + ".gto" if fgto is None else fgto - fgto = fnao.replace(os.path.basename(fnao), fgto) # make sure that only the file name is changed + fgto = fnao.replace( + os.path.basename(fnao), fgto + ) # make sure that only the file name is changed plt.savefig(fgto + ".png") plt.close() @@ -439,46 +499,50 @@ def convert_nao_to_gto(fnao, fgto = None, ngto: int = 7, rel_r: float = 2): return gto + #################### # Molden Generate # #################### + def write_molden_gto(total_gto: GTORadials, labels: list): """Molden file will write GTO information for each atom rather than each type of atoms. However, the total_gto is the collection of GTO by type. - + Args: total_gto (GTORadials): the total GTO radials labels (list): the labels of each atom, its values start from 0 """ out = "[GTO]\n" for iat, l in enumerate(labels): - out += total_gto.molden(l, iat + 1) # iat starts from 0, molden starts from 1 + out += total_gto.molden(l, iat + 1) # iat starts from 0, molden starts from 1 return out -def read_abacus_lowf(flowf, pat=r'^WFC_NAO_(K\d+|GAMMA(1|2)).txt$'): + +def read_abacus_lowf(flowf, pat=r"^WFC_NAO_(K\d+|GAMMA(1|2)).txt$"): """Read the ABACUS WFC_NAO_(K|GAMMA) file, which contains the coefficients of MOs. Please note, only Gamma-only calculation is supported. For ABACUS version earlier than 3.7.1, the `flowf` file is something like LOWF_K_. Manually change the file name and run is okay. - + Args: flowf (str): the file name of the ABACUS WFC_NAO_(K|GAMMA) file pat (str): the pattern to match the file name - + Returns: tuple: the number of bands, the number of local orbitals, the occupation of each MO, the band index, the energy of each MO, the coefficients of MOs """ import re, os import numpy as np + if not re.match(pat, os.path.basename(flowf)): return None - - with open(flowf, 'r') as file: + + with open(flowf, "r") as file: lines = file.readlines() - if lines[0].endswith('(index of k points)\n'): + if lines[0].endswith("(index of k points)\n"): # discard the first two lines lines = lines[2:] # initialize lists @@ -494,19 +558,19 @@ def read_abacus_lowf(flowf, pat=r'^WFC_NAO_(K\d+|GAMMA(1|2)).txt$'): # loop over lines and process while i < len(lines): line = lines[i].strip() - if '(band)' in line: - band.append(int(line.split(' ')[0])) - elif '(Ry)' in line: - ener.append(float(line.split(' ')[0])) - elif '(Occupations)' in line: - occ.append(float(line.split(' ')[0])) + if "(band)" in line: + band.append(int(line.split(" ")[0])) + elif "(Ry)" in line: + ener.append(float(line.split(" ")[0])) + elif "(Occupations)" in line: + occ.append(float(line.split(" ")[0])) else: data.extend([float(x) for x in line.split()]) i += 1 # check if the data we collected has the correct number of elements - if "WFC_NAO_K" in flowf: # multi-k case, the coef will be complex - data = [complex(data[i], data[i+1]) for i in range(0, len(data), 2)] + if "WFC_NAO_K" in flowf: # multi-k case, the coef will be complex + data = [complex(data[i], data[i + 1]) for i in range(0, len(data), 2)] data = [d.real for d in data] data = np.array(data).reshape(nbands, nlocal) if data.shape != (nbands, nlocal): @@ -516,75 +580,78 @@ def read_abacus_lowf(flowf, pat=r'^WFC_NAO_(K\d+|GAMMA(1|2)).txt$'): return nbands, nlocal, occ, band, ener, data + def write_molden_mo(coefs, mo_map, occ, ener, spin=0, ndigits=3): """Write Molden [MO] section from the coefficients, occupations and energies. - Args: - coefs (list): list of list of floats, the coefficients of MOs, each element of the list is a list of coefficients - occ (list): list of floats, the occupation of each MO - ener (list): list of floats, the energy of each MO - spin (int): 0 for alpha, 1 for beta - ndigits (int): number of digits to be printed for the coefficients - - Returns: - str: the string formatted in Molden format + Args: + coefs (list): list of list of floats, the coefficients of MOs, each element of the list is a list of coefficients + occ (list): list of floats, the occupation of each MO + ener (list): list of floats, the energy of each MO + spin (int): 0 for alpha, 1 for beta + ndigits (int): number of digits to be printed for the coefficients + + Returns: + str: the string formatted in Molden format + + Notes: + + for writing Molecular Orbitals (MOs) in molden file required format. For the lack of documents on the Internet, + I post some useful information here. + + ### Order of m within l + The [MO] section should start with declaration of the type of GTO used, whether spherical or cartesian. [5D] means + there will be 5 channels for D-orbital, which means, spherical, otherwise the Molden will by default assume the D + as cartesian, which will have 6 channels. In summary for this point, see the following table: + + 5D: D 0, D+1, D-1, D+2, D-2 + 6D: xx, yy, zz, xy, xz, yz + + 7F: F 0, F+1, F-1, F+2, F-2, F+3, F-3 + 10F: xxx, yyy, zzz, xyy, xxy, xxz, xzz, yzz, yyz, xyz + + 9G: G 0, G+1, G-1, G+2, G-2, G+3, G-3, G+4, G-4 + 15G: xxxx yyyy zzzz xxxy xxxz yyyx yyyz zzzx zzzy, + xxyy xxzz yyzz xxyz yyxz zzxy + + HOWEVER, Molden arranges the P-orbitals like px, py, pz, whose m is 1, -1, 0! + https://en.wikipedia.org/wiki/Table_of_spherical_harmonics#Real_spherical_harmonics + + On the other hand, what is important is the order of orbitals. The example above has shown the order of m with in + l, but the order of l, atom and type are not shown. The order of m coincides with ABACUS and ORCA internal + implementation. + + ### Order of l + The angular momentum always arranges in the common order, then the zeta. + + ### Order of atom + Unlike ABACUS, the molden arranges atoms in the same order as [ATOM]. + + ### Summray + The order of MOs in Molden file is: + 1. first loop over all atoms in the order defined in [ATOM] + 2. for each atom, loop over all angular momentums from 0 to the highest l + 3. for each l, loop over all zeta with in the l + 4. for each zeta, loop over all m with in the l + 5. then the next atom - Notes: - - for writing Molecular Orbitals (MOs) in molden file required format. For the lack of documents on the Internet, - I post some useful information here. - - ### Order of m within l - The [MO] section should start with declaration of the type of GTO used, whether spherical or cartesian. [5D] means - there will be 5 channels for D-orbital, which means, spherical, otherwise the Molden will by default assume the D - as cartesian, which will have 6 channels. In summary for this point, see the following table: - - 5D: D 0, D+1, D-1, D+2, D-2 - 6D: xx, yy, zz, xy, xz, yz - - 7F: F 0, F+1, F-1, F+2, F-2, F+3, F-3 - 10F: xxx, yyy, zzz, xyy, xxy, xxz, xzz, yzz, yyz, xyz - - 9G: G 0, G+1, G-1, G+2, G-2, G+3, G-3, G+4, G-4 - 15G: xxxx yyyy zzzz xxxy xxxz yyyx yyyz zzzx zzzy, - xxyy xxzz yyzz xxyz yyxz zzxy - - HOWEVER, Molden arranges the P-orbitals like px, py, pz, whose m is 1, -1, 0! - https://en.wikipedia.org/wiki/Table_of_spherical_harmonics#Real_spherical_harmonics - - On the other hand, what is important is the order of orbitals. The example above has shown the order of m with in - l, but the order of l, atom and type are not shown. The order of m coincides with ABACUS and ORCA internal - implementation. - - ### Order of l - The angular momentum always arranges in the common order, then the zeta. - - ### Order of atom - Unlike ABACUS, the molden arranges atoms in the same order as [ATOM]. - - ### Summray - The order of MOs in Molden file is: - 1. first loop over all atoms in the order defined in [ATOM] - 2. for each atom, loop over all angular momentums from 0 to the highest l - 3. for each l, loop over all zeta with in the l - 4. for each zeta, loop over all m with in the l - 5. then the next atom - - In ABACUS, the numerical atomic orbitals are always arranged in the way like it, ia, l, izeta, m, where ia is the atom - index within the type. + In ABACUS, the numerical atomic orbitals are always arranged in the way like it, ia, l, izeta, m, where ia is the atom + index within the type. """ import numpy as np + def mo(ener, spin, occ, coef, ndigits=3): spin = "Alpha" if spin == 0 else "Beta" - out = f"Ene={ener:>20.10e}\n" + out = f"Ene={ener:>20.10e}\n" out += f"Spin={spin:>6s}\n" out += f"Occup={occ:>12.7f}\n" for ic in range(len(coef)): c = coef[abs(mo_map[ic])] - c *= -1 if mo_map[ic] < 0 else 1 # here the Condon-Shortley phase is added - if abs(c) >= 10**(-ndigits): + c *= -1 if mo_map[ic] < 0 else 1 # here the Condon-Shortley phase is added + if abs(c) >= 10 ** (-ndigits): out += f"{ic+1:5d} {c:>{ndigits+4+3}.{ndigits}e}\n" return out + nbands, nlocal = np.array(coefs).shape assert nbands == len(occ) == len(ener) assert spin in [0, 1] @@ -593,12 +660,14 @@ def mo(ener, spin, occ, coef, ndigits=3): out += mo(ener[i], spin, occ[i], coefs[i], ndigits) return out + def read_abacus_stru(fstru): """this function benefit from the implementation by jinzx10""" return read_stru(fstru) + def _parse_coordinate_line(line): - ''' + """ Parses a coordinate line (which may include extra parameters) in the ATOMIC_POSITIONS block. A coordinate line always contains the x, y, z coordinates of an atom, and may also include @@ -609,57 +678,77 @@ def _parse_coordinate_line(line): See https://abacus.deepmodeling.com/en/latest/advanced/input_files/stru.html#More-Key-Words for details. - ''' + """ fields = line.split() - result = { 'coord' : [float(x) for x in fields[0:3]] } + result = {"coord": [float(x) for x in fields[0:3]]} idx = 3 while idx < len(fields): - if fields[idx].isdigit(): # no keyword, 0/1 -> frozen atom - result['m'] = [int(x) for x in fields[idx:idx+3]] + if fields[idx].isdigit(): # no keyword, 0/1 -> frozen atom + result["m"] = [int(x) for x in fields[idx : idx + 3]] idx += 3 - elif fields[idx] == 'm': # frozen atom - result['m'] = [int(x) for x in fields[idx+1:idx+4]] + elif fields[idx] == "m": # frozen atom + result["m"] = [int(x) for x in fields[idx + 1 : idx + 4]] idx += 4 - elif fields[idx] in ['v', 'vel', 'velocity']: # initial velocity - result['v'] = [float(x) for x in fields[idx+1:idx+4]] + elif fields[idx] in ["v", "vel", "velocity"]: # initial velocity + result["v"] = [float(x) for x in fields[idx + 1 : idx + 4]] idx += 4 - elif fields[idx] in ['mag', 'magmom']: - ''' + elif fields[idx] in ["mag", "magmom"]: + """ here we assume that frozen atom info cannot be placed after a collinear mag info without a keyword i.e., the following coordinate line 0.0 0.0 0.0 mag 1.0 0 0 0 is not allowed; one must explicitly specify 'm' in this case: 0.0 0.0 0.0 mag 1.0 m 0 0 0 - ''' - if idx + 2 < len(fields) and fields[idx+2] == 'angle1': - result['mag'] = ('Spherical', [float(fields[idx+1]), float(fields[idx+3]), float(fields[idx+5])]) + """ + if idx + 2 < len(fields) and fields[idx + 2] == "angle1": + result["mag"] = ( + "Spherical", + [ + float(fields[idx + 1]), + float(fields[idx + 3]), + float(fields[idx + 5]), + ], + ) idx += 6 - elif idx + 2 < len(fields) and fields[idx+2][0].isdigit(): - result['mag'] = ('Cartesian', [float(fields[idx+1]), float(fields[idx+2]), float(fields[idx+3])]) + elif idx + 2 < len(fields) and fields[idx + 2][0].isdigit(): + result["mag"] = ( + "Cartesian", + [ + float(fields[idx + 1]), + float(fields[idx + 2]), + float(fields[idx + 3]), + ], + ) idx += 4 - else: # collinear - result['mag'] = float(fields[idx+1]) + else: # collinear + result["mag"] = float(fields[idx + 1]) idx += 2 else: - raise ValueError('Error: unknown keyword %s'%fields[idx]) + raise ValueError("Error: unknown keyword %s" % fields[idx]) return result + def _atomic_positions_gen(lines): - ''' + """ Iteratively generates info per species from the ATOMIC_POSITIONS block. - ''' + """ natom = int(lines[2]) - yield { 'symbol': lines[0], 'mag_each': float(lines[1]), 'natom': natom, \ - 'atom': [ _parse_coordinate_line(line) for line in lines[3:3+natom] ] } + yield { + "symbol": lines[0], + "mag_each": float(lines[1]), + "natom": natom, + "atom": [_parse_coordinate_line(line) for line in lines[3 : 3 + natom]], + } if len(lines) > 3 + natom: - yield from _atomic_positions_gen(lines[3+natom:]) + yield from _atomic_positions_gen(lines[3 + natom :]) + def read_stru(fpath): - ''' + """ Builds a STRU dict from a ABACUS STRU file. Returns @@ -668,54 +757,73 @@ def read_stru(fpath): 'species' : list of dict List of atomic species. Each dict contains 'symbol', 'mass', 'pp_file', and optionally 'pp_type'. - - ''' - block_title = ['ATOMIC_SPECIES', 'NUMERICAL_ORBITAL', 'LATTICE_CONSTANT', 'LATTICE_PARAMETER', \ - 'LATTICE_VECTORS', 'ATOMIC_POSITIONS'] - _trim = lambda line: line.split('#')[0].split('//')[0].strip(' \t\n') - with open(fpath, 'r') as f: - lines = [_trim(line).replace('\t', ' ') for line in f.readlines() if len(_trim(line)) > 0] + """ + block_title = [ + "ATOMIC_SPECIES", + "NUMERICAL_ORBITAL", + "LATTICE_CONSTANT", + "LATTICE_PARAMETER", + "LATTICE_VECTORS", + "ATOMIC_POSITIONS", + ] + + _trim = lambda line: line.split("#")[0].split("//")[0].strip(" \t\n") + with open(fpath, "r") as f: + lines = [ + _trim(line).replace("\t", " ") + for line in f.readlines() + if len(_trim(line)) > 0 + ] # break the content into blocks delim = [i for i, line in enumerate(lines) if line in block_title] + [len(lines)] - blocks = { lines[delim[i]] : lines[delim[i]+1:delim[i+1]] for i in range(len(delim) - 1) } + blocks = { + lines[delim[i]]: lines[delim[i] + 1 : delim[i + 1]] + for i in range(len(delim) - 1) + } stru = {} - #============ LATTICE_CONSTANT/PARAMETER/VECTORS ============ - stru['lat'] = {'const': float(blocks['LATTICE_CONSTANT'][0])} - if 'LATTICE_VECTORS' in blocks: - stru['lat']['vec'] = [[float(x) for x in line.split()] for line in blocks['LATTICE_VECTORS']] - elif 'LATTICE_PARAMETER' in blocks: - stru['lat']['param'] = [float(x) for x in blocks['LATTICE_PARAMETERS'].split()] - - #============ ATOMIC_SPECIES ============ - stru['species'] = [ dict(zip(['symbol', 'mass', 'pp_file', 'pp_type'], line.split())) for line in blocks['ATOMIC_SPECIES'] ] - for s in stru['species']: - s['mass'] = float(s['mass']) - - #============ NUMERICAL_ORBITAL ============ - if 'NUMERICAL_ORBITAL' in blocks: - for i, s in enumerate(stru['species']): - s['orb_file'] = blocks['NUMERICAL_ORBITAL'][i] - - #============ ATOMIC_POSITIONS ============ - stru['coord_type'] = blocks['ATOMIC_POSITIONS'][0] - index = { s['symbol'] : i for i, s in enumerate(stru['species']) } - for ap in _atomic_positions_gen(blocks['ATOMIC_POSITIONS'][1:]): - stru['species'][index[ap['symbol']]].update(ap) + # ============ LATTICE_CONSTANT/PARAMETER/VECTORS ============ + stru["lat"] = {"const": float(blocks["LATTICE_CONSTANT"][0])} + if "LATTICE_VECTORS" in blocks: + stru["lat"]["vec"] = [ + [float(x) for x in line.split()] for line in blocks["LATTICE_VECTORS"] + ] + elif "LATTICE_PARAMETER" in blocks: + stru["lat"]["param"] = [float(x) for x in blocks["LATTICE_PARAMETERS"].split()] + + # ============ ATOMIC_SPECIES ============ + stru["species"] = [ + dict(zip(["symbol", "mass", "pp_file", "pp_type"], line.split())) + for line in blocks["ATOMIC_SPECIES"] + ] + for s in stru["species"]: + s["mass"] = float(s["mass"]) + + # ============ NUMERICAL_ORBITAL ============ + if "NUMERICAL_ORBITAL" in blocks: + for i, s in enumerate(stru["species"]): + s["orb_file"] = blocks["NUMERICAL_ORBITAL"][i] + + # ============ ATOMIC_POSITIONS ============ + stru["coord_type"] = blocks["ATOMIC_POSITIONS"][0] + index = {s["symbol"]: i for i, s in enumerate(stru["species"])} + for ap in _atomic_positions_gen(blocks["ATOMIC_POSITIONS"][1:]): + stru["species"][index[ap["symbol"]]].update(ap) return stru + def write_molden_cell(const, vec): """The Molden requires the cell information in Angstrom, while ABACUS uses Bohr. - + Args: - const (float): the `LATTICE_CONSTANT` set in ABACUS STRU file, always used for + const (float): the `LATTICE_CONSTANT` set in ABACUS STRU file, always used for scaling the cell vectors and atomic positions if not set `*_Angstrom` explicitly. This quantity actually have unit as Bohr. vec (list): the cell vectors, dimensionless, 3 x 3 matrix - + Returns: str: the string formatted in Molden format """ @@ -728,17 +836,19 @@ def write_molden_cell(const, vec): out += f"{vec[i][0]*const:>15.10f}{vec[i][1]*const:>15.10f}{vec[i][2]*const:>15.10f}\n" return out + def ptable(elem): """ periodic table to index Args: elem (str): the element symbol - + Returns: int: the index of the element in the periodic table """ import re + m = re.match(r"([A-Z][a-z]?)", elem) if m is None: print(f"WARNING: {elem} is not a valid element symbol.") @@ -747,62 +857,163 @@ def ptable(elem): print(f"WARNING: down-size the element symbol {elem} to {m.group(1)}") elem = m.group(1) PERIODIC_TABLE_TOINDEX = { - 'H': 1, 'He': 2, 'Li': 3, 'Be': 4, 'B': 5, 'C': 6, 'N': 7, - 'O': 8, 'F': 9, 'Ne': 10, 'Na': 11, 'Mg': 12, 'Al': 13, - 'Si': 14, 'P': 15, 'S': 16, 'Cl': 17, 'Ar': 18, 'K': 19, - 'Ca': 20, 'Sc': 21, 'Ti': 22, 'V': 23, 'Cr': 24, 'Mn': 25, - 'Fe': 26, 'Co': 27, 'Ni': 28, 'Cu': 29, 'Zn': 30, 'Ga': 31, - 'Ge': 32, 'As': 33, 'Se': 34, 'Br': 35, 'Kr': 36, 'Rb': 37, - 'Sr': 38, 'Y': 39, 'Zr': 40, 'Nb': 41, 'Mo': 42, 'Tc': 43, - 'Ru': 44, 'Rh': 45, 'Pd': 46, 'Ag': 47, 'Cd': 48, 'In': 49, - 'Sn': 50, 'Sb': 51, 'Te': 52, 'I': 53, 'Xe': 54, 'Cs': 55, - 'Ba': 56, 'La': 57, 'Ce': 58, 'Pr': 59, 'Nd': 60, 'Pm': 61, - 'Sm': 62, 'Eu': 63, 'Gd': 64, 'Tb': 65, 'Dy': 66, 'Ho': 67, - 'Er': 68, 'Tm': 69, 'Yb': 70, 'Lu': 71, 'Hf': 72, 'Ta': 73, - 'W': 74, 'Re': 75, 'Os': 76, 'Ir': 77, 'Pt': 78, 'Au': 79, - 'Hg': 80, 'Tl': 81, 'Pb': 82, 'Bi': 83, 'Po': 84, 'At': 85, - 'Rn': 86, 'Fr': 87, 'Ra': 88, 'Ac': 89, 'Th': 90, 'Pa': 91, - 'U': 92, 'Np': 93, 'Pu': 94, 'Am': 95, 'Cm': 96, 'Bk': 97, - 'Cf': 98, 'Es': 99, 'Fm': 100, 'Md': 101, 'No': 102, 'Lr': 103, - 'Rf': 104, 'Db': 105, 'Sg': 106, 'Bh': 107, 'Hs': 108, 'Mt': 109, - 'Ds': 110, 'Rg': 111, 'Cn': 112, 'Nh': 113, 'Fl': 114, 'Mc': 115, - 'Lv': 116, 'Ts': 117, 'Og': 118 + "H": 1, + "He": 2, + "Li": 3, + "Be": 4, + "B": 5, + "C": 6, + "N": 7, + "O": 8, + "F": 9, + "Ne": 10, + "Na": 11, + "Mg": 12, + "Al": 13, + "Si": 14, + "P": 15, + "S": 16, + "Cl": 17, + "Ar": 18, + "K": 19, + "Ca": 20, + "Sc": 21, + "Ti": 22, + "V": 23, + "Cr": 24, + "Mn": 25, + "Fe": 26, + "Co": 27, + "Ni": 28, + "Cu": 29, + "Zn": 30, + "Ga": 31, + "Ge": 32, + "As": 33, + "Se": 34, + "Br": 35, + "Kr": 36, + "Rb": 37, + "Sr": 38, + "Y": 39, + "Zr": 40, + "Nb": 41, + "Mo": 42, + "Tc": 43, + "Ru": 44, + "Rh": 45, + "Pd": 46, + "Ag": 47, + "Cd": 48, + "In": 49, + "Sn": 50, + "Sb": 51, + "Te": 52, + "I": 53, + "Xe": 54, + "Cs": 55, + "Ba": 56, + "La": 57, + "Ce": 58, + "Pr": 59, + "Nd": 60, + "Pm": 61, + "Sm": 62, + "Eu": 63, + "Gd": 64, + "Tb": 65, + "Dy": 66, + "Ho": 67, + "Er": 68, + "Tm": 69, + "Yb": 70, + "Lu": 71, + "Hf": 72, + "Ta": 73, + "W": 74, + "Re": 75, + "Os": 76, + "Ir": 77, + "Pt": 78, + "Au": 79, + "Hg": 80, + "Tl": 81, + "Pb": 82, + "Bi": 83, + "Po": 84, + "At": 85, + "Rn": 86, + "Fr": 87, + "Ra": 88, + "Ac": 89, + "Th": 90, + "Pa": 91, + "U": 92, + "Np": 93, + "Pu": 94, + "Am": 95, + "Cm": 96, + "Bk": 97, + "Cf": 98, + "Es": 99, + "Fm": 100, + "Md": 101, + "No": 102, + "Lr": 103, + "Rf": 104, + "Db": 105, + "Sg": 106, + "Bh": 107, + "Hs": 108, + "Mt": 109, + "Ds": 110, + "Rg": 111, + "Cn": 112, + "Nh": 113, + "Fl": 114, + "Mc": 115, + "Lv": 116, + "Ts": 117, + "Og": 118, } return PERIODIC_TABLE_TOINDEX[elem] + def write_molden_atoms(labels, kinds, labels_kinds_map, coords): """write the Molden [Atoms] section - + Args: labels (list): the labels of atoms kinds (list): the kinds of atoms labels_kinds_map (list): the mapping from labels to kinds coords (list): the coordinates of atoms - + Returns: str: the string formatted in Molden format """ assert len(labels) == len(coords) natom = len(labels) - lkm = labels_kinds_map # just for short notation - out = "[Atoms] AU\n" + lkm = labels_kinds_map # just for short notation + out = "[Atoms] AU\n" for i in range(natom): elem = kinds[lkm[i]] out += f"{elem:<2s}{i+1:>8d}{ptable(elem):>8d}{coords[i][0]:>15.6f}{coords[i][1]:>15.6f}{coords[i][2]:>15.6f}\n" return out + def read_abacus_input(finput): """Read the ABACUS input file and return the key-value pairs - + Args: finput (str): the file name of the ABACUS input file - + Returns: dict: the key-value pairs in the input file """ import os, re + assert os.path.basename(finput) == "INPUT" - with open(finput, 'r') as file: + with open(finput, "r") as file: lines = file.readlines() if lines[0] == "INPUT_PARAMETERS\n": lines = lines[1:] @@ -816,6 +1027,7 @@ def read_abacus_input(finput): kv[m.group(1)] = m.group(2) return kv + def read_abacus_kpt(fkpt): """the way to organize information of KPT file of ABACUS still has some degree of freedom. However, the only one wanted should have content like the following: @@ -832,7 +1044,7 @@ def read_abacus_kpt(fkpt): This function is not really read kpoints and return something, instead, it is for assert the number of kpoints is 1. """ - with open(fkpt, 'r') as file: + with open(fkpt, "r") as file: lines = file.readlines() lines = [line.strip() for line in lines] if lines[0] == "K_POINTS": @@ -843,70 +1055,74 @@ def read_abacus_kpt(fkpt): raise ValueError(f"Invalid KPT file {fkpt}. Presently only 1 kpoint calculation \ (implicit or explicit) Gamma-only calculation is supported.") + def CondonShortleyPhase(index): - """Imposing the Condon-Shortley phase on the MO index. - Molden requires the magnetic quantum number to be arranged like 0, +1, -1, +2, -2, ... + """Imposing the Condon-Shortley phase on the MO index. + Molden requires the magnetic quantum number to be arranged like 0, +1, -1, +2, -2, ... for orbitals with l >= 2, while for l = 1, it should be 1, -1, 0. - ABACUS arranges all the orbital in sequence 0, +1, -1, +2, -2, ... for all l, but + ABACUS arranges all the orbital in sequence 0, +1, -1, +2, -2, ... for all l, but missing the Condon-Shortley phase. This function will add the phase to the index. Args: index (list): the index of the MO - + Returns: list: the index containing elements with the indication whether the (-1) phase should be added. """ if len(index) == 1: return index - elif len(index) == 3: # P orbital + elif len(index) == 3: # P orbital a, b, c = index return [-a, -b, c] # more complicated case, the (-1)^m. - l = int((len(index) - 1)/2) - out = [index[i]*(-1)**(int((i+1)/2)%2) for i in range(len(index))] + l = int((len(index) - 1) / 2) + out = [index[i] * (-1) ** (int((i + 1) / 2) % 2) for i in range(len(index))] return [int(o) for o in out] + def indexing_mo(total_gto: GTORadials, labels: list): """Rearrange the GTOs according to requirement of Molden format - + Args: total_gto (GTORadials): the total GTO radials labels (list): the labels of each atom, its values start from 0 - + Returns: list: the rearranged index of MOs """ - #ntype = len(total_gto.NumericalRadials) + # ntype = len(total_gto.NumericalRadials) i, out = 0, [] for it in labels: lmax = len(total_gto.NumericalRadials[it]) for l in range(lmax): nz = len(total_gto.NumericalRadials[it][l]) for iz in range(nz): - appendee = [i+1, i+2, i] if l == 1 else range(i, i+(2*l+1)) + appendee = [i + 1, i + 2, i] if l == 1 else range(i, i + (2 * l + 1)) out.extend(CondonShortleyPhase(appendee)) - i += 2*l+1 + i += 2 * l + 1 return out + def moldengen(folder: str, ndigits=3, ngto=7, rel_r=2, fmolden="ABACUS.molden"): - """Entrance function: generate molden file by reading the outdir of ABACUS, for only LCAO + """Entrance function: generate molden file by reading the outdir of ABACUS, for only LCAO calculation. - + Args: folder (str): the folder containing the ABACUS input and output files ndigits (int): the number of digits to be printed for the coefficients ngto (int): the number of GTOs to be fitted to the numerical atomic orbitals fmolden (str): the file name of the molden file - + Returns: str: the content of the molden file""" import os import numpy as np files = os.listdir(folder) - assert ("STRU" in files) and ("INPUT" in files) and ("KPT" in files),\ - "STRU, INPUT, KPT files are required in the folder." + assert ( + ("STRU" in files) and ("INPUT" in files) and ("KPT" in files) + ), "STRU, INPUT, KPT files are required in the folder." cwd = os.path.abspath(os.getcwd()) os.chdir(folder) #################### @@ -920,26 +1136,26 @@ def moldengen(folder: str, ndigits=3, ngto=7, rel_r=2, fmolden="ABACUS.molden"): kv = read_abacus_input("INPUT") _ = read_abacus_kpt(kv.get("kpoint_file", "KPT")) stru = read_abacus_stru(kv.get("stru_file", "STRU")) - out += write_molden_cell(stru['lat']['const'], stru['lat']['vec']) - + out += write_molden_cell(stru["lat"]["const"], stru["lat"]["vec"]) + #################### # write the atoms # #################### # molden requires coordinates in Bohr - - kinds = [spec['symbol'] for spec in stru['species']] + + kinds = [spec["symbol"] for spec in stru["species"]] labels_kinds_map = [] - for i, spec in enumerate(stru['species']): - labels_kinds_map.extend([i]*spec['natom']) + for i, spec in enumerate(stru["species"]): + labels_kinds_map.extend([i] * spec["natom"]) labels = [kinds[i] for i in labels_kinds_map] - coords = [atom['coord'] for spec in stru['species'] for atom in spec['atom']] + coords = [atom["coord"] for spec in stru["species"] for atom in spec["atom"]] coords = np.array(coords).reshape(-1, 3) - if stru['coord_type'] == "Cartesian": # not direct but in Bohr - coords *= stru['lat']['const'] - elif stru['coord_type'] == "Direct": # in fractional coordinates - vec = np.array(stru['lat']['vec']) * stru['lat']['const'] + if stru["coord_type"] == "Cartesian": # not direct but in Bohr + coords *= stru["lat"]["const"] + elif stru["coord_type"] == "Direct": # in fractional coordinates + vec = np.array(stru["lat"]["vec"]) * stru["lat"]["const"] coords = np.dot(coords, vec) - elif stru['coord_type'].startswith("Cartesian_angstrom"): + elif stru["coord_type"].startswith("Cartesian_angstrom"): # including *_center_xy, *_center_z, *_center_xyz, ... cases coords *= 0.529177249 else: @@ -950,9 +1166,9 @@ def moldengen(folder: str, ndigits=3, ngto=7, rel_r=2, fmolden="ABACUS.molden"): # write the basis # #################### orbital_dir = kv.get("orbital_dir", "./") - forbs = [os.path.join(orbital_dir, spec['orb_file']) for spec in stru["species"]] + forbs = [os.path.join(orbital_dir, spec["orb_file"]) for spec in stru["species"]] forbs = [os.path.abspath(forb) for forb in forbs] - + total_gto = GTORadials() for forb in forbs: gto = convert_nao_to_gto(forb, None, ngto, rel_r) @@ -969,7 +1185,9 @@ def moldengen(folder: str, ndigits=3, ngto=7, rel_r=2, fmolden="ABACUS.molden"): nspin = int(kv.get("nspin", 1)) mo_files = "WFC_NAO_GAMMA1.txt" mo_files = "WFC_NAO_K1.txt" if mo_files not in os.listdir() else mo_files - mo_files = [mo_files] if nspin == 1 else [mo_files, mo_files.replace("1.txt", "2.txt")] + mo_files = ( + [mo_files] if nspin == 1 else [mo_files, mo_files.replace("1.txt", "2.txt")] + ) for ispin, mo_file in enumerate(mo_files): nbands, nlocal, occ, band, ener, data_np = read_abacus_lowf(mo_file) coefs = data_np.tolist() @@ -980,7 +1198,10 @@ def moldengen(folder: str, ndigits=3, ngto=7, rel_r=2, fmolden="ABACUS.molden"): file.write(out) return out + import unittest + + class TestNAO2GTO(unittest.TestCase): def test_cgto_parse(self): data = """ @@ -1003,22 +1224,37 @@ def test_cgto_parse(self): """ symbols, cgtos = GTORadials._cgto_parse(data) self.assertEqual(symbols, ["Li"]) - self.assertEqual(len(cgtos), 1) # only one type - self.assertEqual(len(cgtos[0]), 2) # s and p - self.assertEqual(len(cgtos[0][0]), 4) # 4 CGTOs for s - self.assertEqual(len(cgtos[0][0][0]), 6) # 6 primitive GTOs for the first CGTO of s - self.assertEqual(len(cgtos[0][0][1]), 3) # 3 primitive GTOs for the second CGTO of s - self.assertEqual(len(cgtos[0][0][2]), 1) # 1 primitive GTOs for the third CGTO of s - self.assertEqual(len(cgtos[0][0][3]), 1) # 1 primitive GTOs for the fourth CGTO of s + self.assertEqual(len(cgtos), 1) # only one type + self.assertEqual(len(cgtos[0]), 2) # s and p + self.assertEqual(len(cgtos[0][0]), 4) # 4 CGTOs for s + self.assertEqual( + len(cgtos[0][0][0]), 6 + ) # 6 primitive GTOs for the first CGTO of s + self.assertEqual( + len(cgtos[0][0][1]), 3 + ) # 3 primitive GTOs for the second CGTO of s + self.assertEqual( + len(cgtos[0][0][2]), 1 + ) # 1 primitive GTOs for the third CGTO of s + self.assertEqual( + len(cgtos[0][0][3]), 1 + ) # 1 primitive GTOs for the fourth CGTO of s # thus it is 6-311G basis for Li - self.assertEqual(len(cgtos[0][1]), 3) # 2 CGTOs for p - self.assertEqual(len(cgtos[0][1][0]), 3) # 3 primitive GTOs for the first CGTO of p - self.assertEqual(len(cgtos[0][1][1]), 1) # 1 primitive GTOs for the second CGTO of p - self.assertEqual(len(cgtos[0][1][2]), 1) # 1 primitive GTOs for the third CGTO of p + self.assertEqual(len(cgtos[0][1]), 3) # 2 CGTOs for p + self.assertEqual( + len(cgtos[0][1][0]), 3 + ) # 3 primitive GTOs for the first CGTO of p + self.assertEqual( + len(cgtos[0][1][1]), 1 + ) # 1 primitive GTOs for the second CGTO of p + self.assertEqual( + len(cgtos[0][1][2]), 1 + ) # 1 primitive GTOs for the third CGTO of p def test_build(self): import numpy as np import uuid, os + data = """ Ca 0 S 6 1.00 @@ -1072,30 +1308,33 @@ def test_build(self): with open(fgto, "w") as f: f.write(data) gto_obj = GTORadials(fgto) - os.remove(fgto) # remove the temporary file + os.remove(fgto) # remove the temporary file ngrid = 100 dr = 0.1 - rgrid = np.linspace(0, ngrid*dr, ngrid) # the evenly spaced grid points, the simplest case + rgrid = np.linspace( + 0, ngrid * dr, ngrid + ) # the evenly spaced grid points, the simplest case gto = gto_obj.build(rgrid) - self.assertEqual(len(gto), 1) # only one type - self.assertEqual(len(gto[0]), 3) # s, p, d - self.assertEqual(len(gto[0][0]), 8) # 8 CGTOs for s + self.assertEqual(len(gto), 1) # only one type + self.assertEqual(len(gto[0]), 3) # s, p, d + self.assertEqual(len(gto[0][0]), 8) # 8 CGTOs for s ncgto = len(gto[0][0]) for ic in range(ncgto): self.assertEqual(len(gto[0][0][ic]), ngrid) - self.assertEqual(len(gto[0][1]), 7) # 7 CGTOs for p + self.assertEqual(len(gto[0][1]), 7) # 7 CGTOs for p ncgto = len(gto[0][1]) for ic in range(ncgto): self.assertEqual(len(gto[0][1][ic]), ngrid) - self.assertEqual(len(gto[0][2]), 2) # 2 CGTOs for d + self.assertEqual(len(gto[0][2]), 2) # 2 CGTOs for d ncgto = len(gto[0][2]) for ic in range(ncgto): self.assertEqual(len(gto[0][2][ic]), ngrid) - + def test_inbuilt_str_method(self): import numpy as np import uuid, os + data = """ Ca 0 S 6 1.00 @@ -1149,7 +1388,7 @@ def test_inbuilt_str_method(self): with open(fgto, "w") as f: f.write(data) gto_obj = GTORadials(fgto) - os.remove(fgto) # remove the temporary file + os.remove(fgto) # remove the temporary file # will return """Ca 0 S 6 1.00 @@ -1199,11 +1438,12 @@ def test_inbuilt_str_method(self): D 1 1.00 2.6000000000e-01 1.0000000000e+00 """ - gto_obj.register_cgto([1, 2, 3], [0.1, 0.2, 0.3], 1, 'Arbitrary', 'a') + gto_obj.register_cgto([1, 2, 3], [0.1, 0.2, 0.3], 1, "Arbitrary", "a") def test_cgto_molden(self): import numpy as np import uuid, os + data = """ Li 0 S 6 1.00 @@ -1226,7 +1466,7 @@ def test_cgto_molden(self): with open(fgto, "w") as f: f.write(data) gto_obj = GTORadials(fgto) - os.remove(fgto) # remove the temporary file + os.remove(fgto) # remove the temporary file out = gto_obj.molden_all() print(out) @@ -1245,8 +1485,9 @@ def est_fit_radial_with_gto(self): gto = np.zeros_like(rgrid) for a_, c_ in zip(a, c): gto += GTORadials._build_gto(a_, c_, l, rgrid) - + import matplotlib.pyplot as plt + plt.plot(rgrid, chi, label="NAO") plt.plot(rgrid, gto, label="GTO") plt.axhline(0, color="black", linestyle="--") @@ -1254,9 +1495,10 @@ def est_fit_radial_with_gto(self): plt.savefig("nao2gto.png") plt.close() + class TestABACUSMolden(unittest.TestCase): def test_condon_shortley(self): - index = list(range(5)) # d orbital + index = list(range(5)) # d orbital out = CondonShortleyPhase(index) self.assertEqual(out, [0, -1, -2, 3, 4]) index = list(range(7)) @@ -1269,17 +1511,17 @@ def test_condon_shortley(self): index = [2, 3, 4] out = CondonShortleyPhase(index) self.assertEqual(out, [-2, -3, 4]) - index = list(range(2, 2+5)) + index = list(range(2, 2 + 5)) out = CondonShortleyPhase(index) self.assertEqual(out, [2, -3, -4, 5, 6]) - index = list(range(3, 3+7)) + index = list(range(3, 3 + 7)) out = CondonShortleyPhase(index) self.assertEqual(out, [3, -4, -5, 6, 7, -8, -9]) - def test_mo_rearrange(self): self.maxDiff = None import os, uuid + basissetexchange = """ Li 0 S 6 1.00 @@ -1301,19 +1543,61 @@ def test_mo_rearrange(self): fgto = "gto_" + str(uuid.uuid4()) with open(fgto, "w") as file: file.write(basissetexchange) - + total_gto = GTORadials(fgto=fgto) os.remove(fgto) labels = [0, 0, 0] mo_index = indexing_mo(total_gto, labels) - self.assertEqual(mo_index, [0, 1, 2, 3, -5, -6, 4, -8, -9, 7, -11, -12, 10, 13, 14, - 15, 16, -18, -19, 17, -21, -22, 20, -24, -25, 23, 26, 27, - 28, 29, -31, -32, 30, -34, -35, 33, -37, -38, 36]) + self.assertEqual( + mo_index, + [ + 0, + 1, + 2, + 3, + -5, + -6, + 4, + -8, + -9, + 7, + -11, + -12, + 10, + 13, + 14, + 15, + 16, + -18, + -19, + 17, + -21, + -22, + 20, + -24, + -25, + 23, + 26, + 27, + 28, + 29, + -31, + -32, + 30, + -34, + -35, + 33, + -37, + -38, + 36, + ], + ) + def _argparse(): """Parse the command line arguments Support the following flags: - + -f, --folder: the folder of the ABACUS calculation, in which the STRU, INPUT, KPT, and OUT* folders are located. -n, --ndigits: the number of digits for the MO coefficients. For MO coefficients smaller than 10^-n, they will be set to 0. -g, --ngto: the number of GTOs to fit ABACUS NAOs. The default is 7. @@ -1321,28 +1605,60 @@ def _argparse(): -o, --output: the output Molden file name. The default is ABACUS.molden. """ import argparse - parser = argparse.ArgumentParser(description="Generate Molden file from ABACUS LCAO calculation via NAO2GTO method") + + parser = argparse.ArgumentParser( + description="Generate Molden file from ABACUS LCAO calculation via NAO2GTO method" + ) welcome = """WARNING: use at your own risk because the NAO2GTO will not always conserve the shape of radial function, therefore the total number of electrons may not be conserved. Always use after a re-normalization operation. Once meet any problem, please submit an issue at: https://github.com/deepmodeling/abacus-develop/issues """ parser.epilog = welcome - parser.add_argument("-f", "--folder", type=str, help="the folder of the ABACUS calculation") - parser.add_argument("-n", "--ndigits", type=int, default=3, help="the number of digits for the MO coefficients") - parser.add_argument("-g", "--ngto", type=int, default=7, help="the number of GTOs to fit ABACUS NAOs") - parser.add_argument("-r", "--rel_r", type=int, default=2, help="the relative cutoff radius for the GTOs") - parser.add_argument("-o", "--output", type=str, default="ABACUS.molden", help="the output Molden file name") + parser.add_argument( + "-f", "--folder", type=str, help="the folder of the ABACUS calculation" + ) + parser.add_argument( + "-n", + "--ndigits", + type=int, + default=3, + help="the number of digits for the MO coefficients", + ) + parser.add_argument( + "-g", + "--ngto", + type=int, + default=7, + help="the number of GTOs to fit ABACUS NAOs", + ) + parser.add_argument( + "-r", + "--rel_r", + type=int, + default=2, + help="the relative cutoff radius for the GTOs", + ) + parser.add_argument( + "-o", + "--output", + type=str, + default="ABACUS.molden", + help="the output Molden file name", + ) args = parser.parse_args() return args + if __name__ == "__main__": - #unittest.main(exit=False) + # unittest.main(exit=False) args = _argparse() moldengen(args.folder, args.ndigits, args.ngto, args.rel_r, args.output) - print(" ".join("*"*10).center(80, " ")) - print(f"""MOLDEN: Generated Molden file {args.output} from ABACUS calculation in folder {args.folder}. + print(" ".join("*" * 10).center(80, " ")) + print( + f"""MOLDEN: Generated Molden file {args.output} from ABACUS calculation in folder {args.folder}. WARNING: use at your own risk because the NAO2GTO will not always conserve the shape of radial function, therefore -the total number of electrons may not be conserved. Always use after a re-normalization operation.""") +the total number of electrons may not be conserved. Always use after a re-normalization operation.""" + ) citation = """If you use this script in your research, please cite the following paper:\n ABACUS: Li P, Liu X, Chen M, et al. Large-scale ab initio simulations based on systematically improvable atomic basis[J]. @@ -1352,4 +1668,4 @@ def _argparse(): Qin X, Shang H, Xiang H, et al. HONPAS: A linear scaling open-source solution for large system simulations[J]. International Journal of Quantum Chemistry, 2015, 115(10): 647-655. """ - print(citation, flush=True) \ No newline at end of file + print(citation, flush=True) diff --git a/tools/opt_abfs_bash/exx.py b/tools/opt_abfs_bash/exx.py index 9f0306a11ed..c901ad6b454 100644 --- a/tools/opt_abfs_bash/exx.py +++ b/tools/opt_abfs_bash/exx.py @@ -5,70 +5,72 @@ import utils import read_stru + def cal(): - pathlib.Path(utils.folder_exx).mkdir(parents=True,exist_ok=False) - - os.system(f"cp INPUT {utils.folder_exx}/") - os.system(f"cp KPT {utils.folder_exx}/") - - with open(f"{utils.folder_exx}/INPUT","w") as file: - input_dict = read_stru.get_input_dict() - input_dict["pseudo_dir"] = os.path.abspath(input_dict.get("pseudo_dir",r"./")) - read_stru.print_input(file,input_dict,1) - - with open("STRU","r") as file: - strus = re.compile("LATTICE_CONSTANT").split(file.read()) - with open(f"{utils.folder_exx}/STRU","w") as file: - Ts = read_stru.get_T() - file.write("ATOMIC_SPECIES\n") - pseudo_path = read_stru.get_pseudo_path() - for T in Ts: - file.write(f"{T} 12 {pseudo_path[T]}\n") - file.write("\nNUMERICAL_ORBITAL\n") - lcao_path = read_stru.get_lcao_path() - for T in Ts: - file.write(f"{lcao_path[T]}\n") - file.write("\nABFS_ORBITAL\n") - for T in read_stru.get_T(): - file.write(f"../{utils.folder_opt}/orb_{T}.dat\n") - file.write("\nLATTICE_CONSTANT") - file.write(strus[1]) - - info = utils.read_info() - if utils.sub=="qsub": - with open(f"{utils.folder_exx}/sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/bash - #PBS -q gold5120 - #PBS -l nodes=2:ppn=28 - #PBS -l walltime=99:99:99 - #PBS -o job.log - #PBS -e job.err - ulimit -s unlimited - cd $PBS_O_WORKDIR - EXEC={info["ABACUS"]} - mpirun -n 2 -env OMP_NUM_THREADS=28 $EXEC - """)) - elif utils.sub=="bsub": - with open(f"{utils.folder_exx}/sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/sh - #BSUB -q renxg - #BSUB -o job.log -e job.err - #BSUB -n 6 - mpirun -n 2 -env OMP_NUM_THREADS=28 {info['ABACUS']} - """)) + pathlib.Path(utils.folder_exx).mkdir(parents=True, exist_ok=False) + + os.system(f"cp INPUT {utils.folder_exx}/") + os.system(f"cp KPT {utils.folder_exx}/") + + with open(f"{utils.folder_exx}/INPUT", "w") as file: + input_dict = read_stru.get_input_dict() + input_dict["pseudo_dir"] = os.path.abspath(input_dict.get("pseudo_dir", r"./")) + read_stru.print_input(file, input_dict, 1) + + with open("STRU", "r") as file: + strus = re.compile("LATTICE_CONSTANT").split(file.read()) + with open(f"{utils.folder_exx}/STRU", "w") as file: + Ts = read_stru.get_T() + file.write("ATOMIC_SPECIES\n") + pseudo_path = read_stru.get_pseudo_path() + for T in Ts: + file.write(f"{T} 12 {pseudo_path[T]}\n") + file.write("\nNUMERICAL_ORBITAL\n") + lcao_path = read_stru.get_lcao_path() + for T in Ts: + file.write(f"{lcao_path[T]}\n") + file.write("\nABFS_ORBITAL\n") + for T in read_stru.get_T(): + file.write(f"../{utils.folder_opt}/orb_{T}.dat\n") + file.write("\nLATTICE_CONSTANT") + file.write(strus[1]) + + info = utils.read_info() + if utils.sub == "qsub": + with open(f"{utils.folder_exx}/sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #PBS -q gold5120 + #PBS -l nodes=2:ppn=28 + #PBS -l walltime=99:99:99 + #PBS -o job.log + #PBS -e job.err + ulimit -s unlimited + cd $PBS_O_WORKDIR + EXEC={info["ABACUS"]} + mpirun -n 2 -env OMP_NUM_THREADS=28 $EXEC + """)) + elif utils.sub == "bsub": + with open(f"{utils.folder_exx}/sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/sh + #BSUB -q renxg + #BSUB -o job.log -e job.err + #BSUB -n 6 + mpirun -n 2 -env OMP_NUM_THREADS=28 {info['ABACUS']} + """)) + + os.chdir(utils.folder_exx) + if utils.sub == "qsub": + os.system("qsub sub.sh") + elif utils.sub == "bsub": + os.system(f"bsub < sub.sh") + elif utils.sub == "tianhe2": + os.system(f'yhrun -N 1 -n 1 -c 24 -t 1440 {info["ABACUS"]} >Log.txt 2>&1 &') + else: + raise ValueError("utils.sub") + os.chdir("../") + - os.chdir(utils.folder_exx) - if utils.sub=="qsub": - os.system("qsub sub.sh") - elif utils.sub=="bsub": - os.system(f"bsub < sub.sh") - elif utils.sub=="tianhe2": - os.system(f'yhrun -N 1 -n 1 -c 24 -t 1440 {info["ABACUS"]} >Log.txt 2>&1 &') - else: - raise ValueError("utils.sub") - os.chdir("../") - -if __name__=="__main__": - cal() +if __name__ == "__main__": + cal() diff --git a/tools/opt_abfs_bash/opt_orb.py b/tools/opt_abfs_bash/opt_orb.py index 53ba04eaa56..0dfbfae2631 100644 --- a/tools/opt_abfs_bash/opt_orb.py +++ b/tools/opt_abfs_bash/opt_orb.py @@ -6,96 +6,106 @@ import read_stru import utils + def cp_matrix(folders_matrix): - pathlib.Path(utils.folder_opt+"/"+utils.folder_opt_matrix).mkdir(parents=True,exist_ok=False) - folders_same_atom = set() - for folder_matrix in folders_matrix: - T1,T2 = folder_matrix.split("_")[0].split("-") - dis = float(folder_matrix.split("_")[1]) - if dis: - if T1==T2: - matrix_file = "matrix_0_0_0_1" - else: - matrix_file = "matrix_0_0_1_0" - else: - matrix_file = "matrix_0_0_0_0" - os.system(f"cp {folder_matrix}/{matrix_file} {utils.folder_opt}/{utils.folder_opt_matrix}/{folder_matrix}") - + pathlib.Path(utils.folder_opt + "/" + utils.folder_opt_matrix).mkdir( + parents=True, exist_ok=False + ) + folders_same_atom = set() + for folder_matrix in folders_matrix: + T1, T2 = folder_matrix.split("_")[0].split("-") + dis = float(folder_matrix.split("_")[1]) + if dis: + if T1 == T2: + matrix_file = "matrix_0_0_0_1" + else: + matrix_file = "matrix_0_0_1_0" + else: + matrix_file = "matrix_0_0_0_0" + os.system( + f"cp {folder_matrix}/{matrix_file} {utils.folder_opt}/{utils.folder_opt_matrix}/{folder_matrix}" + ) + + def add_nbands(folders_matrix): - for folder_matrix in folders_matrix: - with open(f"{utils.folder_opt}/{utils.folder_opt_matrix}/{folder_matrix}","r") as file: - nband = int(re.compile(r"(\d+)\s+nbands").search(file.read()).group(1)) - folders_matrix[folder_matrix] = (folders_matrix[folder_matrix], nband) + for folder_matrix in folders_matrix: + with open( + f"{utils.folder_opt}/{utils.folder_opt_matrix}/{folder_matrix}", "r" + ) as file: + nband = int(re.compile(r"(\d+)\s+nbands").search(file.read()).group(1)) + folders_matrix[folder_matrix] = (folders_matrix[folder_matrix], nband) + def set_input(folders_matrix): - Ts = read_stru.get_T() - input_dict = read_stru.get_input_dict() - Ecut = float(input_dict["ecutwfc"]) - info = utils.read_info() - input = { - "file_list": [f"{utils.folder_opt_matrix}/"+folder_matrix for folder_matrix in folders_matrix], - "info": - { - "Nt_all": Ts, - "Nu": {T:info["Nu"] for T in Ts}, - "Nb_true": [nbands for weight,nbands in folders_matrix.values()], - "weight": [weight for weight,nbands in folders_matrix.values()], - "Rcut": read_stru.get_Rcut(), - "dr": {T:utils.dr for T in Ts}, - "Ecut": {T:Ecut for T in Ts}, - "lr": utils.lr - }, - "C_init_info":{ "init_from_file": False }, - "V_info": - { - "init_from_file": True, - "same_band": False - } - } - return json.dumps(input,indent=4) - + Ts = read_stru.get_T() + input_dict = read_stru.get_input_dict() + Ecut = float(input_dict["ecutwfc"]) + info = utils.read_info() + input = { + "file_list": [ + f"{utils.folder_opt_matrix}/" + folder_matrix + for folder_matrix in folders_matrix + ], + "info": { + "Nt_all": Ts, + "Nu": {T: info["Nu"] for T in Ts}, + "Nb_true": [nbands for weight, nbands in folders_matrix.values()], + "weight": [weight for weight, nbands in folders_matrix.values()], + "Rcut": read_stru.get_Rcut(), + "dr": {T: utils.dr for T in Ts}, + "Ecut": {T: Ecut for T in Ts}, + "lr": utils.lr, + }, + "C_init_info": {"init_from_file": False}, + "V_info": {"init_from_file": True, "same_band": False}, + } + return json.dumps(input, indent=4) + + def cal(input): - info = utils.read_info() - with open(f"{utils.folder_opt}/input.json","w") as file: - file.write(input) - if utils.sub=="qsub": - with open(f"{utils.folder_opt}/sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/bash - #PBS -q gold5120 - #PBS -l nodes=1:ppn=1 - #PBS -l walltime=2:00:00 - #PBS -o job.log - #PBS -e job.err - ulimit -s unlimited - cd $PBS_O_WORKDIR - export OMP_NUM_THREADS=1 - EXEC={info["opt_orb"]} - python3 -u $EXEC - """)) - elif utils.sub=="tianhe2": - with open(f"{utils.folder_opt}/sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/bash - EXEC={info["opt_orb"]} - python3 -u $EXEC >Log.txt - """)) - os.chdir(utils.folder_opt) - if utils.sub=="qsub": - os.system("qsub sub.sh") - elif utils.sub=="tianhe2": - os.system("yhbatch -N 1 sub.sh") -# os.system(f'python3 -u {info["opt_orb"]}') - os.chdir("../") - + info = utils.read_info() + with open(f"{utils.folder_opt}/input.json", "w") as file: + file.write(input) + if utils.sub == "qsub": + with open(f"{utils.folder_opt}/sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #PBS -q gold5120 + #PBS -l nodes=1:ppn=1 + #PBS -l walltime=2:00:00 + #PBS -o job.log + #PBS -e job.err + ulimit -s unlimited + cd $PBS_O_WORKDIR + export OMP_NUM_THREADS=1 + EXEC={info["opt_orb"]} + python3 -u $EXEC + """)) + elif utils.sub == "tianhe2": + with open(f"{utils.folder_opt}/sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/bash + EXEC={info["opt_orb"]} + python3 -u $EXEC >Log.txt + """)) + os.chdir(utils.folder_opt) + if utils.sub == "qsub": + os.system("qsub sub.sh") + elif utils.sub == "tianhe2": + os.system("yhbatch -N 1 sub.sh") + # os.system(f'python3 -u {info["opt_orb"]}') + os.chdir("../") + + def all(): - pathlib.Path(utils.folder_opt).mkdir(parents=True,exist_ok=False) - with open("folders","r") as file: - folders_matrix = json.loads(file.read()) - cp_matrix(folders_matrix.keys()) - add_nbands(folders_matrix) - input = set_input(folders_matrix) - cal(input) - -if __name__=="__main__": - all() \ No newline at end of file + pathlib.Path(utils.folder_opt).mkdir(parents=True, exist_ok=False) + with open("folders", "r") as file: + folders_matrix = json.loads(file.read()) + cp_matrix(folders_matrix.keys()) + add_nbands(folders_matrix) + input = set_input(folders_matrix) + cal(input) + + +if __name__ == "__main__": + all() diff --git a/tools/opt_abfs_bash/read_stru.py b/tools/opt_abfs_bash/read_stru.py index c8bf06756a5..b57dc9c129a 100644 --- a/tools/opt_abfs_bash/read_stru.py +++ b/tools/opt_abfs_bash/read_stru.py @@ -10,231 +10,259 @@ import json import utils + def skip_notes(line): - line = re.compile(r"#.*").sub("",line) - line = re.compile(r"//.*").sub("",line) - line = line.strip() - return line + line = re.compile(r"#.*").sub("", line) + line = re.compile(r"//.*").sub("", line) + line = line.strip() + return line + @functools.lru_cache(maxsize=None) def get_input_dict(): - input_dict = dict() - with open("INPUT","r") as file: - for line in file: - line = skip_notes(line) - if not line or line=="INPUT_PARAMETERS": - continue - label, value = re.compile(r"\s+").split( line, maxsplit=1 ) - input_dict[label] = value - return input_dict - -def print_input(file,input_dict,tag=0): - print("INPUT_PARAMETERS",file=file) - max_len = max([len(label) for label in input_dict]) - for label,value in input_dict.items(): - if tag==0 and label in ["nelec", "ocp", "ocp_set"]: - continue - print( label, " "*(max_len-len(label)+4), value, file=file) - - + input_dict = dict() + with open("INPUT", "r") as file: + for line in file: + line = skip_notes(line) + if not line or line == "INPUT_PARAMETERS": + continue + label, value = re.compile(r"\s+").split(line, maxsplit=1) + input_dict[label] = value + return input_dict + + +def print_input(file, input_dict, tag=0): + print("INPUT_PARAMETERS", file=file) + max_len = max([len(label) for label in input_dict]) + for label, value in input_dict.items(): + if tag == 0 and label in ["nelec", "ocp", "ocp_set"]: + continue + print(label, " " * (max_len - len(label) + 4), value, file=file) + + """ @functools.lru_cache(maxsize=None) def search_in_input(label): - with open("INPUT","r") as file: - regex = label+"\s+(\d+)" - value = re.compile(regex).search(file.read()).group(1) - return value + with open("INPUT","r") as file: + regex = label+"\s+(\d+)" + value = re.compile(regex).search(file.read()).group(1) + return value """ + @functools.lru_cache(maxsize=None) def get_k(): - with open("KPT","r") as file: - utils.search_sentence(file,"Gamma") - return list(map(int,skip_notes(file.readline()).split()[:3])) + with open("KPT", "r") as file: + utils.search_sentence(file, "Gamma") + return list(map(int, skip_notes(file.readline()).split()[:3])) + @functools.lru_cache(maxsize=None) def get_T(): - ntype = int(get_input_dict()["ntype"]) - T = [] - with open("STRU","r") as file: - utils.search_sentence(file,"ATOMIC_SPECIES") - for it in range(ntype): - line = skip_notes(file.readline()) - T.append(line.split()[0]) - return T + ntype = int(get_input_dict()["ntype"]) + T = [] + with open("STRU", "r") as file: + utils.search_sentence(file, "ATOMIC_SPECIES") + for it in range(ntype): + line = skip_notes(file.readline()) + T.append(line.split()[0]) + return T + @functools.lru_cache(maxsize=None) def get_Rcut(): - Ts = get_T() - lcao_path = get_lcao_path() - Rcut = dict() - for T in Ts: - with open(lcao_path[T],"r") as file: - for line in file: - line = skip_notes(line) - if line.startswith("Radius Cutoff(a.u.)"): - Rcut[T] = float(line.split()[-1]) - break - return Rcut + Ts = get_T() + lcao_path = get_lcao_path() + Rcut = dict() + for T in Ts: + with open(lcao_path[T], "r") as file: + for line in file: + line = skip_notes(line) + if line.startswith("Radius Cutoff(a.u.)"): + Rcut[T] = float(line.split()[-1]) + break + return Rcut + @functools.lru_cache(maxsize=None) def get_pseudo_path(): - Ts = get_T() - path = dict() - with open("STRU","r") as file: - utils.search_sentence(file,"ATOMIC_SPECIES") - for T in Ts: - path[T] = skip_notes(file.readline()).split()[-1] - return path - + Ts = get_T() + path = dict() + with open("STRU", "r") as file: + utils.search_sentence(file, "ATOMIC_SPECIES") + for T in Ts: + path[T] = skip_notes(file.readline()).split()[-1] + return path + + @functools.lru_cache(maxsize=None) def get_lcao_path(): - Ts = get_T() - path = dict() - with open("STRU","r") as file: - utils.search_sentence(file,"NUMERICAL_ORBITAL") - for T in Ts: - path[T] = os.path.abspath(skip_notes(file.readline())) - return path - + Ts = get_T() + path = dict() + with open("STRU", "r") as file: + utils.search_sentence(file, "NUMERICAL_ORBITAL") + for T in Ts: + path[T] = os.path.abspath(skip_notes(file.readline())) + return path + + @functools.lru_cache(maxsize=None) def get_lattice(): - with open("STRU","r") as file: - utils.search_sentence(file,"LATTICE_CONSTANT") - lat0 = float(skip_notes(file.readline()).split()[0]) - with open("STRU","r") as file: - utils.search_sentence(file,"LATTICE_VECTORS") - lat_vec = [] - for i in range(3): - lat_vec.append(list(map(float,skip_notes(file.readline()).split()))) - lat_vec = np.array(lat_vec) - with open("STRU","r") as file: - utils.search_sentence(file,"ATOMIC_POSITIONS") - position = skip_notes(file.readline()) - return lat0, lat_vec, position - + with open("STRU", "r") as file: + utils.search_sentence(file, "LATTICE_CONSTANT") + lat0 = float(skip_notes(file.readline()).split()[0]) + with open("STRU", "r") as file: + utils.search_sentence(file, "LATTICE_VECTORS") + lat_vec = [] + for i in range(3): + lat_vec.append(list(map(float, skip_notes(file.readline()).split()))) + lat_vec = np.array(lat_vec) + with open("STRU", "r") as file: + utils.search_sentence(file, "ATOMIC_POSITIONS") + position = skip_notes(file.readline()) + return lat0, lat_vec, position + + @functools.lru_cache(maxsize=None) def get_lcao(): - lcao = collections.defaultdict(list) - lcao_path = get_lcao_path() - for T in lcao_path: - with open(lcao_path[T],"r") as file: - for line in file: - line = skip_notes(line) - if line.startswith("Number of"): - lcao[T].append(int(line.split()[-1])) - return dict(lcao) - + lcao = collections.defaultdict(list) + lcao_path = get_lcao_path() + for T in lcao_path: + with open(lcao_path[T], "r") as file: + for line in file: + line = skip_notes(line) + if line.startswith("Number of"): + lcao[T].append(int(line.split()[-1])) + return dict(lcao) + + @functools.lru_cache(maxsize=None) def get_nw(): - nw = dict() - lcao = get_lcao() - for T in lcao: - nw[T] = functools.reduce(operator.add,((2*l+1)*n for l,n in enumerate(lcao[T]))) - return nw + nw = dict() + lcao = get_lcao() + for T in lcao: + nw[T] = functools.reduce( + operator.add, ((2 * l + 1) * n for l, n in enumerate(lcao[T])) + ) + return nw + # R[T] = [..., [xi,yi,zi], ...] def get_R(): - Ts = get_T() - R = dict() - with open("STRU","r") as file: - for T in Ts: - utils.search_sentence(file,T) - utils.ignore_lines(file,1) - na = int(skip_notes(file.readline()).split()[0]) - R_tmp = [] - for i in range(na): - R_tmp.append(list(map(float,skip_notes(file.readline()).split()[:3]))) - R[T] = np.array(R_tmp) - return R + Ts = get_T() + R = dict() + with open("STRU", "r") as file: + for T in Ts: + utils.search_sentence(file, T) + utils.ignore_lines(file, 1) + na = int(skip_notes(file.readline()).split()[0]) + R_tmp = [] + for i in range(na): + R_tmp.append(list(map(float, skip_notes(file.readline()).split()[:3]))) + R[T] = np.array(R_tmp) + return R + def change_R(R): - lat0, lat_vec, position = get_lattice() - R_new = R.copy() - if position == "Direct": - for T in R_new: - R_new[T] = np.dot(R_new[T],lat_vec) - elif position == "Cartesian_angstrom": - for T in R_new: - R_new[T] /= 0.529166 - for T in R_new: - R_new[T] *= lat0 - return R_new + lat0, lat_vec, position = get_lattice() + R_new = R.copy() + if position == "Direct": + for T in R_new: + R_new[T] = np.dot(R_new[T], lat_vec) + elif position == "Cartesian_angstrom": + for T in R_new: + R_new[T] /= 0.529166 + for T in R_new: + R_new[T] *= lat0 + return R_new + def supercell_R(R): - nx,ny,nz = get_k() - lat0, lat_vec, position = get_lattice() - lat_vec *= lat0 - R_new = dict() - for T in R: - R_new_T = [] - for ix in range(nx): - for iy in range(ny): - for iz in range(nz): - R_new_T.append( R[T] + np.dot(np.array([ix,iy,iz]), lat_vec) ) - R_new[T] = np.concatenate(R_new_T) - return R_new + nx, ny, nz = get_k() + lat0, lat_vec, position = get_lattice() + lat_vec *= lat0 + R_new = dict() + for T in R: + R_new_T = [] + for ix in range(nx): + for iy in range(ny): + for iz in range(nz): + R_new_T.append(R[T] + np.dot(np.array([ix, iy, iz]), lat_vec)) + R_new[T] = np.concatenate(R_new_T) + return R_new + # dis[T1,T2] = {..., i_dis:num, ...} -def cal_dis(R1,R2): - dis = dict() - for T1,T2 in itertools.combinations_with_replacement(R1,2): - dis_TT = collections.defaultdict(int) - for ia1,ia2 in itertools.product(R1[T1],R2[T2]): - i_dis = np.linalg.norm(ia1-ia2) - dis_TT[i_dis] += 1 - dis[T1,T2] = dict(dis_TT) - return dis - -def round_dis(dis,precision): - dis_round = dict() - for T1,T2 in dis: - dis_TT = collections.defaultdict(int) - for i_dis,num in dis[T1,T2].items(): - i_dis = float(decimal.Decimal(i_dis).quantize(decimal.Decimal(str(precision)), rounding=decimal.ROUND_HALF_UP)) # test - dis_TT[i_dis] += num - dis_round[T1,T2] = dict(dis_TT) - return dis_round +def cal_dis(R1, R2): + dis = dict() + for T1, T2 in itertools.combinations_with_replacement(R1, 2): + dis_TT = collections.defaultdict(int) + for ia1, ia2 in itertools.product(R1[T1], R2[T2]): + i_dis = np.linalg.norm(ia1 - ia2) + dis_TT[i_dis] += 1 + dis[T1, T2] = dict(dis_TT) + return dis + + +def round_dis(dis, precision): + dis_round = dict() + for T1, T2 in dis: + dis_TT = collections.defaultdict(int) + for i_dis, num in dis[T1, T2].items(): + i_dis = float( + decimal.Decimal(i_dis).quantize( + decimal.Decimal(str(precision)), rounding=decimal.ROUND_HALF_UP + ) + ) # test + dis_TT[i_dis] += num + dis_round[T1, T2] = dict(dis_TT) + return dis_round + def cut_dis(dis): - Rcut = get_Rcut() - dis_cut = dict() - for T1,T2 in dis: - Rcut_sum = Rcut[T1]+Rcut[T2] - dis_cut[T1,T2] = { i_dis:num for i_dis,num in dis[T1,T2].items() if i_disRcut_sum): - norm = np.linalg.norm(delta) - if norm>0 and normRcut_sum): + norm = np.linalg.norm(delta) + if norm>0 and normLog.txt') - os.chdir("../") - -# dis_opt[T1,T2] = [..., dis, ...] + +def cal_ABACUS(T1, T2, i_dis): + folder = pathlib.Path(utils.folder_name(T1, T2, i_dis)).resolve() + folder.mkdir(parents=True, exist_ok=False) + + with open(folder / "INPUT", "w") as file: + info = utils.read_info() + input_dict = read_stru.get_input_dict() + input_dict["ntype"] = 1 if T1 == T2 else 2 + input_dict["exx_hybrid_type"] = "opt_orb" + input_dict["nbands"] = ( + read_stru.get_nw()[T1] + if abs(i_dis) < 1e-10 + else read_stru.get_nw()[T1] + read_stru.get_nw()[T2] + ) + input_dict["nspin"] = 1 + input_dict["gamma_only"] = 1 + input_dict["pseudo_dir"] = os.path.abspath(input_dict.get("pseudo_dir", r"./")) + input_dict["exx_opt_orb_lmax"] = len(info["Nu"]) - 1 + read_stru.print_input(file, input_dict, 0) + + with open(folder / "STRU", "w") as file: + Ts = (T1,) if T1 == T2 else (T1, T2) + file.write("ATOMIC_SPECIES\n") + pseudo_path = read_stru.get_pseudo_path() + for T in Ts: + file.write(f"{T} 1 {pseudo_path[T]}\n") + file.write("\nNUMERICAL_ORBITAL\n") + lcao_path = read_stru.get_lcao_path() + for T in Ts: + file.write(f"{lcao_path[T]}\n") + file.write(textwrap.dedent(f""" + LATTICE_CONSTANT + 1\n + LATTICE_VECTORS + 30 0 0 + 0 30 0 + 0 0 30\n + ATOMIC_POSITIONS + Cartesian + """)) + if T1 == T2: + if abs(i_dis) < 1e-10: + file.write(textwrap.dedent(f""" + {T1} + 0 + 1 + 0 0 0 0 0 0 + """)) + else: + file.write(textwrap.dedent(f""" + {T1} + 0 + 2 + 0 0 0 0 0 0 + {i_dis} 0 0 0 0 0 + """)) + else: + file.write(textwrap.dedent(f""" + {T1} + 0 + 1 + 0 0 0 0 0 0\n + {T2} + 0 + 1 + {i_dis} 0 0 0 0 0 + """)) + + with open(folder / "KPT", "w") as file: + file.write(textwrap.dedent(f"""\ + K_POINTS + 0 + Gamma + 1 1 1 0 0 0 + """)) + + info = utils.read_info() + if utils.sub == "qsub": + with open(folder / "sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #PBS -q gold5120 + #PBS -l nodes=1:ppn=1 + #PBS -l walltime=12:00:00 + #PBS -o job.log + #PBS -e job.err + ulimit -s unlimited + cd $PBS_O_WORKDIR + EXEC={info["ABACUS"]} + mpirun -n 1 -env OMP_NUM_THREADS=1 $EXEC + """)) + elif utils.sub == "bsub": + with open(folder / "sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/sh + #BSUB -q renxg + #BSUB -o job.log -e job.err + #BSUB -n 1 + EXEC={info["ABACUS"]} + mpirun -n 1 -env OMP_NUM_THREADS=1 $EXEC + """)) + + os.chdir(folder) + if utils.sub == "qsub": + os.system("qsub sub.sh") + elif utils.sub == "bsub": + os.system("bsub < sub.sh") + elif utils.sub == "tianh2": + os.system(f'yhrun -n 1 -c 1 {info["ABACUS"]} >Log.txt') + os.chdir("../") + + +# dis_opt[T1,T2] = [..., dis, ...] def get_dis_opt(dis): - opt_mode = "kmeans" - dis_opt = dict() - info = utils.read_info() - for T1,T2 in dis: - dis_tmp = read_stru.delete_zero(dis[T1,T2]) - if len(dis_tmp)<=info["dimer_num"]: - dis_opt[T1,T2] = list(dis_tmp.keys()) - else: - if opt_mode=="linspace": - dis_opt[T1,T2] = np.linspace( min(dis_tmp), max(dis_tmp), info["dimer_num"] ) - elif opt_mode=="kmeans": - kmeans = KMeans(n_clusters=info["dimer_num"]) - label = kmeans.fit_predict( - np.array(list(dis_tmp.keys())).reshape(-1,1), - sample_weight = [num/i_dis**2 for i_dis,num in dis_tmp.items()]) - dis_opt[T1,T2] = list(kmeans.cluster_centers_.reshape(-1)) - pprint.pprint(dict(zip(dis_tmp.keys(),label))) - if T1==T2: - dis_opt[T1,T2].append(0.0) - return dis_opt - + opt_mode = "kmeans" + dis_opt = dict() + info = utils.read_info() + for T1, T2 in dis: + dis_tmp = read_stru.delete_zero(dis[T1, T2]) + if len(dis_tmp) <= info["dimer_num"]: + dis_opt[T1, T2] = list(dis_tmp.keys()) + else: + if opt_mode == "linspace": + dis_opt[T1, T2] = np.linspace( + min(dis_tmp), max(dis_tmp), info["dimer_num"] + ) + elif opt_mode == "kmeans": + kmeans = KMeans(n_clusters=info["dimer_num"]) + label = kmeans.fit_predict( + np.array(list(dis_tmp.keys())).reshape(-1, 1), + sample_weight=[num / i_dis**2 for i_dis, num in dis_tmp.items()], + ) + dis_opt[T1, T2] = list(kmeans.cluster_centers_.reshape(-1)) + pprint.pprint(dict(zip(dis_tmp.keys(), label))) + if T1 == T2: + dis_opt[T1, T2].append(0.0) + return dis_opt + + # dis_weight[T1,T2] = {..., i_dis_opt:weight, ...} -def cal_dis_weight(dis_opt,dis_all): - def weight_func(x,D): - return (2/D**3)*x**3 + (-3/D**2)*x**2 + 1 - dis_weight = collections.defaultdict(dict) - for T1,T2 in dis_opt: - dis_opt_TT = sorted(dis_opt[T1,T2]) - for index,i_dis_opt in enumerate(dis_opt_TT): - i_weight = 0 - i_dis_low = dis_opt_TT[index-1] if index>0 else -np.infty - i_dis_up = dis_opt_TT[index+1] if index 0 else -np.infty + i_dis_up = ( + dis_opt_TT[index + 1] if index < len(dis_opt_TT) - 1 else np.infty + ) + for i_dis, num in dis_all[T1, T2].items(): + if i_dis_low < i_dis < i_dis_opt: + i_weight += ( + weight_func(i_dis_opt - i_dis, i_dis_opt - i_dis_low) * num + ) + elif i_dis == i_dis_opt: + i_weight += num + elif i_dis_opt < i_dis < i_dis_up: + i_weight += ( + weight_func(i_dis_opt - i_dis, i_dis_opt - i_dis_up) * num + ) + dis_weight[T1, T2][i_dis_opt] = i_weight + return dis_weight + + def cal(): - R = read_stru.change_R(read_stru.get_R()) - R_supercell = read_stru.supercell_R(R) - dis = read_stru.cut_dis(read_stru.cal_dis(R,R_supercell)) - dis_decimal = read_stru.round_dis(dis,1E-6) - pprint.pprint(dis_decimal) - dis_opt = get_dis_opt(dis_decimal) - for T1,T2 in dis_opt: - for i_dis in dis_opt[T1,T2]: - cal_ABACUS(T1,T2,i_dis) - dis_weight = cal_dis_weight(dis_opt,dis) - read_stru.print_folders(dis_weight) - -if __name__=="__main__": - cal() \ No newline at end of file + R = read_stru.change_R(read_stru.get_R()) + R_supercell = read_stru.supercell_R(R) + dis = read_stru.cut_dis(read_stru.cal_dis(R, R_supercell)) + dis_decimal = read_stru.round_dis(dis, 1e-6) + pprint.pprint(dis_decimal) + dis_opt = get_dis_opt(dis_decimal) + for T1, T2 in dis_opt: + for i_dis in dis_opt[T1, T2]: + cal_ABACUS(T1, T2, i_dis) + dis_weight = cal_dis_weight(dis_opt, dis) + read_stru.print_folders(dis_weight) + + +if __name__ == "__main__": + cal() diff --git a/tools/opt_abfs_bash/utils.py b/tools/opt_abfs_bash/utils.py index 8e676b6a460..83af732b34e 100644 --- a/tools/opt_abfs_bash/utils.py +++ b/tools/opt_abfs_bash/utils.py @@ -1,42 +1,50 @@ import json import functools + @functools.lru_cache(maxsize=None) def read_info(flag=True): - """ - { - "ABACUS":"dir/ABACUS/ABACUS.mpi.1.0.0", - "opt_orb":"dir/opt_orb/main.py", - "Nu":[7,10,8,3,1], - "dimer_num":5 - } - """ - with open("info","r") as file: - return json.loads(file.read()) - -def ignore_lines(file,n): - for i in range(n): - file.readline() - -def search_sentence(file,sentence): - sentence = sentence.strip() - for line in file: - if line.strip() == sentence: - break - + """ + { + "ABACUS":"dir/ABACUS/ABACUS.mpi.1.0.0", + "opt_orb":"dir/opt_orb/main.py", + "Nu":[7,10,8,3,1], + "dimer_num":5 + } + """ + with open("info", "r") as file: + return json.loads(file.read()) + + +def ignore_lines(file, n): + for i in range(n): + file.readline() + + +def search_sentence(file, sentence): + sentence = sentence.strip() + for line in file: + if line.strip() == sentence: + break + + def floatlist_str(l): - return "-".join(list(map(str,l))) + return "-".join(list(map(str, l))) + sub = "qsub" -dr = 0.01 -lr = 0.01 +dr = 0.01 +lr = 0.01 + + +def folder_name(T1, T2, i_dis): + return f"{T1}-{T2}_{i_dis}" + -def folder_name(T1,T2,i_dis): - return f"{T1}-{T2}_{i_dis}" try: - info = read_info(False) - folder_opt = "opt_orb_"+floatlist_str(info["Nu"]) - folder_exx = "exx_"+floatlist_str(info["Nu"]) - folder_opt_matrix = "matrix" + info = read_info(False) + folder_opt = "opt_orb_" + floatlist_str(info["Nu"]) + folder_exx = "exx_" + floatlist_str(info["Nu"]) + folder_opt_matrix = "matrix" except FileNotFoundError: - print("info FileNotFoundError") \ No newline at end of file + print("info FileNotFoundError") diff --git a/tools/opt_lcao_bash/dis.py b/tools/opt_lcao_bash/dis.py index ed071177f2b..916efb57b86 100644 --- a/tools/opt_lcao_bash/dis.py +++ b/tools/opt_lcao_bash/dis.py @@ -1,104 +1,104 @@ dis = { - "H": [ 0.6, 0.75, 0.9, 1.2, 1.5 ], - "He": [ 1.25, 1.75, 2.4, 3.25 ], - "Li": [ 1.5, 2.1, 2.5, 2.8, 3.2, 3.5, 4.2 ], - "Be": [ 1.75, 2, 2.375, 3, 4 ], - "B": [ 1.25, 1.625, 2.5, 3.5 ], - "C": [ 1, 1.25, 1.5, 2, 3 ], - "N": [ 1, 1.1, 1.5, 2, 3 ], - "O": [ 1, 1.208, 1.5, 2, 3 ], - "F": [ 1.2, 1.418, 1.75, 2.25, 3.25 ], - "Ne": [ 1.5, 1.75, 2.25, 2.625, 3, 3.5 ], - "Na": [ 2.05, 2.4, 2.8, 3.1, 3.3, 3.8, 4.3 ], - "Mg": [ 2.125, 2.375, 2.875, 3.375, 4.5 ], - "Al": [ 2, 2.5, 3, 3.75, 4.5 ], - "Si": [ 1.75, 2, 2.25, 2.75, 3.75 ], - "P": [ 1.625, 1.875, 2.5, 3.25, 4 ], - "S": [ 1.6, 1.9, 2.5, 3.25, 4 ], - "Cl": [ 1.65, 2, 2.5, 3.25, 4 ], - "Ar": [ 2.25, 2.625, 3, 3.375, 4 ], - "K": [ 1.8, 2.6, 3.4, 3.8, 4, 4.4, 4.8 ], - "Ca": [ 2.5, 3, 3.5, 4, 5 ], - "Sc": [ 1.75, 2.15, 2.75, 3.5, 4.5 ], - "Ti": [ 1.6, 1.85, 2.5, 3.25, 4.25 ], - "V": [ 1.45, 1.65, 2.25, 3, 4 ], - "Cr": [ 1.375, 1.55, 2, 2.75, 3.75 ], - "Mn": [ 1.4, 1.6, 2.1, 2.75, 3.75 ], - "Fe": [ 1.45, 1.725, 2.25, 3, 4 ], - "Co": [ 1.8, 2, 2.5, 3.5 ], - "Ni": [ 1.65, 2, 2.5, 3, 4 ], - "Cu": [ 1.8, 2.2, 3, 4 ], - "Zn": [ 2, 2.3, 2.85, 3.5, 4.25 ], - "Ga": [ 1.85, 2.1, 2.45, 3, 4 ], - "Ge": [ 1.8, 2, 2.35, 3, 4 ], - "As": [ 1.75, 2.1, 2.5, 3, 4 ], - "Se": [ 1.85, 2.15, 2.5, 3, 4 ], - "Br": [ 1.9, 2.25, 2.75, 3.25, 4 ], - "Kr": [ 2.4, 3, 3.675, 4.25, 5 ], - "Rb": [ 2.45, 3, 4, 5 ], - "Sr": [ 2.75, 3.5, 4.4, 5 ], - "Y": [ 2.125, 2.5, 2.875, 3.25, 4, 5 ], - "Zr": [ 1.9, 2.25, 3, 4 ], - "Nb": [ 1.75, 2.05, 2.4, 3, 4 ], - "Mo": [ 1.675, 1.9, 2.375, 3, 4 ], - "Tc": [ 1.7, 1.915, 2.375, 3, 4 ], - "Ru": [ 1.725, 1.925, 2.375, 3, 4 ], - "Rh": [ 1.8, 2.1, 2.5, 3, 4 ], - "Pd": [ 2, 2.275, 2.75, 3.75 ], - "Ag": [ 2.1, 2.45, 3, 4 ], - "Cd": [ 2.15, 2.5, 3.1, 4, 5 ], - "In": [ 2.15, 2.5, 3, 3.75, 4.75 ], - "Sn": [ 2.1, 2.4, 3.75, 3.5, 4.5 ], - "Sb": [ 2.1, 2.5, 3, 3.5, 4.5 ], - "Te": [ 2.15, 2.55, 3.1, 3.6, 4.5 ], - "I": [ 2.22, 2.65, 3.25, 4.25 ], - "Xe": [ 3, 3.5, 4.06, 4.5, 5.25 ], - "Cs": [ 2.7, 3.5, 4.5, 5.5 ], - "Ba": [ 2.65, 3, 3.5, 4.4, 5.5 ], - "La": [ 2.2, 2.6, 3.25, 4, 5 ], - "Ce": [ 2, 2.375, 2.875, 3.5, 4.5 ], - "Pr": [ 1.9, 2.25, 2.75, 3.5, 4.5 ], - "Nd": [ 1.8, 2.125, 2.625, 3.375, 4.5 ], - "Pm": [ 1.775, 2.05, 2.5, 3.25, 4.25 ], - "Sm": [ 1.775, 2.05, 2.5, 3.25, 4.25 ], - "Eu": [ 1.775, 2.075, 2.5, 3.25, 4.25 ], - "Gd": [ 1.8, 2.11, 2.625, 3.375, 4.1, 5 ], - "Tb": [ 1.825, 2.16, 2.625, 3.375, 4.1, 5 ], - "Dy": [ 1.85, 2.24, 2.625, 3.375, 4.1, 5 ], - "Ho": [ 1.93, 2.375, 3, 4.1, 5 ], - "Er": [ 2.025, 2.5, 3.125, 4.1, 5 ], - "Tm": [ 2.2, 2.625, 3.25, 4.1, 5 ], - "Yb": [ 2.5, 3, 3.5, 4.1, 5 ], - "Lu": [ 2.2, 2.5, 3.04, 4, 5 ], - "Hf": [ 1.975, 2.49, 3.25, 4.5 ], - "Ta": [ 1.85, 2.12, 2.625, 3.25, 4.5 ], - "W": [ 1.775, 1.99, 2.5, 3.25, 4.5 ], - "Re": [ 1.775, 2.01, 2.5, 3.25, 4.25 ], - "Os": [ 1.8, 2.04, 2.5, 3.25, 4.5 ], - "Ir": [ 1.85, 2.125, 2.5, 3.25, 4.25 ], - "Pt": [ 2, 2.275, 2.75, 3.75 ], - "Au": [ 2.1, 2.45, 3, 4 ], - "Hg": [ 2.225, 2.5, 3.04, 4, 5 ], - "Tl": [ 2.21, 2.6, 3.11, 3.75, 4.75 ], - "Pb": [ 2.225, 2.5, 2.88, 3.625, 4.5 ], - "Bi": [ 2.225, 2.61, 3.125, 3.75, 4.75 ], - "Po": [ 2.3, 2.72, 3.25, 3.875, 4.75 ], - "At": [ 2.375, 2.83, 3.5, 4.5 ], - "Rn": [ 2.8, 3.5, 4.17, 4.75, 5.5 ], - "Fr": [ 2.85, 3.5, 4.43, 5.5 ], - "Ra": [ 3.15, 3.5, 4.25, 5.12, 6 ], - "Ac": [ 2.48, 3.1, 3.72, 4.25, 5 ], - "Th": [ 2.25, 2.65, 3.25, 4, 5 ], - "Pa": [ 2.04, 2.3, 3, 3.75, 4.75 ], - "U": [ 1.89, 2.09, 2.75, 3.5, 4.5 ], - "Np": [ 1.84, 2.05, 2.625, 3.375, 4.5 ], - "Pu": [ 1.81, 2.02, 2.5, 3.25, 4.25 ], - "Am": [ 1.81, 2.03, 2.5, 3.25, 4.25 ], - "Cm": [ 1.83, 2.07, 2.5, 3.25, 4.25 ], - "Bk": [ 1.86, 2.12, 2.5, 3, 4 ], - "Cf": [ 1.89, 2.19, 2.625, 3.125, 4 ], - "Es": [ 1.93, 2.29, 2.625, 3.125, 4 ], - "Fm": [ 1.98, 2.375, 2.75, 3.25, 4.25 ], - "Md": [ 2.08, 2.5, 3, 3.43, 4.25 ], - "No": [ 2.6, 3.125, 3.75, 4.27, 5 ] -} \ No newline at end of file + "H": [0.6, 0.75, 0.9, 1.2, 1.5], + "He": [1.25, 1.75, 2.4, 3.25], + "Li": [1.5, 2.1, 2.5, 2.8, 3.2, 3.5, 4.2], + "Be": [1.75, 2, 2.375, 3, 4], + "B": [1.25, 1.625, 2.5, 3.5], + "C": [1, 1.25, 1.5, 2, 3], + "N": [1, 1.1, 1.5, 2, 3], + "O": [1, 1.208, 1.5, 2, 3], + "F": [1.2, 1.418, 1.75, 2.25, 3.25], + "Ne": [1.5, 1.75, 2.25, 2.625, 3, 3.5], + "Na": [2.05, 2.4, 2.8, 3.1, 3.3, 3.8, 4.3], + "Mg": [2.125, 2.375, 2.875, 3.375, 4.5], + "Al": [2, 2.5, 3, 3.75, 4.5], + "Si": [1.75, 2, 2.25, 2.75, 3.75], + "P": [1.625, 1.875, 2.5, 3.25, 4], + "S": [1.6, 1.9, 2.5, 3.25, 4], + "Cl": [1.65, 2, 2.5, 3.25, 4], + "Ar": [2.25, 2.625, 3, 3.375, 4], + "K": [1.8, 2.6, 3.4, 3.8, 4, 4.4, 4.8], + "Ca": [2.5, 3, 3.5, 4, 5], + "Sc": [1.75, 2.15, 2.75, 3.5, 4.5], + "Ti": [1.6, 1.85, 2.5, 3.25, 4.25], + "V": [1.45, 1.65, 2.25, 3, 4], + "Cr": [1.375, 1.55, 2, 2.75, 3.75], + "Mn": [1.4, 1.6, 2.1, 2.75, 3.75], + "Fe": [1.45, 1.725, 2.25, 3, 4], + "Co": [1.8, 2, 2.5, 3.5], + "Ni": [1.65, 2, 2.5, 3, 4], + "Cu": [1.8, 2.2, 3, 4], + "Zn": [2, 2.3, 2.85, 3.5, 4.25], + "Ga": [1.85, 2.1, 2.45, 3, 4], + "Ge": [1.8, 2, 2.35, 3, 4], + "As": [1.75, 2.1, 2.5, 3, 4], + "Se": [1.85, 2.15, 2.5, 3, 4], + "Br": [1.9, 2.25, 2.75, 3.25, 4], + "Kr": [2.4, 3, 3.675, 4.25, 5], + "Rb": [2.45, 3, 4, 5], + "Sr": [2.75, 3.5, 4.4, 5], + "Y": [2.125, 2.5, 2.875, 3.25, 4, 5], + "Zr": [1.9, 2.25, 3, 4], + "Nb": [1.75, 2.05, 2.4, 3, 4], + "Mo": [1.675, 1.9, 2.375, 3, 4], + "Tc": [1.7, 1.915, 2.375, 3, 4], + "Ru": [1.725, 1.925, 2.375, 3, 4], + "Rh": [1.8, 2.1, 2.5, 3, 4], + "Pd": [2, 2.275, 2.75, 3.75], + "Ag": [2.1, 2.45, 3, 4], + "Cd": [2.15, 2.5, 3.1, 4, 5], + "In": [2.15, 2.5, 3, 3.75, 4.75], + "Sn": [2.1, 2.4, 3.75, 3.5, 4.5], + "Sb": [2.1, 2.5, 3, 3.5, 4.5], + "Te": [2.15, 2.55, 3.1, 3.6, 4.5], + "I": [2.22, 2.65, 3.25, 4.25], + "Xe": [3, 3.5, 4.06, 4.5, 5.25], + "Cs": [2.7, 3.5, 4.5, 5.5], + "Ba": [2.65, 3, 3.5, 4.4, 5.5], + "La": [2.2, 2.6, 3.25, 4, 5], + "Ce": [2, 2.375, 2.875, 3.5, 4.5], + "Pr": [1.9, 2.25, 2.75, 3.5, 4.5], + "Nd": [1.8, 2.125, 2.625, 3.375, 4.5], + "Pm": [1.775, 2.05, 2.5, 3.25, 4.25], + "Sm": [1.775, 2.05, 2.5, 3.25, 4.25], + "Eu": [1.775, 2.075, 2.5, 3.25, 4.25], + "Gd": [1.8, 2.11, 2.625, 3.375, 4.1, 5], + "Tb": [1.825, 2.16, 2.625, 3.375, 4.1, 5], + "Dy": [1.85, 2.24, 2.625, 3.375, 4.1, 5], + "Ho": [1.93, 2.375, 3, 4.1, 5], + "Er": [2.025, 2.5, 3.125, 4.1, 5], + "Tm": [2.2, 2.625, 3.25, 4.1, 5], + "Yb": [2.5, 3, 3.5, 4.1, 5], + "Lu": [2.2, 2.5, 3.04, 4, 5], + "Hf": [1.975, 2.49, 3.25, 4.5], + "Ta": [1.85, 2.12, 2.625, 3.25, 4.5], + "W": [1.775, 1.99, 2.5, 3.25, 4.5], + "Re": [1.775, 2.01, 2.5, 3.25, 4.25], + "Os": [1.8, 2.04, 2.5, 3.25, 4.5], + "Ir": [1.85, 2.125, 2.5, 3.25, 4.25], + "Pt": [2, 2.275, 2.75, 3.75], + "Au": [2.1, 2.45, 3, 4], + "Hg": [2.225, 2.5, 3.04, 4, 5], + "Tl": [2.21, 2.6, 3.11, 3.75, 4.75], + "Pb": [2.225, 2.5, 2.88, 3.625, 4.5], + "Bi": [2.225, 2.61, 3.125, 3.75, 4.75], + "Po": [2.3, 2.72, 3.25, 3.875, 4.75], + "At": [2.375, 2.83, 3.5, 4.5], + "Rn": [2.8, 3.5, 4.17, 4.75, 5.5], + "Fr": [2.85, 3.5, 4.43, 5.5], + "Ra": [3.15, 3.5, 4.25, 5.12, 6], + "Ac": [2.48, 3.1, 3.72, 4.25, 5], + "Th": [2.25, 2.65, 3.25, 4, 5], + "Pa": [2.04, 2.3, 3, 3.75, 4.75], + "U": [1.89, 2.09, 2.75, 3.5, 4.5], + "Np": [1.84, 2.05, 2.625, 3.375, 4.5], + "Pu": [1.81, 2.02, 2.5, 3.25, 4.25], + "Am": [1.81, 2.03, 2.5, 3.25, 4.25], + "Cm": [1.83, 2.07, 2.5, 3.25, 4.25], + "Bk": [1.86, 2.12, 2.5, 3, 4], + "Cf": [1.89, 2.19, 2.625, 3.125, 4], + "Es": [1.93, 2.29, 2.625, 3.125, 4], + "Fm": [1.98, 2.375, 2.75, 3.25, 4.25], + "Md": [2.08, 2.5, 3, 3.43, 4.25], + "No": [2.6, 3.125, 3.75, 4.27, 5], +} diff --git a/tools/opt_lcao_bash/opt_orb.py b/tools/opt_lcao_bash/opt_orb.py index 35ed2c9dd3e..bbee27f3bb9 100644 --- a/tools/opt_lcao_bash/opt_orb.py +++ b/tools/opt_lcao_bash/opt_orb.py @@ -6,36 +6,39 @@ from dis import dis import utils + def cal_pw(): - info = read_info("info.json") - for distance in dis[info["input"]["element"]]: - folder = f'{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}' - pathlib.Path(folder).mkdir(parents=True,exist_ok=False) - os.chdir(folder) - print_file_pw(info,distance) - if utils.sub in ["qsub", "sbatch"]: - os.system(f"{utils.sub} sub.sh") - elif utils.sub=="bsub": - os.system("bsub < sub.sh") - else: - raise KeyError("utils.sub = ",utils.sub) - os.chdir("../") - + info = read_info("info.json") + for distance in dis[info["input"]["element"]]: + folder = f'{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}' + pathlib.Path(folder).mkdir(parents=True, exist_ok=False) + os.chdir(folder) + print_file_pw(info, distance) + if utils.sub in ["qsub", "sbatch"]: + os.system(f"{utils.sub} sub.sh") + elif utils.sub == "bsub": + os.system("bsub < sub.sh") + else: + raise KeyError("utils.sub = ", utils.sub) + os.chdir("../") + + def cal_opt(): - info = read_info("info.json") - pathlib.Path("opt_orb").mkdir(parents=True,exist_ok=False) - os.chdir("opt_orb") - print_file_opt(info,dis) - if utils.sub in ["qsub", "sbatch"]: - os.system(f"{utils.sub} sub.sh") - elif utils.sub=="bsub": - os.system("bsub < sub.sh") - else: - raise KeyError("utils.sub = ",utils.sub) - os.chdir("../") - -if __name__=="__main__": - if sys.argv[1]=='1': - cal_pw() - elif sys.argv[1]=='2': - cal_opt() \ No newline at end of file + info = read_info("info.json") + pathlib.Path("opt_orb").mkdir(parents=True, exist_ok=False) + os.chdir("opt_orb") + print_file_opt(info, dis) + if utils.sub in ["qsub", "sbatch"]: + os.system(f"{utils.sub} sub.sh") + elif utils.sub == "bsub": + os.system("bsub < sub.sh") + else: + raise KeyError("utils.sub = ", utils.sub) + os.chdir("../") + + +if __name__ == "__main__": + if sys.argv[1] == "1": + cal_pw() + elif sys.argv[1] == "2": + cal_opt() diff --git a/tools/opt_lcao_bash/print_file.py b/tools/opt_lcao_bash/print_file.py index 7e885d3a9ae..71097164bcd 100644 --- a/tools/opt_lcao_bash/print_file.py +++ b/tools/opt_lcao_bash/print_file.py @@ -2,222 +2,214 @@ import utils import textwrap -def print_file_pw(info,dis): - - with open("INPUT","w") as file: - file.write(textwrap.dedent(f"""\ - INPUT_PARAMETERS - pseudo_dir {info["input"]["pseudo_dir"]} - calculation scf - ntype 1 - nspin 1 - lmaxmax {len(info["orbital"])-1} - basis_type pw - ks_solver cg - - symmetry 0 - gamma_only 1 - nbands {info["input"]["nbands"]} - - ecutwfc {info["input"]["ecut"]} - scf_thr 1.0e-8 // about iteration - scf_nmax 1000 - - smearing_method gauss - smearing_sigma {info["input"]["smearing_sigma"]} - - mixing_type pulay // about charge mixing - mixing_beta 0.4 - mixing_ndim 8 - printe 1 - """)) - - - - with open("INPUTw","w") as file: - file.write(textwrap.dedent(f"""\ - WANNIER_PARAMETERS - rcut {info["input"]["rcut"]} - out_spillage 2 - spillage_outdir orb_matrix - """)) - - - - with open("INPUTs","w") as file: - file.write(textwrap.dedent(f"""\ - INPUT_ORBITAL_INFORMATION - - {int(info["input"]["smooth"])} // smooth or not - 0.1 // smearing_sigma - {info["input"]["ecut"]} // energy cutoff for spherical bessel functions(Ry) - {info["input"]["rcut"]} // cutoff of wavefunctions(a.u.) - 1.0e-12 // tolerence - - """)) - - - - with open("STRU","w") as file: - file.write("ATOMIC_SPECIES\n") - file.write(f'{info["input"]["element"]} 1 {info["input"]["pseudo"]}\n') - file.write(textwrap.dedent(f"""\ - LATTICE_CONSTANT - {utils.lat0}\n - LATTICE_VECTORS - 1 0 0 - 0 1 0 - 0 0 1\n - ATOMIC_POSITIONS - Cartesian_angstrom - """)) - if info["input"]["element"] in ["Na","Li","K","Ca"]: - file.write(textwrap.dedent(f"""\ - {info["input"]["element"]} - 0.0 - 3 - 0 0 0 0 0 0 - 0 0 {dis} 0 0 0 - 0 {dis*0.86603} {dis*0.5} 0 0 0 - """)) - else: - file.write(textwrap.dedent(f"""\ - {info["input"]["element"]} - 0.0 - 2 - 0 0 0 0 0 0 - 0 0 {dis} 0 0 0 - """)) - - - - with open("KPT","w") as file: - file.write(textwrap.dedent(f"""\ - K_POINTS - 0 - Gamma - 1 1 1 0 0 0 - """)) - - - - if utils.sub=="qsub": - with open("sub.sh","w") as file: - core = info["exe"]["qsub"][0]*info["exe"]["qsub"][1] - file.write(textwrap.dedent(f"""\ - #!/bin/bash - #PBS -q gold5120 - #PBS -l nodes={info["exe"]["qsub"][0]}:ppn={info["exe"]["qsub"][1]} - #PBS -l walltime=12:00:00 - #PBS -o job.log - #PBS -e job.err - ulimit -s unlimited - cd $PBS_O_WORKDIR - EXEC={info["exe"]["exe_pw"]} - mpirun -n {core} -env OMP_NUM_THREADS=1 $EXEC - """)) - elif utils.sub=="sbatch": - with open("sub.sh","w") as file: - core = info["exe"]["qsub"][0]*info["exe"]["qsub"][1] - file.write(textwrap.dedent(f"""\ - #!/bin/bash - #SBATCH -J {info["input"]["element"]}_{dis} - #SBATCH -p regular - #SBATCH -N {info["exe"]["qsub"][0]} - #SBATCH -o test.out - EXEC={info["exe"]["exe_pw"]} - mpirun -n {core} -env OMP_NUM_THREADS=1 $EXEC - """)) - elif utils.sub=="bsub": - with open("sub.sh","w") as file: - core = info["exe"]["qsub"][0]*info["exe"]["qsub"][1] - file.write(textwrap.dedent(f"""\ - #!/bin/sh - #BSUB -q renxg - #BSUB -o job.log -e job.err - #BSUB -n {core} - EXEC={info["exe"]["exe_pw"]} - mpirun -n {core} -env OMP_NUM_THREADS=1 $EXEC - """)) - else: - raise KeyError("utils.sub = ",utils.sub) - - - - - -def print_file_opt(info,dis): - - with open("INPUT","w") as file: - input = { - "file_list": { - "origin": [ f'../{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}/orb_matrix/orb_matrix.0.dat' for distance in dis[info["input"]["element"]] ], - "linear": [[ f'../{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}/orb_matrix/orb_matrix.1.dat' for distance in dis[info["input"]["element"]] ]] - }, - "info": { - "Nt_all": [info["input"]["element"]], - "Nu": {info["input"]["element"] : info["orbital"]}, - "Rcut": {info["input"]["element"] : info["input"]["rcut"]}, - "dr": {info["input"]["element"] : utils.dr}, - "Ecut": {info["input"]["element"] : info["input"]["ecut"]}, - "lr": utils.lr, - "cal_T": False, - "cal_smooth": info["input"]["smooth"] - }, - "weight": - { - "stru": [1] * len(dis[info["input"]["element"]]), - "bands_file": [ f'../{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}/OUT.ABACUS/istate.info' for distance in dis[info["input"]["element"]] ] - }, - "C_init_info": { - "init_from_file": False - }, - "V_info": { - "same_band": True, - "init_from_file": True - } - } - file.write(json.dumps(input,indent=4)) - - - if utils.sub=="qsub": - with open("sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/bash - #PBS -q gold5120 - #PBS -l nodes=1:ppn=1 - #PBS -l walltime=1:00:00 - #PBS -o job.log - #PBS -e job.err - ulimit -s unlimited - cd $PBS_O_WORKDIR - export OMP_NUM_THREADS=1 - EXEC={info["exe"]["exe_orbital"]} - python3 $EXEC - """)) - elif utils.sub=="sbatch": - with open("sub.sh","w") as file: - core = info["exe"]["qsub"][0]*info["exe"]["qsub"][1] - file.write(textwrap.dedent(f"""\ - #!/bin/bash - #SBATCH -J {info["input"]["element"]}_opt-orb - #SBATCH -p regular - #SBATCH -N 1 - #SBATCH -o test.out - export OMP_NUM_THREADS={core} - EXEC={info["exe"]["exe_orbital"]} - python3 $EXEC - """)) - elif utils.sub=="bsub": - with open("sub.sh","w") as file: - file.write(textwrap.dedent(f"""\ - #!/bin/sh - #BSUB -q renxg - #BSUB -o job.log -e job.err - #BSUB -n 1 - export OMP_NUM_THREADS=1 - EXEC={info["exe"]["exe_orbital"]} - python3 $EXEC - """)) - else: - raise KeyError("utils.sub = ",utils.sub) \ No newline at end of file + +def print_file_pw(info, dis): + + with open("INPUT", "w") as file: + file.write(textwrap.dedent(f"""\ + INPUT_PARAMETERS + pseudo_dir {info["input"]["pseudo_dir"]} + calculation scf + ntype 1 + nspin 1 + lmaxmax {len(info["orbital"])-1} + basis_type pw + ks_solver cg + + symmetry 0 + gamma_only 1 + nbands {info["input"]["nbands"]} + + ecutwfc {info["input"]["ecut"]} + scf_thr 1.0e-8 // about iteration + scf_nmax 1000 + + smearing_method gauss + smearing_sigma {info["input"]["smearing_sigma"]} + + mixing_type pulay // about charge mixing + mixing_beta 0.4 + mixing_ndim 8 + printe 1 + """)) + + with open("INPUTw", "w") as file: + file.write(textwrap.dedent(f"""\ + WANNIER_PARAMETERS + rcut {info["input"]["rcut"]} + out_spillage 2 + spillage_outdir orb_matrix + """)) + + with open("INPUTs", "w") as file: + file.write(textwrap.dedent(f"""\ + INPUT_ORBITAL_INFORMATION + + {int(info["input"]["smooth"])} // smooth or not + 0.1 // smearing_sigma + {info["input"]["ecut"]} // energy cutoff for spherical bessel functions(Ry) + {info["input"]["rcut"]} // cutoff of wavefunctions(a.u.) + 1.0e-12 // tolerence + + """)) + + with open("STRU", "w") as file: + file.write("ATOMIC_SPECIES\n") + file.write(f'{info["input"]["element"]} 1 {info["input"]["pseudo"]}\n') + file.write(textwrap.dedent(f"""\ + LATTICE_CONSTANT + {utils.lat0}\n + LATTICE_VECTORS + 1 0 0 + 0 1 0 + 0 0 1\n + ATOMIC_POSITIONS + Cartesian_angstrom + """)) + if info["input"]["element"] in ["Na", "Li", "K", "Ca"]: + file.write(textwrap.dedent(f"""\ + {info["input"]["element"]} + 0.0 + 3 + 0 0 0 0 0 0 + 0 0 {dis} 0 0 0 + 0 {dis*0.86603} {dis*0.5} 0 0 0 + """)) + else: + file.write(textwrap.dedent(f"""\ + {info["input"]["element"]} + 0.0 + 2 + 0 0 0 0 0 0 + 0 0 {dis} 0 0 0 + """)) + + with open("KPT", "w") as file: + file.write(textwrap.dedent(f"""\ + K_POINTS + 0 + Gamma + 1 1 1 0 0 0 + """)) + + if utils.sub == "qsub": + with open("sub.sh", "w") as file: + core = info["exe"]["qsub"][0] * info["exe"]["qsub"][1] + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #PBS -q gold5120 + #PBS -l nodes={info["exe"]["qsub"][0]}:ppn={info["exe"]["qsub"][1]} + #PBS -l walltime=12:00:00 + #PBS -o job.log + #PBS -e job.err + ulimit -s unlimited + cd $PBS_O_WORKDIR + EXEC={info["exe"]["exe_pw"]} + mpirun -n {core} -env OMP_NUM_THREADS=1 $EXEC + """)) + elif utils.sub == "sbatch": + with open("sub.sh", "w") as file: + core = info["exe"]["qsub"][0] * info["exe"]["qsub"][1] + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #SBATCH -J {info["input"]["element"]}_{dis} + #SBATCH -p regular + #SBATCH -N {info["exe"]["qsub"][0]} + #SBATCH -o test.out + EXEC={info["exe"]["exe_pw"]} + mpirun -n {core} -env OMP_NUM_THREADS=1 $EXEC + """)) + elif utils.sub == "bsub": + with open("sub.sh", "w") as file: + core = info["exe"]["qsub"][0] * info["exe"]["qsub"][1] + file.write(textwrap.dedent(f"""\ + #!/bin/sh + #BSUB -q renxg + #BSUB -o job.log -e job.err + #BSUB -n {core} + EXEC={info["exe"]["exe_pw"]} + mpirun -n {core} -env OMP_NUM_THREADS=1 $EXEC + """)) + else: + raise KeyError("utils.sub = ", utils.sub) + + +def print_file_opt(info, dis): + + with open("INPUT", "w") as file: + input = { + "file_list": { + "origin": [ + f'../{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}/orb_matrix/orb_matrix.0.dat' + for distance in dis[info["input"]["element"]] + ], + "linear": [ + [ + f'../{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}/orb_matrix/orb_matrix.1.dat' + for distance in dis[info["input"]["element"]] + ] + ], + }, + "info": { + "Nt_all": [info["input"]["element"]], + "Nu": {info["input"]["element"]: info["orbital"]}, + "Rcut": {info["input"]["element"]: info["input"]["rcut"]}, + "dr": {info["input"]["element"]: utils.dr}, + "Ecut": {info["input"]["element"]: info["input"]["ecut"]}, + "lr": utils.lr, + "cal_T": False, + "cal_smooth": info["input"]["smooth"], + }, + "weight": { + "stru": [1] * len(dis[info["input"]["element"]]), + "bands_file": [ + f'../{info["input"]["element"]}-{info["input"]["rcut"]}-{distance}/OUT.ABACUS/istate.info' + for distance in dis[info["input"]["element"]] + ], + }, + "C_init_info": {"init_from_file": False}, + "V_info": {"same_band": True, "init_from_file": True}, + } + file.write(json.dumps(input, indent=4)) + + if utils.sub == "qsub": + with open("sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #PBS -q gold5120 + #PBS -l nodes=1:ppn=1 + #PBS -l walltime=1:00:00 + #PBS -o job.log + #PBS -e job.err + ulimit -s unlimited + cd $PBS_O_WORKDIR + export OMP_NUM_THREADS=1 + EXEC={info["exe"]["exe_orbital"]} + python3 $EXEC + """)) + elif utils.sub == "sbatch": + with open("sub.sh", "w") as file: + core = info["exe"]["qsub"][0] * info["exe"]["qsub"][1] + file.write(textwrap.dedent(f"""\ + #!/bin/bash + #SBATCH -J {info["input"]["element"]}_opt-orb + #SBATCH -p regular + #SBATCH -N 1 + #SBATCH -o test.out + export OMP_NUM_THREADS={core} + EXEC={info["exe"]["exe_orbital"]} + python3 $EXEC + """)) + elif utils.sub == "bsub": + with open("sub.sh", "w") as file: + file.write(textwrap.dedent(f"""\ + #!/bin/sh + #BSUB -q renxg + #BSUB -o job.log -e job.err + #BSUB -n 1 + export OMP_NUM_THREADS=1 + EXEC={info["exe"]["exe_orbital"]} + python3 $EXEC + """)) + else: + raise KeyError("utils.sub = ", utils.sub) diff --git a/tools/opt_lcao_bash/read_info.py b/tools/opt_lcao_bash/read_info.py index 82c148a5f7b..0a78b7800f9 100644 --- a/tools/opt_lcao_bash/read_info.py +++ b/tools/opt_lcao_bash/read_info.py @@ -1,34 +1,35 @@ import json import os + def read_info(file_name): - with open(file_name,"r") as file: - info = file.read() - info = json.loads(info) - info["input"]["pseudo_dir"] = os.path.abspath(info["input"].get("pseudo_dir","./")) - info["exe"]["qsub"] = info["exe"].get("qsub",[1,1]) - return info + with open(file_name, "r") as file: + info = file.read() + info = json.loads(info) + info["input"]["pseudo_dir"] = os.path.abspath(info["input"].get("pseudo_dir", "./")) + info["exe"]["qsub"] = info["exe"].get("qsub", [1, 1]) + return info + """ info.json { - "exe": - { - "exe_pw": "/home/linpz/ABACUS/ABACUS.1.0.1_2016-12-19/bin/ABACUS.mpi.1.0.0", - "exe_orbital": "/home/linpz/ABACUS/ABACUS_RI_git/tools/opt_orb_pytorch/main.py", - "qsub": [1,8] - }, - "input": - { - "element": "N", - "nbands": 8, - "ecut": 50, - "rcut": 6, - "pseudo_dir": "../", - "pseudo": "N_ONCV_PBE-1.0.upf", - "smearing_sigma": 0.01, - "smooth": false, - }, - "orbital": [2,2,1] + "exe": + { + "exe_pw": "/home/linpz/ABACUS/ABACUS.1.0.1_2016-12-19/bin/ABACUS.mpi.1.0.0", + "exe_orbital": "/home/linpz/ABACUS/ABACUS_RI_git/tools/opt_orb_pytorch/main.py", + "qsub": [1,8] + }, + "input": + { + "element": "N", + "nbands": 8, + "ecut": 50, + "rcut": 6, + "pseudo_dir": "../", + "pseudo": "N_ONCV_PBE-1.0.upf", + "smearing_sigma": 0.01, + "smooth": false, + }, + "orbital": [2,2,1] } """ - diff --git a/tools/opt_lcao_bash/utils.py b/tools/opt_lcao_bash/utils.py index 57713d026fe..fa02e38dccc 100644 --- a/tools/opt_lcao_bash/utils.py +++ b/tools/opt_lcao_bash/utils.py @@ -1,4 +1,4 @@ lat0 = 30 -dr = 0.01 -lr = 0.01 -sub = "qsub" \ No newline at end of file +dr = 0.01 +lr = 0.01 +sub = "qsub" diff --git a/tools/opt_orb_pytorch/IO/func_C.py b/tools/opt_orb_pytorch/IO/func_C.py index 2e28b1c3dfb..fe396622713 100644 --- a/tools/opt_orb_pytorch/IO/func_C.py +++ b/tools/opt_orb_pytorch/IO/func_C.py @@ -2,84 +2,90 @@ import torch import numpy as np + def random_C_init(info): - """ C[it][il][ie,iu] """ - C = dict() - for it in info.Nt_all: - C[it] = ND_list(info.Nl[it]) - for il in range(info.Nl[it]): - C[it][il] = torch.tensor(np.random.uniform(-1,1, (info.Ne[it], info.Nu[it][il])), dtype=torch.float32, requires_grad=True) - return C - - - -def read_C_init(file_name,info): - """ C[it][il][ie,iu] """ - C = random_C_init(info) + """C[it][il][ie,iu]""" + C = dict() + for it in info.Nt_all: + C[it] = ND_list(info.Nl[it]) + for il in range(info.Nl[it]): + C[it][il] = torch.tensor( + np.random.uniform(-1, 1, (info.Ne[it], info.Nu[it][il])), + dtype=torch.float32, + requires_grad=True, + ) + return C + + +def read_C_init(file_name, info): + """C[it][il][ie,iu]""" + C = random_C_init(info) + + with open(file_name, "r") as file: + + for line in file: + if line.strip() == "": + line = None + break + ignore_line(file, 1) + + while True: + line = file.readline().strip() + if line.startswith("Type"): + it, il, iu = list(map(int, file.readline().split())) + it = info.Nt_all[it - 1] + iu -= 1 + line = file.readline().split() + for ie in range(info.Ne[it]): + if not line: + line = file.readline().split() + C[it][il].data[ie, iu] = float(line.pop(0)) + elif line.startswith(""): + break + else: + raise IOError("unknown line in read_C_init " + file_name + "\n" + line) + return C + + +def copy_C(C, info): + C_copy = dict() + for it in info.Nt_all: + C_copy[it] = ND_list(info.Nl[it]) + for il in range(info.Nl[it]): + C_copy[it][il] = C[it][il].clone() + return C_copy + + +def write_C(file_name, info, C): + with open(file_name, "w") as file: + print("", file=file) + print("\tTotal number of radial orbitals.", file=file) + for it, C_t in C.items(): + for il, C_tl in enumerate(C_t): + for iu in range(C_tl.size()[1]): + print("\tType\tL\tZeta-Orbital", file=file) + print( + f"\t {info.Nt_all.index(it)+1} \t{il}\t {iu+1}", file=file + ) + for ie in range(C_tl.size()[0]): + print("\t", C_tl[ie, iu].item(), file=file) + print("", file=file) - with open(file_name,"r") as file: - - for line in file: - if line.strip() == "": - line=None - break - ignore_line(file,1) - - while True: - line = file.readline().strip() - if line.startswith("Type"): - it,il,iu = list(map(int,file.readline().split())); - it=info.Nt_all[it-1]; iu-=1 - line = file.readline().split() - for ie in range(info.Ne[it]): - if not line: line = file.readline().split() - C[it][il].data[ie,iu] = float(line.pop(0)) - elif line.startswith(""): - break; - else: - raise IOError("unknown line in read_C_init "+file_name+"\n"+line) - return C - - -def copy_C(C,info): - C_copy = dict() - for it in info.Nt_all: - C_copy[it] = ND_list(info.Nl[it]) - for il in range(info.Nl[it]): - C_copy[it][il] = C[it][il].clone() - return C_copy - - - -def write_C(file_name,info,C): - with open(file_name,"w") as file: - print("", file=file) - print("\tTotal number of radial orbitals.", file=file) - for it,C_t in C.items(): - for il,C_tl in enumerate(C_t): - for iu in range(C_tl.size()[1]): - print("\tType\tL\tZeta-Orbital", file=file) - print(f"\t {info.Nt_all.index(it)+1} \t{il}\t {iu+1}", file=file) - for ie in range(C_tl.size()[0]): - print("\t", C_tl[ie,iu].item(), file=file) - print("", file=file) - - -#def init_C(info): -# """ C[it][il][ie,iu] """ -# C = ND_list(max(info.Nt)) -# for it in range(len(C)): -# C[it] = ND_list(info.Nl[it]) -# for il in range(info.Nl[it]): -# C[it][il] = torch.autograd.Variable( torch.Tensor( info.Ne, info.Nu[it][il] ), requires_grad = True ) -# -# with open("C_init.dat","r") as file: -# line = [] -# for it in range(len(C)): -# for il in range(info.Nl[it]): -# for i_n in range(info.Nu[it][il]): -# for ie in range(info.Ne[it]): -# if not line: line=file.readline().split() -# C[it][il].data[ie,i_n] = float(line.pop(0)) -# return C \ No newline at end of file +# def init_C(info): +# """ C[it][il][ie,iu] """ +# C = ND_list(max(info.Nt)) +# for it in range(len(C)): +# C[it] = ND_list(info.Nl[it]) +# for il in range(info.Nl[it]): +# C[it][il] = torch.autograd.Variable( torch.Tensor( info.Ne, info.Nu[it][il] ), requires_grad = True ) +# +# with open("C_init.dat","r") as file: +# line = [] +# for it in range(len(C)): +# for il in range(info.Nl[it]): +# for i_n in range(info.Nu[it][il]): +# for ie in range(info.Ne[it]): +# if not line: line=file.readline().split() +# C[it][il].data[ie,i_n] = float(line.pop(0)) +# return C diff --git a/tools/opt_orb_pytorch/IO/print_QSV.py b/tools/opt_orb_pytorch/IO/print_QSV.py index 1b0f88c59ef..ca8527ed293 100644 --- a/tools/opt_orb_pytorch/IO/print_QSV.py +++ b/tools/opt_orb_pytorch/IO/print_QSV.py @@ -1,29 +1,30 @@ -def print_V(V,file_name): - """ V[ist][ib] """ - with open(file_name,"w") as file: - for V_s in V: - for V_sb in V_s: - print(1-V_sb.item(),end="\t",file=file) - print(file=file) - -def print_S(S,file_name): - """ S[ist][it1,it2][il1][il2][ia1*im1*in1,ia2*im2*in2] """ - with open(file_name,"w") as file: - for ist,S_s in enumerate(S): - for (it1,it2),S_tt in S_s.items(): - for il1,S_ttl in enumerate(S_tt): - for il2,S_ttll in enumerate(S_ttl): - print(ist,it1,it2,il1,il2,file=file) - print(S_ttll.real.numpy(),file=file) - print(S_ttll.imag.numpy(),"\n",file=file) - -def print_Q(Q,file_name): - """ Q[ist][it][il][ib,ia*im*iu] """ - with open(file_name,"w") as file: - for ist,Q_s in enumerate(Q): - for it,Q_st in Q_s.items(): - for il,Q_stl in enumerate(Q_st): - print(ist,it,il,file=file) - print(Q_stl.real.numpy(),file=file) - print(Q_stl.imag.numpy(),"\n",file=file) - \ No newline at end of file +def print_V(V, file_name): + """V[ist][ib]""" + with open(file_name, "w") as file: + for V_s in V: + for V_sb in V_s: + print(1 - V_sb.item(), end="\t", file=file) + print(file=file) + + +def print_S(S, file_name): + """S[ist][it1,it2][il1][il2][ia1*im1*in1,ia2*im2*in2]""" + with open(file_name, "w") as file: + for ist, S_s in enumerate(S): + for (it1, it2), S_tt in S_s.items(): + for il1, S_ttl in enumerate(S_tt): + for il2, S_ttll in enumerate(S_ttl): + print(ist, it1, it2, il1, il2, file=file) + print(S_ttll.real.numpy(), file=file) + print(S_ttll.imag.numpy(), "\n", file=file) + + +def print_Q(Q, file_name): + """Q[ist][it][il][ib,ia*im*iu]""" + with open(file_name, "w") as file: + for ist, Q_s in enumerate(Q): + for it, Q_st in Q_s.items(): + for il, Q_stl in enumerate(Q_st): + print(ist, it, il, file=file) + print(Q_stl.real.numpy(), file=file) + print(Q_stl.imag.numpy(), "\n", file=file) diff --git a/tools/opt_orb_pytorch/IO/print_orbital.py b/tools/opt_orb_pytorch/IO/print_orbital.py index 69a68858c4e..681c701b7f2 100644 --- a/tools/opt_orb_pytorch/IO/print_orbital.py +++ b/tools/opt_orb_pytorch/IO/print_orbital.py @@ -1,43 +1,59 @@ -def print_orbital(orb,info): - """ orb[it][il][iu][r] """ - for it,orb_t in orb.items(): - with open("orb_{0}.dat".format(it),"w") as file: - print_orbital_head(file,info,it) - for il,orb_tl in enumerate(orb_t): - for iu,orb_tlu in enumerate(orb_tl): - print(""" Type L N""",file=file) - print(""" 0 {0} {1}""".format(il,iu),file=file) - for ir,orb_tlur in enumerate(orb_tlu): - print(orb_tlur,end="\t",file=file) - if ir%4==3: print(file=file) - print(file=file) - - -def plot_orbital(orb,Rcut,dr): - for it,orb_t in orb.items(): - with open("orb_{0}_plot.dat".format(it),"w") as file: - Nr = int(Rcut[it]/dr[it])+1 - for ir in range(Nr): - print(ir*dr[it],end="\t",file=file) - for il,orb_tl in enumerate(orb_t): - for orb_tlu in orb_tl: - print(orb_tlu[ir],end="\t",file=file) - print(file=file) - - -def print_orbital_head(file,info,it): - print( "---------------------------------------------------------------------------", file=file ) - print( "Element {0}".format(it), file=file ) - print( "Energy Cutoff(Ry) {0}".format(info.Ecut[it]), file=file ) - print( "Radius Cutoff(a.u.) {0}".format(info.Rcut[it]), file=file ) - print( "Lmax {0}".format(info.Nl[it]-1), file=file ) - l_name = ["S","P","D"]+list(map(chr,range(ord('F'),ord('Z')+1))) - for il,iu in enumerate(info.Nu[it]): - print( "Number of {0}orbital--> {1}".format(l_name[il],iu), file=file ) - print( "---------------------------------------------------------------------------", file=file ) - print( "SUMMARY END", file=file ) - print( file=file ) - print( "Mesh {0}".format(int(info.Rcut[it]/info.dr[it])+1), file=file ) - print( "dr {0}".format(info.dr[it]), file=file ) +def print_orbital(orb, info): + """orb[it][il][iu][r]""" + for it, orb_t in orb.items(): + with open("orb_{0}.dat".format(it), "w") as file: + print_orbital_head(file, info, it) + for il, orb_tl in enumerate(orb_t): + for iu, orb_tlu in enumerate(orb_tl): + print( + """ Type L N""", + file=file, + ) + print( + """ 0 {0} {1}""".format( + il, iu + ), + file=file, + ) + for ir, orb_tlur in enumerate(orb_tlu): + print(orb_tlur, end="\t", file=file) + if ir % 4 == 3: + print(file=file) + print(file=file) - \ No newline at end of file + +def plot_orbital(orb, Rcut, dr): + for it, orb_t in orb.items(): + with open("orb_{0}_plot.dat".format(it), "w") as file: + Nr = int(Rcut[it] / dr[it]) + 1 + for ir in range(Nr): + print(ir * dr[it], end="\t", file=file) + for il, orb_tl in enumerate(orb_t): + for orb_tlu in orb_tl: + print(orb_tlu[ir], end="\t", file=file) + print(file=file) + + +def print_orbital_head(file, info, it): + print( + "---------------------------------------------------------------------------", + file=file, + ) + print("Element {0}".format(it), file=file) + print("Energy Cutoff(Ry) {0}".format(info.Ecut[it]), file=file) + print("Radius Cutoff(a.u.) {0}".format(info.Rcut[it]), file=file) + print("Lmax {0}".format(info.Nl[it] - 1), file=file) + l_name = ["S", "P", "D"] + list(map(chr, range(ord("F"), ord("Z") + 1))) + for il, iu in enumerate(info.Nu[it]): + print("Number of {0}orbital--> {1}".format(l_name[il], iu), file=file) + print( + "---------------------------------------------------------------------------", + file=file, + ) + print("SUMMARY END", file=file) + print(file=file) + print( + "Mesh {0}".format(int(info.Rcut[it] / info.dr[it]) + 1), + file=file, + ) + print("dr {0}".format(info.dr[it]), file=file) diff --git a/tools/opt_orb_pytorch/IO/read_QSV.py b/tools/opt_orb_pytorch/IO/read_QSV.py index 761e407e716..271c753d72b 100644 --- a/tools/opt_orb_pytorch/IO/read_QSV.py +++ b/tools/opt_orb_pytorch/IO/read_QSV.py @@ -6,159 +6,208 @@ import time -def read_file(info,file_list,V_info): - """ QI[ist][it][il][ib*ia*im,ie] """ - """ SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] """ - """ VI[ist][ib] """ - import copy - info_true = copy.deepcopy(info) - info_true.Nst = len(file_list) - info_true.Nt = ND_list(info_true.Nst,element="list()") - info_true.Na = ND_list(info_true.Nst,element="dict()") - info_true.Nb = ND_list(info_true.Nst) - info_true.Nk = ND_list(info_true.Nst) - info_true.Ne = dict() - info_true.weight = ND_list(info_true.Nst,element="list()") - QI=[]; SI=[]; VI=[] - - for ist_true,file_name in enumerate(file_list): - print(file_name) - with open(file_name,"r") as file: - - ignore_line(file,4) - Nt_tmp = int(file.readline().split()[0]) - for it in range(Nt_tmp): - t_tmp = file.readline().split()[0] - assert t_tmp in info.Nt_all - info_true.Nt[ist_true].append( t_tmp ) - info_true.Na[ist_true][t_tmp] = int(file.readline().split()[0]) - ignore_line( file, info_true.Na[ist_true][t_tmp] ) - ignore_line(file,6) - Nl_ist = int(file.readline().split()[0])+1 - for it,Nl_C in info.Nl.items(): - print(it,Nl_ist,Nl_C) - assert Nl_ist>=Nl_C - info_true.Nl[it] = Nl_ist - info_true.Nk[ist_true] = int(file.readline().split()[0]) - info_true.Nb[ist_true] = int(file.readline().split()[0]) - ignore_line(file,1) - Ne_tmp = list(map(int,file.readline().split()[:Nt_tmp])) - for it,Ne in zip(info_true.Nt[ist_true],Ne_tmp): - assert info_true.Ne.setdefault(it,Ne)==Ne - ignore_line(file,1) - for ik in range(info_true.Nk[ist_true]): - info_true.weight[ist_true].append(float(file.readline().split()[-1])) - ignore_line(file,3) - - line = None - for ik in range(info_true.Nk[ist_true]): - print("read QI:",ist_true,ik) - qi,line = read_QI(info_true,ist_true,file,line) - QI.append( qi ) - ignore_line(file,3) - for ik in range(info_true.Nk[ist_true]): - print("read SI:",ist_true,ik) - si,line = read_SI(info_true,ist_true,file,line) - SI.append( si ) - if V_info["init_from_file"]: - ignore_line(file,3) - for ik in range(info_true.Nk[ist_true]): - print("read VI:",ist_true,ik) - vi,line = read_VI(info_true,V_info,ist_true,file,line) - VI.append( vi ) - - info.Nst = sum(info_true.Nk,0) - import itertools - repeat_Nk = lambda x: list( itertools.chain.from_iterable( map( lambda x:itertools.repeat(*x), zip(x,info_true.Nk) ) ) ) - info.Nt = repeat_Nk(info_true.Nt) - info.Na = repeat_Nk(info_true.Na) - info.Nb = repeat_Nk(info_true.Nb) - info.Nb_true = repeat_Nk(info.Nb_true) - info.Ne = info_true.Ne - info.weight = list(itertools.chain.from_iterable([np.array(wk)*ws for wk,ws in zip(info_true.weight,info.weight)])) # info_true.weight[ist][ik] * info.weight[ist] - - return QI,SI,VI - - - - -def read_QI(info,ist,file,line=None): - """ QI[it][il][ib*ia*im,ie] """ - QI = dict() - for it in info.Nt[ist]: - QI[it] = ND_list(info.Nl[it]) - for il in range(info.Nl[it]): - QI[it][il] = torch_complex.ComplexTensor( - np.empty((info.Nb[ist],info.Na[ist][it],info.Nm(il),info.Ne[it]),dtype=np.float32), - np.empty((info.Nb[ist],info.Na[ist][it],info.Nm(il),info.Ne[it]),dtype=np.float32) ) - for ib in range(info.Nb[ist]): - for it in info.Nt[ist]: - for ia in range(info.Na[ist][it]): - for il in range(info.Nl[it]): - for im in range(info.Nm(il)): - for ie in range(info.Ne[it]): - if not line: line = file.readline().split() - QI[it][il].real[ib,ia,im,ie] = float(line.pop(0)) - if not line: line = file.readline().split() - QI[it][il].imag[ib,ia,im,ie] = float(line.pop(0)) - for it in info.Nt[ist]: - for il in range(info.Nl[it]): - QI[it][il] = torch_complex.ComplexTensor( - torch.from_numpy(QI[it][il].real).view(-1,info.Ne[it]), - torch.from_numpy(QI[it][il].imag).view(-1,info.Ne[it])) - return QI,line - - - -def read_SI(info,ist,file,line=None): - """ SI[it1,it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] """ - SI = dict() - for it1,it2 in itertools.product( info.Nt[ist], info.Nt[ist] ): - SI[it1,it2] = ND_list(info.Nl[it1],info.Nl[it2]) - for il1,il2 in itertools.product( range(info.Nl[it1]), range(info.Nl[it2]) ): - SI[it1,it2][il1][il2] = torch_complex.ComplexTensor( - np.empty((info.Na[ist][it1],info.Nm(il1),info.Ne[it1],info.Na[ist][it2],info.Nm(il2),info.Ne[it2]),dtype=np.float32), - np.empty((info.Na[ist][it1],info.Nm(il1),info.Ne[it1],info.Na[ist][it2],info.Nm(il2),info.Ne[it2]),dtype=np.float32) ) - for it1 in info.Nt[ist]: - for ia1 in range(info.Na[ist][it1]): - for il1 in range(info.Nl[it1]): - for im1 in range(info.Nm(il1)): - for it2 in info.Nt[ist]: - for ia2 in range(info.Na[ist][it2]): - for il2 in range(info.Nl[it2]): - for im2 in range(info.Nm(il2)): - for ie1 in range(info.Ne[it1]): - for ie2 in range(info.Ne[it2]): - if not line: line = file.readline().split() - SI[it1,it2][il1][il2].real[ia1,im1,ie1,ia2,im2,ie2] = float(line.pop(0)) - if not line: line = file.readline().split() - SI[it1,it2][il1][il2].imag[ia1,im1,ie1,ia2,im2,ie2] = float(line.pop(0)) - for it1,it2 in itertools.product( info.Nt[ist], info.Nt[ist] ): - for il1,il2 in itertools.product( range(info.Nl[it1]), range(info.Nl[it2]) ): - SI[it1,it2][il1][il2] = torch_complex.ComplexTensor( - torch.from_numpy(SI[it1,it2][il1][il2].real), - torch.from_numpy(SI[it1,it2][il1][il2].imag)) - return SI,line - - - -def read_VI(info,V_info,ist,file,line=None): - if V_info["same_band"]: - """ VI[ib] """ - if V_info["init_from_file"]: - VI = np.empty(info.Nb[ist],dtype=np.float32) - for ib in range(info.Nb[ist]): - if not line: line = file.readline().split() - VI.data[ib] = float(line.pop(0)) - else: - VI = np.ones(info.Nb[ist],dtype=np.float32) - else: - """ VI[ib1,ib2] """ - if V_info["init_from_file"]: - VI = np.empty((info.Nb[ist],info.Nb[ist]),dtype=np.float32) - for ib1,ib2 in itertools.product( range(info.Nb[ist]), range(info.Nb[ist]) ): - if not line: line = file.readline().split() - VI[ib1,ib2] = float(line.pop(0)) - else: - VI = np.eye(info.Nb[ist],info.Nb[ist],dtype=np.float32) - return torch.from_numpy(VI),line + +def read_file(info, file_list, V_info): + """QI[ist][it][il][ib*ia*im,ie]""" + """ SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] """ + """ VI[ist][ib] """ + import copy + + info_true = copy.deepcopy(info) + info_true.Nst = len(file_list) + info_true.Nt = ND_list(info_true.Nst, element="list()") + info_true.Na = ND_list(info_true.Nst, element="dict()") + info_true.Nb = ND_list(info_true.Nst) + info_true.Nk = ND_list(info_true.Nst) + info_true.Ne = dict() + info_true.weight = ND_list(info_true.Nst, element="list()") + QI = [] + SI = [] + VI = [] + + for ist_true, file_name in enumerate(file_list): + print(file_name) + with open(file_name, "r") as file: + + ignore_line(file, 4) + Nt_tmp = int(file.readline().split()[0]) + for it in range(Nt_tmp): + t_tmp = file.readline().split()[0] + assert t_tmp in info.Nt_all + info_true.Nt[ist_true].append(t_tmp) + info_true.Na[ist_true][t_tmp] = int(file.readline().split()[0]) + ignore_line(file, info_true.Na[ist_true][t_tmp]) + ignore_line(file, 6) + Nl_ist = int(file.readline().split()[0]) + 1 + for it, Nl_C in info.Nl.items(): + print(it, Nl_ist, Nl_C) + assert Nl_ist >= Nl_C + info_true.Nl[it] = Nl_ist + info_true.Nk[ist_true] = int(file.readline().split()[0]) + info_true.Nb[ist_true] = int(file.readline().split()[0]) + ignore_line(file, 1) + Ne_tmp = list(map(int, file.readline().split()[:Nt_tmp])) + for it, Ne in zip(info_true.Nt[ist_true], Ne_tmp): + assert info_true.Ne.setdefault(it, Ne) == Ne + ignore_line(file, 1) + for ik in range(info_true.Nk[ist_true]): + info_true.weight[ist_true].append(float(file.readline().split()[-1])) + ignore_line(file, 3) + + line = None + for ik in range(info_true.Nk[ist_true]): + print("read QI:", ist_true, ik) + qi, line = read_QI(info_true, ist_true, file, line) + QI.append(qi) + ignore_line(file, 3) + for ik in range(info_true.Nk[ist_true]): + print("read SI:", ist_true, ik) + si, line = read_SI(info_true, ist_true, file, line) + SI.append(si) + if V_info["init_from_file"]: + ignore_line(file, 3) + for ik in range(info_true.Nk[ist_true]): + print("read VI:", ist_true, ik) + vi, line = read_VI(info_true, V_info, ist_true, file, line) + VI.append(vi) + + info.Nst = sum(info_true.Nk, 0) + import itertools + + repeat_Nk = lambda x: list( + itertools.chain.from_iterable( + map(lambda x: itertools.repeat(*x), zip(x, info_true.Nk)) + ) + ) + info.Nt = repeat_Nk(info_true.Nt) + info.Na = repeat_Nk(info_true.Na) + info.Nb = repeat_Nk(info_true.Nb) + info.Nb_true = repeat_Nk(info.Nb_true) + info.Ne = info_true.Ne + info.weight = list( + itertools.chain.from_iterable( + [np.array(wk) * ws for wk, ws in zip(info_true.weight, info.weight)] + ) + ) # info_true.weight[ist][ik] * info.weight[ist] + + return QI, SI, VI + + +def read_QI(info, ist, file, line=None): + """QI[it][il][ib*ia*im,ie]""" + QI = dict() + for it in info.Nt[ist]: + QI[it] = ND_list(info.Nl[it]) + for il in range(info.Nl[it]): + QI[it][il] = torch_complex.ComplexTensor( + np.empty( + (info.Nb[ist], info.Na[ist][it], info.Nm(il), info.Ne[it]), + dtype=np.float32, + ), + np.empty( + (info.Nb[ist], info.Na[ist][it], info.Nm(il), info.Ne[it]), + dtype=np.float32, + ), + ) + for ib in range(info.Nb[ist]): + for it in info.Nt[ist]: + for ia in range(info.Na[ist][it]): + for il in range(info.Nl[it]): + for im in range(info.Nm(il)): + for ie in range(info.Ne[it]): + if not line: + line = file.readline().split() + QI[it][il].real[ib, ia, im, ie] = float(line.pop(0)) + if not line: + line = file.readline().split() + QI[it][il].imag[ib, ia, im, ie] = float(line.pop(0)) + for it in info.Nt[ist]: + for il in range(info.Nl[it]): + QI[it][il] = torch_complex.ComplexTensor( + torch.from_numpy(QI[it][il].real).view(-1, info.Ne[it]), + torch.from_numpy(QI[it][il].imag).view(-1, info.Ne[it]), + ) + return QI, line + + +def read_SI(info, ist, file, line=None): + """SI[it1,it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2]""" + SI = dict() + for it1, it2 in itertools.product(info.Nt[ist], info.Nt[ist]): + SI[it1, it2] = ND_list(info.Nl[it1], info.Nl[it2]) + for il1, il2 in itertools.product(range(info.Nl[it1]), range(info.Nl[it2])): + SI[it1, it2][il1][il2] = torch_complex.ComplexTensor( + np.empty( + ( + info.Na[ist][it1], + info.Nm(il1), + info.Ne[it1], + info.Na[ist][it2], + info.Nm(il2), + info.Ne[it2], + ), + dtype=np.float32, + ), + np.empty( + ( + info.Na[ist][it1], + info.Nm(il1), + info.Ne[it1], + info.Na[ist][it2], + info.Nm(il2), + info.Ne[it2], + ), + dtype=np.float32, + ), + ) + for it1 in info.Nt[ist]: + for ia1 in range(info.Na[ist][it1]): + for il1 in range(info.Nl[it1]): + for im1 in range(info.Nm(il1)): + for it2 in info.Nt[ist]: + for ia2 in range(info.Na[ist][it2]): + for il2 in range(info.Nl[it2]): + for im2 in range(info.Nm(il2)): + for ie1 in range(info.Ne[it1]): + for ie2 in range(info.Ne[it2]): + if not line: + line = file.readline().split() + SI[it1, it2][il1][il2].real[ + ia1, im1, ie1, ia2, im2, ie2 + ] = float(line.pop(0)) + if not line: + line = file.readline().split() + SI[it1, it2][il1][il2].imag[ + ia1, im1, ie1, ia2, im2, ie2 + ] = float(line.pop(0)) + for it1, it2 in itertools.product(info.Nt[ist], info.Nt[ist]): + for il1, il2 in itertools.product(range(info.Nl[it1]), range(info.Nl[it2])): + SI[it1, it2][il1][il2] = torch_complex.ComplexTensor( + torch.from_numpy(SI[it1, it2][il1][il2].real), + torch.from_numpy(SI[it1, it2][il1][il2].imag), + ) + return SI, line + + +def read_VI(info, V_info, ist, file, line=None): + if V_info["same_band"]: + """VI[ib]""" + if V_info["init_from_file"]: + VI = np.empty(info.Nb[ist], dtype=np.float32) + for ib in range(info.Nb[ist]): + if not line: + line = file.readline().split() + VI.data[ib] = float(line.pop(0)) + else: + VI = np.ones(info.Nb[ist], dtype=np.float32) + else: + """VI[ib1,ib2]""" + if V_info["init_from_file"]: + VI = np.empty((info.Nb[ist], info.Nb[ist]), dtype=np.float32) + for ib1, ib2 in itertools.product(range(info.Nb[ist]), range(info.Nb[ist])): + if not line: + line = file.readline().split() + VI[ib1, ib2] = float(line.pop(0)) + else: + VI = np.eye(info.Nb[ist], info.Nb[ist], dtype=np.float32) + return torch.from_numpy(VI), line diff --git a/tools/opt_orb_pytorch/IO/read_json.py b/tools/opt_orb_pytorch/IO/read_json.py index 52887f9775b..aea78f57fd6 100644 --- a/tools/opt_orb_pytorch/IO/read_json.py +++ b/tools/opt_orb_pytorch/IO/read_json.py @@ -1,64 +1,65 @@ import json from util import Info + def read_json(file_name): - with open(file_name,"r") as file: - input = file.read() - input = json.loads(input) - - info = Info() - for info_attr,info_value in input["info"].items(): - info.__dict__[info_attr] = info_value - info.Nl = { it:len(Nu) for it,Nu in info.Nu.items() } - - return input["file_list"], info, input["C_init_info"], input["V_info"] + with open(file_name, "r") as file: + input = file.read() + input = json.loads(input) + + info = Info() + for info_attr, info_value in input["info"].items(): + info.__dict__[info_attr] = info_value + info.Nl = {it: len(Nu) for it, Nu in info.Nu.items()} + + return input["file_list"], info, input["C_init_info"], input["V_info"] + + """ file_name + { + "file_list": + [ + "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/S2/S2.10.dat", + "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SO2/SO2.10.dat", + "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SO/SO.10.dat" + ], + "info": + { + "Nt_all": ["S","O"], + "Nu": {"S":[3,3,2],"O":[3,3,2]}, + "Nb_true": [7,9,7], + "weight": [2,3,1.5], + "Rcut": {"S":10,"O":10}, + "dr": {"S":0.01,"O":0.01}, + "Ecut": {"S":100,"O":100}, + "lr": 0.01 + }, + "C_init_info": + { + "init_from_file": false, + "C_init_file": "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SIA/ORBITAL_RESULTS.txt" + }, + "V_info": + { + "init_from_file": true, + "same_band": false + } + } + """ - """ file_name - { - "file_list": - [ - "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/S2/S2.10.dat", - "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SO2/SO2.10.dat", - "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SO/SO.10.dat" - ], - "info": - { - "Nt_all": ["S","O"], - "Nu": {"S":[3,3,2],"O":[3,3,2]}, - "Nb_true": [7,9,7], - "weight": [2,3,1.5], - "Rcut": {"S":10,"O":10}, - "dr": {"S":0.01,"O":0.01}, - "Ecut": {"S":100,"O":100}, - "lr": 0.01 - }, - "C_init_info": - { - "init_from_file": false, - "C_init_file": "/public/udata/linpz/try/SIA/pytorch/test/many_atoms/SIA/ORBITAL_RESULTS.txt" - }, - "V_info": - { - "init_from_file": true, - "same_band": false - } - } - """ - - """ info - Nt_all ["S", "O"] - Nu {"S":[3,3,2], "O":[3,3,2]} - Nb_true [7, 9, 7] - weight [2, 3, 1.5] - Rcut {"S":10, "O":10} - dr {"S":0.01, "O":0.01} - Ecut {"S":100, "O":100} - lr 0.01 - Nl {"S":2, "O":2} - Nst 3 - Nt [["S"], ["S","O"], ["S","O"]] - Na [{"S":2}, {"S":1,"O":2}, {"S":1,"O":1}] - Nb [7, 9, 7] - Ne {"S":22, "O":19} - """ \ No newline at end of file + """ info + Nt_all ["S", "O"] + Nu {"S":[3,3,2], "O":[3,3,2]} + Nb_true [7, 9, 7] + weight [2, 3, 1.5] + Rcut {"S":10, "O":10} + dr {"S":0.01, "O":0.01} + Ecut {"S":100, "O":100} + lr 0.01 + Nl {"S":2, "O":2} + Nst 3 + Nt [["S"], ["S","O"], ["S","O"]] + Na [{"S":2}, {"S":1,"O":2}, {"S":1,"O":1}] + Nb [7, 9, 7] + Ne {"S":22, "O":19} + """ diff --git a/tools/opt_orb_pytorch/inverse.py b/tools/opt_orb_pytorch/inverse.py index 311519fae15..87bc82dc329 100644 --- a/tools/opt_orb_pytorch/inverse.py +++ b/tools/opt_orb_pytorch/inverse.py @@ -1,55 +1,56 @@ -import torch - - -def inverse_DC(A,B,C,D): - tmp_A = inverse(A) # A^{-1} - #print("tmp_A",tmp_A) - tmp_AB = torch.mm(tmp_A,B) # A^{-1} B - #print("tmp_AB",tmp_AB) - tmp_CA = torch.mm(C,tmp_A) # C A^{-1} - #print("tmp_CA",tmp_CA) - tmp_X = inverse(D-torch.mm(tmp_CA,B)) # ( D - C A^{-1} B )^{-1} - #print("tmp_X",tmp_X) - tmp_ABX = torch.mm(tmp_AB,tmp_X) # A^{-1} B ( D - C A^{-1} B )^{-1} - #print("tmp_ABX",tmp_ABX) - tmp_XCA = torch.mm(tmp_X,tmp_CA) # ( D - C A^{-1} B )^{-1} C A^{-1} - #print("tmp_XCA",tmp_XCA) - tmp_ABXCA = torch.mm(tmp_ABX,tmp_CA) # A^{-1} B ( D - C A^{-1} B )^{-1} C A^{-1} - #print("tmp_ABXCA",tmp_ABXCA) - - tmp_up = torch.cat( [ tmp_A+tmp_ABXCA, -tmp_ABX ], dim=1 ) - tmp_down = torch.cat( [ -tmp_XCA, tmp_X ], dim=1 ) - I = torch.cat( [tmp_up,tmp_down], dim=0 ) - return I - - - -def inverse(M): - -# assert len(M.size()) == 2, "inverse must be 2D" -# assert M.size()[0] == M.size()[1], "inverse row != column" - - L = M.size()[0] - - if L==1: - return 1/M - - elif L==2: - det = torch.cat(list( M[:1,:1]*M[1:,1:] - M[:1,1:]*M[1:,:1] )*4).view(2,2) - I_up = torch.cat([M[1:,1:],-M[:1,1:]],dim=1) - I_down = torch.cat([-M[1:,:1],M[:1,:1]],dim=1) - I_all = torch.cat([I_up,I_down],dim=0) - return I_all/det - - elif L==3: - threshold = 1e-10 - if M[0,0].abs() > threshold: - return inverse_DC( M[:1,:1], M[:1,1:], M[1:,:1], M[1:,1:] ) - elif M[2,2].abs() > threshold: - return inverse_DC( M[:2,:2], M[:2,2:], M[2:,:2], M[2:,2:] ) - else: - raise ZeroDivisionError("matrix inverse") - - else: - L2 = L//2 - return inverse_DC( M[:L2,:L2], M[:L2,L2:], M[L2:,:L2], M[L2:,L2:] ) \ No newline at end of file +import torch + + +def inverse_DC(A, B, C, D): + tmp_A = inverse(A) # A^{-1} + # print("tmp_A",tmp_A) + tmp_AB = torch.mm(tmp_A, B) # A^{-1} B + # print("tmp_AB",tmp_AB) + tmp_CA = torch.mm(C, tmp_A) # C A^{-1} + # print("tmp_CA",tmp_CA) + tmp_X = inverse(D - torch.mm(tmp_CA, B)) # ( D - C A^{-1} B )^{-1} + # print("tmp_X",tmp_X) + tmp_ABX = torch.mm(tmp_AB, tmp_X) # A^{-1} B ( D - C A^{-1} B )^{-1} + # print("tmp_ABX",tmp_ABX) + tmp_XCA = torch.mm(tmp_X, tmp_CA) # ( D - C A^{-1} B )^{-1} C A^{-1} + # print("tmp_XCA",tmp_XCA) + tmp_ABXCA = torch.mm(tmp_ABX, tmp_CA) # A^{-1} B ( D - C A^{-1} B )^{-1} C A^{-1} + # print("tmp_ABXCA",tmp_ABXCA) + + tmp_up = torch.cat([tmp_A + tmp_ABXCA, -tmp_ABX], dim=1) + tmp_down = torch.cat([-tmp_XCA, tmp_X], dim=1) + I = torch.cat([tmp_up, tmp_down], dim=0) + return I + + +def inverse(M): + + # assert len(M.size()) == 2, "inverse must be 2D" + # assert M.size()[0] == M.size()[1], "inverse row != column" + + L = M.size()[0] + + if L == 1: + return 1 / M + + elif L == 2: + det = torch.cat(list(M[:1, :1] * M[1:, 1:] - M[:1, 1:] * M[1:, :1]) * 4).view( + 2, 2 + ) + I_up = torch.cat([M[1:, 1:], -M[:1, 1:]], dim=1) + I_down = torch.cat([-M[1:, :1], M[:1, :1]], dim=1) + I_all = torch.cat([I_up, I_down], dim=0) + return I_all / det + + elif L == 3: + threshold = 1e-10 + if M[0, 0].abs() > threshold: + return inverse_DC(M[:1, :1], M[:1, 1:], M[1:, :1], M[1:, 1:]) + elif M[2, 2].abs() > threshold: + return inverse_DC(M[:2, :2], M[:2, 2:], M[2:, :2], M[2:, 2:]) + else: + raise ZeroDivisionError("matrix inverse") + + else: + L2 = L // 2 + return inverse_DC(M[:L2, :L2], M[:L2, L2:], M[L2:, :L2], M[L2:, L2:]) diff --git a/tools/opt_orb_pytorch/main.py b/tools/opt_orb_pytorch/main.py index 49d8753e6bf..bdc401d934f 100644 --- a/tools/opt_orb_pytorch/main.py +++ b/tools/opt_orb_pytorch/main.py @@ -9,64 +9,82 @@ import numpy as np import time -print("seed:",torch.initial_seed()) +print("seed:", torch.initial_seed()) time_start = time.time() file_list, info, C_init_info, V_info = IO.read_json.read_json("input.json") -QI,SI,VI = IO.read_QSV.read_file(info,file_list,V_info) +QI, SI, VI = IO.read_QSV.read_file(info, file_list, V_info) print(info) if C_init_info["init_from_file"]: - C = IO.func_C.read_C_init( C_init_info["C_init_file"], info ) + C = IO.func_C.read_C_init(C_init_info["C_init_file"], info) else: - C = IO.func_C.random_C_init(info) -E = orbital.set_E(info,info.Rcut) -orbital.normalize( orbital.generate_orbital(info,C,E,info.Rcut,info.dr), info.dr,C,flag_norm_C=True) + C = IO.func_C.random_C_init(info) +E = orbital.set_E(info, info.Rcut) +orbital.normalize( + orbital.generate_orbital(info, C, E, info.Rcut, info.dr), + info.dr, + C, + flag_norm_C=True, +) opt_orb = opt_orbital.Opt_Orbital() -#opt = torch.optim.Adam(sum( ([c.real,c.imag] for c in sum(C,[])), []), lr=info.lr, eps=1e-8) -opt = torch.optim.Adam( sum(C.values(),[]), lr=info.lr, eps=1e-20) +# opt = torch.optim.Adam(sum( ([c.real,c.imag] for c in sum(C,[])), []), lr=info.lr, eps=1e-8) +opt = torch.optim.Adam(sum(C.values(), []), lr=info.lr, eps=1e-20) -with open("Spillage.dat","w") as S_file: +with open("Spillage.dat", "w") as S_file: - loss_old = np.inf + loss_old = np.inf - for i in range(20000): - Q = opt_orb.cal_Q(QI,C,info) - S = opt_orb.cal_S(SI,C,info) - V = opt_orb.cal_V(Q,S,info,V_info) + for i in range(20000): + Q = opt_orb.cal_Q(QI, C, info) + S = opt_orb.cal_S(SI, C, info) + V = opt_orb.cal_V(Q, S, info, V_info) - V_delta = ( torch.abs(VIi-Vi) for VIi,Vi in zip(VI,V) ) # abs or **2? - if V_info["same_band"]: - Spillage = sum( Vi[:info.Nb_true[ist]].sum() * info.weight[ist] for ist,Vi in enumerate(V_delta) ) / sum( Nb_true*weight for Nb_true,weight in zip(info.Nb_true,info.weight) ) - else: - Spillage = sum( Vi[:info.Nb_true[ist],:info.Nb_true[ist]].sum() * info.weight[ist] for ist,Vi in enumerate(V_delta) ) / sum( Nb_true**2*weight for Nb_true,weight in zip(info.Nb_true,info.weight) ) - T = opt_orb.cal_T(C,E) - if not "TSrate" in vars(): TSrate = torch.abs(0.002*Spillage/T).data[0] - Loss = Spillage + TSrate*T + V_delta = (torch.abs(VIi - Vi) for VIi, Vi in zip(VI, V)) # abs or **2? + if V_info["same_band"]: + Spillage = sum( + Vi[: info.Nb_true[ist]].sum() * info.weight[ist] + for ist, Vi in enumerate(V_delta) + ) / sum( + Nb_true * weight for Nb_true, weight in zip(info.Nb_true, info.weight) + ) + else: + Spillage = sum( + Vi[: info.Nb_true[ist], : info.Nb_true[ist]].sum() * info.weight[ist] + for ist, Vi in enumerate(V_delta) + ) / sum( + Nb_true**2 * weight + for Nb_true, weight in zip(info.Nb_true, info.weight) + ) + T = opt_orb.cal_T(C, E) + if not "TSrate" in vars(): + TSrate = torch.abs(0.002 * Spillage / T).data[0] + Loss = Spillage + TSrate * T - print(Spillage.item(),T.item(),Loss.item(),file=S_file) - if Loss.item() < loss_old: - loss_old = Loss.item() - C_old = IO.func_C.copy_C(C,info) - flag_finish = 0 - else: - flag_finish += 1 - if flag_finish > 50: break + print(Spillage.item(), T.item(), Loss.item(), file=S_file) + if Loss.item() < loss_old: + loss_old = Loss.item() + C_old = IO.func_C.copy_C(C, info) + flag_finish = 0 + else: + flag_finish += 1 + if flag_finish > 50: + break - opt.zero_grad() - Loss.backward() - opt.step() -# orbital.normalize( orbital.generate_orbital(info,C,E,info.Rcut,info.dr), info.dr,C,flag_norm_C=True) + opt.zero_grad() + Loss.backward() + opt.step() + # orbital.normalize( orbital.generate_orbital(info,C,E,info.Rcut,info.dr), info.dr,C,flag_norm_C=True) - orb = orbital.generate_orbital(info,C_old,E,info.Rcut,info.dr) - orbital.smooth_orbital(orb,info.Rcut,info.dr,0.1) - orbital.orth(orb,info.dr) - IO.print_orbital.print_orbital(orb,info) - IO.print_orbital.plot_orbital(orb,info.Rcut,info.dr) + orb = orbital.generate_orbital(info, C_old, E, info.Rcut, info.dr) + orbital.smooth_orbital(orb, info.Rcut, info.dr, 0.1) + orbital.orth(orb, info.dr) + IO.print_orbital.print_orbital(orb, info) + IO.print_orbital.plot_orbital(orb, info.Rcut, info.dr) - IO.func_C.write_C("C.dat",info,C_old) + IO.func_C.write_C("C.dat", info, C_old) - print("time:\t",time.time()-time_start) \ No newline at end of file + print("time:\t", time.time() - time_start) diff --git a/tools/opt_orb_pytorch/opt_orbital.py b/tools/opt_orb_pytorch/opt_orbital.py index 6f3a3579826..cca21342290 100644 --- a/tools/opt_orb_pytorch/opt_orbital.py +++ b/tools/opt_orb_pytorch/opt_orbital.py @@ -5,133 +5,137 @@ import itertools import torch + class Opt_Orbital: - - def cal_Q(self,QI,C,info): - """ - Q[ist][it][il][ib,ia*im*iu] - = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] - """ - Q = ND_list(info.Nst,element="dict()") - for ist in range(info.Nst): - for it in info.Nt[ist]: - Q[ist][it] = ND_list(info.Nl[it]) - for ist in range(info.Nst): - for it in info.Nt[ist]: - for il in range(info.Nl[it]): - Q[ist][it][il] = torch_complex.mm( QI[ist][it][il], C[it][il] ).view(info.Nb[ist],-1) - return Q + def cal_Q(self, QI, C, info): + """ + Q[ist][it][il][ib,ia*im*iu] + = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] + """ + Q = ND_list(info.Nst, element="dict()") + for ist in range(info.Nst): + for it in info.Nt[ist]: + Q[ist][it] = ND_list(info.Nl[it]) + + for ist in range(info.Nst): + for it in info.Nt[ist]: + for il in range(info.Nl[it]): + Q[ist][it][il] = torch_complex.mm(QI[ist][it][il], C[it][il]).view( + info.Nb[ist], -1 + ) + return Q + + def cal_S(self, SI, C, info): + """ + S[ist][it1,it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2] + = sum_{ie1 ie2} C^*[it1][il1][ie1,iu1] * SI[ist][it1,it2][il1][il2][ia1,im1,ie1,ia2,im2,ie2] * C[it2][[il2][ie2,iu2] + """ + S = ND_list(info.Nst, element="dict()") + for ist in range(info.Nst): + for it1, it2 in itertools.product(info.Nt[ist], info.Nt[ist]): + S[ist][it1, it2] = ND_list(info.Nl[it1], info.Nl[it2]) + + for ist in range(info.Nst): + for it1, it2 in itertools.product(info.Nt[ist], info.Nt[ist]): + for il1, il2 in itertools.product( + range(info.Nl[it1]), range(info.Nl[it2]) + ): + # SI_C[ia1*im1*ie1*ia2*im2,iu2] + SI_C = torch_complex.mm( + SI[ist][it1, it2][il1][il2].view(-1, info.Ne[it2]), C[it2][il2] + ) + # SI_C[ia1*im1,ie1,ia2*im2*iu2] + SI_C = SI_C.view(info.Na[ist][it1] * info.Nm(il1), info.Ne[it1], -1) + # Ct[iu1,ie1] + Ct = C[it1][il1].t() + C_mm = functools.partial(torch_complex.mm, Ct) + # C_SI_C[ia1*im1][iu1,ia2*im2*iu2] + C_SI_C = list(map(C_mm, SI_C)) + # C_SI_C[ia1*im1*iu1,ia2*im2*iu2] + C_SI_C = torch_complex.cat(C_SI_C, dim=0) + # ??? C_SI_C = C_SI_C.view(info.Na[ist][it1]*info.Nm(il1)*info.Nu[it1][il1],-1) + S[ist][it1, it2][il1][il2] = C_SI_C + return S + + def cal_V(self, Q, S, info, V_info): + """ + V[ist][ib] + = sum_{it1,ia1,il1,im1,iu1} sum_{it2,ia2,il2,im2,iu2} + Q[ist][it1][il1][ib,ia1*im1*iu1] * S[ist]{[it1][it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*iu2] + V[ist][ib1,ib2] + = sum_{it1,ia1,il1,im1,iu1} sum_{it2,ia2,il2,im2,iu2} + Q[ist][it1][il1][ib1,ia1*im1*iu1] * S[ist]{[it1][it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2]}^{-1} * Q[ist][it2][il2][ib2,ia2*im2*iu2] + """ + V = ND_list(info.Nst) + for ist in range(info.Nst): - - - def cal_S(self,SI,C,info): - """ - S[ist][it1,it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2] - = sum_{ie1 ie2} C^*[it1][il1][ie1,iu1] * SI[ist][it1,it2][il1][il2][ia1,im1,ie1,ia2,im2,ie2] * C[it2][[il2][ie2,iu2] - """ - S = ND_list(info.Nst,element="dict()") - for ist in range(info.Nst): - for it1,it2 in itertools.product( info.Nt[ist], info.Nt[ist] ): - S[ist][it1,it2] = ND_list(info.Nl[it1],info.Nl[it2]) + # S_s[it1][il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] + S_s = dict() + for it1 in info.Nt[ist]: + # S_st[it2][il1*ia1*im1*iu1,il2*ia2*im2*iu2] + S_st = dict() + for it2 in info.Nt[ist]: + # S_stt[il1][ia1*im1*iu1,il2*ia2*im2*iu2] + S_stt = ND_list(info.Nl[it1]) + for il1 in range(info.Nl[it1]): + S_stt[il1] = torch_complex.cat(S[ist][it1, it2][il1], dim=1) + S_st[it2] = torch_complex.cat(S_stt, dim=0) + S_s[it1] = torch_complex.cat(list(S_st.values()), dim=1) + # S_cat[it1*il1*iat*im1*iu1,iat2*il2*ia2*im2*iu2] + S_cat = torch_complex.cat(list(S_s.values()), dim=0) + S_I = torch_complex.inverse(S_cat) - for ist in range(info.Nst): - for it1,it2 in itertools.product( info.Nt[ist], info.Nt[ist] ): - for il1,il2 in itertools.product( range(info.Nl[it1]), range(info.Nl[it2]) ): - # SI_C[ia1*im1*ie1*ia2*im2,iu2] - SI_C = torch_complex.mm( - SI[ist][it1,it2][il1][il2].view(-1,info.Ne[it2]), - C[it2][il2] ) - # SI_C[ia1*im1,ie1,ia2*im2*iu2] - SI_C = SI_C.view( info.Na[ist][it1]*info.Nm(il1), info.Ne[it1], -1 ) - # Ct[iu1,ie1] - Ct = C[it1][il1].t() - C_mm = functools.partial(torch_complex.mm,Ct) - # C_SI_C[ia1*im1][iu1,ia2*im2*iu2] - C_SI_C = list(map( C_mm, SI_C )) - # C_SI_C[ia1*im1*iu1,ia2*im2*iu2] - C_SI_C = torch_complex.cat( C_SI_C, dim=0 ) -#??? C_SI_C = C_SI_C.view(info.Na[ist][it1]*info.Nm(il1)*info.Nu[it1][il1],-1) - S[ist][it1,it2][il1][il2] = C_SI_C - return S + if V_info["same_band"]: + # V_s[ib] + V_s = ND_list(info.Nb[ist]) + for ib in range(info.Nb[ist]): + # Q_s[it][il*ia*im*iu] + Q_s = dict() + for it in info.Nt[ist]: + # Q_ts[il][ia*im*iu] + Q_ts = [Q_stl[ib] for Q_stl in Q[ist][it]] + Q_s[it] = torch_complex.cat(Q_ts) + # Q_cat[it*il*ia*im*iu] + Q_cat = torch_complex.cat(list(Q_s.values())) + V_s[ib] = torch_complex.dot( + Q_cat.conj(), torch_complex.mv(S_I, Q_cat) + ).real.view(-1) + # V[ist][ib] + V[ist] = torch.cat(V_s) + else: + # Q_b[ib][0,it*il*ia*im*iu] + Q_b = ND_list(info.Nb[ist]) + for ib in range(info.Nb[ist]): + # Q_s[it][il*ia*im*iu] + Q_s = dict() + for it in info.Nt[ist]: + # Q_ts[il][ia*im*iu] + Q_ts = [Q_stl[ib] for Q_stl in Q[ist][it]] + Q_s[it] = torch_complex.cat(Q_ts) + Q_b[ib] = torch_complex.cat(list(Q_s.values())).view(1, -1) + # Q_cat[ib,it*il*ia*im*iu] + Q_cat = torch_complex.cat(Q_b, dim=0) + # V[ist][ib1,ib2] + V[ist] = torch_complex.mm( + Q_cat.conj(), torch_complex.mm(S_I, Q_cat.t()) + ).real - - - def cal_V(self,Q,S,info,V_info): - """ - V[ist][ib] - = sum_{it1,ia1,il1,im1,iu1} sum_{it2,ia2,il2,im2,iu2} - Q[ist][it1][il1][ib,ia1*im1*iu1] * S[ist]{[it1][it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*iu2] - V[ist][ib1,ib2] - = sum_{it1,ia1,il1,im1,iu1} sum_{it2,ia2,il2,im2,iu2} - Q[ist][it1][il1][ib1,ia1*im1*iu1] * S[ist]{[it1][it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2]}^{-1} * Q[ist][it2][il2][ib2,ia2*im2*iu2] - """ - V = ND_list(info.Nst) - for ist in range(info.Nst): - - # S_s[it1][il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] - S_s = dict() - for it1 in info.Nt[ist]: - # S_st[it2][il1*ia1*im1*iu1,il2*ia2*im2*iu2] - S_st = dict() - for it2 in info.Nt[ist]: - # S_stt[il1][ia1*im1*iu1,il2*ia2*im2*iu2] - S_stt = ND_list(info.Nl[it1]) - for il1 in range(info.Nl[it1]): - S_stt[il1] = torch_complex.cat( S[ist][it1,it2][il1], dim=1 ) - S_st[it2] = torch_complex.cat( S_stt, dim=0 ) - S_s[it1] = torch_complex.cat( list(S_st.values()), dim=1 ) - # S_cat[it1*il1*iat*im1*iu1,iat2*il2*ia2*im2*iu2] - S_cat = torch_complex.cat( list(S_s.values()), dim=0 ) - S_I = torch_complex.inverse(S_cat) - - if V_info["same_band"]: - # V_s[ib] - V_s = ND_list(info.Nb[ist]) - for ib in range(info.Nb[ist]): - # Q_s[it][il*ia*im*iu] - Q_s = dict() - for it in info.Nt[ist]: - # Q_ts[il][ia*im*iu] - Q_ts = [ Q_stl[ib] for Q_stl in Q[ist][it] ] - Q_s[it] = torch_complex.cat(Q_ts) - # Q_cat[it*il*ia*im*iu] - Q_cat = torch_complex.cat(list(Q_s.values())) - V_s[ib] = torch_complex.dot( Q_cat.conj(), torch_complex.mv( S_I, Q_cat ) ).real.view(-1) - # V[ist][ib] - V[ist] = torch.cat(V_s) - else: - # Q_b[ib][0,it*il*ia*im*iu] - Q_b = ND_list(info.Nb[ist]) - for ib in range(info.Nb[ist]): - # Q_s[it][il*ia*im*iu] - Q_s = dict() - for it in info.Nt[ist]: - # Q_ts[il][ia*im*iu] - Q_ts = [ Q_stl[ib] for Q_stl in Q[ist][it] ] - Q_s[it] = torch_complex.cat(Q_ts) - Q_b[ib] = torch_complex.cat(list(Q_s.values())).view(1,-1) - # Q_cat[ib,it*il*ia*im*iu] - Q_cat = torch_complex.cat( Q_b, dim=0 ) - # V[ist][ib1,ib2] - V[ist] = torch_complex.mm( Q_cat.conj(), torch_complex.mm( S_I, Q_cat.t() ) ).real + return V - return V - - - def cal_T(self,C,E): - """ T = 0.5* sum_{it,il,iu} sum_{ie} ( E[it][il,ie] * C[it][il][ie,iu] )**2 """ - T = torch.zeros(1) - num = 0 - for it,C_t in C.items(): - for il,C_tl in enumerate(C_t): - for iu in range(C_tl.size()[1]): - T_tlu = torch.zeros(1) - Z_tlu = 0 - for ie in range(C_tl.size()[0]): - T_tlu = T_tlu + ( E[it][il,ie] * C_tl[ie,iu] )**2 - Z_tlu = Z_tlu + E[it][il,ie].item()**2 - T = T + T_tlu/Z_tlu - num += C_tl.size()[1] - T = 0.5 * T / num - return T \ No newline at end of file + def cal_T(self, C, E): + """T = 0.5* sum_{it,il,iu} sum_{ie} ( E[it][il,ie] * C[it][il][ie,iu] )**2""" + T = torch.zeros(1) + num = 0 + for it, C_t in C.items(): + for il, C_tl in enumerate(C_t): + for iu in range(C_tl.size()[1]): + T_tlu = torch.zeros(1) + Z_tlu = 0 + for ie in range(C_tl.size()[0]): + T_tlu = T_tlu + (E[it][il, ie] * C_tl[ie, iu]) ** 2 + Z_tlu = Z_tlu + E[it][il, ie].item() ** 2 + T = T + T_tlu / Z_tlu + num += C_tl.size()[1] + T = 0.5 * T / num + return T diff --git a/tools/opt_orb_pytorch/opt_orbital.py_real b/tools/opt_orb_pytorch/opt_orbital.py_real index 5ade0f90fc4..65e91aeb0d4 100644 --- a/tools/opt_orb_pytorch/opt_orbital.py_real +++ b/tools/opt_orb_pytorch/opt_orbital.py_real @@ -1,86 +1,86 @@ -from global_function import ND_list -import inverse -import torch - -class SIA: - - def cal_Q(self,QI,C): - """ - Q[ist][it][il][ib,ia*im*iu] - = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] - """ - Q = ND_list(self.Nst) - for ist in range(self.Nst): - Q[ist] = ND_list(self.Nt[ist]) - for it in range(self.Nt[ist]): - Q[ist][it] = ND_list(self.Nl[it]) - - for ist in range(self.Nst): - for it in range(self.Nt[ist]): - for il in range(self.Nl[it]): - Q[ist][it][il] = torch.mm( QI[ist][it][il], C[it][il] ).view(self.Nb[ist],-1) - return Q - - - - def cal_S(self,SI,C): - """ - S[ist][it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2] - = sum_{ie1 ie2} C[it1][il1][ie1,in1] * SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] * C[it2][[il2][ie2,in2] - """ - S = ND_list(self.Nst) - for ist in range(self.Nst): - S[ist] = ND_list(self.Nt[ist],self.Nt[ist]) - for it1 in range(self.Nt[ist]): - for it2 in range(self.Nt[ist]): - S[ist][it1][it2] = ND_list(self.Nl[it1],self.Nl[it2]) - - for ist in range(self.Nst): - for it1 in range(self.Nt[ist]): - for it2 in range(self.Nt[ist]): - for il1 in range(self.Nl[it1]): - for il2 in range(self.Nl[it2]): - S[ist][it1][it2][il1][il2] = torch.mm( - C[it1][il1].t(), - torch.mm( SI[ist][it1][it2][il1][il2].view(-1,self.Ne), C[it2][il2] ).view(self.Ne,-1) - ).view(self.Nn[it1][il1],self.Na[ist][it1]*self.Nm[il1],-1).transpose(0,1).view(self.Na[ist][it1]*self.Nm[il1]*self.Nn[it1][il1],-1) - return S - - - - def cal_V(self,Q,S): - """ - V[ist][ib] - = sum_{it1,ia1,il1,im1,in1} sum_{it2,ia2,il2,im2,in2} - Q[ist][it1][il1][ib,ia1*im1*in1] * S[ist]{[it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*in2] - """ - V = ND_list(self.Nst) - for ist in range(self.Nst): - V[ist] = ND_list(self.Nb[ist]) - - for ist in range(self.Nst): - - S_s = ND_list(self.Nt[ist]) - for it1 in range(self.Nt[ist]): - S_st = ND_list(self.Nt[ist]) - for it2 in range(self.Nt[ist]): - S_stt = ND_list(self.Nl[it1]) - for il1 in range(self.Nl[it1]): - S_stt[il1] = torch.cat( S[ist][it1][it2][il1], dim=1 ) - S_st[it2] = torch.cat( S_stt, dim=0 ) - S_s[it1] = torch.cat( S_st, dim=1 ) - S_cat = torch.cat( S_s, dim=0 ) - - S_I = inverse.inverse(S_cat) -# S_I = 1/S_cat - - for ib in range(self.Nb[ist]): - - Q_s = ND_list(self.Nt[ist]) - for it in range(self.Nt[ist]): - Q_s[it] = torch.cat([ Q_st[ib] for Q_st in Q[ist][it] ]) - Q_cat = torch.cat(Q_s) - - V[ist][ib] = torch.dot( Q_cat, torch.mv( S_I, Q_cat ) ) - - return V \ No newline at end of file +from global_function import ND_list +import inverse +import torch + +class SIA: + + def cal_Q(self,QI,C): + """ + Q[ist][it][il][ib,ia*im*iu] + = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] + """ + Q = ND_list(self.Nst) + for ist in range(self.Nst): + Q[ist] = ND_list(self.Nt[ist]) + for it in range(self.Nt[ist]): + Q[ist][it] = ND_list(self.Nl[it]) + + for ist in range(self.Nst): + for it in range(self.Nt[ist]): + for il in range(self.Nl[it]): + Q[ist][it][il] = torch.mm( QI[ist][it][il], C[it][il] ).view(self.Nb[ist],-1) + return Q + + + + def cal_S(self,SI,C): + """ + S[ist][it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2] + = sum_{ie1 ie2} C[it1][il1][ie1,in1] * SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] * C[it2][[il2][ie2,in2] + """ + S = ND_list(self.Nst) + for ist in range(self.Nst): + S[ist] = ND_list(self.Nt[ist],self.Nt[ist]) + for it1 in range(self.Nt[ist]): + for it2 in range(self.Nt[ist]): + S[ist][it1][it2] = ND_list(self.Nl[it1],self.Nl[it2]) + + for ist in range(self.Nst): + for it1 in range(self.Nt[ist]): + for it2 in range(self.Nt[ist]): + for il1 in range(self.Nl[it1]): + for il2 in range(self.Nl[it2]): + S[ist][it1][it2][il1][il2] = torch.mm( + C[it1][il1].t(), + torch.mm( SI[ist][it1][it2][il1][il2].view(-1,self.Ne), C[it2][il2] ).view(self.Ne,-1) + ).view(self.Nn[it1][il1],self.Na[ist][it1]*self.Nm[il1],-1).transpose(0,1).view(self.Na[ist][it1]*self.Nm[il1]*self.Nn[it1][il1],-1) + return S + + + + def cal_V(self,Q,S): + """ + V[ist][ib] + = sum_{it1,ia1,il1,im1,in1} sum_{it2,ia2,il2,im2,in2} + Q[ist][it1][il1][ib,ia1*im1*in1] * S[ist]{[it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*in2] + """ + V = ND_list(self.Nst) + for ist in range(self.Nst): + V[ist] = ND_list(self.Nb[ist]) + + for ist in range(self.Nst): + + S_s = ND_list(self.Nt[ist]) + for it1 in range(self.Nt[ist]): + S_st = ND_list(self.Nt[ist]) + for it2 in range(self.Nt[ist]): + S_stt = ND_list(self.Nl[it1]) + for il1 in range(self.Nl[it1]): + S_stt[il1] = torch.cat( S[ist][it1][it2][il1], dim=1 ) + S_st[it2] = torch.cat( S_stt, dim=0 ) + S_s[it1] = torch.cat( S_st, dim=1 ) + S_cat = torch.cat( S_s, dim=0 ) + + S_I = inverse.inverse(S_cat) +# S_I = 1/S_cat + + for ib in range(self.Nb[ist]): + + Q_s = ND_list(self.Nt[ist]) + for it in range(self.Nt[ist]): + Q_s[it] = torch.cat([ Q_st[ib] for Q_st in Q[ist][it] ]) + Q_cat = torch.cat(Q_s) + + V[ist][ib] = torch.dot( Q_cat, torch.mv( S_I, Q_cat ) ) + + return V \ No newline at end of file diff --git a/tools/opt_orb_pytorch/orbital.py b/tools/opt_orb_pytorch/orbital.py index 75c7748187b..8711ab6284e 100644 --- a/tools/opt_orb_pytorch/orbital.py +++ b/tools/opt_orb_pytorch/orbital.py @@ -6,75 +6,89 @@ import functools import torch -def generate_orbital(info,C,E,Rcut,dr): - """ C[it][il][ie,iu] """ - """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ - orb = dict() - for it in info.Nt_all: - Nr = int(Rcut[it]/dr[it])+1 - orb[it] = ND_list(info.Nl[it]) - for il in range(info.Nl[it]): - orb[it][il] = ND_list(info.Nu[it][il]) - for iu in range(info.Nu[it][il]): - orb[it][il][iu] = np.zeros(Nr) - for ir in range(Nr): - r = ir * dr[it] - for ie in range(info.Ne[it]): - orb[it][il][iu][ir] += C[it][il][ie,iu].item() * spherical_jn(il,E[it][il,ie].item()*r) - return orb - - -def smooth_orbital(orb,Rcut,dr,smearing_sigma): - for it,orb_t in orb.items(): - for orb_tl in orb_t: - for orb_tlu in orb_tl: - for ir in range(orb_tlu.shape[0]): - assert orb_tlu.shape[0] == int(Rcut[it]/dr[it])+1 - r = ir * dr[it] - orb_tlu[ir] *= 1-np.exp( -(r-Rcut[it])**2/(2*smearing_sigma**2) ) - - - -def inner_product( orb1, orb2, dr ): - assert orb1.shape == orb2.shape - r = np.array(range(orb1.shape[0]))*dr - return simps( orb1 * orb2 * r * r, dx=dr ) - -def normalize(orb,dr,C=None,flag_norm_orb=False,flag_norm_C=False): - """ C[it][il][ie,iu] """ - """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ - for it,orb_t in orb.items(): - for il,orb_tl in enumerate(orb_t): - for iu,orb_tlu in enumerate(orb_tl): - norm = np.sqrt(inner_product(orb_tlu,orb_tlu,dr[it])) - if flag_norm_orb: orb_tlu[:] = orb_tlu / norm - if flag_norm_C: C[it][il].data[:,iu] = C[it][il].data[:,iu] / norm - -def orth(orb,dr): - """ |n'> = 1/Z ( |n> - \sum_{i=0}^{n-1} |i> ) """ - """ orb[it][il][iu,r] """ - for it,orb_t in orb.items(): - for il,orb_tl in enumerate(orb_t): - for iu1,orb_tlu1 in enumerate(orb_tl): - for iu2 in range(iu1): - orb_tlu1[:] -= orb_tl[iu2] * inner_product(orb_tlu1,orb_tl[iu2],dr[it]) - orb_tlu1[:] = orb_tlu1 / np.sqrt(inner_product(orb_tlu1,orb_tlu1,dr[it])) - -def find_eigenvalue(Nl,Ne): - """ E[il,ie] """ - E = np.zeros((Nl,Ne+Nl+1)) - for ie in range(1,Ne+Nl+1): - E[0,ie] = ie*np.pi - for il in range(1,Nl): - jl = functools.partial(spherical_jn,il) - for ie in range(1,Ne+Nl+1-il): - E[il,ie] = fsolve( jl, (E[il-1,ie]+E[il-1,ie+1])/2 ) - return E[:,1:Ne+1] - -def set_E(info,Rcut): - """ E[it][il,ie] """ - eigenvalue = { it:find_eigenvalue(info.Nl[it],info.Ne[it]) for it in info.Nt_all } - E = dict() - for it in Rcut: - E[it] = torch.from_numpy(( eigenvalue[it]/Rcut[it] ).astype("float32")) - return E \ No newline at end of file + +def generate_orbital(info, C, E, Rcut, dr): + """C[it][il][ie,iu]""" + """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ + orb = dict() + for it in info.Nt_all: + Nr = int(Rcut[it] / dr[it]) + 1 + orb[it] = ND_list(info.Nl[it]) + for il in range(info.Nl[it]): + orb[it][il] = ND_list(info.Nu[it][il]) + for iu in range(info.Nu[it][il]): + orb[it][il][iu] = np.zeros(Nr) + for ir in range(Nr): + r = ir * dr[it] + for ie in range(info.Ne[it]): + orb[it][il][iu][ir] += C[it][il][ie, iu].item() * spherical_jn( + il, E[it][il, ie].item() * r + ) + return orb + + +def smooth_orbital(orb, Rcut, dr, smearing_sigma): + for it, orb_t in orb.items(): + for orb_tl in orb_t: + for orb_tlu in orb_tl: + for ir in range(orb_tlu.shape[0]): + assert orb_tlu.shape[0] == int(Rcut[it] / dr[it]) + 1 + r = ir * dr[it] + orb_tlu[ir] *= 1 - np.exp( + -((r - Rcut[it]) ** 2) / (2 * smearing_sigma**2) + ) + + +def inner_product(orb1, orb2, dr): + assert orb1.shape == orb2.shape + r = np.array(range(orb1.shape[0])) * dr + return simps(orb1 * orb2 * r * r, dx=dr) + + +def normalize(orb, dr, C=None, flag_norm_orb=False, flag_norm_C=False): + """C[it][il][ie,iu]""" + """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ + for it, orb_t in orb.items(): + for il, orb_tl in enumerate(orb_t): + for iu, orb_tlu in enumerate(orb_tl): + norm = np.sqrt(inner_product(orb_tlu, orb_tlu, dr[it])) + if flag_norm_orb: + orb_tlu[:] = orb_tlu / norm + if flag_norm_C: + C[it][il].data[:, iu] = C[it][il].data[:, iu] / norm + + +def orth(orb, dr): + """|n'> = 1/Z ( |n> - \sum_{i=0}^{n-1} |i> )""" + """ orb[it][il][iu,r] """ + for it, orb_t in orb.items(): + for il, orb_tl in enumerate(orb_t): + for iu1, orb_tlu1 in enumerate(orb_tl): + for iu2 in range(iu1): + orb_tlu1[:] -= orb_tl[iu2] * inner_product( + orb_tlu1, orb_tl[iu2], dr[it] + ) + orb_tlu1[:] = orb_tlu1 / np.sqrt( + inner_product(orb_tlu1, orb_tlu1, dr[it]) + ) + + +def find_eigenvalue(Nl, Ne): + """E[il,ie]""" + E = np.zeros((Nl, Ne + Nl + 1)) + for ie in range(1, Ne + Nl + 1): + E[0, ie] = ie * np.pi + for il in range(1, Nl): + jl = functools.partial(spherical_jn, il) + for ie in range(1, Ne + Nl + 1 - il): + E[il, ie] = fsolve(jl, (E[il - 1, ie] + E[il - 1, ie + 1]) / 2) + return E[:, 1 : Ne + 1] + + +def set_E(info, Rcut): + """E[it][il,ie]""" + eigenvalue = {it: find_eigenvalue(info.Nl[it], info.Ne[it]) for it in info.Nt_all} + E = dict() + for it in Rcut: + E[it] = torch.from_numpy((eigenvalue[it] / Rcut[it]).astype("float32")) + return E diff --git a/tools/opt_orb_pytorch/pf.py b/tools/opt_orb_pytorch/pf.py index e518fa02f73..cc3f08f0642 100644 --- a/tools/opt_orb_pytorch/pf.py +++ b/tools/opt_orb_pytorch/pf.py @@ -1,2 +1,3 @@ import profile -profile.run("import main","profile.dat") \ No newline at end of file + +profile.run("import main", "profile.dat") diff --git a/tools/opt_orb_pytorch/torch_complex.py b/tools/opt_orb_pytorch/torch_complex.py index d5f338d5d74..62171145f6f 100644 --- a/tools/opt_orb_pytorch/torch_complex.py +++ b/tools/opt_orb_pytorch/torch_complex.py @@ -1,83 +1,133 @@ -import torch - -class ComplexTensor: - def __init__(self,real,imag): - self.real = real - self.imag = imag - - def view(self,*args,**kwargs): - return ComplexTensor( self.real.view(*args,**kwargs), self.imag.view(*args,**kwargs) ) - def t(self,*args,**kwargs): - return ComplexTensor( self.real.t(*args,**kwargs), self.imag.t(*args,**kwargs) ) -# def transpose(self,*args,**kwargs): -# return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) - def __getitem__(self,*args,**kwargs): - return ComplexTensor( self.real.__getitem__(*args,**kwargs), self.imag.__getitem__(*args,**kwargs) ) - def __str__(self): - return "<{0};{1}>".format(self.real, self.imag) - __repr__=__str__ -# def size(self,*args,**kwargs): -# return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) - - def conj(self): - return ComplexTensor( self.real, -self.imag ) - - - -def dot( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1.real,x2.real, *args,**kwargs ) - torch.dot( x1.imag,x2.imag, *args,**kwargs ), torch.dot( x1.real,x2.imag, *args,**kwargs ) + torch.dot( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.dot( x1.real,x2, *args,**kwargs ), torch.dot( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1,x2.real, *args,**kwargs ), torch.dot( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.dot( x1,x2, *args,**kwargs ) -def mv( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1.real,x2.real, *args,**kwargs ) - torch.mv( x1.imag,x2.imag, *args,**kwargs ), torch.mv( x1.real,x2.imag, *args,**kwargs ) + torch.mv( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mv( x1.real,x2, *args,**kwargs ), torch.mv( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1,x2.real, *args,**kwargs ), torch.mv( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mv( x1,x2, *args,**kwargs ) -def mm( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1.real,x2.real, *args,**kwargs ) - torch.mm( x1.imag,x2.imag, *args,**kwargs ), torch.mm( x1.real,x2.imag, *args,**kwargs ) + torch.mm( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mm( x1.real,x2, *args,**kwargs ), torch.mm( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1,x2.real, *args,**kwargs ), torch.mm( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mm( x1,x2, *args,**kwargs ) - - -def cat( xs, *args,**kwargs ): - if isinstance(xs[0],ComplexTensor): - xs_real = []; xs_imag = [] - for x in xs: - xs_real.append(x.real) - xs_imag.append(x.imag) - return ComplexTensor( torch.cat(xs_real,*args,**kwargs), torch.cat(xs_imag,*args,**kwargs) ) - else: - return torch.cat(xs,*args,**kwargs) - - - -import inverse as inverse_real -def inverse(M): - if isinstance(M,ComplexTensor): - A=M.real - B=M.imag - tmp_AB = torch.mm(A.inverse(),B) # A^{-1} B - tmp_X = (A+torch.mm(B,tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} - return ComplexTensor( tmp_X, -torch.mm(tmp_AB,tmp_X) ) - else: - return M.inverse() \ No newline at end of file +import torch + + +class ComplexTensor: + def __init__(self, real, imag): + self.real = real + self.imag = imag + + def view(self, *args, **kwargs): + return ComplexTensor( + self.real.view(*args, **kwargs), self.imag.view(*args, **kwargs) + ) + + def t(self, *args, **kwargs): + return ComplexTensor(self.real.t(*args, **kwargs), self.imag.t(*args, **kwargs)) + + # def transpose(self,*args,**kwargs): + # return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) + def __getitem__(self, *args, **kwargs): + return ComplexTensor( + self.real.__getitem__(*args, **kwargs), + self.imag.__getitem__(*args, **kwargs), + ) + + def __str__(self): + return "<{0};{1}>".format(self.real, self.imag) + + __repr__ = __str__ + # def size(self,*args,**kwargs): + # return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) + + def conj(self): + return ComplexTensor(self.real, -self.imag) + + +def dot(x1, x2, *args, **kwargs): + if isinstance(x1, ComplexTensor): + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.dot(x1.real, x2.real, *args, **kwargs) + - torch.dot(x1.imag, x2.imag, *args, **kwargs), + torch.dot(x1.real, x2.imag, *args, **kwargs) + + torch.dot(x1.imag, x2.real, *args, **kwargs), + ) + else: + return ComplexTensor( + torch.dot(x1.real, x2, *args, **kwargs), + torch.dot(x1.imag, x2, *args, **kwargs), + ) + else: + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.dot(x1, x2.real, *args, **kwargs), + torch.dot(x1, x2.imag, *args, **kwargs), + ) + else: + return torch.dot(x1, x2, *args, **kwargs) + + +def mv(x1, x2, *args, **kwargs): + if isinstance(x1, ComplexTensor): + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mv(x1.real, x2.real, *args, **kwargs) + - torch.mv(x1.imag, x2.imag, *args, **kwargs), + torch.mv(x1.real, x2.imag, *args, **kwargs) + + torch.mv(x1.imag, x2.real, *args, **kwargs), + ) + else: + return ComplexTensor( + torch.mv(x1.real, x2, *args, **kwargs), + torch.mv(x1.imag, x2, *args, **kwargs), + ) + else: + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mv(x1, x2.real, *args, **kwargs), + torch.mv(x1, x2.imag, *args, **kwargs), + ) + else: + return torch.mv(x1, x2, *args, **kwargs) + + +def mm(x1, x2, *args, **kwargs): + if isinstance(x1, ComplexTensor): + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mm(x1.real, x2.real, *args, **kwargs) + - torch.mm(x1.imag, x2.imag, *args, **kwargs), + torch.mm(x1.real, x2.imag, *args, **kwargs) + + torch.mm(x1.imag, x2.real, *args, **kwargs), + ) + else: + return ComplexTensor( + torch.mm(x1.real, x2, *args, **kwargs), + torch.mm(x1.imag, x2, *args, **kwargs), + ) + else: + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mm(x1, x2.real, *args, **kwargs), + torch.mm(x1, x2.imag, *args, **kwargs), + ) + else: + return torch.mm(x1, x2, *args, **kwargs) + + +def cat(xs, *args, **kwargs): + if isinstance(xs[0], ComplexTensor): + xs_real = [] + xs_imag = [] + for x in xs: + xs_real.append(x.real) + xs_imag.append(x.imag) + return ComplexTensor( + torch.cat(xs_real, *args, **kwargs), torch.cat(xs_imag, *args, **kwargs) + ) + else: + return torch.cat(xs, *args, **kwargs) + + +import inverse as inverse_real + + +def inverse(M): + if isinstance(M, ComplexTensor): + A = M.real + B = M.imag + tmp_AB = torch.mm(A.inverse(), B) # A^{-1} B + tmp_X = (A + torch.mm(B, tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} + return ComplexTensor(tmp_X, -torch.mm(tmp_AB, tmp_X)) + else: + return M.inverse() diff --git a/tools/opt_orb_pytorch/unittest_inverse.py b/tools/opt_orb_pytorch/unittest_inverse.py index f4d43156108..07aaecc888d 100644 --- a/tools/opt_orb_pytorch/unittest_inverse.py +++ b/tools/opt_orb_pytorch/unittest_inverse.py @@ -1,29 +1,30 @@ -import unittest -import inverse -import torch - -class unittest_inverse(unittest.TestCase): - - def inverse_test(self,a,ai_true): - - a=torch.Tensor(a) - a=torch.autograd.Variable(a) - - ai_test=inverse.inverse(a) - - ai_true = torch.Tensor(ai_true) - ai_true=torch.autograd.Variable(ai_true) - - self.assertFalse((ai_test!=ai_true).data.sum()) - - def test_inverse_1(self): - self.inverse_test( - [[1,2],[2,3]], - [[-3,2],[2,-1]] ) - def test_inverse_2(self): - self.inverse_test( - [[1,2,3],[2,4,5],[3,5,6]], - [[1,-3,2],[-3,3,-1],[2,-1,0]] ) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file +import unittest +import inverse +import torch + + +class unittest_inverse(unittest.TestCase): + + def inverse_test(self, a, ai_true): + + a = torch.Tensor(a) + a = torch.autograd.Variable(a) + + ai_test = inverse.inverse(a) + + ai_true = torch.Tensor(ai_true) + ai_true = torch.autograd.Variable(ai_true) + + self.assertFalse((ai_test != ai_true).data.sum()) + + def test_inverse_1(self): + self.inverse_test([[1, 2], [2, 3]], [[-3, 2], [2, -1]]) + + def test_inverse_2(self): + self.inverse_test( + [[1, 2, 3], [2, 4, 5], [3, 5, 6]], [[1, -3, 2], [-3, 3, -1], [2, -1, 0]] + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/opt_orb_pytorch/util.py b/tools/opt_orb_pytorch/util.py index ac05ae2034d..7a6e05f8927 100644 --- a/tools/opt_orb_pytorch/util.py +++ b/tools/opt_orb_pytorch/util.py @@ -1,36 +1,44 @@ -def ND_list(*sizes,element=None): - size_1,*size_other = sizes - l = [element] * size_1 - if size_other: - for i in range(len(l)): - l[i] = ND_list(*size_other,element=element) - else: - if element in ["dict()","list()"]: - for i in range(size_1): - l[i] = eval(element) - return l - - -def ignore_line(file,N): - for _ in range(N): - file.readline() - - +def ND_list(*sizes, element=None): + size_1, *size_other = sizes + l = [element] * size_1 + if size_other: + for i in range(len(l)): + l[i] = ND_list(*size_other, element=element) + else: + if element in ["dict()", "list()"]: + for i in range(size_1): + l[i] = eval(element) + return l + + +def ignore_line(file, N): + for _ in range(N): + file.readline() + + class Info: - def Nm(self,il): return 2*il+1 - def __str__(self): - return "\n".join([name+"\t"+str(value) for name,value in self.__dict__.items()]) - __repr__=__str__ - + def Nm(self, il): + return 2 * il + 1 + + def __str__(self): + return "\n".join( + [name + "\t" + str(value) for name, value in self.__dict__.items()] + ) + + __repr__ = __str__ + + def change_to_cuda(s): - if isinstance(s,list): - return [change_to_cuda(x) for x in s] - elif isinstance(s,dict): - return {i:change_to_cuda(x) for i,x in s.items()} - elif isinstance(s,torch.Tensor): - return s.cuda() - elif isinstance(s,torch_complex.ComplexTensor): - return torch_complex.ComplexTensor( change_to_cuda(s.real), change_to_cuda(s.imag) ) - else: - print(s) - raise TypeError("change_to_cuda") \ No newline at end of file + if isinstance(s, list): + return [change_to_cuda(x) for x in s] + elif isinstance(s, dict): + return {i: change_to_cuda(x) for i, x in s.items()} + elif isinstance(s, torch.Tensor): + return s.cuda() + elif isinstance(s, torch_complex.ComplexTensor): + return torch_complex.ComplexTensor( + change_to_cuda(s.real), change_to_cuda(s.imag) + ) + else: + print(s) + raise TypeError("change_to_cuda") diff --git a/tools/opt_orb_pytorch_dpsi/IO/cal_weight.py b/tools/opt_orb_pytorch_dpsi/IO/cal_weight.py index 7580d6717d8..d1a6604145a 100644 --- a/tools/opt_orb_pytorch_dpsi/IO/cal_weight.py +++ b/tools/opt_orb_pytorch_dpsi/IO/cal_weight.py @@ -1,70 +1,80 @@ -import IO.read_istate -import torch -import re -import functools -import operator - -def cal_weight(info_weight, flag_same_band, stru_file_list=None): - """ weight[ist][ib] """ - - if "bands_file" in info_weight.keys(): - if "bands_range" in info_weight.keys(): - raise IOError('"bands_file" and "bands_range" only once') - - weight = [] # weight[ist][ib] - for weight_stru, file_name in zip(info_weight["stru"], info_weight["bands_file"]): - occ = IO.read_istate.read_istate(file_name) - weight += [occ_k * weight_stru for occ_k in occ] - - elif "bands_range" in info_weight.keys(): - k_weight = read_k_weight(stru_file_list) # k_weight[ist][ik] - nbands = read_nbands(stru_file_list) # nbands[ist] - - st_weight = [] # st_weight[ist][ib] - for weight_stru, bands_range, nbands_ist in zip(info_weight["stru"], info_weight["bands_range"], nbands): - st_weight_tmp = torch.zeros((nbands_ist,)) - st_weight_tmp[:bands_range] = weight_stru - st_weight.append( st_weight_tmp ) - - weight = [] # weight[ist][ib] - for ist,_ in enumerate(k_weight): - for ik,_ in enumerate(k_weight[ist]): - weight.append(st_weight[ist] * k_weight[ist][ik]) - - else: - raise IOError('"bands_file" and "bands_range" must once') - - - if not flag_same_band: - for ist,_ in enumerate(weight): - weight[ist] = torch.tensordot(weight[ist], weight[ist], dims=0) - - - normalization = functools.reduce(operator.add, map(torch.sum, weight), 0) - weight = list(map(lambda x:x/normalization, weight)) - - return weight - - -def read_k_weight(stru_file_list): - """ weight[ist][ik] """ - weight = [] # weight[ist][ik] - for file_name in stru_file_list: - weight_k = [] # weight_k[ik] - with open(file_name,"r") as file: - data = re.compile(r"(.+)", re.S).search(file.read()).group(1).split("\n") - for line in data: - line = line.strip() - if line: - weight_k.append(float(line.split()[-1])) - weight.append(weight_k) - return weight - - -def read_nbands(stru_file_list): - """ nbands[ib] """ - nbands = [] - for file_name in stru_file_list: - with open(file_name,"r") as file: - nbands.append(int(re.compile(r"(\d+)\s+nbands").search(file.read()).group(1))) - return nbands +import IO.read_istate +import torch +import re +import functools +import operator + + +def cal_weight(info_weight, flag_same_band, stru_file_list=None): + """weight[ist][ib]""" + + if "bands_file" in info_weight.keys(): + if "bands_range" in info_weight.keys(): + raise IOError('"bands_file" and "bands_range" only once') + + weight = [] # weight[ist][ib] + for weight_stru, file_name in zip( + info_weight["stru"], info_weight["bands_file"] + ): + occ = IO.read_istate.read_istate(file_name) + weight += [occ_k * weight_stru for occ_k in occ] + + elif "bands_range" in info_weight.keys(): + k_weight = read_k_weight(stru_file_list) # k_weight[ist][ik] + nbands = read_nbands(stru_file_list) # nbands[ist] + + st_weight = [] # st_weight[ist][ib] + for weight_stru, bands_range, nbands_ist in zip( + info_weight["stru"], info_weight["bands_range"], nbands + ): + st_weight_tmp = torch.zeros((nbands_ist,)) + st_weight_tmp[:bands_range] = weight_stru + st_weight.append(st_weight_tmp) + + weight = [] # weight[ist][ib] + for ist, _ in enumerate(k_weight): + for ik, _ in enumerate(k_weight[ist]): + weight.append(st_weight[ist] * k_weight[ist][ik]) + + else: + raise IOError('"bands_file" and "bands_range" must once') + + if not flag_same_band: + for ist, _ in enumerate(weight): + weight[ist] = torch.tensordot(weight[ist], weight[ist], dims=0) + + normalization = functools.reduce(operator.add, map(torch.sum, weight), 0) + weight = list(map(lambda x: x / normalization, weight)) + + return weight + + +def read_k_weight(stru_file_list): + """weight[ist][ik]""" + weight = [] # weight[ist][ik] + for file_name in stru_file_list: + weight_k = [] # weight_k[ik] + with open(file_name, "r") as file: + data = ( + re.compile(r"(.+)", re.S) + .search(file.read()) + .group(1) + .split("\n") + ) + for line in data: + line = line.strip() + if line: + weight_k.append(float(line.split()[-1])) + weight.append(weight_k) + return weight + + +def read_nbands(stru_file_list): + """nbands[ib]""" + nbands = [] + for file_name in stru_file_list: + with open(file_name, "r") as file: + nbands.append( + int(re.compile(r"(\d+)\s+nbands").search(file.read()).group(1)) + ) + return nbands diff --git a/tools/opt_orb_pytorch_dpsi/IO/change_info.py b/tools/opt_orb_pytorch_dpsi/IO/change_info.py index e9012042dde..c2d6cc21f55 100644 --- a/tools/opt_orb_pytorch_dpsi/IO/change_info.py +++ b/tools/opt_orb_pytorch_dpsi/IO/change_info.py @@ -1,98 +1,101 @@ -import addict -import util -import itertools - -def change_info(info_old, weight_old): - info_stru = [None] * info_old.Nst - for ist in range(len(info_stru)): - info_stru[ist] = addict.Dict() - for ist,Na in enumerate(info_old.Na): - info_stru[ist].Na = Na - for ist,weight in enumerate(weight_old): - info_stru[ist].weight = weight - info_stru[ist].Nb = weight.shape[0] - for ib in range(weight.shape[0], 0, -1): - if weight[ib-1]>0: - info_stru[ist].Nb_true = ib - break - - info_element = addict.Dict() - for it_index,it in enumerate(info_old.Nt_all): - info_element[it].index = it_index - for it,Nu in info_old.Nu.items(): - info_element[it].Nu = Nu - info_element[it].Nl = len(Nu) - for it,Rcut in info_old.Rcut.items(): - info_element[it].Rcut = Rcut - for it,dr in info_old.dr.items(): - info_element[it].dr = dr - for it,Ecut in info_old.Ecut.items(): - info_element[it].Ecut = Ecut - for it,Ne in info_old.Ne.items(): - info_element[it].Ne = Ne - - info_opt = addict.Dict() - info_opt.lr = info_old.lr - info_opt.cal_T = info_old.cal_T - info_opt.cal_smooth = info_old.cal_smooth - - return info_stru, info_element, info_opt - - """ - info_stru = - [{'Na': {'C': 1}, - 'Nb': 6, - 'Nb_true': 4, - 'weight': tensor([0.0333, 0.0111, 0.0111, 0.0111, 0.0000, 0.0000])}, - {'Na': {'C': 1}, - 'Nb': 6, - 'Nb_true': 2, - 'weight': tensor([0.0667, 0.0667, 0.0000, 0.0000, 0.0000, 0.0000])}, - {'Na': {'C': 1, 'O': 2}, - 'Nb': 10, - 'Nb_true': 8, - 'weight': tensor([0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.0000, 0.0000])}] - - info_element = - {'C': { - 'Ecut': 200, - 'Ne': 19, - 'Nl': 3, - 'Nu': [2, 2, 1], - 'Rcut': 6, - 'dr': 0.01, - 'index': 0}, - 'O': { - 'Ecut': 200, - 'Ne': 19, - 'Nl': 3, - 'Nu': [3, 2, 1], - 'Rcut': 6, - 'dr': 0.01, - 'index': 1}} - - info_opt = - {'cal_T': False, - 'cal_smooth': False, - 'lr': 0.01} - """ - - -def get_info_max(info_stru, info_element): - info_max = [None] * len(info_stru) - for ist in range(len(info_stru)): - Nt = info_stru[ist].Na.keys() - info_max[ist] = addict.Dict() - info_max[ist].Nt = len(Nt) - info_max[ist].Na = max((info_stru[ist].Na[it] for it in Nt)) - info_max[ist].Nl = max([info_element[it].Nl for it in Nt]) - info_max[ist].Nm = max((util.Nm(info_element[it].Nl-1) for it in Nt)) - info_max[ist].Nu = max(itertools.chain.from_iterable([info_element[it].Nu for it in Nt])) - info_max[ist].Ne = max((info_element[it].Ne for it in Nt)) - info_max[ist].Nb = info_stru[ist].Nb - return info_max - - """ - [{'Na': 2, 'Nb': 6, 'Ne': 19, 'Nl': 3, 'Nm': 5, 'Nt': 1, 'Nu': 2}, - {'Na': 2, 'Nb': 6, 'Ne': 19, 'Nl': 3, 'Nm': 5, 'Nt': 1, 'Nu': 2}] - """ +import addict +import util +import itertools + + +def change_info(info_old, weight_old): + info_stru = [None] * info_old.Nst + for ist in range(len(info_stru)): + info_stru[ist] = addict.Dict() + for ist, Na in enumerate(info_old.Na): + info_stru[ist].Na = Na + for ist, weight in enumerate(weight_old): + info_stru[ist].weight = weight + info_stru[ist].Nb = weight.shape[0] + for ib in range(weight.shape[0], 0, -1): + if weight[ib - 1] > 0: + info_stru[ist].Nb_true = ib + break + + info_element = addict.Dict() + for it_index, it in enumerate(info_old.Nt_all): + info_element[it].index = it_index + for it, Nu in info_old.Nu.items(): + info_element[it].Nu = Nu + info_element[it].Nl = len(Nu) + for it, Rcut in info_old.Rcut.items(): + info_element[it].Rcut = Rcut + for it, dr in info_old.dr.items(): + info_element[it].dr = dr + for it, Ecut in info_old.Ecut.items(): + info_element[it].Ecut = Ecut + for it, Ne in info_old.Ne.items(): + info_element[it].Ne = Ne + + info_opt = addict.Dict() + info_opt.lr = info_old.lr + info_opt.cal_T = info_old.cal_T + info_opt.cal_smooth = info_old.cal_smooth + + return info_stru, info_element, info_opt + + """ + info_stru = + [{'Na': {'C': 1}, + 'Nb': 6, + 'Nb_true': 4, + 'weight': tensor([0.0333, 0.0111, 0.0111, 0.0111, 0.0000, 0.0000])}, + {'Na': {'C': 1}, + 'Nb': 6, + 'Nb_true': 2, + 'weight': tensor([0.0667, 0.0667, 0.0000, 0.0000, 0.0000, 0.0000])}, + {'Na': {'C': 1, 'O': 2}, + 'Nb': 10, + 'Nb_true': 8, + 'weight': tensor([0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.0000, 0.0000])}] + + info_element = + {'C': { + 'Ecut': 200, + 'Ne': 19, + 'Nl': 3, + 'Nu': [2, 2, 1], + 'Rcut': 6, + 'dr': 0.01, + 'index': 0}, + 'O': { + 'Ecut': 200, + 'Ne': 19, + 'Nl': 3, + 'Nu': [3, 2, 1], + 'Rcut': 6, + 'dr': 0.01, + 'index': 1}} + + info_opt = + {'cal_T': False, + 'cal_smooth': False, + 'lr': 0.01} + """ + + +def get_info_max(info_stru, info_element): + info_max = [None] * len(info_stru) + for ist in range(len(info_stru)): + Nt = info_stru[ist].Na.keys() + info_max[ist] = addict.Dict() + info_max[ist].Nt = len(Nt) + info_max[ist].Na = max((info_stru[ist].Na[it] for it in Nt)) + info_max[ist].Nl = max([info_element[it].Nl for it in Nt]) + info_max[ist].Nm = max((util.Nm(info_element[it].Nl - 1) for it in Nt)) + info_max[ist].Nu = max( + itertools.chain.from_iterable([info_element[it].Nu for it in Nt]) + ) + info_max[ist].Ne = max((info_element[it].Ne for it in Nt)) + info_max[ist].Nb = info_stru[ist].Nb + return info_max + + """ + [{'Na': 2, 'Nb': 6, 'Ne': 19, 'Nl': 3, 'Nm': 5, 'Nt': 1, 'Nu': 2}, + {'Na': 2, 'Nb': 6, 'Ne': 19, 'Nl': 3, 'Nm': 5, 'Nt': 1, 'Nu': 2}] + """ diff --git a/tools/opt_orb_pytorch_dpsi/IO/func_C.py b/tools/opt_orb_pytorch_dpsi/IO/func_C.py index 95a7603556c..830fbace466 100644 --- a/tools/opt_orb_pytorch_dpsi/IO/func_C.py +++ b/tools/opt_orb_pytorch_dpsi/IO/func_C.py @@ -2,98 +2,103 @@ import torch import numpy as np + def random_C_init(info_element): - """ C[it][il][ie,iu] """ - C = dict() - for it in info_element.keys(): - C[it] = ND_list(info_element[it].Nl) - for il in range(info_element[it].Nl): - C[it][il] = torch.tensor(np.random.uniform(-1,1, (info_element[it].Ne, info_element[it].Nu[il])), dtype=torch.float64, requires_grad=True) - return C - - - -def read_C_init(file_name,info_element): - """ C[it][il][ie,iu] """ - C = random_C_init(info_element) + """C[it][il][ie,iu] """ + C = dict() + for it in info_element.keys(): + C[it] = ND_list(info_element[it].Nl) + for il in range(info_element[it].Nl): + C[it][il] = torch.tensor( + np.random.uniform( + -1, 1, (info_element[it].Ne, info_element[it].Nu[il]) + ), + dtype=torch.float64, + requires_grad=True, + ) + return C + + +def read_C_init(file_name, info_element): + """C[it][il][ie,iu] """ + C = random_C_init(info_element) + + with open(file_name, "r") as file: + + for line in file: + if line.strip() == "": + line = None + break + ignore_line(file, 1) + + C_read_index = set() + while True: + line = file.readline().strip() + if line.startswith("Type"): + it, il, iu = file.readline().split() + il = int(il) + iu = int(iu) - 1 + C_read_index.add((it, il, iu)) + line = file.readline().split() + for ie in range(info_element[it].Ne): + if not line: + line = file.readline().split() + C[it][il].data[ie, iu] = float(line.pop(0)) + elif line.startswith(""): + break + else: + raise IOError("unknown line in read_C_init " + file_name + "\n" + line) + return C, C_read_index + + +def copy_C(C, info_element): + C_copy = dict() + for it in info_element.keys(): + C_copy[it] = ND_list(info_element[it].Nl) + for il in range(info_element[it].Nl): + C_copy[it][il] = C[it][il].clone() + return C_copy + - with open(file_name,"r") as file: - - for line in file: - if line.strip() == "": - line=None - break - ignore_line(file,1) - - C_read_index = set() - while True: - line = file.readline().strip() - if line.startswith("Type"): - it,il,iu = file.readline().split(); - il = int(il) - iu = int(iu)-1 - C_read_index.add((it,il,iu)) - line = file.readline().split() - for ie in range(info_element[it].Ne): - if not line: line = file.readline().split() - C[it][il].data[ie,iu] = float(line.pop(0)) - elif line.startswith(""): - break; - else: - raise IOError("unknown line in read_C_init "+file_name+"\n"+line) - return C, C_read_index +def write_C(file_name, C, Spillage): + with open(file_name, "w") as file: + print("", file=file) + # print("\tTotal number of radial orbitals.", file=file) + nTotal = 0 + for it, C_t in C.items(): + for il, C_tl in enumerate(C_t): + for iu in range(C_tl.size()[1]): + nTotal += 1 + # nTotal = sum(info["Nu"][it]) + print("\t %s Total number of radial orbitals." % nTotal, file=file) + # print("\tTotal number of radial orbitals.", file=file) + for it, C_t in C.items(): + for il, C_tl in enumerate(C_t): + for iu in range(C_tl.size()[1]): + print("\tType\tL\tZeta-Orbital", file=file) + print(f"\t {it} \t{il}\t {iu+1}", file=file) + for ie in range(C_tl.size()[0]): + print("\t", "%18.14f" % C_tl[ie, iu].item(), file=file) + print("", file=file) + print("", file=file) + print("Left spillage = %.10e" % Spillage.item(), file=file) + print("", file=file) - - -def copy_C(C,info_element): - C_copy = dict() - for it in info_element.keys(): - C_copy[it] = ND_list(info_element[it].Nl) - for il in range(info_element[it].Nl): - C_copy[it][il] = C[it][il].clone() - return C_copy - - - -def write_C(file_name,C,Spillage): - with open(file_name,"w") as file: - print("", file=file) - #print("\tTotal number of radial orbitals.", file=file) - nTotal = 0 - for it,C_t in C.items(): - for il,C_tl in enumerate(C_t): - for iu in range(C_tl.size()[1]): - nTotal += 1 - #nTotal = sum(info["Nu"][it]) - print("\t %s Total number of radial orbitals."%nTotal , file=file) - #print("\tTotal number of radial orbitals.", file=file) - for it,C_t in C.items(): - for il,C_tl in enumerate(C_t): - for iu in range(C_tl.size()[1]): - print("\tType\tL\tZeta-Orbital", file=file) - print(f"\t {it} \t{il}\t {iu+1}", file=file) - for ie in range(C_tl.size()[0]): - print("\t", '%18.14f'%C_tl[ie,iu].item(), file=file) - print("", file=file) - print("", file=file) - print("Left spillage = %.10e"%Spillage.item(), file=file) - print("", file=file) - -#def init_C(info): -# """ C[it][il][ie,iu] """ -# C = ND_list(max(info.Nt)) -# for it in range(len(C)): -# C[it] = ND_list(info.Nl[it]) -# for il in range(info.Nl[it]): -# C[it][il] = torch.autograd.Variable( torch.Tensor( info.Ne, info.Nu[it][il] ), requires_grad = True ) -# -# with open("C_init.dat","r") as file: -# line = [] -# for it in range(len(C)): -# for il in range(info.Nl[it]): -# for i_n in range(info.Nu[it][il]): -# for ie in range(info.Ne[it]): -# if not line: line=file.readline().split() -# C[it][il].data[ie,i_n] = float(line.pop(0)) -# return C +# def init_C(info): +# """ C[it][il][ie,iu] """ +# C = ND_list(max(info.Nt)) +# for it in range(len(C)): +# C[it] = ND_list(info.Nl[it]) +# for il in range(info.Nl[it]): +# C[it][il] = torch.autograd.Variable( torch.Tensor( info.Ne, info.Nu[it][il] ), requires_grad = True ) +# +# with open("C_init.dat","r") as file: +# line = [] +# for it in range(len(C)): +# for il in range(info.Nl[it]): +# for i_n in range(info.Nu[it][il]): +# for ie in range(info.Ne[it]): +# if not line: line=file.readline().split() +# C[it][il].data[ie,i_n] = float(line.pop(0)) +# return C diff --git a/tools/opt_orb_pytorch_dpsi/IO/print_QSV.py b/tools/opt_orb_pytorch_dpsi/IO/print_QSV.py index 1b0f88c59ef..ca8527ed293 100644 --- a/tools/opt_orb_pytorch_dpsi/IO/print_QSV.py +++ b/tools/opt_orb_pytorch_dpsi/IO/print_QSV.py @@ -1,29 +1,30 @@ -def print_V(V,file_name): - """ V[ist][ib] """ - with open(file_name,"w") as file: - for V_s in V: - for V_sb in V_s: - print(1-V_sb.item(),end="\t",file=file) - print(file=file) - -def print_S(S,file_name): - """ S[ist][it1,it2][il1][il2][ia1*im1*in1,ia2*im2*in2] """ - with open(file_name,"w") as file: - for ist,S_s in enumerate(S): - for (it1,it2),S_tt in S_s.items(): - for il1,S_ttl in enumerate(S_tt): - for il2,S_ttll in enumerate(S_ttl): - print(ist,it1,it2,il1,il2,file=file) - print(S_ttll.real.numpy(),file=file) - print(S_ttll.imag.numpy(),"\n",file=file) - -def print_Q(Q,file_name): - """ Q[ist][it][il][ib,ia*im*iu] """ - with open(file_name,"w") as file: - for ist,Q_s in enumerate(Q): - for it,Q_st in Q_s.items(): - for il,Q_stl in enumerate(Q_st): - print(ist,it,il,file=file) - print(Q_stl.real.numpy(),file=file) - print(Q_stl.imag.numpy(),"\n",file=file) - \ No newline at end of file +def print_V(V, file_name): + """V[ist][ib]""" + with open(file_name, "w") as file: + for V_s in V: + for V_sb in V_s: + print(1 - V_sb.item(), end="\t", file=file) + print(file=file) + + +def print_S(S, file_name): + """S[ist][it1,it2][il1][il2][ia1*im1*in1,ia2*im2*in2]""" + with open(file_name, "w") as file: + for ist, S_s in enumerate(S): + for (it1, it2), S_tt in S_s.items(): + for il1, S_ttl in enumerate(S_tt): + for il2, S_ttll in enumerate(S_ttl): + print(ist, it1, it2, il1, il2, file=file) + print(S_ttll.real.numpy(), file=file) + print(S_ttll.imag.numpy(), "\n", file=file) + + +def print_Q(Q, file_name): + """Q[ist][it][il][ib,ia*im*iu]""" + with open(file_name, "w") as file: + for ist, Q_s in enumerate(Q): + for it, Q_st in Q_s.items(): + for il, Q_stl in enumerate(Q_st): + print(ist, it, il, file=file) + print(Q_stl.real.numpy(), file=file) + print(Q_stl.imag.numpy(), "\n", file=file) diff --git a/tools/opt_orb_pytorch_dpsi/IO/print_orbital.py b/tools/opt_orb_pytorch_dpsi/IO/print_orbital.py index f3d0aadee39..0867a1588c4 100644 --- a/tools/opt_orb_pytorch_dpsi/IO/print_orbital.py +++ b/tools/opt_orb_pytorch_dpsi/IO/print_orbital.py @@ -1,70 +1,145 @@ -periodtable = { 'H': 1, 'He': 2, 'Li': 3, 'Be': 4, 'B': 5, 'C': 6, 'N': 7, - 'O': 8, 'F': 9, 'Ne': 10, 'Na': 11, 'Mg': 12, 'Al': 13, - 'Si': 14, 'P': 15, 'S': 16, 'Cl': 17, 'Ar': 18, 'K': 19, - 'Ca': 20, 'Sc': 21, 'Ti': 22, 'V': 23, 'Cr': 24, 'Mn': 25, - 'Fe': 26, 'Co': 27, 'Ni': 28, 'Cu': 29, 'Zn': 30, 'Ga': 31, - 'Ge': 32, 'As': 33, 'Se': 34, 'Br': 35, 'Kr': 36, 'Rb': 37, - 'Sr': 38, 'Y': 39, 'Zr': 40, 'Nb': 41, 'Mo': 42, 'Tc': 43, - 'Ru': 44, 'Rh': 45, 'Pd': 46, 'Ag': 47, 'Cd': 48, 'In': 49, - 'Sn': 50, 'Sb': 51, 'Te': 52, 'I': 53, 'Xe': 54, 'Cs': 55, - 'Ba': 56, #'La': 57, 'Ce': 58, 'Pr': 59, 'Nd': 60, 'Pm': 61, - ## 'Sm': 62, 'Eu': 63, 'Gd': 64, 'Tb': 65, 'Dy': 66, 'Ho': 67, - ## 'Er': 68, 'Tm': 69, 'Yb': 70, - ## 'Lu': 71, - 'Hf': 72, 'Ta': 73, - 'W': 74, 'Re': 75, 'Os': 76, 'Ir': 77, 'Pt': 78, 'Au': 79, - 'Hg': 80, 'Tl': 81, 'Pb': 82, 'Bi': 83, - ## 'Po': 84, #'At': 85, - ## 'Rn': 86, #'Fr': 87, 'Ra': 88, 'Ac': 89, 'Th': 90, 'Pa': 91, - ## 'U': 92, 'Np': 93, 'Pu': 94, 'Am': 95, 'Cm': 96, 'Bk': 97, - ## 'Cf': 98, 'Es': 99, 'Fm': 100, 'Md': 101, 'No': 102, 'Lr': 103, - ## 'Rf': 104, 'Db': 105, 'Sg': 106, 'Bh': 107, 'Hs': 108, - ## 'Mt': 109, 'Ds': 110, 'Rg': 111, 'Cn': 112, 'Uut': 113, - ## 'Fl': 114, 'Uup': 115, 'Lv': 116, 'Uus': 117, 'Uuo': 118 - } +periodtable = { + "H": 1, + "He": 2, + "Li": 3, + "Be": 4, + "B": 5, + "C": 6, + "N": 7, + "O": 8, + "F": 9, + "Ne": 10, + "Na": 11, + "Mg": 12, + "Al": 13, + "Si": 14, + "P": 15, + "S": 16, + "Cl": 17, + "Ar": 18, + "K": 19, + "Ca": 20, + "Sc": 21, + "Ti": 22, + "V": 23, + "Cr": 24, + "Mn": 25, + "Fe": 26, + "Co": 27, + "Ni": 28, + "Cu": 29, + "Zn": 30, + "Ga": 31, + "Ge": 32, + "As": 33, + "Se": 34, + "Br": 35, + "Kr": 36, + "Rb": 37, + "Sr": 38, + "Y": 39, + "Zr": 40, + "Nb": 41, + "Mo": 42, + "Tc": 43, + "Ru": 44, + "Rh": 45, + "Pd": 46, + "Ag": 47, + "Cd": 48, + "In": 49, + "Sn": 50, + "Sb": 51, + "Te": 52, + "I": 53, + "Xe": 54, + "Cs": 55, + "Ba": 56, #'La': 57, 'Ce': 58, 'Pr': 59, 'Nd': 60, 'Pm': 61, + ## 'Sm': 62, 'Eu': 63, 'Gd': 64, 'Tb': 65, 'Dy': 66, 'Ho': 67, + ## 'Er': 68, 'Tm': 69, 'Yb': 70, + ## 'Lu': 71, + "Hf": 72, + "Ta": 73, + "W": 74, + "Re": 75, + "Os": 76, + "Ir": 77, + "Pt": 78, + "Au": 79, + "Hg": 80, + "Tl": 81, + "Pb": 82, + "Bi": 83, + ## 'Po': 84, #'At': 85, + ## 'Rn': 86, #'Fr': 87, 'Ra': 88, 'Ac': 89, 'Th': 90, 'Pa': 91, + ## 'U': 92, 'Np': 93, 'Pu': 94, 'Am': 95, 'Cm': 96, 'Bk': 97, + ## 'Cf': 98, 'Es': 99, 'Fm': 100, 'Md': 101, 'No': 102, 'Lr': 103, + ## 'Rf': 104, 'Db': 105, 'Sg': 106, 'Bh': 107, 'Hs': 108, + ## 'Mt': 109, 'Ds': 110, 'Rg': 111, 'Cn': 112, 'Uut': 113, + ## 'Fl': 114, 'Uup': 115, 'Lv': 116, 'Uus': 117, 'Uuo': 118 +} -def print_orbital(orb,info_element): - """ orb[it][il][iu][r] """ - for it,orb_t in orb.items(): - #with open("orb_{0}.dat".format(it),"w") as file: - with open("ORBITAL_{0}U.dat".format( periodtable[it] ),"w") as file: - print_orbital_head(file,info_element,it) - for il,orb_tl in enumerate(orb_t): - for iu,orb_tlu in enumerate(orb_tl): - print(""" Type L N""",file=file) - print(""" 0 {0} {1}""".format(il,iu),file=file) - for ir,orb_tlur in enumerate(orb_tlu): - print( '%.14e'%orb_tlur, end=" ",file=file) - if ir%4==3: print(file=file) - print(file=file) - - -def plot_orbital(orb,Rcut,dr): - for it,orb_t in orb.items(): - #with open("orb_{0}_plot.dat".format(it),"w") as file: - with open("ORBITAL_PLOTU.dat", "w") as file: - Nr = int(Rcut[it]/dr[it])+1 - for ir in range(Nr): - print( '%10.6f'%(ir*dr[it]),end=" ",file=file) - for il,orb_tl in enumerate(orb_t): - for orb_tlu in orb_tl: - print( '%18.14f'%orb_tlu[ir],end=" ",file=file) - print(file=file) - - -def print_orbital_head(file,info_element,it): - print( "---------------------------------------------------------------------------", file=file ) - print( "Element {0}".format(it), file=file ) - print( "Energy Cutoff(Ry) {0}".format(info_element[it].Ecut), file=file ) - print( "Radius Cutoff(a.u.) {0}".format(info_element[it].Rcut), file=file ) - print( "Lmax {0}".format(info_element[it].Nl-1), file=file ) - l_name = ["S","P","D"]+list(map(chr,range(ord('F'),ord('Z')+1))) - for il,iu in enumerate(info_element[it].Nu): - print( "Number of {0}orbital--> {1}".format(l_name[il],iu), file=file ) - print( "---------------------------------------------------------------------------", file=file ) - print( "SUMMARY END", file=file ) - print( file=file ) - print( "Mesh {0}".format(int(info_element[it].Rcut/info_element[it].dr)+1), file=file ) - print( "dr {0}".format(info_element[it].dr), file=file ) - +def print_orbital(orb, info_element): + """orb[it][il][iu][r]""" + for it, orb_t in orb.items(): + # with open("orb_{0}.dat".format(it),"w") as file: + with open("ORBITAL_{0}U.dat".format(periodtable[it]), "w") as file: + print_orbital_head(file, info_element, it) + for il, orb_tl in enumerate(orb_t): + for iu, orb_tlu in enumerate(orb_tl): + print( + """ Type L N""", + file=file, + ) + print( + """ 0 {0} {1}""".format( + il, iu + ), + file=file, + ) + for ir, orb_tlur in enumerate(orb_tlu): + print("%.14e" % orb_tlur, end=" ", file=file) + if ir % 4 == 3: + print(file=file) + print(file=file) + + +def plot_orbital(orb, Rcut, dr): + for it, orb_t in orb.items(): + # with open("orb_{0}_plot.dat".format(it),"w") as file: + with open("ORBITAL_PLOTU.dat", "w") as file: + Nr = int(Rcut[it] / dr[it]) + 1 + for ir in range(Nr): + print("%10.6f" % (ir * dr[it]), end=" ", file=file) + for il, orb_tl in enumerate(orb_t): + for orb_tlu in orb_tl: + print("%18.14f" % orb_tlu[ir], end=" ", file=file) + print(file=file) + + +def print_orbital_head(file, info_element, it): + print( + "---------------------------------------------------------------------------", + file=file, + ) + print("Element {0}".format(it), file=file) + print("Energy Cutoff(Ry) {0}".format(info_element[it].Ecut), file=file) + print("Radius Cutoff(a.u.) {0}".format(info_element[it].Rcut), file=file) + print("Lmax {0}".format(info_element[it].Nl - 1), file=file) + l_name = ["S", "P", "D"] + list(map(chr, range(ord("F"), ord("Z") + 1))) + for il, iu in enumerate(info_element[it].Nu): + print("Number of {0}orbital--> {1}".format(l_name[il], iu), file=file) + print( + "---------------------------------------------------------------------------", + file=file, + ) + print("SUMMARY END", file=file) + print(file=file) + print( + "Mesh {0}".format( + int(info_element[it].Rcut / info_element[it].dr) + 1 + ), + file=file, + ) + print("dr {0}".format(info_element[it].dr), file=file) diff --git a/tools/opt_orb_pytorch_dpsi/IO/read_QSV.py b/tools/opt_orb_pytorch_dpsi/IO/read_QSV.py index b959d9ce737..e89312da2ce 100644 --- a/tools/opt_orb_pytorch_dpsi/IO/read_QSV.py +++ b/tools/opt_orb_pytorch_dpsi/IO/read_QSV.py @@ -5,156 +5,187 @@ import re import copy -def read_file_head(info,file_list): - """ QI[ist][it][il][ib*ia*im,ie] <\psi|jY> """ - """ SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] """ - """ VI[ist][ib] <\psi|\psi> """ - info_true = copy.deepcopy(info) - info_true.Nst = len(file_list) - info_true.Nt = util.ND_list(info_true.Nst,element="list()") - info_true.Na = util.ND_list(info_true.Nst,element="dict()") - info_true.Nb = util.ND_list(info_true.Nst) - info_true.Nk = util.ND_list(info_true.Nst) - info_true.Ne = dict() - for ist_true,file_name in enumerate(file_list): - print(file_name) - with open(file_name,"r") as file: +def read_file_head(info, file_list): + """QI[ist][it][il][ib*ia*im,ie] <\psi|jY>""" + """ SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] """ + """ VI[ist][ib] <\psi|\psi> """ + info_true = copy.deepcopy(info) + info_true.Nst = len(file_list) + info_true.Nt = util.ND_list(info_true.Nst, element="list()") + info_true.Na = util.ND_list(info_true.Nst, element="dict()") + info_true.Nb = util.ND_list(info_true.Nst) + info_true.Nk = util.ND_list(info_true.Nst) + info_true.Ne = dict() - util.ignore_line(file,4) - Nt_tmp = int(file.readline().split()[0]) - for it in range(Nt_tmp): - t_tmp = file.readline().split()[0] - assert t_tmp in info.Nt_all - info_true.Nt[ist_true].append( t_tmp ) - info_true.Na[ist_true][t_tmp] = int(file.readline().split()[0]) - util.ignore_line( file, info_true.Na[ist_true][t_tmp] ) - util.ignore_line(file,6) - Nl_ist = int(file.readline().split()[0])+1 - for it,Nl_C in info.Nl.items(): - print(it,Nl_ist,Nl_C) - assert Nl_ist>=Nl_C - info_true.Nl[it] = Nl_ist - info_true.Nk[ist_true] = int(file.readline().split()[0]) - info_true.Nb[ist_true] = int(file.readline().split()[0]) - util.ignore_line(file,1) - #Ne_tmp = list(map(int,file.readline().split()[:Nt_tmp])) - #for it,Ne in zip(info_true.Nt[ist_true],Ne_tmp): - # assert info_true.Ne.setdefault(it,Ne)==Ne - Ne_tmp = int(file.readline().split()[0]) - for it in info_true.Nt[ist_true]: - info_true.Ne[it] = Ne_tmp + for ist_true, file_name in enumerate(file_list): + print(file_name) + with open(file_name, "r") as file: - info_all = copy.deepcopy(info) - info_all.Nst = sum(info_true.Nk,0) - repeat_Nk = lambda x: list( itertools.chain.from_iterable( map( lambda x:itertools.repeat(*x), zip(x,info_true.Nk) ) ) ) - info_all.Nt = repeat_Nk(info_true.Nt) - info_all.Na = repeat_Nk(info_true.Na) - info_all.Nb = repeat_Nk(info_true.Nb) - info_all.Ne = info_true.Ne + util.ignore_line(file, 4) + Nt_tmp = int(file.readline().split()[0]) + for it in range(Nt_tmp): + t_tmp = file.readline().split()[0] + assert t_tmp in info.Nt_all + info_true.Nt[ist_true].append(t_tmp) + info_true.Na[ist_true][t_tmp] = int(file.readline().split()[0]) + util.ignore_line(file, info_true.Na[ist_true][t_tmp]) + util.ignore_line(file, 6) + Nl_ist = int(file.readline().split()[0]) + 1 + for it, Nl_C in info.Nl.items(): + print(it, Nl_ist, Nl_C) + assert Nl_ist >= Nl_C + info_true.Nl[it] = Nl_ist + info_true.Nk[ist_true] = int(file.readline().split()[0]) + info_true.Nb[ist_true] = int(file.readline().split()[0]) + util.ignore_line(file, 1) + # Ne_tmp = list(map(int,file.readline().split()[:Nt_tmp])) + # for it,Ne in zip(info_true.Nt[ist_true],Ne_tmp): + # assert info_true.Ne.setdefault(it,Ne)==Ne + Ne_tmp = int(file.readline().split()[0]) + for it in info_true.Nt[ist_true]: + info_true.Ne[it] = Ne_tmp - return info_all + info_all = copy.deepcopy(info) + info_all.Nst = sum(info_true.Nk, 0) + repeat_Nk = lambda x: list( + itertools.chain.from_iterable( + map(lambda x: itertools.repeat(*x), zip(x, info_true.Nk)) + ) + ) + info_all.Nt = repeat_Nk(info_true.Nt) + info_all.Na = repeat_Nk(info_true.Na) + info_all.Nb = repeat_Nk(info_true.Nb) + info_all.Ne = info_true.Ne + + return info_all def read_QSV(info_stru, info_element, file_list, V_info): - QI=[]; SI=[]; VI=[] - ist = 0 - for ist_true,file_name in enumerate(file_list): - with open(file_name,"r") as file: - Nk = int(re.compile(r"(\d+)\s+nks").search(file.read()).group(1)) - with open(file_name,"r") as file: - data = re.compile(r"(.+)", re.S).search(file.read()) - data = map(float,data.group(1).split()) - for ik in range(Nk): - print("read QI:",ist_true,ik) - qi = read_QI(info_stru[ist+ik], info_element, data) - QI.append( qi ) - with open(file_name,"r") as file: - data = re.compile(r"(.+)", re.S).search(file.read()) - data = map(float,data.group(1).split()) - for ik in range(Nk): - print("read SI:",ist_true,ik) - si = read_SI(info_stru[ist+ik], info_element, data) - SI.append( si ) - if V_info["init_from_file"]: - with open(file_name,"r") as file: - data = re.compile(r"(.+)", re.S).search(file.read()) - data = map(float,data.group(1).split()) - else: - data = () - for ik in range(Nk): - print("read VI:",ist_true,ik) - vi = read_VI(info_stru[ist+ik], V_info, ist_true, data) - VI.append( vi ) - ist += Nk - print() - return QI,SI,VI + QI = [] + SI = [] + VI = [] + ist = 0 + for ist_true, file_name in enumerate(file_list): + with open(file_name, "r") as file: + Nk = int(re.compile(r"(\d+)\s+nks").search(file.read()).group(1)) + with open(file_name, "r") as file: + data = re.compile(r"(.+)", re.S).search(file.read()) + data = map(float, data.group(1).split()) + for ik in range(Nk): + print("read QI:", ist_true, ik) + qi = read_QI(info_stru[ist + ik], info_element, data) + QI.append(qi) + with open(file_name, "r") as file: + data = re.compile(r"(.+)", re.S).search( + file.read() + ) + data = map(float, data.group(1).split()) + for ik in range(Nk): + print("read SI:", ist_true, ik) + si = read_SI(info_stru[ist + ik], info_element, data) + SI.append(si) + if V_info["init_from_file"]: + with open(file_name, "r") as file: + data = re.compile(r"(.+)", re.S).search( + file.read() + ) + data = map(float, data.group(1).split()) + else: + data = () + for ik in range(Nk): + print("read VI:", ist_true, ik) + vi = read_VI(info_stru[ist + ik], V_info, ist_true, data) + VI.append(vi) + ist += Nk + print() + return QI, SI, VI def read_QI(info_stru, info_element, data): - """ QI[it][il][ib*ia*im,ie] <\psi|jY> """ - QI = dict() - for it in info_stru.Na.keys(): - QI[it] = util.ND_list(info_element[it].Nl) - for il in range(info_element[it].Nl): - QI[it][il] = torch.zeros((info_stru.Nb, info_stru.Na[it], util.Nm(il), info_element[it].Ne), dtype=torch.complex128) - for ib in range(info_stru.Nb): - for it in info_stru.Na.keys(): - for ia in range(info_stru.Na[it]): - for il in range(info_element[it].Nl): - for im in range(util.Nm(il)): - for ie in range(info_element[it].Ne): - QI[it][il][ib,ia,im,ie] = complex(next(data), next(data)) - for it in info_stru.Na.keys(): - for il in range(info_element[it].Nl): - QI[it][il] = QI[it][il][:info_stru.Nb_true,:,:,:].view(-1,info_element[it].Ne).conj() - return QI + """QI[it][il][ib*ia*im,ie] <\psi|jY>""" + QI = dict() + for it in info_stru.Na.keys(): + QI[it] = util.ND_list(info_element[it].Nl) + for il in range(info_element[it].Nl): + QI[it][il] = torch.zeros( + (info_stru.Nb, info_stru.Na[it], util.Nm(il), info_element[it].Ne), + dtype=torch.complex128, + ) + for ib in range(info_stru.Nb): + for it in info_stru.Na.keys(): + for ia in range(info_stru.Na[it]): + for il in range(info_element[it].Nl): + for im in range(util.Nm(il)): + for ie in range(info_element[it].Ne): + QI[it][il][ib, ia, im, ie] = complex(next(data), next(data)) + for it in info_stru.Na.keys(): + for il in range(info_element[it].Nl): + QI[it][il] = ( + QI[it][il][: info_stru.Nb_true, :, :, :] + .view(-1, info_element[it].Ne) + .conj() + ) + return QI def read_SI(info_stru, info_element, data): - """ SI[it1,it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] """ - SI = dict() - for it1,it2 in itertools.product( info_stru.Na.keys(), info_stru.Na.keys() ): - SI[it1,it2] = util.ND_list(info_element[it1].Nl, info_element[it2].Nl) - for il1,il2 in itertools.product( range(info_element[it1].Nl), range(info_element[it2].Nl) ): - SI[it1,it2][il1][il2] = torch.zeros((info_stru.Na[it1], util.Nm(il1), info_element[it1].Ne, info_stru.Na[it2], util.Nm(il2), info_element[it2].Ne), dtype=torch.complex128) - for it1 in info_stru.Na.keys(): - for ia1 in range(info_stru.Na[it1]): - for il1 in range(info_element[it1].Nl): - for im1 in range(util.Nm(il1)): - for it2 in info_stru.Na.keys(): - for ia2 in range(info_stru.Na[it2]): - for il2 in range(info_element[it2].Nl): - for im2 in range(util.Nm(il2)): - for ie1 in range(info_element[it1].Ne): - for ie2 in range(info_element[it2].Ne): - SI[it1,it2][il1][il2][ia1,im1,ie1,ia2,im2,ie2] = complex(next(data), next(data)) -# for it1,it2 in itertools.product( info.Nt[ist], info.Nt[ist] ): -# for il1,il2 in itertools.product( range(info.Nl[it1]), range(info.Nl[it2]) ): -# SI[it1,it2][il1][il2] = torch_complex.ComplexTensor( -# torch.from_numpy(SI[it1,it2][il1][il2].real), -# torch.from_numpy(SI[it1,it2][il1][il2].imag)) - return SI - + """SI[it1,it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] """ + SI = dict() + for it1, it2 in itertools.product(info_stru.Na.keys(), info_stru.Na.keys()): + SI[it1, it2] = util.ND_list(info_element[it1].Nl, info_element[it2].Nl) + for il1, il2 in itertools.product( + range(info_element[it1].Nl), range(info_element[it2].Nl) + ): + SI[it1, it2][il1][il2] = torch.zeros( + ( + info_stru.Na[it1], + util.Nm(il1), + info_element[it1].Ne, + info_stru.Na[it2], + util.Nm(il2), + info_element[it2].Ne, + ), + dtype=torch.complex128, + ) + for it1 in info_stru.Na.keys(): + for ia1 in range(info_stru.Na[it1]): + for il1 in range(info_element[it1].Nl): + for im1 in range(util.Nm(il1)): + for it2 in info_stru.Na.keys(): + for ia2 in range(info_stru.Na[it2]): + for il2 in range(info_element[it2].Nl): + for im2 in range(util.Nm(il2)): + for ie1 in range(info_element[it1].Ne): + for ie2 in range(info_element[it2].Ne): + SI[it1, it2][il1][il2][ + ia1, im1, ie1, ia2, im2, ie2 + ] = complex(next(data), next(data)) + # for it1,it2 in itertools.product( info.Nt[ist], info.Nt[ist] ): + # for il1,il2 in itertools.product( range(info.Nl[it1]), range(info.Nl[it2]) ): + # SI[it1,it2][il1][il2] = torch_complex.ComplexTensor( + # torch.from_numpy(SI[it1,it2][il1][il2].real), + # torch.from_numpy(SI[it1,it2][il1][il2].imag)) + return SI -def read_VI(info_stru,V_info,ist,data): - if V_info["same_band"]: - """ VI[ib] """ - if V_info["init_from_file"]: - VI = np.empty(info_stru.Nb,dtype=np.float64) - for ib in range(info_stru.Nb): - VI.data[ib] = next(data) - VI = VI[:info_stru.Nb_true] - else: - VI = np.ones(info_stru.Nb_true, dtype=np.float64) - else: - """ VI[ib1,ib2] """ - if V_info["init_from_file"]: - VI = np.empty((info_stru.Nb,info_stru.Nb),dtype=np.float64) - for ib1,ib2 in itertools.product( range(info_stru.Nb), range(info_stru.Nb) ): - VI[ib1,ib2] = next(data) - VI = VI[info_stru.Nb_true, info_stru.Nb_true] - else: - VI = np.eye(info_stru.Nb_true, info_stru.Nb_true, dtype=np.float64) - return torch.from_numpy(VI) +def read_VI(info_stru, V_info, ist, data): + if V_info["same_band"]: + """VI[ib] """ + if V_info["init_from_file"]: + VI = np.empty(info_stru.Nb, dtype=np.float64) + for ib in range(info_stru.Nb): + VI.data[ib] = next(data) + VI = VI[: info_stru.Nb_true] + else: + VI = np.ones(info_stru.Nb_true, dtype=np.float64) + else: + """VI[ib1,ib2] """ + if V_info["init_from_file"]: + VI = np.empty((info_stru.Nb, info_stru.Nb), dtype=np.float64) + for ib1, ib2 in itertools.product(range(info_stru.Nb), range(info_stru.Nb)): + VI[ib1, ib2] = next(data) + VI = VI[info_stru.Nb_true, info_stru.Nb_true] + else: + VI = np.eye(info_stru.Nb_true, info_stru.Nb_true, dtype=np.float64) + return torch.from_numpy(VI) diff --git a/tools/opt_orb_pytorch_dpsi/IO/read_istate.py b/tools/opt_orb_pytorch_dpsi/IO/read_istate.py index e1e7277e47a..1df0a59a6fd 100644 --- a/tools/opt_orb_pytorch_dpsi/IO/read_istate.py +++ b/tools/opt_orb_pytorch_dpsi/IO/read_istate.py @@ -1,42 +1,50 @@ -import re -import torch -import itertools - -# occ[ik][ib] -def read_istate(file_name): - nspin0 = get_nspin0(file_name) - if nspin0==1: occ = [[]] - elif nspin0==2: occ = [[],[]] - with open(file_name,"r") as file: - content = file.read().split("BAND") - for content_k in content[1:]: - content_k = content_k.split("\n") - k = get_k(content_k[0]) - for ispin in range(nspin0): - occ[ispin].append([]) - for line in content_k[1:]: - line = line.strip() - if line: - line = line.split() - if nspin0==1: - occ[0][-1].append(float(line[2])) - elif nspin0==2: - occ[0][-1].append(float(line[2])) - occ[1][-1].append(float(line[4])) - for ispin in range(nspin0): - occ[ispin][-1] = torch.Tensor(occ[ispin][-1]) - occ = list(itertools.chain(*occ)) - return occ - -def get_k(line): - k = re.compile(r"Kpoint\s*=\s*(\d+)").search(line).group(1) - return int(k) - -def get_nspin0(file_name): - with open(file_name,"r") as file: - file.readline() - line = file.readline() - lens = len(line.split()) - if lens == 3: return 1 - elif lens == 5: return 2 - else: raise \ No newline at end of file +import re +import torch +import itertools + + +# occ[ik][ib] +def read_istate(file_name): + nspin0 = get_nspin0(file_name) + if nspin0 == 1: + occ = [[]] + elif nspin0 == 2: + occ = [[], []] + with open(file_name, "r") as file: + content = file.read().split("BAND") + for content_k in content[1:]: + content_k = content_k.split("\n") + k = get_k(content_k[0]) + for ispin in range(nspin0): + occ[ispin].append([]) + for line in content_k[1:]: + line = line.strip() + if line: + line = line.split() + if nspin0 == 1: + occ[0][-1].append(float(line[2])) + elif nspin0 == 2: + occ[0][-1].append(float(line[2])) + occ[1][-1].append(float(line[4])) + for ispin in range(nspin0): + occ[ispin][-1] = torch.Tensor(occ[ispin][-1]) + occ = list(itertools.chain(*occ)) + return occ + + +def get_k(line): + k = re.compile(r"Kpoint\s*=\s*(\d+)").search(line).group(1) + return int(k) + + +def get_nspin0(file_name): + with open(file_name, "r") as file: + file.readline() + line = file.readline() + lens = len(line.split()) + if lens == 3: + return 1 + elif lens == 5: + return 2 + else: + raise diff --git a/tools/opt_orb_pytorch_dpsi/IO/read_json.py b/tools/opt_orb_pytorch_dpsi/IO/read_json.py index 67705b4b307..142f92bba97 100644 --- a/tools/opt_orb_pytorch_dpsi/IO/read_json.py +++ b/tools/opt_orb_pytorch_dpsi/IO/read_json.py @@ -1,82 +1,89 @@ import json from util import Info + def read_json(file_name): - with open(file_name,"r") as file: - input = file.read() - input = json.loads(input) - - info = Info() - for info_attr,info_value in input["info"].items(): - info.__dict__[info_attr] = info_value - info.Nl = { it:len(Nu) for it,Nu in info.Nu.items() } - - return input["file_list"], info, input["weight"], input["C_init_info"], input["V_info"] + with open(file_name, "r") as file: + input = file.read() + input = json.loads(input) + + info = Info() + for info_attr, info_value in input["info"].items(): + info.__dict__[info_attr] = info_value + info.Nl = {it: len(Nu) for it, Nu in info.Nu.items()} + + return ( + input["file_list"], + info, + input["weight"], + input["C_init_info"], + input["V_info"], + ) + + """ file_name + { + "file_list": { + "origin": [ + "~/C_bulk/orb_matrix/test.0.dat", + "~/CO2/orb_matrix/test.0.dat" + ], + "linear": [ + [ + "~/C_bulk/orb_matrix/test.1.dat", + "~/CO2/orb_matrix/test.1.dat" + ], + [ + "~/C_bulk/orb_matrix/test.2.dat", + "~/CO2/orb_matrix/test.2.dat" + ], + ] + }, + "info": { + "Nt_all": [ "C", "O" ], + "Nu": { "C":[2,2,1], "O":[3,2,1] }, + "Rcut": { "C":6, "O":6 }, + "dr": { "C":0.01, "O":0.01 }, + "Ecut": { "C":200, "O":200 }, + "lr": 0.01, + "cal_T": false, + "cal_smooth": false + }, + "weight": + { + "stru": [1, 2.3], + "bands_range": [10, 15], # "bands_range" and "bands_file" only once + "bands_file": + [ + "~/C_bulk/OUT.ABACUS/istate.info", + "~/CO2/OUT.ABACUS/istate.info" + ] + }, + "C_init_info": { + "init_from_file": false, + "C_init_file": "~/CO/ORBITAL_RESULTS.txt", + "opt_C_read": false + }, + "V_info": { + "init_from_file": true, + "same_band": true + } + } + """ - """ file_name - { - "file_list": { - "origin": [ - "~/C_bulk/orb_matrix/test.0.dat", - "~/CO2/orb_matrix/test.0.dat" - ], - "linear": [ - [ - "~/C_bulk/orb_matrix/test.1.dat", - "~/CO2/orb_matrix/test.1.dat" - ], - [ - "~/C_bulk/orb_matrix/test.2.dat", - "~/CO2/orb_matrix/test.2.dat" - ], - ] - }, - "info": { - "Nt_all": [ "C", "O" ], - "Nu": { "C":[2,2,1], "O":[3,2,1] }, - "Rcut": { "C":6, "O":6 }, - "dr": { "C":0.01, "O":0.01 }, - "Ecut": { "C":200, "O":200 }, - "lr": 0.01, - "cal_T": false, - "cal_smooth": false - }, - "weight": - { - "stru": [1, 2.3], - "bands_range": [10, 15], # "bands_range" and "bands_file" only once - "bands_file": - [ - "~/C_bulk/OUT.ABACUS/istate.info", - "~/CO2/OUT.ABACUS/istate.info" - ] - }, - "C_init_info": { - "init_from_file": false, - "C_init_file": "~/CO/ORBITAL_RESULTS.txt", - "opt_C_read": false - }, - "V_info": { - "init_from_file": true, - "same_band": true - } - } - """ - - """ info - Nt_all ['C', 'O'] - Nu {'C': [2, 2, 1], 'O': [3, 2, 1]} - Rcut {'C': 6, 'O': 6} - dr {'C': 0.01, 'O': 0.01} - Ecut {'C': 200, 'O': 200} - lr 0.01 - cal_T False - cal_smooth False - Nl {'C': 3, 'O': 3} - Nst 3 - Nt [['C'], ['C'], ['C', 'O']] - Na [{'C': 1}, {'C': 1}, {'C': 1, 'O': 2}] - Nb [6, 6, 10] - Ne {'C': 19, 'O': 19} - """ \ No newline at end of file + """ info + Nt_all ['C', 'O'] + Nu {'C': [2, 2, 1], 'O': [3, 2, 1]} + Rcut {'C': 6, 'O': 6} + dr {'C': 0.01, 'O': 0.01} + Ecut {'C': 200, 'O': 200} + lr 0.01 + cal_T False + cal_smooth False + Nl {'C': 3, 'O': 3} + Nst 3 + Nt [['C'], ['C'], ['C', 'O']] + Na [{'C': 1}, {'C': 1}, {'C': 1, 'O': 2}] + Nb [6, 6, 10] + Ne {'C': 19, 'O': 19} + """ diff --git a/tools/opt_orb_pytorch_dpsi/main.py b/tools/opt_orb_pytorch_dpsi/main.py index ff7fc63d8aa..e9a7b4e958f 100755 --- a/tools/opt_orb_pytorch_dpsi/main.py +++ b/tools/opt_orb_pytorch_dpsi/main.py @@ -10,151 +10,209 @@ import torch import numpy as np import time -import torch_optimizer +import torch_optimizer import IO.cal_weight import util import IO.change_info import pprint + def main(): - seed = int(1000*time.time())%(2**32) - np.random.seed(seed) - print("seed:",seed) - time_start = time.time() - - file_list, info_true, weight_info, C_init_info, V_info = IO.read_json.read_json("INPUT") - - weight = IO.cal_weight.cal_weight(weight_info, V_info["same_band"], file_list["origin"]) - - info_kst = IO.read_QSV.read_file_head(info_true,file_list["origin"]) - - info_stru, info_element, info_opt = IO.change_info.change_info(info_kst,weight) - info_max = IO.change_info.get_info_max(info_stru, info_element) - - print("info_kst:", info_kst, sep="\n", end="\n"*2, flush=True) - print("info_stru:", pprint.pformat(info_stru), sep="\n", end="\n"*2, flush=True) - print("info_element:", pprint.pformat(info_element,width=40), sep="\n", end="\n"*2, flush=True) - print("info_opt:", pprint.pformat(info_opt,width=40), sep="\n", end="\n"*2, flush=True) - print("info_max:", pprint.pformat(info_max), sep="\n", end="\n"*2, flush=True) - - QI,SI,VI_origin = IO.read_QSV.read_QSV(info_stru, info_element, file_list["origin"], V_info) - if "linear" in file_list.keys(): - QI_linear, SI_linear, VI_linear = list(zip(*( IO.read_QSV.read_QSV(info_stru, info_element, file, V_info) for file in file_list["linear"] ))) - - if C_init_info["init_from_file"]: - C, C_read_index = IO.func_C.read_C_init( C_init_info["C_init_file"], info_element ) - else: - C = IO.func_C.random_C_init(info_element) - E = orbital.set_E(info_element) - orbital.normalize( - orbital.generate_orbital(info_element,C,E), - {it:info_element[it].dr for it in info_element}, - C, flag_norm_C=True) - - opt_orb = opt_orbital.Opt_Orbital() - - #opt = torch.optim.Adam(sum( ([c.real,c.imag] for c in sum(C,[])), []), lr=info_opt.lr, eps=1e-8) - #opt = torch.optim.Adam( sum(C.values(),[]), lr=info_opt.lr, eps=1e-20, weight_decay=info_opt.weight_decay) - #opt = radam.RAdam( sum(C.values(),[]), lr=info_opt.lr, eps=1e-20 ) - opt = torch_optimizer.SWATS( sum(C.values(),[]), lr=info_opt.lr, eps=1e-20 ) - - - with open("Spillage.dat","w") as S_file: - - print( "\nSee \"Spillage.dat\" for detail status: " , flush=True ) - if info_opt.cal_T: - print( '%5s'%"istep", "%20s"%"Spillage", "%20s"%"T.item()", "%20s"%"Loss", flush=True ) - else: - print( '%5s'%"istep", "%20s"%"Spillage", flush=True ) - - loss_old = np.inf - for istep in range(10000): - - Spillage = 0 - for ist in range(len(info_stru)): - - Q = opt_orb.change_index_Q(opt_orb.cal_Q(QI[ist],C,info_stru[ist],info_element),info_stru[ist]) - S = opt_orb.change_index_S(opt_orb.cal_S(SI[ist],C,info_stru[ist],info_element),info_stru[ist],info_element) - coef = opt_orb.cal_coef(Q,S) - V = opt_orb.cal_V(coef,Q) - V_origin = opt_orb.cal_V_origin(V,V_info) - - if "linear" in file_list.keys(): - V_linear = [None] * len(file_list["linear"]) - for i in range(len(file_list["linear"])): - Q_linear = opt_orb.change_index_Q(opt_orb.cal_Q(QI_linear[i][ist],C,info_stru[ist],info_element),info_stru[ist]) - S_linear = opt_orb.change_index_S(opt_orb.cal_S(SI_linear[i][ist],C,info_stru[ist],info_element),info_stru[ist],info_element) - V_linear[i] = opt_orb.cal_V_linear(coef,Q_linear,S_linear,V,V_info) - - def cal_Spillage(V_delta): - Spillage = (V_delta * weight[ist][:info_stru[ist].Nb_true]).sum() - return Spillage - - def cal_delta(VI, V): - return ((VI[ist]-V)/util.update0(VI[ist])).abs() # abs or **2? - - Spillage += 2*cal_Spillage(cal_delta(VI_origin,V_origin)) - if "linear" in file_list.keys(): - for i in range(len(file_list["linear"])): - Spillage += cal_Spillage(cal_delta(VI_linear[i],V_linear[i])) - - if info_opt.cal_T: - T = opt_orb.cal_T(C,E) - if not "TSrate" in vars(): TSrate = torch.abs(0.002*Spillage/T).data[0] - Loss = Spillage + TSrate*T - else: - Loss = Spillage - - if info_opt.cal_T: - print_content = [istep, Spillage.item(), T.item(), Loss.item()] - else: - print_content = [istep, Spillage.item()] - print(*print_content, sep="\t", file=S_file, flush=True) - if not istep%100: - print(*print_content, sep="\t", flush=True) - - if Loss.item() < loss_old: - loss_old = Loss.item() - C_old = IO.func_C.copy_C(C,info_element) - flag_finish = 0 - else: - flag_finish += 1 - if flag_finish > 50: - break - - opt.zero_grad() - Loss.backward() - if C_init_info["init_from_file"] and not C_init_info["opt_C_read"]: - for it,il,iu in C_read_index: - C[it][il].grad[:,iu] = 0 - opt.step() - #orbital.normalize( - # orbital.generate_orbital(info_element,C,E), - # {it:info_element[it].dr for it in info_element}, - # C, flag_norm_C=True) - - orb = orbital.generate_orbital(info_element,C_old,E) - if info_opt.cal_smooth: - orbital.smooth_orbital( - orb, - {it:info_element[it].Rcut for it in info_element}, {it:info_element[it].dr for it in info_element}, - 0.1) - orbital.orth( - orb, - {it:info_element[it].dr for it in info_element}) - IO.print_orbital.print_orbital(orb,info_element) - IO.print_orbital.plot_orbital( - orb, - {it:info_element[it].Rcut for it in info_element}, - {it:info_element[it].dr for it in info_element}) - - IO.func_C.write_C("ORBITAL_RESULTS.txt",C_old,Spillage) - - print("Time (PyTorch): %s\n"%(time.time()-time_start), flush=True ) - - -if __name__=="__main__": - import sys - np.set_printoptions(threshold=sys.maxsize, linewidth=10000) - print( sys.version, flush=True ) - main() + seed = int(1000 * time.time()) % (2**32) + np.random.seed(seed) + print("seed:", seed) + time_start = time.time() + + file_list, info_true, weight_info, C_init_info, V_info = IO.read_json.read_json( + "INPUT" + ) + + weight = IO.cal_weight.cal_weight( + weight_info, V_info["same_band"], file_list["origin"] + ) + + info_kst = IO.read_QSV.read_file_head(info_true, file_list["origin"]) + + info_stru, info_element, info_opt = IO.change_info.change_info(info_kst, weight) + info_max = IO.change_info.get_info_max(info_stru, info_element) + + print("info_kst:", info_kst, sep="\n", end="\n" * 2, flush=True) + print("info_stru:", pprint.pformat(info_stru), sep="\n", end="\n" * 2, flush=True) + print( + "info_element:", + pprint.pformat(info_element, width=40), + sep="\n", + end="\n" * 2, + flush=True, + ) + print( + "info_opt:", + pprint.pformat(info_opt, width=40), + sep="\n", + end="\n" * 2, + flush=True, + ) + print("info_max:", pprint.pformat(info_max), sep="\n", end="\n" * 2, flush=True) + + QI, SI, VI_origin = IO.read_QSV.read_QSV( + info_stru, info_element, file_list["origin"], V_info + ) + if "linear" in file_list.keys(): + QI_linear, SI_linear, VI_linear = list( + zip( + *( + IO.read_QSV.read_QSV(info_stru, info_element, file, V_info) + for file in file_list["linear"] + ) + ) + ) + + if C_init_info["init_from_file"]: + C, C_read_index = IO.func_C.read_C_init( + C_init_info["C_init_file"], info_element + ) + else: + C = IO.func_C.random_C_init(info_element) + E = orbital.set_E(info_element) + orbital.normalize( + orbital.generate_orbital(info_element, C, E), + {it: info_element[it].dr for it in info_element}, + C, + flag_norm_C=True, + ) + + opt_orb = opt_orbital.Opt_Orbital() + + # opt = torch.optim.Adam(sum( ([c.real,c.imag] for c in sum(C,[])), []), lr=info_opt.lr, eps=1e-8) + # opt = torch.optim.Adam( sum(C.values(),[]), lr=info_opt.lr, eps=1e-20, weight_decay=info_opt.weight_decay) + # opt = radam.RAdam( sum(C.values(),[]), lr=info_opt.lr, eps=1e-20 ) + opt = torch_optimizer.SWATS(sum(C.values(), []), lr=info_opt.lr, eps=1e-20) + + with open("Spillage.dat", "w") as S_file: + + print('\nSee "Spillage.dat" for detail status: ', flush=True) + if info_opt.cal_T: + print( + "%5s" % "istep", + "%20s" % "Spillage", + "%20s" % "T.item()", + "%20s" % "Loss", + flush=True, + ) + else: + print("%5s" % "istep", "%20s" % "Spillage", flush=True) + + loss_old = np.inf + for istep in range(10000): + + Spillage = 0 + for ist in range(len(info_stru)): + + Q = opt_orb.change_index_Q( + opt_orb.cal_Q(QI[ist], C, info_stru[ist], info_element), + info_stru[ist], + ) + S = opt_orb.change_index_S( + opt_orb.cal_S(SI[ist], C, info_stru[ist], info_element), + info_stru[ist], + info_element, + ) + coef = opt_orb.cal_coef(Q, S) + V = opt_orb.cal_V(coef, Q) + V_origin = opt_orb.cal_V_origin(V, V_info) + + if "linear" in file_list.keys(): + V_linear = [None] * len(file_list["linear"]) + for i in range(len(file_list["linear"])): + Q_linear = opt_orb.change_index_Q( + opt_orb.cal_Q( + QI_linear[i][ist], C, info_stru[ist], info_element + ), + info_stru[ist], + ) + S_linear = opt_orb.change_index_S( + opt_orb.cal_S( + SI_linear[i][ist], C, info_stru[ist], info_element + ), + info_stru[ist], + info_element, + ) + V_linear[i] = opt_orb.cal_V_linear( + coef, Q_linear, S_linear, V, V_info + ) + + def cal_Spillage(V_delta): + Spillage = (V_delta * weight[ist][: info_stru[ist].Nb_true]).sum() + return Spillage + + def cal_delta(VI, V): + return ((VI[ist] - V) / util.update0(VI[ist])).abs() # abs or **2? + + Spillage += 2 * cal_Spillage(cal_delta(VI_origin, V_origin)) + if "linear" in file_list.keys(): + for i in range(len(file_list["linear"])): + Spillage += cal_Spillage(cal_delta(VI_linear[i], V_linear[i])) + + if info_opt.cal_T: + T = opt_orb.cal_T(C, E) + if not "TSrate" in vars(): + TSrate = torch.abs(0.002 * Spillage / T).data[0] + Loss = Spillage + TSrate * T + else: + Loss = Spillage + + if info_opt.cal_T: + print_content = [istep, Spillage.item(), T.item(), Loss.item()] + else: + print_content = [istep, Spillage.item()] + print(*print_content, sep="\t", file=S_file, flush=True) + if not istep % 100: + print(*print_content, sep="\t", flush=True) + + if Loss.item() < loss_old: + loss_old = Loss.item() + C_old = IO.func_C.copy_C(C, info_element) + flag_finish = 0 + else: + flag_finish += 1 + if flag_finish > 50: + break + + opt.zero_grad() + Loss.backward() + if C_init_info["init_from_file"] and not C_init_info["opt_C_read"]: + for it, il, iu in C_read_index: + C[it][il].grad[:, iu] = 0 + opt.step() + # orbital.normalize( + # orbital.generate_orbital(info_element,C,E), + # {it:info_element[it].dr for it in info_element}, + # C, flag_norm_C=True) + + orb = orbital.generate_orbital(info_element, C_old, E) + if info_opt.cal_smooth: + orbital.smooth_orbital( + orb, + {it: info_element[it].Rcut for it in info_element}, + {it: info_element[it].dr for it in info_element}, + 0.1, + ) + orbital.orth(orb, {it: info_element[it].dr for it in info_element}) + IO.print_orbital.print_orbital(orb, info_element) + IO.print_orbital.plot_orbital( + orb, + {it: info_element[it].Rcut for it in info_element}, + {it: info_element[it].dr for it in info_element}, + ) + + IO.func_C.write_C("ORBITAL_RESULTS.txt", C_old, Spillage) + + print("Time (PyTorch): %s\n" % (time.time() - time_start), flush=True) + + +if __name__ == "__main__": + import sys + + np.set_printoptions(threshold=sys.maxsize, linewidth=10000) + print(sys.version, flush=True) + main() diff --git a/tools/opt_orb_pytorch_dpsi/opt_orbital.py b/tools/opt_orb_pytorch_dpsi/opt_orbital.py index 342a634adc3..40cc566bfbe 100644 --- a/tools/opt_orb_pytorch_dpsi/opt_orbital.py +++ b/tools/opt_orb_pytorch_dpsi/opt_orbital.py @@ -4,175 +4,176 @@ import itertools import torch + class Opt_Orbital: - - def cal_Q(self,QI,C,info_stru,info_element): - """ - <\psi|\phi> = <\psi|jY> * - Q[it][il][ib,ia*im*iu] - = sum_{q} QI[it][il][ib*ia*im,ie] * C[it][il][ie,iu] - """ - Q = dict() - for it in info_stru.Na.keys(): - Q[it] = ND_list(info_element[it].Nl) - for it in info_stru.Na.keys(): - for il in range(info_element[it].Nl): - Q[it][il] = torch.mm( QI[it][il], C[it][il].to(torch.complex128) ).view(info_stru.Nb_true,-1) - return Q + def cal_Q(self, QI, C, info_stru, info_element): + """ + <\psi|\phi> = <\psi|jY> * + Q[it][il][ib,ia*im*iu] + = sum_{q} QI[it][il][ib*ia*im,ie] * C[it][il][ie,iu] + """ + Q = dict() + for it in info_stru.Na.keys(): + Q[it] = ND_list(info_element[it].Nl) + + for it in info_stru.Na.keys(): + for il in range(info_element[it].Nl): + Q[it][il] = torch.mm(QI[it][il], C[it][il].to(torch.complex128)).view( + info_stru.Nb_true, -1 + ) + return Q + + def cal_S(self, SI, C, info_stru, info_element): + """ + <\phi|\phi> = <\phi|jY> * * + S[it1,it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2] + = sum_{ie1 ie2} C^*[it1][il1][ie1,iu1] * SI[it1,it2][il1][il2][ia1,im1,ie1,ia2,im2,ie2] * C[it2][[il2][ie2,iu2] + """ + S = dict() + for it1, it2 in itertools.product(info_stru.Na.keys(), info_stru.Na.keys()): + S[it1, it2] = ND_list(info_element[it1].Nl, info_element[it2].Nl) + + for it1, it2 in itertools.product(info_stru.Na.keys(), info_stru.Na.keys()): + for il1, il2 in itertools.product( + range(info_element[it1].Nl), range(info_element[it2].Nl) + ): + # SI_C[ia1*im1*ie1*ia2*im2,iu2] + SI_C = torch.mm( + SI[it1, it2][il1][il2].view(-1, info_element[it2].Ne), + C[it2][il2].to(torch.complex128), + ) + # SI_C[ia1*im1,ie1,ia2*im2*iu2] + SI_C = SI_C.view( + info_stru.Na[it1] * util.Nm(il1), info_element[it1].Ne, -1 + ) + # Ct[iu1,ie1] + Ct = C[it1][il1].t().to(torch.complex128) + C_mm = functools.partial(torch.mm, Ct) + # C_SI_C[ia1*im1][iu1,ia2*im2*iu2] + C_SI_C = list(map(C_mm, SI_C)) + # C_SI_C[ia1*im1*iu1,ia2*im2*iu2] + C_SI_C = torch.cat(C_SI_C, dim=0) + # ??? C_SI_C = C_SI_C.view(info_stru.Na[it1]*util.Nm(il1)*info_element[it1].Nu[il1],-1) + S[it1, it2][il1][il2] = C_SI_C + return S + + def change_index_S( + self, S, info_stru, info_element + ): # S[it1,it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2] + """ + <\phi|\phi> + S_cat[it1*il1*iat*im1*iu1,iat2*il2*ia2*im2*iu2] + """ + # S_[it1][il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] + S_ = dict() + for it1 in info_stru.Na.keys(): + # S_t[it2][il1*ia1*im1*iu1,il2*ia2*im2*iu2] + S_t = dict() + for it2 in info_stru.Na.keys(): + # S_tt[il1][ia1*im1*iu1,il2*ia2*im2*iu2] + S_tt = ND_list(info_element[it1].Nl) + for il1 in range(info_element[it1].Nl): + S_tt[il1] = torch.cat(S[it1, it2][il1], dim=1) + S_t[it2] = torch.cat(S_tt, dim=0) + S_[it1] = torch.cat(list(S_t.values()), dim=1) + # S_cat[it1*il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] + S_cat = torch.cat(list(S_.values()), dim=0) + return S_cat + + def change_index_Q(self, Q, info_stru): # Q[it][il][ib,ia*im*iu] + """ + <\psi|\phi> + Q_cat[ib,it*il*ia*im*iu] + """ + # Q_b[ib][0,it*il*ia*im*iu] + Q_b = ND_list(info_stru.Nb_true) + for ib in range(info_stru.Nb_true): + # Q_[it][il*ia*im*iu] + Q_ = dict() + for it in info_stru.Na.keys(): + # Q_ts[il][ia*im*iu] + Q_ts = [Q_tl[ib] for Q_tl in Q[it]] + Q_[it] = torch.cat(Q_ts) + Q_b[ib] = torch.cat(list(Q_.values())).view(1, -1) + # Q_cat[ib,it*il*ia*im*iu] + Q_cat = torch.cat(Q_b, dim=0) + return Q_cat + + def cal_coef(self, Q, S): + # Q[ib,it*il*ia*im*iu] + # S[it1*il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] + """ + <\psi|\phi> * <\phi|\phi>^{-1} + coef[ib,it*il*ia*im*iu] + = Q[ib,it1*il1*ia1*im1*iu1] * S{[it1*il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2]}^{-1} + """ + S_I = torch.inverse(S) + coef = torch.mm(Q, S_I) + return coef - - - def cal_S(self,SI,C,info_stru,info_element): - """ - <\phi|\phi> = <\phi|jY> * * - S[it1,it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2] - = sum_{ie1 ie2} C^*[it1][il1][ie1,iu1] * SI[it1,it2][il1][il2][ia1,im1,ie1,ia2,im2,ie2] * C[it2][[il2][ie2,iu2] - """ - S = dict() - for it1,it2 in itertools.product( info_stru.Na.keys(), info_stru.Na.keys() ): - S[it1,it2] = ND_list(info_element[it1].Nl, info_element[it2].Nl) + def cal_V(self, coef, Q): + # coef[ib,it*il*ia*im*iu] + # Q[ib,it*il*ia*im*iu] + """ + <\psi|\psi> = <\psi|\phi> * <\phi|\phi>^{-1} * <\phi|psi> + V[ib1,ib2] + = sum_{it1,ia1,il1,im1,iu1} sum_{it2,ia2,il2,im2,iu2} + Q[ib1,it1*il1*ia1*im1*iu1] * S{[it1*il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2]}^{-1} * Q[ib2,it2*il2*ia2*im2*iu2] + """ + V = torch.mm(coef, Q.t().conj()).real + return V - for it1,it2 in itertools.product( info_stru.Na.keys(), info_stru.Na.keys() ): - for il1,il2 in itertools.product( range(info_element[it1].Nl), range(info_element[it2].Nl) ): - # SI_C[ia1*im1*ie1*ia2*im2,iu2] - SI_C = torch.mm( - SI[it1,it2][il1][il2].view(-1,info_element[it2].Ne), - C[it2][il2].to(torch.complex128) ) - # SI_C[ia1*im1,ie1,ia2*im2*iu2] - SI_C = SI_C.view( info_stru.Na[it1]*util.Nm(il1), info_element[it1].Ne, -1 ) - # Ct[iu1,ie1] - Ct = C[it1][il1].t().to(torch.complex128) - C_mm = functools.partial(torch.mm,Ct) - # C_SI_C[ia1*im1][iu1,ia2*im2*iu2] - C_SI_C = list(map( C_mm, SI_C )) - # C_SI_C[ia1*im1*iu1,ia2*im2*iu2] - C_SI_C = torch.cat( C_SI_C, dim=0 ) -#??? C_SI_C = C_SI_C.view(info_stru.Na[it1]*util.Nm(il1)*info_element[it1].Nu[il1],-1) - S[it1,it2][il1][il2] = C_SI_C - return S - - - - def change_index_S(self,S,info_stru,info_element): # S[it1,it2][il1][il2][ia1*im1*iu1,ia2*im2*iu2] - """ - <\phi|\phi> - S_cat[it1*il1*iat*im1*iu1,iat2*il2*ia2*im2*iu2] - """ - # S_[it1][il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] - S_ = dict() - for it1 in info_stru.Na.keys(): - # S_t[it2][il1*ia1*im1*iu1,il2*ia2*im2*iu2] - S_t = dict() - for it2 in info_stru.Na.keys(): - # S_tt[il1][ia1*im1*iu1,il2*ia2*im2*iu2] - S_tt = ND_list(info_element[it1].Nl) - for il1 in range(info_element[it1].Nl): - S_tt[il1] = torch.cat( S[it1,it2][il1], dim=1 ) - S_t[it2] = torch.cat( S_tt, dim=0 ) - S_[it1] = torch.cat( list(S_t.values()), dim=1 ) - # S_cat[it1*il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] - S_cat = torch.cat( list(S_.values()), dim=0 ) - return S_cat - - - - def change_index_Q(self,Q,info_stru): # Q[it][il][ib,ia*im*iu] - """ - <\psi|\phi> - Q_cat[ib,it*il*ia*im*iu] - """ - # Q_b[ib][0,it*il*ia*im*iu] - Q_b = ND_list(info_stru.Nb_true) - for ib in range(info_stru.Nb_true): - # Q_[it][il*ia*im*iu] - Q_ = dict() - for it in info_stru.Na.keys(): - # Q_ts[il][ia*im*iu] - Q_ts = [ Q_tl[ib] for Q_tl in Q[it] ] - Q_[it] = torch.cat(Q_ts) - Q_b[ib] = torch.cat(list(Q_.values())).view(1,-1) - # Q_cat[ib,it*il*ia*im*iu] - Q_cat = torch.cat( Q_b, dim=0 ) - return Q_cat - - - - def cal_coef(self,Q,S): - # Q[ib,it*il*ia*im*iu] - # S[it1*il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] - """ - <\psi|\phi> * <\phi|\phi>^{-1} - coef[ib,it*il*ia*im*iu] - = Q[ib,it1*il1*ia1*im1*iu1] * S{[it1*il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2]}^{-1} - """ - S_I = torch.inverse(S) - coef = torch.mm(Q, S_I) - return coef - - - - def cal_V(self,coef,Q): - # coef[ib,it*il*ia*im*iu] - # Q[ib,it*il*ia*im*iu] - """ - <\psi|\psi> = <\psi|\phi> * <\phi|\phi>^{-1} * <\phi|psi> - V[ib1,ib2] - = sum_{it1,ia1,il1,im1,iu1} sum_{it2,ia2,il2,im2,iu2} - Q[ib1,it1*il1*ia1*im1*iu1] * S{[it1*il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2]}^{-1} * Q[ib2,it2*il2*ia2*im2*iu2] - """ - V = torch.mm( coef, Q.t().conj() ).real - return V + def cal_V_origin(self, V, V_info): + # V[ib1,ib2] + """ + <\psi|\psi> = <\psi|\phi> * <\phi|\phi>^{-1} * <\phi|psi> + V_origin[ib] + V_origin[ib1,ib2] + """ + if V_info["same_band"]: + V_origin = V.diag().sqrt() + else: + V_origin = V.sqrt() + return V_origin + def cal_V_linear(self, coef, Q_linear, S_linear, V, V_info): + # coef[ib,it*il*ia*im*iu] + # Q_linear[ib,it*il*ia*im*iu] + # S_linear[it1*il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] + # V[ib1,ib2] + """ + V_linear[ib] + V_linear[ib1,ib2] + """ + V_linear_1 = coef.mm(S_linear).mm(coef.t().conj()).real + V_linear_2 = Q_linear.mm(coef.t().conj()).real + V_linear_3 = coef.mm(Q_linear.t().conj()).real + if V_info["same_band"]: + V_linear_1 = V_linear_1.diag() + V_linear_2 = V_linear_2.diag() + V_linear_3 = V_linear_3.diag() + if V_info["same_band"]: + Z = V.diag().sqrt() + else: + Z = V.sqrt() + Z = util.update0(Z) + V_linear = (-V_linear_1 / Z + V_linear_2 + V_linear_3) / Z + return V_linear - def cal_V_origin(self,V,V_info): - # V[ib1,ib2] - """ - <\psi|\psi> = <\psi|\phi> * <\phi|\phi>^{-1} * <\phi|psi> - V_origin[ib] - V_origin[ib1,ib2] - """ - if V_info["same_band"]: V_origin = V.diag().sqrt() - else: V_origin = V.sqrt() - return V_origin - - - def cal_V_linear(self,coef,Q_linear,S_linear,V,V_info): - # coef[ib,it*il*ia*im*iu] - # Q_linear[ib,it*il*ia*im*iu] - # S_linear[it1*il1*ia1*im1*iu1,it2*il2*ia2*im2*iu2] - # V[ib1,ib2] - """ - V_linear[ib] - V_linear[ib1,ib2] - """ - V_linear_1 = coef.mm(S_linear).mm(coef.t().conj()).real - V_linear_2 = Q_linear.mm(coef.t().conj()).real - V_linear_3 = coef.mm(Q_linear.t().conj()).real - if V_info["same_band"]: - V_linear_1 = V_linear_1.diag() - V_linear_2 = V_linear_2.diag() - V_linear_3 = V_linear_3.diag() - if V_info["same_band"]: Z = V.diag().sqrt() - else: Z = V.sqrt() - Z = util.update0(Z) - V_linear = (-V_linear_1/Z + V_linear_2 + V_linear_3) / Z - return V_linear - - - def cal_T(self,C,E): - """ T = 0.5* sum_{it,il,iu} sum_{ie} ( E[it][il,ie] * C[it][il][ie,iu] )**2 """ - T = torch.zeros(1) - num = 0 - for it,C_t in C.items(): - for il,C_tl in enumerate(C_t): - for iu in range(C_tl.size()[1]): - T_tlu = torch.zeros(1) - Z_tlu = 0 - for ie in range(C_tl.size()[0]): - T_tlu = T_tlu + ( E[it][il,ie] * C_tl[ie,iu] )**2 - Z_tlu = Z_tlu + E[it][il,ie].item()**2 - T = T + T_tlu/Z_tlu - num += C_tl.size()[1] - T = 0.5 * T / num - return T \ No newline at end of file + def cal_T(self, C, E): + """T = 0.5* sum_{it,il,iu} sum_{ie} ( E[it][il,ie] * C[it][il][ie,iu] )**2""" + T = torch.zeros(1) + num = 0 + for it, C_t in C.items(): + for il, C_tl in enumerate(C_t): + for iu in range(C_tl.size()[1]): + T_tlu = torch.zeros(1) + Z_tlu = 0 + for ie in range(C_tl.size()[0]): + T_tlu = T_tlu + (E[it][il, ie] * C_tl[ie, iu]) ** 2 + Z_tlu = Z_tlu + E[it][il, ie].item() ** 2 + T = T + T_tlu / Z_tlu + num += C_tl.size()[1] + T = 0.5 * T / num + return T diff --git a/tools/opt_orb_pytorch_dpsi/orbital.py b/tools/opt_orb_pytorch_dpsi/orbital.py index 7600e778710..f881fd64346 100644 --- a/tools/opt_orb_pytorch_dpsi/orbital.py +++ b/tools/opt_orb_pytorch_dpsi/orbital.py @@ -6,75 +6,94 @@ import functools import torch -def generate_orbital(info_element,C,E): - """ C[it][il][ie,iu] """ - """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ - orb = dict() - for it in info_element: - Nr = int(info_element[it].Rcut/info_element[it].dr)+1 - orb[it] = ND_list(info_element[it].Nl) - for il in range(info_element[it].Nl): - orb[it][il] = ND_list(info_element[it].Nu[il]) - for iu in range(info_element[it].Nu[il]): - orb[it][il][iu] = np.zeros(Nr) - for ir in range(Nr): - r = ir * info_element[it].dr - for ie in range(info_element[it].Ne): - orb[it][il][iu][ir] += C[it][il][ie,iu].item() * spherical_jn(il,E[it][il,ie].item()*r) - return orb - - -def smooth_orbital(orb,Rcut,dr,smearing_sigma): - for it,orb_t in orb.items(): - for orb_tl in orb_t: - for orb_tlu in orb_tl: - for ir in range(orb_tlu.shape[0]): - assert orb_tlu.shape[0] == int(Rcut[it]/dr[it])+1 - r = ir * dr[it] - orb_tlu[ir] *= 1-np.exp( -(r-Rcut[it])**2/(2*smearing_sigma**2) ) - - - -def inner_product( orb1, orb2, dr ): - assert orb1.shape == orb2.shape - r = np.array(range(orb1.shape[0]))*dr - return simps( orb1 * orb2 * r * r, dx=dr ) - -def normalize(orb,dr,C=None,flag_norm_orb=False,flag_norm_C=False): - """ C[it][il][ie,iu] """ - """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ - for it,orb_t in orb.items(): - for il,orb_tl in enumerate(orb_t): - for iu,orb_tlu in enumerate(orb_tl): - norm = np.sqrt(inner_product(orb_tlu,orb_tlu,dr[it])) - if flag_norm_orb: orb_tlu[:] = orb_tlu / norm - if flag_norm_C: C[it][il].data[:,iu] = C[it][il].data[:,iu] / norm - -def orth(orb,dr): - """ |n'> = 1/Z ( |n> - \sum_{i=0}^{n-1} |i> ) """ - """ orb[it][il][iu,r] """ - for it,orb_t in orb.items(): - for il,orb_tl in enumerate(orb_t): - for iu1,orb_tlu1 in enumerate(orb_tl): - for iu2 in range(iu1): - orb_tlu1[:] -= orb_tl[iu2] * inner_product(orb_tlu1,orb_tl[iu2],dr[it]) - orb_tlu1[:] = orb_tlu1 / np.sqrt(inner_product(orb_tlu1,orb_tlu1,dr[it])) - -def find_eigenvalue(Nl,Ne): - """ E[il,ie] """ - E = np.zeros((Nl,Ne+Nl+1)) - for ie in range(1,Ne+Nl+1): - E[0,ie] = ie*np.pi - for il in range(1,Nl): - jl = functools.partial(spherical_jn,il) - for ie in range(1,Ne+Nl+1-il): - E[il,ie] = fsolve( jl, (E[il-1,ie]+E[il-1,ie+1])/2 ) - return E[:,1:Ne+1] - + +def generate_orbital(info_element, C, E): + """C[it][il][ie,iu]""" + """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ + orb = dict() + for it in info_element: + Nr = int(info_element[it].Rcut / info_element[it].dr) + 1 + orb[it] = ND_list(info_element[it].Nl) + for il in range(info_element[it].Nl): + orb[it][il] = ND_list(info_element[it].Nu[il]) + for iu in range(info_element[it].Nu[il]): + orb[it][il][iu] = np.zeros(Nr) + for ir in range(Nr): + r = ir * info_element[it].dr + for ie in range(info_element[it].Ne): + orb[it][il][iu][ir] += C[it][il][ie, iu].item() * spherical_jn( + il, E[it][il, ie].item() * r + ) + return orb + + +def smooth_orbital(orb, Rcut, dr, smearing_sigma): + for it, orb_t in orb.items(): + for orb_tl in orb_t: + for orb_tlu in orb_tl: + for ir in range(orb_tlu.shape[0]): + assert orb_tlu.shape[0] == int(Rcut[it] / dr[it]) + 1 + r = ir * dr[it] + orb_tlu[ir] *= 1 - np.exp( + -((r - Rcut[it]) ** 2) / (2 * smearing_sigma**2) + ) + + +def inner_product(orb1, orb2, dr): + assert orb1.shape == orb2.shape + r = np.array(range(orb1.shape[0])) * dr + return simps(orb1 * orb2 * r * r, dx=dr) + + +def normalize(orb, dr, C=None, flag_norm_orb=False, flag_norm_C=False): + """C[it][il][ie,iu]""" + """ orb[it][il][iu][r] = \suml_{ie} C[it][il][ie,iu] * jn(il,ie*r) """ + for it, orb_t in orb.items(): + for il, orb_tl in enumerate(orb_t): + for iu, orb_tlu in enumerate(orb_tl): + norm = np.sqrt(inner_product(orb_tlu, orb_tlu, dr[it])) + if flag_norm_orb: + orb_tlu[:] = orb_tlu / norm + if flag_norm_C: + C[it][il].data[:, iu] = C[it][il].data[:, iu] / norm + + +def orth(orb, dr): + """|n'> = 1/Z ( |n> - \sum_{i=0}^{n-1} |i> )""" + """ orb[it][il][iu,r] """ + for it, orb_t in orb.items(): + for il, orb_tl in enumerate(orb_t): + for iu1, orb_tlu1 in enumerate(orb_tl): + for iu2 in range(iu1): + orb_tlu1[:] -= orb_tl[iu2] * inner_product( + orb_tlu1, orb_tl[iu2], dr[it] + ) + orb_tlu1[:] = orb_tlu1 / np.sqrt( + inner_product(orb_tlu1, orb_tlu1, dr[it]) + ) + + +def find_eigenvalue(Nl, Ne): + """E[il,ie]""" + E = np.zeros((Nl, Ne + Nl + 1)) + for ie in range(1, Ne + Nl + 1): + E[0, ie] = ie * np.pi + for il in range(1, Nl): + jl = functools.partial(spherical_jn, il) + for ie in range(1, Ne + Nl + 1 - il): + E[il, ie] = fsolve(jl, (E[il - 1, ie] + E[il - 1, ie + 1]) / 2) + return E[:, 1 : Ne + 1] + + def set_E(info_element): - """ E[it][il,ie] """ - eigenvalue = { it:find_eigenvalue(info_element[it].Nl,info_element[it].Ne) for it in info_element } - E = dict() - for it in info_element: - E[it] = torch.from_numpy(( eigenvalue[it]/info_element[it].Rcut ).astype("float64")) - return E \ No newline at end of file + """E[it][il,ie]""" + eigenvalue = { + it: find_eigenvalue(info_element[it].Nl, info_element[it].Ne) + for it in info_element + } + E = dict() + for it in info_element: + E[it] = torch.from_numpy( + (eigenvalue[it] / info_element[it].Rcut).astype("float64") + ) + return E diff --git a/tools/opt_orb_pytorch_dpsi/torch_complex_bak.py b/tools/opt_orb_pytorch_dpsi/torch_complex_bak.py index f08be745a3a..7398016f41e 100644 --- a/tools/opt_orb_pytorch_dpsi/torch_complex_bak.py +++ b/tools/opt_orb_pytorch_dpsi/torch_complex_bak.py @@ -1,84 +1,133 @@ -import torch - -class ComplexTensor: - def __init__(self,real,imag): - self.real = real - self.imag = imag - - def view(self,*args,**kwargs): - return ComplexTensor( self.real.view(*args,**kwargs), self.imag.view(*args,**kwargs) ) - def t(self,*args,**kwargs): - return ComplexTensor( self.real.t(*args,**kwargs), self.imag.t(*args,**kwargs) ) -# def transpose(self,*args,**kwargs): -# return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) - def __getitem__(self,*args,**kwargs): - return ComplexTensor( self.real.__getitem__(*args,**kwargs), self.imag.__getitem__(*args,**kwargs) ) - def __str__(self): - return "<{0};{1}>".format(self.real, self.imag) - __repr__=__str__ -# def size(self,*args,**kwargs): -# return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) - - def conj(self): - return ComplexTensor( self.real, -self.imag ) - - def mm( self,x2, *args,**kwargs ): - return mm( self,x2, *args,**kwargs ) - - -def dot( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1.real,x2.real, *args,**kwargs ) - torch.dot( x1.imag,x2.imag, *args,**kwargs ), torch.dot( x1.real,x2.imag, *args,**kwargs ) + torch.dot( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.dot( x1.real,x2, *args,**kwargs ), torch.dot( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1,x2.real, *args,**kwargs ), torch.dot( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.dot( x1,x2, *args,**kwargs ) -def mv( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1.real,x2.real, *args,**kwargs ) - torch.mv( x1.imag,x2.imag, *args,**kwargs ), torch.mv( x1.real,x2.imag, *args,**kwargs ) + torch.mv( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mv( x1.real,x2, *args,**kwargs ), torch.mv( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1,x2.real, *args,**kwargs ), torch.mv( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mv( x1,x2, *args,**kwargs ) -def mm( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1.real,x2.real, *args,**kwargs ) - torch.mm( x1.imag,x2.imag, *args,**kwargs ), torch.mm( x1.real,x2.imag, *args,**kwargs ) + torch.mm( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mm( x1.real,x2, *args,**kwargs ), torch.mm( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1,x2.real, *args,**kwargs ), torch.mm( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mm( x1,x2, *args,**kwargs ) - - -def cat( xs, *args,**kwargs ): - if isinstance(xs[0],ComplexTensor): - xs_real = []; xs_imag = [] - for x in xs: - xs_real.append(x.real) - xs_imag.append(x.imag) - return ComplexTensor( torch.cat(xs_real,*args,**kwargs), torch.cat(xs_imag,*args,**kwargs) ) - else: - return torch.cat(xs,*args,**kwargs) - - - -def inverse(M): - if isinstance(M,ComplexTensor): - A=M.real - B=M.imag - tmp_AB = torch.mm(A.inverse(),B) # A^{-1} B - tmp_X = (A+torch.mm(B,tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} - return ComplexTensor( tmp_X, -torch.mm(tmp_AB,tmp_X) ) - else: - return M.inverse() \ No newline at end of file +import torch + + +class ComplexTensor: + def __init__(self, real, imag): + self.real = real + self.imag = imag + + def view(self, *args, **kwargs): + return ComplexTensor( + self.real.view(*args, **kwargs), self.imag.view(*args, **kwargs) + ) + + def t(self, *args, **kwargs): + return ComplexTensor(self.real.t(*args, **kwargs), self.imag.t(*args, **kwargs)) + + # def transpose(self,*args,**kwargs): + # return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) + def __getitem__(self, *args, **kwargs): + return ComplexTensor( + self.real.__getitem__(*args, **kwargs), + self.imag.__getitem__(*args, **kwargs), + ) + + def __str__(self): + return "<{0};{1}>".format(self.real, self.imag) + + __repr__ = __str__ + # def size(self,*args,**kwargs): + # return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) + + def conj(self): + return ComplexTensor(self.real, -self.imag) + + def mm(self, x2, *args, **kwargs): + return mm(self, x2, *args, **kwargs) + + +def dot(x1, x2, *args, **kwargs): + if isinstance(x1, ComplexTensor): + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.dot(x1.real, x2.real, *args, **kwargs) + - torch.dot(x1.imag, x2.imag, *args, **kwargs), + torch.dot(x1.real, x2.imag, *args, **kwargs) + + torch.dot(x1.imag, x2.real, *args, **kwargs), + ) + else: + return ComplexTensor( + torch.dot(x1.real, x2, *args, **kwargs), + torch.dot(x1.imag, x2, *args, **kwargs), + ) + else: + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.dot(x1, x2.real, *args, **kwargs), + torch.dot(x1, x2.imag, *args, **kwargs), + ) + else: + return torch.dot(x1, x2, *args, **kwargs) + + +def mv(x1, x2, *args, **kwargs): + if isinstance(x1, ComplexTensor): + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mv(x1.real, x2.real, *args, **kwargs) + - torch.mv(x1.imag, x2.imag, *args, **kwargs), + torch.mv(x1.real, x2.imag, *args, **kwargs) + + torch.mv(x1.imag, x2.real, *args, **kwargs), + ) + else: + return ComplexTensor( + torch.mv(x1.real, x2, *args, **kwargs), + torch.mv(x1.imag, x2, *args, **kwargs), + ) + else: + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mv(x1, x2.real, *args, **kwargs), + torch.mv(x1, x2.imag, *args, **kwargs), + ) + else: + return torch.mv(x1, x2, *args, **kwargs) + + +def mm(x1, x2, *args, **kwargs): + if isinstance(x1, ComplexTensor): + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mm(x1.real, x2.real, *args, **kwargs) + - torch.mm(x1.imag, x2.imag, *args, **kwargs), + torch.mm(x1.real, x2.imag, *args, **kwargs) + + torch.mm(x1.imag, x2.real, *args, **kwargs), + ) + else: + return ComplexTensor( + torch.mm(x1.real, x2, *args, **kwargs), + torch.mm(x1.imag, x2, *args, **kwargs), + ) + else: + if isinstance(x2, ComplexTensor): + return ComplexTensor( + torch.mm(x1, x2.real, *args, **kwargs), + torch.mm(x1, x2.imag, *args, **kwargs), + ) + else: + return torch.mm(x1, x2, *args, **kwargs) + + +def cat(xs, *args, **kwargs): + if isinstance(xs[0], ComplexTensor): + xs_real = [] + xs_imag = [] + for x in xs: + xs_real.append(x.real) + xs_imag.append(x.imag) + return ComplexTensor( + torch.cat(xs_real, *args, **kwargs), torch.cat(xs_imag, *args, **kwargs) + ) + else: + return torch.cat(xs, *args, **kwargs) + + +def inverse(M): + if isinstance(M, ComplexTensor): + A = M.real + B = M.imag + tmp_AB = torch.mm(A.inverse(), B) # A^{-1} B + tmp_X = (A + torch.mm(B, tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} + return ComplexTensor(tmp_X, -torch.mm(tmp_AB, tmp_X)) + else: + return M.inverse() diff --git a/tools/opt_orb_pytorch_dpsi/util.py b/tools/opt_orb_pytorch_dpsi/util.py index 9b64a8e412c..340c4f7c2ec 100644 --- a/tools/opt_orb_pytorch_dpsi/util.py +++ b/tools/opt_orb_pytorch_dpsi/util.py @@ -1,42 +1,52 @@ -def ND_list(*sizes,element=None): - size_1,*size_other = sizes - l = [element] * size_1 - if size_other: - for i in range(len(l)): - l[i] = ND_list(*size_other,element=element) - else: - if element in ["dict()","list()"]: - for i in range(size_1): - l[i] = eval(element) - return l - - -def ignore_line(file,N): - for _ in range(N): - file.readline() - - +def ND_list(*sizes, element=None): + size_1, *size_other = sizes + l = [element] * size_1 + if size_other: + for i in range(len(l)): + l[i] = ND_list(*size_other, element=element) + else: + if element in ["dict()", "list()"]: + for i in range(size_1): + l[i] = eval(element) + return l + + +def ignore_line(file, N): + for _ in range(N): + file.readline() + + class Info: - def Nm(self,il): return 2*il+1 - def __str__(self): - return "\n".join([name+"\t"+str(value) for name,value in self.__dict__.items()]) - __repr__=__str__ - + def Nm(self, il): + return 2 * il + 1 + + def __str__(self): + return "\n".join( + [name + "\t" + str(value) for name, value in self.__dict__.items()] + ) + + __repr__ = __str__ + + def change_to_cuda(s): - if isinstance(s,list): - return [change_to_cuda(x) for x in s] - elif isinstance(s,dict): - return {i:change_to_cuda(x) for i,x in s.items()} - elif isinstance(s,torch.Tensor): - return s.cuda() - elif isinstance(s,torch_complex.ComplexTensor): - return torch_complex.ComplexTensor( change_to_cuda(s.real), change_to_cuda(s.imag) ) - else: - print(s) - raise TypeError("change_to_cuda") + if isinstance(s, list): + return [change_to_cuda(x) for x in s] + elif isinstance(s, dict): + return {i: change_to_cuda(x) for i, x in s.items()} + elif isinstance(s, torch.Tensor): + return s.cuda() + elif isinstance(s, torch_complex.ComplexTensor): + return torch_complex.ComplexTensor( + change_to_cuda(s.real), change_to_cuda(s.imag) + ) + else: + print(s) + raise TypeError("change_to_cuda") + def update0(t): - return t.masked_fill(mask=(t==0), value=1E-10) + return t.masked_fill(mask=(t == 0), value=1e-10) + def Nm(il): - return 2*il+1 \ No newline at end of file + return 2 * il + 1 diff --git a/tools/plot-tools/README.md b/tools/plot-tools/README.md index aac183260b1..8e6c36a32a0 100644 --- a/tools/plot-tools/README.md +++ b/tools/plot-tools/README.md @@ -7,16 +7,16 @@ # Plotting tool for ABACUS -- Band Structure and Fat Bands -- DOS and PDOS -- Dipole and Absorption +- Band Structure and Fat Bands +- DOS and PDOS +- Dipole and Absorption ## Requirements -- [NumPy](https://numpy.org/) -- [Matplotlib](https://matplotlib.org/) -- [lxml](https://lxml.de/) -- [setuptools](https://setuptools.pypa.io/en/latest/index.html) +- [NumPy](https://numpy.org/) +- [Matplotlib](https://matplotlib.org/) +- [lxml](https://lxml.de/) +- [setuptools](https://setuptools.pypa.io/en/latest/index.html) ## Installation @@ -30,8 +30,12 @@ python setup.py install There are two ways to use this tool: -1. Specify parameters in `band.py` (`dos.py`, `dipole.py`) directly, and then `python **.py`. And you can also import module in your own script e.g. `from abacus_plot.band import Band`. (Recommend) -2. Command-line tools are also supported in this tool. In this way, you need prepare an input file and execute some commands (see below). You can use `abacus-plot -h` to check command-line information +1. Specify parameters in `band.py` (`dos.py`, `dipole.py`) directly, and then `python **.py`. And + you can also import module in your own script e.g. `from abacus_plot.band import Band`. + (Recommend) +1. Command-line tools are also supported in this tool. In this way, you need prepare an input file + and execute some commands (see below). You can use `abacus-plot -h` to check command-line + information ### Band Structure @@ -46,20 +50,21 @@ First, prepare a file named 'config.json' in json format: } ``` -| Property | Type | Note | -| :------------: | :-------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| _bandfile_ | `str` or `List[str]` | Bands data file output from ABACUS. 'BANDS*\*.dat' for band structure and 'PBANDS*\*' for projected band structure | -| _efermi_ | `float` or `List[float]` | Fermi level in eV | -| _energy_range_ | `list` | Range of energy in eV | -| _shift_ | `bool` | If set `'true'`, it will evaluate band gap (only for semiconductors and insulators). Default: `'false'` | -| _index_ | `List[int]` or `Dict[str, List[int]]` or `Dict[str, Dict[int, List[int]]]]` | Extract PBANDS of each atom from 'PBANDS\_\*' file e.g. [index_0, index_1...] or {index_0:[l_0, l_1, ...], ...}, [index_0:{l_0:[m_0, m_1, ...], ...}, ...] | -| _atom_index_ | `List[int]` or `Dict[str, List[int]]` or `Dict[str, Dict[int, List[int]]]]` | Extract PBANDS of each atom with same atom*index from 'PBANDS*\*' file e.g. [atom_index_0, atom_index_1...] or {atom_index_0:[l_0, l_1, ...], ...}, [atom_index_0:{l_0:[m_0, m_1, ...], ...}, ...] | -| _species_ | `List[str]` or `Dict[str, List[int]]` or `Dict[str, Dict[int, List[int]]]]` | Extract PBANDS of each atom with same species from 'PBANDS\_\*' file e.g. [elem_0, elem_1...] or {elem_0:[l_0, l_1, ...], ...}, [elem_0:{l_0:[m_0, m_1, ...], ...}, ...] | -| _kptfile_ | `str` | K-points file with `Line` mode in ABACUS format | -| _label_ | `str` or `List[str]` | Label of band structure | -| _color_ | `str` or `List[str]` | Color of band structure | - -If you want to plot band structure of `nspin=2` or compare two band structure on same k-path, you can set _bandfile_, _efermi_, _label_, _color_ in `list` type. +| Property | Type | Note | +| :------------: | :-------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| _bandfile_ | `str` or `List[str]` | Bands data file output from ABACUS. 'BANDS\*\*.dat' for band structure and 'PBANDS\*\*' for projected band structure | +| _efermi_ | `float` or `List[float]` | Fermi level in eV | +| _energy_range_ | `list` | Range of energy in eV | +| _shift_ | `bool` | If set `'true'`, it will evaluate band gap (only for semiconductors and insulators). Default: `'false'` | +| _index_ | `List[int]` or `Dict[str, List[int]]` or `Dict[str, Dict[int, List[int]]]]` | Extract PBANDS of each atom from 'PBANDS\_\*' file e.g. [index_0, index_1...] or {index_0:[l_0, l_1, ...], ...}, \[index_0:{l_0:[m_0, m_1, ...], ...}, ...\] | +| _atom_index_ | `List[int]` or `Dict[str, List[int]]` or `Dict[str, Dict[int, List[int]]]]` | Extract PBANDS of each atom with same atom*index from 'PBANDS*\*' file e.g. [atom_index_0, atom_index_1...] or {atom_index_0:[l_0, l_1, ...], ...}, \[atom_index_0:{l_0:[m_0, m_1, ...], ...}, ...\] | +| _species_ | `List[str]` or `Dict[str, List[int]]` or `Dict[str, Dict[int, List[int]]]]` | Extract PBANDS of each atom with same species from 'PBANDS\_\*' file e.g. [elem_0, elem_1...] or {elem_0:[l_0, l_1, ...], ...}, \[elem_0:{l_0:[m_0, m_1, ...], ...}, ...\] | +| _kptfile_ | `str` | K-points file with `Line` mode in ABACUS format | +| _label_ | `str` or `List[str]` | Label of band structure | +| _color_ | `str` or `List[str]` | Color of band structure | + +If you want to plot band structure of `nspin=2` or compare two band structure on same k-path, you +can set _bandfile_, _efermi_, _label_, _color_ in `list` type. The _kptfile_ should be as follows, and notes after `#` will be set as k-points label automatically. @@ -82,13 +87,15 @@ Then, use the following command to plot band structure: abacus-plot -b ``` -Then, the following command will plot projected band structure and figures output to directory `PBAND*_FIG` ($*=1$ for $nspin=1$, $*=2$ for $nspin=2$): +Then, the following command will plot projected band structure and figures output to directory +`PBAND*_FIG` ($*=1$ for $nspin=1$, $*=2$ for $nspin=2$): ```shell abacus-plot -d -p ``` -Then, the following command will output parsed partial DOS to directory `PBAND*_FILE` ($*=1$ for $nspin=1$, $*=2$ for $nspin=2$): +Then, the following command will output parsed partial DOS to directory `PBAND*_FILE` ($*=1$ for +$nspin=1$, $*=2$ for $nspin=2$): ```shell abacus-plot -d -o @@ -115,19 +122,21 @@ First, prepare a file named 'config.json' in json format: } ``` -If you only want to plot total DOS, you can modify `pdosfile` to `tdosfile` and do not set `species` and `pdosfig`. -| Property | Type | Note | -| :------------: | :-------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| _tdosfile_ | `str` | Total DOS data file output from ABACUS | -| _pdosfile_ | `str` | Partial DOS data file output from ABACUS in xml format | -| _efermi_ | `float` | Fermi level in eV | -| _energy_range_ | `list` | Range of energy in eV | -| _shift_ | `bool` | If set `'true'`, it will evaluate band gap. Default: `'false'` | -| _index_ | `List[int]` or `Dict[str, List[int]]` or `Dict[str, Dict[str, List[int]]]]` | Extract PDOS of each atom e.g. [index_0, index_1...] or {index*0:[l_0, l_1, ...], ...}, [index_0:{l_0:[m_0, m_1, ...], ...}, ...] | -| \_atom_index* | `List[int]` or `Dict[str, List[int]]` or `Dict[str, Dict[str, List[int]]]]` | Extract PDOS of each atom with same atom*index e.g. [atom_index_0, atom_index_1...] or {atom_index_0:[l_0, l_1, ...], ...}, [atom_index_0:{l_0:[m_0, m_1, ...], ...}, ...] | -| \_species* | `List[str]` or `Dict[str, List[int]]` or `Dict[str, Dict[str, List[int]]]]` | Extract PDOS of each atom with same species e.g. [elem_0, elem_1...] or {elem*0:[l_0, l_1, ...], ...}, [elem_0:{l_0:[m_0, m_1, ...], ...}, ...] | -| \_tdosfig* | `str` | Output picture of total DOS | -| _pdosfig_ | `str` | Output picture of partial DOS | +If you only want to plot total DOS, you can modify `pdosfile` to `tdosfile` and do not set `species` +and `pdosfig`. + +| Property | Type | Note | +| :------------: | :-------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| _tdosfile_ | `str` | Total DOS data file output from ABACUS | +| _pdosfile_ | `str` | Partial DOS data file output from ABACUS in xml format | +| _efermi_ | `float` | Fermi level in eV | +| _energy_range_ | `list` | Range of energy in eV | +| _shift_ | `bool` | If set `'true'`, it will evaluate band gap. Default: `'false'` | +| _index_ | `List[int]` or `Dict[str, List[int]]` or `Dict[str, Dict[str, List[int]]]]` | Extract PDOS of each atom e.g. [index_0, index_1...] or {index\*0:[l_0, l_1, ...], ...}, \[index_0:{l_0:[m_0, m_1, ...], ...}, ...\] | +| \_atom_index\* | `List[int]` or `Dict[str, List[int]]` or `Dict[str, Dict[str, List[int]]]]` | Extract PDOS of each atom with same atom\*index e.g. [atom_index_0, atom_index_1...] or {atom_index_0:[l_0, l_1, ...], ...}, \[atom_index_0:{l_0:[m_0, m_1, ...], ...}, ...\] | +| \_species\* | `List[str]` or `Dict[str, List[int]]` or `Dict[str, Dict[str, List[int]]]]` | Extract PDOS of each atom with same species e.g. [elem_0, elem_1...] or {elem\*0:[l_0, l_1, ...], ...}, \[elem_0:{l_0:[m_0, m_1, ...], ...}, ...\] | +| \_tdosfig\* | `str` | Output picture of total DOS | +| _pdosfig_ | `str` | Output picture of partial DOS | Then, the following command will plot total DOS: @@ -146,4 +155,3 @@ Then, the following command will output parsed partial DOS to directory `PDOS_FI ```shell abacus-plot -d -o ``` - diff --git a/tools/plot-tools/abacus_plot/__init__.py b/tools/plot-tools/abacus_plot/__init__.py index 853f351d6f8..4c2770d5f9b 100644 --- a/tools/plot-tools/abacus_plot/__init__.py +++ b/tools/plot-tools/abacus_plot/__init__.py @@ -1,6 +1,6 @@ -''' +""" Date: 2021-08-20 09:11:11 LastEditors: jiyuyang LastEditTime: 2021-08-20 09:11:11 Mail: jiyuyang@mail.ustc.edu.cn, 1041176461@qq.com -''' +""" diff --git a/tools/plot-tools/abacus_plot/band.py b/tools/plot-tools/abacus_plot/band.py index c886da0619f..f911db67df5 100644 --- a/tools/plot-tools/abacus_plot/band.py +++ b/tools/plot-tools/abacus_plot/band.py @@ -1,9 +1,9 @@ -''' +""" Date: 2021-12-29 10:27:01 LastEditors: jiyuyang LastEditTime: 2022-08-02 11:36:22 Mail: jiyuyang@mail.ustc.edu.cn, 1041176461@qq.com -''' +""" from collections import OrderedDict, namedtuple import numpy as np @@ -17,13 +17,27 @@ import matplotlib.pyplot as plt from pathlib import Path -from abacus_plot.utils import energy_minus_efermi, list_elem2str, read_kpt, remove_empty, parse_projected_data, handle_data, get_angular_momentum_name, get_angular_momentum_label +from abacus_plot.utils import ( + energy_minus_efermi, + list_elem2str, + read_kpt, + remove_empty, + parse_projected_data, + handle_data, + get_angular_momentum_name, + get_angular_momentum_label, +) class Band: """Parse Bands data""" - def __init__(self, bandfile: Union[PathLike, Sequence[PathLike]] = None, kptfile: PathLike = '', old_ver=False) -> None: + def __init__( + self, + bandfile: Union[PathLike, Sequence[PathLike]] = None, + kptfile: PathLike = "", + old_ver=False, + ) -> None: self.bandfile = bandfile self.old_ver = old_ver if isinstance(bandfile, list) or isinstance(bandfile, tuple): @@ -33,7 +47,8 @@ def __init__(self, bandfile: Union[PathLike, Sequence[PathLike]] = None, kptfile self.energy.append(e) else: self.k_index, self.energy, self.k_lines = self.read( - self.bandfile, self.old_ver) + self.bandfile, self.old_ver + ) self.kptfile = kptfile self.kpt = None if self.kptfile: @@ -54,16 +69,16 @@ def read(cls, filename: PathLike, old_ver=False): z = None if old_ver: data = np.loadtxt(filename, dtype=float) - X, y = np.split(data, (1, ), axis=1) + X, y = np.split(data, (1,), axis=1) x = X.flatten() else: data = np.loadtxt(filename, dtype=float) - #X, Z, y, _ = np.split(data, [1, 2, data.shape[-1]], axis=1) - #x = X.flatten() - #z = Z.flatten() - x = data[:, 0] # k-index - z = data[:, 1] # k-points - y = data[:, 2:] # band + # X, Z, y, _ = np.split(data, [1, 2, data.shape[-1]], axis=1) + # x = X.flatten() + # z = Z.flatten() + x = data[:, 0] # k-index + z = data[:, 1] # k-points + y = data[:, 2:] # band return x, y, z @@ -74,7 +89,7 @@ def direct_bandgap(cls, vb: namedtuple, cb: namedtuple, klength: int): gap_list = [] i_index = [] for i in range(klength): - gap_list.append(np.min(cb.band[:, i])-np.max(vb.band[:, i])) + gap_list.append(np.min(cb.band[:, i]) - np.max(vb.band[:, i])) i_index.append(i) dgap = np.min(gap_list) @@ -84,15 +99,16 @@ def direct_bandgap(cls, vb: namedtuple, cb: namedtuple, klength: int): def bandgap(cls, vb: namedtuple, cb: namedtuple): """Calculate band gap""" - gap = cb.value-vb.value + gap = cb.value - vb.value return gap @classmethod def band_type(cls, vb: namedtuple, cb: namedtuple): vbm_x, cbm_x = vb.k_index, cb.k_index - longone, shortone = (vbm_x, cbm_x) if len( - vbm_x) >= len(cbm_x) else (cbm_x, vbm_x) + longone, shortone = ( + (vbm_x, cbm_x) if len(vbm_x) >= len(cbm_x) else (cbm_x, vbm_x) + ) for i in shortone: if i in longone: btype = "Direct" @@ -113,9 +129,10 @@ def info(cls, kpath: Sequence, vb: namedtuple, cb: namedtuple): dgap, d_i = cls.direct_bandgap(vb, cb, len(kpath)) btype = cls.band_type(vb, cb) print( - "--------------------------Band Structure--------------------------", flush=True) - print( - f"{'Band character:'.ljust(30)}{btype}", flush=True) + "--------------------------Band Structure--------------------------", + flush=True, + ) + print(f"{'Band character:'.ljust(30)}{btype}", flush=True) if btype == "Indirect": print(f"{'Direct Band gap(eV):'.ljust(30)}{dgap: .4f}", flush=True) print(f"{'Indirect Band gap(eV):'.ljust(30)}{gap: .4f}", flush=True) @@ -123,18 +140,24 @@ def info(cls, kpath: Sequence, vb: namedtuple, cb: namedtuple): print(f"{'Band gap(eV):'.ljust(30)}{gap: .4f}", flush=True) print(f"{'Band index:'.ljust(30)}{'HOMO'.ljust(10)}{'LUMO'}", flush=True) print( - f"{''.ljust(30)}{str(vb.band_index[-1]).ljust(10)}{str(cb.band_index[0])}", flush=True) + f"{''.ljust(30)}{str(vb.band_index[-1]).ljust(10)}{str(cb.band_index[0])}", + flush=True, + ) print(f"{'Eigenvalue of VBM(eV):'.ljust(30)}{vb.value: .4f}", flush=True) print(f"{'Eigenvalue of CBM(eV):'.ljust(30)}{cb.value: .4f}", flush=True) vbm_k = np.unique(kpath[vb.k_index], axis=0) cbm_k = np.unique(kpath[cb.k_index], axis=0) print( - f"{'Location of VBM'.ljust(30)}{' '.join(list_elem2str(vbm_k[0]))}", flush=True) + f"{'Location of VBM'.ljust(30)}{' '.join(list_elem2str(vbm_k[0]))}", + flush=True, + ) for i, j in enumerate(vbm_k): if i != 0: print(f"{''.ljust(30)}{' '.join(list_elem2str(j))}", flush=True) print( - f"{'Location of CBM'.ljust(30)}{' '.join(list_elem2str(cbm_k[0]))}", flush=True) + f"{'Location of CBM'.ljust(30)}{' '.join(list_elem2str(cbm_k[0]))}", + flush=True, + ) for i, j in enumerate(cbm_k): if i != 0: print(f"{''.ljust(30)}{' '.join(list_elem2str(j))}", flush=True) @@ -149,7 +172,7 @@ def set_vcband(cls, energy: Sequence) -> Tuple[namedtuple, namedtuple]: e_T = energy.T num_gt_Ef = (e_T > 0).sum(axis=1) - Band = namedtuple('Band', ['band_index', 'band', 'value', 'k_index']) + Band = namedtuple("Band", ["band_index", "band", "value", "k_index"]) # valance band band_vbm_index = np.where(num_gt_Ef == 0)[0] @@ -179,15 +202,17 @@ def _shift_energy(self, energy, efermi: float = 0, shift: bool = False): return refine_E @classmethod - def plot_data(cls, - fig: Figure, - ax: axes.Axes, - x: Sequence, - y: Sequence, - kzip: Sequence, - efermi: float = 0, - energy_range: Sequence[float] = [], - **kwargs): + def plot_data( + cls, + fig: Figure, + ax: axes.Axes, + x: Sequence, + y: Sequence, + kzip: Sequence, + efermi: float = 0, + energy_range: Sequence[float] = [], + **kwargs, + ): """Plot band structure :params x, y: x-axis and y-axis coordinates @@ -198,22 +223,30 @@ def plot_data(cls, bandplot = BandPlot(fig, ax, **kwargs) if not bandplot._color: - bandplot._color = 'black' + bandplot._color = "black" kpoints, energy = x, y energy = energy_minus_efermi(energy, efermi) - bandplot.ax.plot(kpoints, energy, lw=bandplot._lw, color=bandplot._color, - label=bandplot._label, linestyle=bandplot._linestyle) + bandplot.ax.plot( + kpoints, + energy, + lw=bandplot._lw, + color=bandplot._color, + label=bandplot._label, + linestyle=bandplot._linestyle, + ) bandplot._set_figure(kzip, energy_range) - def plot(self, - fig: Figure, - ax: axes.Axes, - efermi: Union[float, Sequence[float]] = [], - energy_range: Sequence[float] = [], - shift: bool = True, - **kwargs): + def plot( + self, + fig: Figure, + ax: axes.Axes, + efermi: Union[float, Sequence[float]] = [], + energy_range: Sequence[float] = [], + shift: bool = True, + **kwargs, + ): """Plot more than two band structures using data file :params efermi: Fermi levels in unit eV, its length equals to `filename` @@ -227,25 +260,37 @@ def plot(self, nums = len(self.bandfile) if not efermi: efermi = [0.0 for i in range(nums)] - if not kwargs.pop('label', None): - bandplot._label = ['' for i in range(nums)] - if not kwargs.pop('color', None): - bandplot._color = ['black' for i in range(nums)] - if not kwargs.pop('linestyle', None): - bandplot._linestyle = ['solid' for i in range(nums)] + if not kwargs.pop("label", None): + bandplot._label = ["" for i in range(nums)] + if not kwargs.pop("color", None): + bandplot._color = ["black" for i in range(nums)] + if not kwargs.pop("linestyle", None): + bandplot._linestyle = ["solid" for i in range(nums)] for i, band in enumerate(self.energy): band = self._shift_energy(band, efermi[i], shift) - bandplot.ax.plot(self.k_index, band, - lw=bandplot._lw, color=bandplot._color[i], label=bandplot._label[i], linestyle=bandplot._linestyle[i]) + bandplot.ax.plot( + self.k_index, + band, + lw=bandplot._lw, + color=bandplot._color[i], + label=bandplot._label[i], + linestyle=bandplot._linestyle[i], + ) else: if not efermi: efermi = 0.0 band = self._shift_energy(self.energy, efermi, shift) - bandplot.ax.plot(self.k_index, band, - lw=bandplot._lw, color=bandplot._color, label=bandplot._label, linestyle=bandplot._linestyle) + bandplot.ax.plot( + self.k_index, + band, + lw=bandplot._lw, + color=bandplot._color, + label=bandplot._label, + linestyle=bandplot._linestyle, + ) bandplot._set_figure(self._kzip, energy_range) @@ -255,15 +300,17 @@ def plot(self, class BandPlot: """Plot band structure""" - def __init__(self, fig: Figure, ax: axes.Axes, point_to_line=False, **kwargs) -> None: + def __init__( + self, fig: Figure, ax: axes.Axes, point_to_line=False, **kwargs + ) -> None: self.fig = fig self.ax = ax self._point_to_line = point_to_line - self._lw = kwargs.pop('lw', 2) - self._bwidth = kwargs.pop('bwdith', 3) - self._label = kwargs.pop('label', None) - self._color = kwargs.pop('color', 'black') - self._linestyle = kwargs.pop('linestyle', 'solid') + self._lw = kwargs.pop("lw", 2) + self._bwidth = kwargs.pop("bwdith", 3) + self._label = kwargs.pop("label", None) + self._color = kwargs.pop("color", "black") + self._linestyle = kwargs.pop("linestyle", "solid") self.plot_params = kwargs def _set_figure(self, kzip, range: Sequence): @@ -280,7 +327,7 @@ def _set_figure(self, kzip, range: Sequence): keys.append(t[0]) values.append(t[1]) else: - keys.append('') + keys.append("") values.append(int(t)) # x-axis @@ -288,8 +335,7 @@ def _set_figure(self, kzip, range: Sequence): self.ax.set_xticklabels(keys) self.ax.set_xlim(values[0], values[-1]) if "xlabel_params" in self.plot_params.keys(): - self.ax.set_xlabel( - "Wave Vector", **self.plot_params["xlabel_params"]) + self.ax.set_xlabel("Wave Vector", **self.plot_params["xlabel_params"]) else: self.ax.set_xlabel("Wave Vector", size=25) @@ -297,17 +343,27 @@ def _set_figure(self, kzip, range: Sequence): if range: self.ax.set_ylim(range[0], range[1]) if "ylabel_params" in self.plot_params.keys(): - self.ax.set_ylabel( - "Energy(eV)", **self.plot_params["ylabel_params"]) + self.ax.set_ylabel("Energy(eV)", **self.plot_params["ylabel_params"]) else: self.ax.set_ylabel("Energy(eV)", size=25) # notes if "notes" in self.plot_params.keys(): from matplotlib.offsetbox import AnchoredText - if "s" in self.plot_params["notes"].keys() and len(self.plot_params["notes"].keys()) == 1: - self.ax.add_artist(AnchoredText(self.plot_params["notes"]["s"], loc='upper left', prop=dict(size=25), - borderpad=0.2, frameon=False)) + + if ( + "s" in self.plot_params["notes"].keys() + and len(self.plot_params["notes"].keys()) == 1 + ): + self.ax.add_artist( + AnchoredText( + self.plot_params["notes"]["s"], + loc="upper left", + prop=dict(size=25), + borderpad=0.2, + frameon=False, + ) + ) else: self.ax.add_artist(AnchoredText(**self.plot_params["notes"])) @@ -319,41 +375,42 @@ def _set_figure(self, kzip, range: Sequence): # frame bwidth = self._bwidth - self.ax.spines['top'].set_linewidth(bwidth) - self.ax.spines['right'].set_linewidth(bwidth) - self.ax.spines['left'].set_linewidth(bwidth) - self.ax.spines['bottom'].set_linewidth(bwidth) + self.ax.spines["top"].set_linewidth(bwidth) + self.ax.spines["right"].set_linewidth(bwidth) + self.ax.spines["left"].set_linewidth(bwidth) + self.ax.spines["bottom"].set_linewidth(bwidth) # guides - if '' not in keys: + if "" not in keys: if "grid_params" in self.plot_params.keys(): - self.ax.grid(axis='x', **self.plot_params["grid_params"]) + self.ax.grid(axis="x", **self.plot_params["grid_params"]) else: - self.ax.grid(axis='x', lw=1.2) + self.ax.grid(axis="x", lw=1.2) if "hline_params" in self.plot_params.keys(): self.ax.axhline(0, **self.plot_params["hline_params"]) else: - self.ax.axhline(0, linestyle="--", c='b', lw=1.0) + self.ax.axhline(0, linestyle="--", c="b", lw=1.0) if self._label: handles, labels = self.ax.get_legend_handles_labels() by_label = OrderedDict(zip(labels, handles)) if "legend_prop" in self.plot_params.keys(): - self.ax.legend(by_label.values(), by_label.keys(), - prop=self.plot_params["legend_prop"]) + self.ax.legend( + by_label.values(), + by_label.keys(), + prop=self.plot_params["legend_prop"], + ) else: - self.ax.legend(by_label.values(), - by_label.keys(), prop={'size': 15}) + self.ax.legend(by_label.values(), by_label.keys(), prop={"size": 15}) if self._point_to_line: handles = [] for c, l in zip(self._color, self._label): handles.append(Line2D([0], [0], color=c, label=l)) if "legend_prop" in self.plot_params.keys(): - self.ax.legend(handles=handles, - prop=self.plot_params["legend_prop"]) + self.ax.legend(handles=handles, prop=self.plot_params["legend_prop"]) else: - self.ax.legend(handles=handles, prop={'size': 15}) + self.ax.legend(handles=handles, prop={"size": 15}) def _color_to_alpha_cmap(self, color): cmap = LinearSegmentedColormap.from_list("chaos", ["white", color]) @@ -364,20 +421,38 @@ def _color_to_alpha_cmap(self, color): class PBand(Band): - def __init__(self, bandfile: Union[PathLike, Sequence[PathLike]] = None, kptfile: str = '') -> None: + def __init__( + self, bandfile: Union[PathLike, Sequence[PathLike]] = None, kptfile: str = "" + ) -> None: self.bandfile = bandfile if isinstance(bandfile, list) or isinstance(bandfile, tuple): self.energy = [] self.orbitals = [] for file in self.bandfile: - self.nspin, self.norbitals, self.eunit, self.nbands, self.nkpoints, self.k_index, e, orb = self.read( - file) + ( + self.nspin, + self.norbitals, + self.eunit, + self.nbands, + self.nkpoints, + self.k_index, + e, + orb, + ) = self.read(file) self._check_energy(e) self.energy.append(e) self.orbitals.append(orb) else: - self.nspin, self.norbitals, self.eunit, self.nbands, self.nkpoints, self.k_index, self.energy, self.orbitals = self.read( - self.bandfile) + ( + self.nspin, + self.norbitals, + self.eunit, + self.nbands, + self.nkpoints, + self.k_index, + self.energy, + self.orbitals, + ) = self.read(self.bandfile) self._check_energy(self.energy) self.energy = np.asarray(self.energy) self.kptfile = kptfile @@ -393,22 +468,33 @@ def __init__(self, bandfile: Union[PathLike, Sequence[PathLike]] = None, kptfile self._check_weights(self.weights) def _check_energy(self, energy): - assert energy.shape[0] == self.nkpoints, "The dimension of band structure dismatches with the number of k-points." - assert energy.shape[1] == self.nbands, "The dimension of band structure dismatches with the number of bands." + assert ( + energy.shape[0] == self.nkpoints + ), "The dimension of band structure dismatches with the number of k-points." + assert ( + energy.shape[1] == self.nbands + ), "The dimension of band structure dismatches with the number of bands." def _check_weights(self, weights: np.ndarray, prec=1e-5): - assert weights.shape[0] == self.norbitals, "The dimension of weights dismatches with the number of orbitals." - assert weights.shape[1] == self.nkpoints, "The dimension of weights dismatches with the number of k-points." - assert weights.shape[2] == self.nbands, "The dimension of weights dismatches with the number of bands." + assert ( + weights.shape[0] == self.norbitals + ), "The dimension of weights dismatches with the number of orbitals." + assert ( + weights.shape[1] == self.nkpoints + ), "The dimension of weights dismatches with the number of k-points." + assert ( + weights.shape[2] == self.nbands + ), "The dimension of weights dismatches with the number of bands." one_mat = np.ones((self.nkpoints, self.nbands)) - assert (np.abs(weights.sum(axis=0)-one_mat) < prec).all( - ), f"np.abs(weights.sum(axis=0)-np.ones(({self.nkpoints}, {self.nbands}))) < {prec}" + assert ( + np.abs(weights.sum(axis=0) - one_mat) < prec + ).all(), f"np.abs(weights.sum(axis=0)-np.ones(({self.nkpoints}, {self.nbands}))) < {prec}" @property def weights(self): data = np.empty((self.norbitals, self.nkpoints, self.nbands)) for i, orb in enumerate(self.orbitals): - data[i] = orb['data'] + data[i] = orb["data"] return data @classmethod @@ -419,18 +505,16 @@ def read(cls, filename: PathLike): """ from lxml import etree + pbanddata = etree.parse(filename) root = pbanddata.getroot() - nspin = int(root.xpath('//nspin')[0].text.replace(' ', '')) - norbitals = int(root.xpath('//norbitals') - [0].text.replace(' ', '')) - eunit = root.xpath('//band_structure/@units')[0].replace(' ', '') - nbands = int(root.xpath('//band_structure/@nbands') - [0].replace(' ', '')) - nkpoints = int(root.xpath('//band_structure/@nkpoints') - [0].replace(' ', '')) + nspin = int(root.xpath("//nspin")[0].text.replace(" ", "")) + norbitals = int(root.xpath("//norbitals")[0].text.replace(" ", "")) + eunit = root.xpath("//band_structure/@units")[0].replace(" ", "") + nbands = int(root.xpath("//band_structure/@nbands")[0].replace(" ", "")) + nkpoints = int(root.xpath("//band_structure/@nkpoints")[0].replace(" ", "")) k_index = np.arange(nkpoints) - energy = root.xpath('//band_structure')[0].text.split('\n') + energy = root.xpath("//band_structure")[0].text.split("\n") energy = handle_data(energy) remove_empty(energy) energy = np.asarray(energy, dtype=float) @@ -438,25 +522,31 @@ def read(cls, filename: PathLike): orbitals = [] for i in range(norbitals): orb = OrderedDict() - o_index_str = root.xpath( - '//orbital/@index')[i] - orb['index'] = int(o_index_str.replace(' ', '')) - orb['atom_index'] = int(root.xpath( - '//orbital/@atom_index')[i].replace(' ', '')) - orb['species'] = root.xpath( - '//orbital/@species')[i].replace(' ', '') - orb['l'] = int(root.xpath('//orbital/@l')[i].replace(' ', '')) - orb['m'] = int(root.xpath('//orbital/@m')[i].replace(' ', '')) - orb['z'] = int(root.xpath('//orbital/@z')[i].replace(' ', '')) - data = root.xpath('//data')[i].text.split('\n') + o_index_str = root.xpath("//orbital/@index")[i] + orb["index"] = int(o_index_str.replace(" ", "")) + orb["atom_index"] = int( + root.xpath("//orbital/@atom_index")[i].replace(" ", "") + ) + orb["species"] = root.xpath("//orbital/@species")[i].replace(" ", "") + orb["l"] = int(root.xpath("//orbital/@l")[i].replace(" ", "")) + orb["m"] = int(root.xpath("//orbital/@m")[i].replace(" ", "")) + orb["z"] = int(root.xpath("//orbital/@z")[i].replace(" ", "")) + data = root.xpath("//data")[i].text.split("\n") data = handle_data(data) remove_empty(data) - orb['data'] = np.asarray(data, dtype=float) + orb["data"] = np.asarray(data, dtype=float) orbitals.append(orb) return nspin, norbitals, eunit, nbands, nkpoints, k_index, energy, orbitals - def _write(self, species: Union[Sequence[Any], Dict[Any, List[int]], Dict[Any, Dict[int, List[int]]]], keyname='', file_dir: PathLike = ''): + def _write( + self, + species: Union[ + Sequence[Any], Dict[Any, List[int]], Dict[Any, Dict[int, List[int]]] + ], + keyname="", + file_dir: PathLike = "", + ): """Write parsed projected bands data to files Args: @@ -469,88 +559,103 @@ def _write(self, species: Union[Sequence[Any], Dict[Any, List[int]], Dict[Any, D if isinstance(species, (list, tuple)): for elem in band.keys(): - header_list = [''] - with open(file_dir/f"{keyname}-{elem}.dat", 'w') as f: + header_list = [""] + with open(file_dir / f"{keyname}-{elem}.dat", "w") as f: header_list.append( - f"Projected band structure for {keyname}: {elem}") - header_list.append('') - header_list.append( - f'\tNumber of k-points: {self.nkpoints}') - header_list.append(f'\tNumber of bands: {self.nbands}') - header_list.append('') + f"Projected band structure for {keyname}: {elem}" + ) + header_list.append("") + header_list.append(f"\tNumber of k-points: {self.nkpoints}") + header_list.append(f"\tNumber of bands: {self.nbands}") + header_list.append("") for orb in self.orbitals: if orb[keyname] == elem: header_list.append( - f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}") - header_list.append('') - header_list.append( - f'Data shape: ({self.nkpoints}, {self.nbands})') - header_list.append('') - header = '\n'.join(header_list) + f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}" + ) + header_list.append("") + header_list.append(f"Data shape: ({self.nkpoints}, {self.nbands})") + header_list.append("") + header = "\n".join(header_list) np.savetxt(f, band[elem], header=header) elif isinstance(species, dict): for elem in band.keys(): - elem_file_dir = file_dir/f"{keyname}-{elem}" + elem_file_dir = file_dir / f"{keyname}-{elem}" elem_file_dir.mkdir(exist_ok=True) for ang in band[elem].keys(): l_index = int(ang) if isinstance(band[elem][ang], dict): for mag in band[elem][ang].keys(): - header_list = [''] + header_list = [""] m_index = int(mag) - with open(elem_file_dir/f"{keyname}-{elem}_{ang}_{mag}.dat", 'w') as f: + with open( + elem_file_dir / f"{keyname}-{elem}_{ang}_{mag}.dat", "w" + ) as f: header_list.append( - f"Projected band structure for {keyname}: {elem}") - header_list.append('') + f"Projected band structure for {keyname}: {elem}" + ) + header_list.append("") header_list.append( - f'\tNumber of k-points: {self.nkpoints}') - header_list.append( - f'\tNumber of bands: {self.nbands}') - header_list.append('') + f"\tNumber of k-points: {self.nkpoints}" + ) + header_list.append(f"\tNumber of bands: {self.nbands}") + header_list.append("") for orb in self.orbitals: - if orb[keyname] == elem and orb["l"] == l_index and orb["m"] == m_index: + if ( + orb[keyname] == elem + and orb["l"] == l_index + and orb["m"] == m_index + ): header_list.append( - f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}") - header_list.append('') + f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}" + ) + header_list.append("") header_list.append( - f'Data shape: ({self.nkpoints}, {self.nbands})') - header_list.append('') - header = '\n'.join(header_list) - np.savetxt(f, band[elem][ang] - [mag], header=header) + f"Data shape: ({self.nkpoints}, {self.nbands})" + ) + header_list.append("") + header = "\n".join(header_list) + np.savetxt(f, band[elem][ang][mag], header=header) else: - header_list = [''] - with open(elem_file_dir/f"{keyname}-{elem}_{ang}.dat", 'w') as f: - header_list.append( - f"Projected band structure for {keyname}: {elem}") - header_list.append('') + header_list = [""] + with open( + elem_file_dir / f"{keyname}-{elem}_{ang}.dat", "w" + ) as f: header_list.append( - f'\tNumber of k-points: {self.nkpoints}') - header_list.append( - f'\tNumber of bands: {self.nbands}') - header_list.append('') + f"Projected band structure for {keyname}: {elem}" + ) + header_list.append("") + header_list.append(f"\tNumber of k-points: {self.nkpoints}") + header_list.append(f"\tNumber of bands: {self.nbands}") + header_list.append("") for orb in self.orbitals: if orb[keyname] == elem and orb["l"] == l_index: header_list.append( - f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}") - header_list.append('') + f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}" + ) + header_list.append("") header_list.append( - f'Data shape: ({self.nkpoints}, {self.nbands})') - header_list.append('') - header = '\n'.join(header_list) + f"Data shape: ({self.nkpoints}, {self.nbands})" + ) + header_list.append("") + header = "\n".join(header_list) np.savetxt(f, band[elem][ang], header=header) - def write(self, - index: Union[Sequence[int], Dict[int, List[int]], - Dict[int, Dict[int, List[int]]]] = [], - atom_index: Union[Sequence[int], Dict[int, List[int]], - Dict[int, Dict[int, List[int]]]] = [], - species: Union[Sequence[str], Dict[str, List[int]], - Dict[str, Dict[int, List[int]]]] = [], - outdir: PathLike = './' - ): + def write( + self, + index: Union[ + Sequence[int], Dict[int, List[int]], Dict[int, Dict[int, List[int]]] + ] = [], + atom_index: Union[ + Sequence[int], Dict[int, List[int]], Dict[int, Dict[int, List[int]]] + ] = [], + species: Union[ + Sequence[str], Dict[str, List[int]], Dict[str, Dict[int, List[int]]] + ] = [], + outdir: PathLike = "./", + ): """Write parsed partial dos data to files Args: @@ -565,42 +670,39 @@ def write(self, file_dir = Path(f"{outdir}", f"PBAND{i}_FILE") file_dir.mkdir(exist_ok=True) if index: - self._write(index, keyname='index', - file_dir=file_dir) + self._write(index, keyname="index", file_dir=file_dir) if atom_index: - self._write(atom_index, keyname='atom_index', - file_dir=file_dir) + self._write(atom_index, keyname="atom_index", file_dir=file_dir) if species: - self._write(species, keyname='species', - file_dir=file_dir) + self._write(species, keyname="species", file_dir=file_dir) else: file_dir = Path(f"{outdir}", f"PBAND{1}_FILE") file_dir.mkdir(exist_ok=True) if index: - self._write(index, keyname='index', - file_dir=file_dir) + self._write(index, keyname="index", file_dir=file_dir) if atom_index: - self._write(atom_index, keyname='atom_index', - file_dir=file_dir) + self._write(atom_index, keyname="atom_index", file_dir=file_dir) if species: - self._write(species, keyname='species', - file_dir=file_dir) - - def _plot(self, - fig: Figure, - ax: axes.Axes, - energy: np.ndarray, - species: Union[Sequence[Any], Dict[Any, List[int]], - Dict[Any, Dict[int, List[int]]]] = [], - efermi: float = 0, - energy_range: Sequence[float] = [], - shift: bool = False, - keyname: str = '', - outdir: PathLike = './', - out_index: int = 1, - cmap='jet', - **kwargs): + self._write(species, keyname="species", file_dir=file_dir) + + def _plot( + self, + fig: Figure, + ax: axes.Axes, + energy: np.ndarray, + species: Union[ + Sequence[Any], Dict[Any, List[int]], Dict[Any, Dict[int, List[int]]] + ] = [], + efermi: float = 0, + energy_range: Sequence[float] = [], + shift: bool = False, + keyname: str = "", + outdir: PathLike = "./", + out_index: int = 1, + cmap="jet", + **kwargs, + ): """Plot parsed projected bands data Args: @@ -613,14 +715,13 @@ def _plot(self, keyname (str, optional): the keyword that extracts the PBANDS. Defaults to ''. Returns: - BandPlot object: for manually plotting picture with bandplot.ax + BandPlot object: for manually plotting picture with bandplot.ax """ def _seg_plot(bandplot, lc, file_dir, name): cbar = bandplot.fig.colorbar(lc, ax=bandplot.ax) bandplot._set_figure(self._kzip, energy_range) - bandplot.fig.savefig( - file_dir/f'{keyname}-{bandplot._label}.pdf', dpi=400) + bandplot.fig.savefig(file_dir / f"{keyname}-{bandplot._label}.pdf", dpi=400) cbar.remove() plt.cla() @@ -644,26 +745,26 @@ def _seg_plot(bandplot, lc, file_dir, name): bandplot = BandPlot(fig, ax, **kwargs) bandplot._label = elem for ib in range(self.nbands): - points = np.array( - (self.k_index, energy[0:, ib])).T.reshape(-1, 1, 2) - segments = np.concatenate( - [points[:-1], points[1:]], axis=1) + points = np.array((self.k_index, energy[0:, ib])).T.reshape( + -1, 1, 2 + ) + segments = np.concatenate([points[:-1], points[1:]], axis=1) norm = Normalize( - vmin=wei[elem][0:, ib].min(), vmax=wei[elem][0:, ib].max()) - lc = LineCollection( - segments, cmap=plt.get_cmap(cmap), norm=norm) + vmin=wei[elem][0:, ib].min(), vmax=wei[elem][0:, ib].max() + ) + lc = LineCollection(segments, cmap=plt.get_cmap(cmap), norm=norm) lc.set_array(wei[elem][0:, ib]) lc.set_label(bandplot._label) bandplot.ax.add_collection(lc) - _seg_plot(bandplot, lc, file_dir, name=f'{elem}') + _seg_plot(bandplot, lc, file_dir, name=f"{elem}") bandplots.append(bandplot) return bandplots elif isinstance(species, dict): bandplots = [] for i, elem in enumerate(wei.keys()): - elem_file_dir = file_dir/f"{keyname}-{elem}" + elem_file_dir = file_dir / f"{keyname}-{elem}" elem_file_dir.mkdir(exist_ok=True) for ang in wei[elem].keys(): l_index = int(ang) @@ -671,63 +772,80 @@ def _seg_plot(bandplot, lc, file_dir, name): for mag in wei[elem][ang].keys(): bandplot = BandPlot(fig, ax, **kwargs) m_index = int(mag) - bandplot._label = f"{elem}-{get_angular_momentum_name(l_index, m_index)}" + bandplot._label = ( + f"{elem}-{get_angular_momentum_name(l_index, m_index)}" + ) for ib in range(self.nbands): points = np.array( - (self.k_index, energy[0:, ib])).T.reshape(-1, 1, 2) + (self.k_index, energy[0:, ib]) + ).T.reshape(-1, 1, 2) segments = np.concatenate( - [points[:-1], points[1:]], axis=1) - norm = Normalize(vmin=wei[elem][ang][mag][0:, ib].min( - ), vmax=wei[elem][ang][mag][0:, ib].max()) + [points[:-1], points[1:]], axis=1 + ) + norm = Normalize( + vmin=wei[elem][ang][mag][0:, ib].min(), + vmax=wei[elem][ang][mag][0:, ib].max(), + ) lc = LineCollection( - segments, cmap=plt.get_cmap(cmap), norm=norm) + segments, cmap=plt.get_cmap(cmap), norm=norm + ) lc.set_array(wei[elem][ang][mag][0:, ib]) lc.set_label(bandplot._label) bandplot.ax.add_collection(lc) - _seg_plot(bandplot, lc, elem_file_dir, - name=f'{elem}_{ang}_{mag}') + _seg_plot( + bandplot, lc, elem_file_dir, name=f"{elem}_{ang}_{mag}" + ) bandplots.append(bandplot) else: bandplot = BandPlot(fig, ax, **kwargs) - bandplot._label = f"{elem}-{get_angular_momentum_label(l_index)}" + bandplot._label = ( + f"{elem}-{get_angular_momentum_label(l_index)}" + ) for ib in range(self.nbands): - points = np.array( - (self.k_index, energy[0:, ib])).T.reshape(-1, 1, 2) - segments = np.concatenate( - [points[:-1], points[1:]], axis=1) - norm = Normalize(vmin=wei[elem][ang][0:, ib].min( - ), vmax=wei[elem][ang][0:, ib].max()) + points = np.array((self.k_index, energy[0:, ib])).T.reshape( + -1, 1, 2 + ) + segments = np.concatenate([points[:-1], points[1:]], axis=1) + norm = Normalize( + vmin=wei[elem][ang][0:, ib].min(), + vmax=wei[elem][ang][0:, ib].max(), + ) lc = LineCollection( - segments, cmap=plt.get_cmap(cmap), norm=norm) + segments, cmap=plt.get_cmap(cmap), norm=norm + ) lc.set_array(wei[elem][ang][0:, ib]) lc.set_label(bandplot._label) bandplot.ax.add_collection(lc) - _seg_plot(bandplot, lc, elem_file_dir, - name=f'{elem}_{ang}') + _seg_plot(bandplot, lc, elem_file_dir, name=f"{elem}_{ang}") bandplots.append(bandplot) return bandplots plt.clf() - def plot(self, - fig: Figure, - ax: Union[axes.Axes, Sequence[axes.Axes]], - index: Union[Sequence[int], Dict[int, List[int]], - Dict[int, Dict[int, List[int]]]] = [], - atom_index: Union[Sequence[int], Dict[int, List[int]], - Dict[int, Dict[int, List[int]]]] = [], - species: Union[Sequence[str], Dict[str, List[int]], - Dict[str, Dict[int, List[int]]]] = [], - efermi: Union[float, Sequence[float]] = [], - energy_range: Sequence[float] = [], - shift: bool = False, - outdir: PathLike = './', - cmapname='jet', - **kwargs): + def plot( + self, + fig: Figure, + ax: Union[axes.Axes, Sequence[axes.Axes]], + index: Union[ + Sequence[int], Dict[int, List[int]], Dict[int, Dict[int, List[int]]] + ] = [], + atom_index: Union[ + Sequence[int], Dict[int, List[int]], Dict[int, Dict[int, List[int]]] + ] = [], + species: Union[ + Sequence[str], Dict[str, List[int]], Dict[str, Dict[int, List[int]]] + ] = [], + efermi: Union[float, Sequence[float]] = [], + energy_range: Sequence[float] = [], + shift: bool = False, + outdir: PathLike = "./", + cmapname="jet", + **kwargs, + ): """Plot parsed projected band data Args: @@ -743,59 +861,157 @@ def plot(self, cmapname (str): Default: 'jet' Returns: - BandPlot object: for manually plotting picture with bandplot.ax + BandPlot object: for manually plotting picture with bandplot.ax """ if isinstance(self.bandfile, list): nums = len(self.bandfile) if not efermi: efermi = [0.0 for i in range(nums)] - _linestyle = kwargs.pop( - 'linestyle', ['solid' for i in range(nums)]) + _linestyle = kwargs.pop("linestyle", ["solid" for i in range(nums)]) for i, band in enumerate(self.energy): if not index and not atom_index and not species: - bandplot = self._plot(fig=fig, ax=ax, energy=band, species=[ - ], efermi=efermi[i], energy_range=energy_range, shift=shift, keyname='', linestyle=_linestyle[i], outdir=outdir, out_index=i, cmapname=cmapname, **kwargs) + bandplot = self._plot( + fig=fig, + ax=ax, + energy=band, + species=[], + efermi=efermi[i], + energy_range=energy_range, + shift=shift, + keyname="", + linestyle=_linestyle[i], + outdir=outdir, + out_index=i, + cmapname=cmapname, + **kwargs, + ) if index: - bandplot = self._plot(fig=fig, ax=ax, energy=band, species=index, efermi=efermi[i], - energy_range=energy_range, shift=shift, keyname='index', linestyle=_linestyle[i], outdir=outdir, out_index=i, cmapname=cmapname, **kwargs) + bandplot = self._plot( + fig=fig, + ax=ax, + energy=band, + species=index, + efermi=efermi[i], + energy_range=energy_range, + shift=shift, + keyname="index", + linestyle=_linestyle[i], + outdir=outdir, + out_index=i, + cmapname=cmapname, + **kwargs, + ) if atom_index: - bandplot = self._plot(fig=fig, ax=ax, energy=band, species=atom_index, efermi=efermi[i], - energy_range=energy_range, shift=shift, keyname='atom_index', linestyle=_linestyle[i], outdir=outdir, out_index=i, cmapname=cmapname, **kwargs) + bandplot = self._plot( + fig=fig, + ax=ax, + energy=band, + species=atom_index, + efermi=efermi[i], + energy_range=energy_range, + shift=shift, + keyname="atom_index", + linestyle=_linestyle[i], + outdir=outdir, + out_index=i, + cmapname=cmapname, + **kwargs, + ) if species: - bandplot = self._plot(fig=fig, ax=ax, energy=band, species=species, efermi=efermi[i], - energy_range=energy_range, shift=shift, keyname='species', linestyle=_linestyle[i], outdir=outdir, out_index=i, cmapname=cmapname, **kwargs) + bandplot = self._plot( + fig=fig, + ax=ax, + energy=band, + species=species, + efermi=efermi[i], + energy_range=energy_range, + shift=shift, + keyname="species", + linestyle=_linestyle[i], + outdir=outdir, + out_index=i, + cmapname=cmapname, + **kwargs, + ) else: if not index and not atom_index and not species: - bandplot = self._plot(fig=fig, ax=ax, energy=self.energy, species=[ - ], efermi=efermi, energy_range=energy_range, shift=shift, keyname='', outdir=outdir, out_index=1, **kwargs) + bandplot = self._plot( + fig=fig, + ax=ax, + energy=self.energy, + species=[], + efermi=efermi, + energy_range=energy_range, + shift=shift, + keyname="", + outdir=outdir, + out_index=1, + **kwargs, + ) if index: - bandplot = self._plot(fig=fig, ax=ax, energy=self.energy, species=index, efermi=efermi, - energy_range=energy_range, shift=shift, keyname='index', outdir=outdir, out_index=1, **kwargs) + bandplot = self._plot( + fig=fig, + ax=ax, + energy=self.energy, + species=index, + efermi=efermi, + energy_range=energy_range, + shift=shift, + keyname="index", + outdir=outdir, + out_index=1, + **kwargs, + ) if atom_index: - bandplot = self._plot(fig=fig, ax=ax, energy=self.energy, species=atom_index, efermi=efermi, - energy_range=energy_range, shift=shift, keyname='atom_index', outdir=outdir, out_index=1, **kwargs) + bandplot = self._plot( + fig=fig, + ax=ax, + energy=self.energy, + species=atom_index, + efermi=efermi, + energy_range=energy_range, + shift=shift, + keyname="atom_index", + outdir=outdir, + out_index=1, + **kwargs, + ) if species: - bandplot = self._plot(fig=fig, ax=ax, energy=self.energy, species=species, efermi=efermi, - energy_range=energy_range, shift=shift, keyname='species', outdir=outdir, out_index=1, **kwargs) + bandplot = self._plot( + fig=fig, + ax=ax, + energy=self.energy, + species=species, + efermi=efermi, + energy_range=energy_range, + shift=shift, + keyname="species", + outdir=outdir, + out_index=1, + **kwargs, + ) return bandplot - def _plot_contributions(self, - fig: Figure, - ax: axes.Axes, - energy: np.ndarray, - species: Union[Sequence[Any], Dict[Any, List[int]], - Dict[Any, Dict[int, List[int]]]] = [], - efermi: float = 0, - energy_range: Sequence[float] = [], - shift: bool = False, - keyname: str = '', - colors: list = [], - scale_width_factor: int = 5, - **kwargs): + def _plot_contributions( + self, + fig: Figure, + ax: axes.Axes, + energy: np.ndarray, + species: Union[ + Sequence[Any], Dict[Any, List[int]], Dict[Any, Dict[int, List[int]]] + ] = [], + efermi: float = 0, + energy_range: Sequence[float] = [], + shift: bool = False, + keyname: str = "", + colors: list = [], + scale_width_factor: int = 5, + **kwargs, + ): """Plot parsed projected bands data of different contributions Args: @@ -808,7 +1024,7 @@ def _plot_contributions(self, keyname (str, optional): the keyword that extracts the PBANDS. Defaults to ''. Returns: - BandPlot object: for manually plotting picture with bandplot.ax + BandPlot object: for manually plotting picture with bandplot.ax """ wei, totnum = parse_projected_data(self.orbitals, species, keyname) @@ -836,29 +1052,43 @@ def _plot_contributions(self, for mag in wei[elem][ang].keys(): m_index = int(mag) whole_label_parsed.append( - f"{elem}-{get_angular_momentum_name(l_index, m_index)}") + f"{elem}-{get_angular_momentum_name(l_index, m_index)}" + ) whole_data_parsed.append(wei[elem][ang][mag]) else: whole_label_parsed.append( - f"{elem}-{get_angular_momentum_label(l_index)}") + f"{elem}-{get_angular_momentum_label(l_index)}" + ) whole_data_parsed.append(wei[elem][ang]) if len(colors) == 0: cmap = plt.cm.get_cmap("tab10") - colors = [cmap(c) - for c in np.linspace(0, 1, len(whole_label_parsed))] + colors = [cmap(c) for c in np.linspace(0, 1, len(whole_label_parsed))] bandplot = BandPlot( - fig, ax, color=colors, label=whole_label_parsed, point_to_line=True, **kwargs) + fig, + ax, + color=colors, + label=whole_label_parsed, + point_to_line=True, + **kwargs, + ) norm = Normalize(vmin=0, vmax=1) cmaps = [bandplot._color_to_alpha_cmap(c) for c in colors] - swidth = np.array(whole_data_parsed)*scale_width_factor + swidth = np.array(whole_data_parsed) * scale_width_factor for ib in range(self.nbands): for i, con in enumerate(swidth): bandplot.ax.scatter( - self.k_index, energy[:, ib], c=con[:, ib], s=con[:, ib], norm=norm, cmap=cmaps[i], label=whole_label_parsed[i]) + self.k_index, + energy[:, ib], + c=con[:, ib], + s=con[:, ib], + norm=norm, + cmap=cmaps[i], + label=whole_label_parsed[i], + ) # clb = plt.colorbar( # plt.cm.ScalarMappable(norm=norm, cmap=cmaps), ax=bandplot.ax @@ -869,20 +1099,25 @@ def _plot_contributions(self, return bandplot - def plot_contributions(self, - fig: Figure, - ax: Union[axes.Axes, Sequence[axes.Axes]], - index: Union[Sequence[int], Dict[int, List[int]], - Dict[int, Dict[int, List[int]]]] = [], - atom_index: Union[Sequence[int], Dict[int, List[int]], - Dict[int, Dict[int, List[int]]]] = [], - species: Union[Sequence[str], Dict[str, List[int]], - Dict[str, Dict[int, List[int]]]] = [], - efermi: Union[float, Sequence[float]] = [], - energy_range: Sequence[float] = [], - shift: bool = False, - colors: list = [], - **kwargs): + def plot_contributions( + self, + fig: Figure, + ax: Union[axes.Axes, Sequence[axes.Axes]], + index: Union[ + Sequence[int], Dict[int, List[int]], Dict[int, Dict[int, List[int]]] + ] = [], + atom_index: Union[ + Sequence[int], Dict[int, List[int]], Dict[int, Dict[int, List[int]]] + ] = [], + species: Union[ + Sequence[str], Dict[str, List[int]], Dict[str, Dict[int, List[int]]] + ] = [], + efermi: Union[float, Sequence[float]] = [], + energy_range: Sequence[float] = [], + shift: bool = False, + colors: list = [], + **kwargs, + ): """Plot parsed projected band data of different contributions Args: @@ -897,43 +1132,125 @@ def plot_contributions(self, colors (list, optional): Default:[] Returns: - BandPlot object: for manually plotting picture with bandplot.ax + BandPlot object: for manually plotting picture with bandplot.ax """ if isinstance(self.bandfile, list): nums = len(self.bandfile) if not efermi: efermi = [0.0 for i in range(nums)] - _linestyle = kwargs.pop( - 'linestyle', ['solid' for i in range(nums)]) + _linestyle = kwargs.pop("linestyle", ["solid" for i in range(nums)]) for i, band in enumerate(self.energy): if not index and not atom_index and not species: - bandplot = self._plot_contributions(fig=fig, ax=ax, energy=band, species=[ - ], efermi=efermi[i], energy_range=energy_range, shift=shift, keyname='', linestyle=_linestyle[i], **kwargs) + bandplot = self._plot_contributions( + fig=fig, + ax=ax, + energy=band, + species=[], + efermi=efermi[i], + energy_range=energy_range, + shift=shift, + keyname="", + linestyle=_linestyle[i], + **kwargs, + ) if index: - bandplot = self._plot_contributions(fig=fig, ax=ax, energy=band, species=index, efermi=efermi[i], - energy_range=energy_range, shift=shift, keyname='index', linestyle=_linestyle[i], colors=colors, **kwargs) + bandplot = self._plot_contributions( + fig=fig, + ax=ax, + energy=band, + species=index, + efermi=efermi[i], + energy_range=energy_range, + shift=shift, + keyname="index", + linestyle=_linestyle[i], + colors=colors, + **kwargs, + ) if atom_index: - bandplot = self._plot_contributions(fig=fig, ax=ax, energy=band, species=atom_index, efermi=efermi[i], - energy_range=energy_range, shift=shift, keyname='atom_index', linestyle=_linestyle[i], colors=colors, **kwargs) + bandplot = self._plot_contributions( + fig=fig, + ax=ax, + energy=band, + species=atom_index, + efermi=efermi[i], + energy_range=energy_range, + shift=shift, + keyname="atom_index", + linestyle=_linestyle[i], + colors=colors, + **kwargs, + ) if species: - bandplot = self._plot_contributions(fig=fig, ax=ax, energy=band, species=species, efermi=efermi[i], - energy_range=energy_range, shift=shift, keyname='species', linestyle=_linestyle[i], colors=colors, **kwargs) + bandplot = self._plot_contributions( + fig=fig, + ax=ax, + energy=band, + species=species, + efermi=efermi[i], + energy_range=energy_range, + shift=shift, + keyname="species", + linestyle=_linestyle[i], + colors=colors, + **kwargs, + ) else: if not index and not atom_index and not species: - bandplot = self._plot_contributions(fig=fig, ax=ax, energy=self.energy, species=[ - ], efermi=efermi, energy_range=energy_range, shift=shift, keyname='', colors=colors, **kwargs) + bandplot = self._plot_contributions( + fig=fig, + ax=ax, + energy=self.energy, + species=[], + efermi=efermi, + energy_range=energy_range, + shift=shift, + keyname="", + colors=colors, + **kwargs, + ) if index: - bandplot = self._plot_contributions(fig=fig, ax=ax, energy=self.energy, species=index, efermi=efermi, - energy_range=energy_range, shift=shift, keyname='index', colors=colors, **kwargs) + bandplot = self._plot_contributions( + fig=fig, + ax=ax, + energy=self.energy, + species=index, + efermi=efermi, + energy_range=energy_range, + shift=shift, + keyname="index", + colors=colors, + **kwargs, + ) if atom_index: - bandplot = self._plot_contributions(fig=fig, ax=ax, energy=self.energy, species=atom_index, efermi=efermi, - energy_range=energy_range, shift=shift, keyname='atom_index', colors=colors, **kwargs) + bandplot = self._plot_contributions( + fig=fig, + ax=ax, + energy=self.energy, + species=atom_index, + efermi=efermi, + energy_range=energy_range, + shift=shift, + keyname="atom_index", + colors=colors, + **kwargs, + ) if species: - bandplot = self._plot_contributions(fig=fig, ax=ax, energy=self.energy, species=species, efermi=efermi, - energy_range=energy_range, shift=shift, keyname='species', colors=colors, **kwargs) + bandplot = self._plot_contributions( + fig=fig, + ax=ax, + energy=self.energy, + species=species, + efermi=efermi, + energy_range=energy_range, + shift=shift, + keyname="species", + colors=colors, + **kwargs, + ) return bandplot @@ -941,15 +1258,16 @@ def plot_contributions(self, if __name__ == "__main__": import matplotlib.pyplot as plt from pathlib import Path + parent = Path(r"../examples/Si") name = "PBANDS_1" - path = parent/name - kptfile = parent/'KLINES' + path = parent / name + kptfile = parent / "KLINES" fig, ax = plt.subplots(figsize=(12, 6)) energy_range = [-5, 7] efermi = 6.585653952007503 shift = False - #species = {"Ag": [2], "Cl": [1], "In": [0]} + # species = {"Ag": [2], "Cl": [1], "In": [0]} atom_index = {1: {1: [0, 1]}} pband = PBand(str(path), kptfile) @@ -960,8 +1278,14 @@ def plot_contributions(self, # pband.write(atom_index=atom_index) # 2. plot different contributions in single picture - pband.plot_contributions(fig, ax, atom_index=atom_index, efermi=efermi, - energy_range=energy_range, shift=shift) + pband.plot_contributions( + fig, + ax, + atom_index=atom_index, + efermi=efermi, + energy_range=energy_range, + shift=shift, + ) plt.show() # 3. plot different contributions to different pictures with colobar denoting weightes diff --git a/tools/plot-tools/abacus_plot/dos.py b/tools/plot-tools/abacus_plot/dos.py index f128f931252..170c4d6eee0 100644 --- a/tools/plot-tools/abacus_plot/dos.py +++ b/tools/plot-tools/abacus_plot/dos.py @@ -1,9 +1,9 @@ -''' +""" Date: 2021-12-29 15:02:13 LastEditors: jiyuyang LastEditTime: 2022-01-03 17:18:21 Mail: jiyuyang@mail.ustc.edu.cn, 1041176461@qq.com -''' +""" from collections import OrderedDict, namedtuple import numpy as np @@ -13,8 +13,14 @@ from matplotlib.figure import Figure from matplotlib import axes -from abacus_plot.utils import (energy_minus_efermi, get_angular_momentum_label, - get_angular_momentum_name, remove_empty, handle_data, parse_projected_data) +from abacus_plot.utils import ( + energy_minus_efermi, + get_angular_momentum_label, + get_angular_momentum_name, + remove_empty, + handle_data, + parse_projected_data, +) class DOS: @@ -29,21 +35,31 @@ def __init__(self, nspin) -> None: def _plot(self, dosplot, energy_f, dos, label): if self._nsplit == 1: - dosplot.ax.plot(energy_f, dos, - - lw=dosplot._lw, label=label) + dosplot.ax.plot(energy_f, dos, lw=dosplot._lw, label=label) elif self._nsplit == 2: dos_up, dos_dw = np.split(dos, self._nsplit, axis=1) - dosplot.ax.plot(energy_f, dos_up, lw=dosplot._lw, linestyle="-", - label=f'{label}'+r'$\uparrow$') + dosplot.ax.plot( + energy_f, + dos_up, + lw=dosplot._lw, + linestyle="-", + label=f"{label}" + r"$\uparrow$", + ) dos_dw = -dos_dw - dosplot.ax.plot(energy_f, dos_dw, lw=dosplot._lw, linestyle="--", - label=f'{label}'+r'$\downarrow$') + dosplot.ax.plot( + energy_f, + dos_dw, + lw=dosplot._lw, + linestyle="--", + label=f"{label}" + r"$\downarrow$", + ) return dosplot.ax @classmethod - def set_vcband(cls, energy: Sequence, dos: Sequence, prec=0.01) -> Tuple[namedtuple, namedtuple]: + def set_vcband( + cls, energy: Sequence, dos: Sequence, prec=0.01 + ) -> Tuple[namedtuple, namedtuple]: """Separate valence and conduct band :params energy: band energy after subtracting the Fermi level @@ -51,20 +67,19 @@ def set_vcband(cls, energy: Sequence, dos: Sequence, prec=0.01) -> Tuple[namedtu :params prec: dos below this value thought to be zero. Default: 0.01 """ - Band = namedtuple('Band', ['band', 'value']) + Band = namedtuple("Band", ["band", "value"]) # valance band band_vbm_index = np.where(energy <= 0)[0] evbm = energy[np.where(dos[band_vbm_index] > prec)[0][-1]][0] band_vbm = energy[band_vbm_index] - vb = Band(band_vbm-evbm, evbm-evbm) + vb = Band(band_vbm - evbm, evbm - evbm) # conduct band band_cbm_index = np.where(energy > 0)[0] band_cbm = energy[band_cbm_index] - ecbm = energy[np.where(dos[band_cbm_index] > prec)[ - 0][0]+band_cbm_index[0]][0] - cb = Band(band_cbm-evbm, ecbm-evbm) + ecbm = energy[np.where(dos[band_cbm_index] > prec)[0][0] + band_cbm_index[0]][0] + cb = Band(band_cbm - evbm, ecbm - evbm) return vb, cb @@ -72,19 +87,22 @@ def set_vcband(cls, energy: Sequence, dos: Sequence, prec=0.01) -> Tuple[namedtu def info(cls, vb: namedtuple, cb: namedtuple): """Output the information of band structure - :params kpath: k-points path + :params kpath: k-points path :params energy: band energy after subtracting the Fermi level """ gap = cls.bandgap(vb, cb) - print("--------------------------Density of State--------------------------", flush=True) + print( + "--------------------------Density of State--------------------------", + flush=True, + ) print(f"{'Band gap(eV):'.ljust(30)}{gap: .4f}", flush=True) @classmethod def bandgap(cls, vb: namedtuple, cb: namedtuple): """Calculate band gap""" - gap = cb.value-vb.value + gap = cb.value - vb.value return gap @@ -92,15 +110,19 @@ def bandgap(cls, vb: namedtuple, cb: namedtuple): class DOSPlot: """Plot density of state(DOS)""" - def __init__(self, fig: Figure = None, ax: axes.Axes = None, nspin: int = 1, **kwargs) -> None: + def __init__( + self, fig: Figure = None, ax: axes.Axes = None, nspin: int = 1, **kwargs + ) -> None: self.nspin = nspin self.fig = fig self.ax = ax - self._lw = kwargs.pop('lw', 2) - self._bwidth = kwargs.pop('bwdith', 3) + self._lw = kwargs.pop("lw", 2) + self._bwidth = kwargs.pop("bwdith", 3) self.plot_params = kwargs - def _set_figure(self, energy_range: Sequence = [], dos_range: Sequence = [], notes: Dict = {}): + def _set_figure( + self, energy_range: Sequence = [], dos_range: Sequence = [], notes: Dict = {} + ): """set figure and axes for plotting :params energy_range: range of energy @@ -122,9 +144,17 @@ def _set_figure(self, energy_range: Sequence = [], dos_range: Sequence = [], not # notes if notes: from matplotlib.offsetbox import AnchoredText + if "s" in notes.keys() and len(notes.keys()) == 1: - self.ax.add_artist(AnchoredText(notes["s"], loc='upper left', prop=dict(size=25), - borderpad=0.2, frameon=False)) + self.ax.add_artist( + AnchoredText( + notes["s"], + loc="upper left", + prop=dict(size=25), + borderpad=0.2, + frameon=False, + ) + ) else: self.ax.add_artist(AnchoredText(**self.plot_params["notes"])) @@ -136,27 +166,27 @@ def _set_figure(self, energy_range: Sequence = [], dos_range: Sequence = [], not # frame bwidth = self._bwidth - self.ax.spines['top'].set_linewidth(bwidth) - self.ax.spines['right'].set_linewidth(bwidth) - self.ax.spines['left'].set_linewidth(bwidth) - self.ax.spines['bottom'].set_linewidth(bwidth) + self.ax.spines["top"].set_linewidth(bwidth) + self.ax.spines["right"].set_linewidth(bwidth) + self.ax.spines["left"].set_linewidth(bwidth) + self.ax.spines["bottom"].set_linewidth(bwidth) if "vline_params" in self.plot_params.keys(): self.ax.axvline(0, **self.plot_params["vline_params"]) else: - self.ax.axvline(0, linestyle="--", c='b', lw=1.0) + self.ax.axvline(0, linestyle="--", c="b", lw=1.0) if self.nspin == 2: - self.ax.axhline(0, linestyle="--", c='gray', lw=1.0) + self.ax.axhline(0, linestyle="--", c="gray", lw=1.0) handles, labels = self.ax.get_legend_handles_labels() by_label = OrderedDict(zip(labels, handles)) if "legend_prop" in self.plot_params.keys(): - self.ax.legend(by_label.values(), by_label.keys(), - prop=self.plot_params["legend_prop"]) + self.ax.legend( + by_label.values(), by_label.keys(), prop=self.plot_params["legend_prop"] + ) else: - self.ax.legend(by_label.values(), - by_label.keys(), prop={'size': 15}) + self.ax.legend(by_label.values(), by_label.keys(), prop={"size": 15}) class TDOS(DOS): @@ -174,17 +204,18 @@ def _read(self) -> tuple: """ data = np.loadtxt(self.tdosfile) - self.nspin = data.shape[1]-1 + self.nspin = data.shape[1] - 1 if self.nspin == 1: - self.energy, self.dos = np.split(data, self.nspin+1, axis=1) + self.energy, self.dos = np.split(data, self.nspin + 1, axis=1) elif self.nspin == 2: - self.energy, dos_up, dos_dw = np.split(data, self.nspin+1, axis=1) + self.energy, dos_up, dos_dw = np.split(data, self.nspin + 1, axis=1) self.dos = np.hstack((dos_up, dos_dw)) def _shift_energy(self, efermi: float = 0, shift: bool = False, prec: float = 0.01): if shift: vb, cb = self.set_vcband( - energy_minus_efermi(self.energy, efermi), self.dos, prec) + energy_minus_efermi(self.energy, efermi), self.dos, prec + ) self.info(vb, cb) energy_f = np.concatenate((vb.band, cb.band)) else: @@ -192,15 +223,26 @@ def _shift_energy(self, efermi: float = 0, shift: bool = False, prec: float = 0. return energy_f - def plot(self, fig: Figure, ax: Union[axes.Axes, Sequence[axes.Axes]], efermi: float = 0, energy_range: Sequence[float] = [], dos_range: Sequence[float] = [], shift: bool = False, prec: float = 0.01, **kwargs): + def plot( + self, + fig: Figure, + ax: Union[axes.Axes, Sequence[axes.Axes]], + efermi: float = 0, + energy_range: Sequence[float] = [], + dos_range: Sequence[float] = [], + shift: bool = False, + prec: float = 0.01, + **kwargs, + ): energy_f = self._shift_energy(efermi, shift, prec) dosplot = DOSPlot(fig, ax, self.nspin, **kwargs) dosplot.ax = self._plot(dosplot, energy_f, self.dos, "TDOS") if "notes" in dosplot.plot_params.keys(): - dosplot._set_figure(energy_range, dos_range, - notes=dosplot.plot_params["notes"]) + dosplot._set_figure( + energy_range, dos_range, notes=dosplot.plot_params["notes"] + ) else: dosplot._set_figure(energy_range, dos_range) @@ -222,30 +264,29 @@ def _read(self): """ from lxml import etree + pdosdata = etree.parse(self.pdosfile) root = pdosdata.getroot() - self.nspin = int(root.xpath('//nspin')[0].text.replace(' ', '')) - norbitals = int(root.xpath('//norbitals')[0].text.replace(' ', '')) - self.eunit = root.xpath('//energy_values/@units')[0].replace(' ', '') - e_list = root.xpath( - '//energy_values')[0].text.replace(' ', '').split('\n') + self.nspin = int(root.xpath("//nspin")[0].text.replace(" ", "")) + norbitals = int(root.xpath("//norbitals")[0].text.replace(" ", "")) + self.eunit = root.xpath("//energy_values/@units")[0].replace(" ", "") + e_list = root.xpath("//energy_values")[0].text.replace(" ", "").split("\n") remove_empty(e_list) self.orbitals = [] for i in range(norbitals): orb = OrderedDict() - orb['index'] = int(root.xpath( - '//orbital/@index')[i].replace(' ', '')) - orb['atom_index'] = int(root.xpath( - '//orbital/@atom_index')[i].replace(' ', '')) - orb['species'] = root.xpath( - '//orbital/@species')[i].replace(' ', '') - orb['l'] = int(root.xpath('//orbital/@l')[i].replace(' ', '')) - orb['m'] = int(root.xpath('//orbital/@m')[i].replace(' ', '')) - orb['z'] = int(root.xpath('//orbital/@z')[i].replace(' ', '')) - data = root.xpath('//data')[i].text.split('\n') + orb["index"] = int(root.xpath("//orbital/@index")[i].replace(" ", "")) + orb["atom_index"] = int( + root.xpath("//orbital/@atom_index")[i].replace(" ", "") + ) + orb["species"] = root.xpath("//orbital/@species")[i].replace(" ", "") + orb["l"] = int(root.xpath("//orbital/@l")[i].replace(" ", "")) + orb["m"] = int(root.xpath("//orbital/@m")[i].replace(" ", "")) + orb["z"] = int(root.xpath("//orbital/@z")[i].replace(" ", "")) + data = root.xpath("//data")[i].text.split("\n") data = handle_data(data) remove_empty(data) - orb['data'] = np.asarray(data, dtype=float) + orb["data"] = np.asarray(data, dtype=float) self.orbitals.append(orb) self.energy = np.reshape(e_list, newshape=(-1, 1)).astype(float) @@ -253,10 +294,17 @@ def _read(self): def _all_sum(self) -> Tuple[np.ndarray, int]: res = np.zeros_like(self.orbitals[0]["data"], dtype=float) for orb in self.orbitals: - res = res + orb['data'] + res = res + orb["data"] return res - def _write(self, species: Union[Sequence[Any], Dict[Any, List[int]], Dict[Any, Dict[int, List[int]]]], keyname='', outdir: PathLike = './'): + def _write( + self, + species: Union[ + Sequence[Any], Dict[Any, List[int]], Dict[Any, Dict[int, List[int]]] + ], + keyname="", + outdir: PathLike = "./", + ): """Write parsed partial dos data to files Args: @@ -265,85 +313,107 @@ def _write(self, species: Union[Sequence[Any], Dict[Any, List[int]], Dict[Any, D """ dos, totnum = parse_projected_data(self.orbitals, species, keyname) - fmt = ['%13.7f', '%15.8f'] if self._nsplit == 1 else [ - '%13.7f', '%15.8f', '%15.8f'] + fmt = ( + ["%13.7f", "%15.8f"] + if self._nsplit == 1 + else ["%13.7f", "%15.8f", "%15.8f"] + ) file_dir = Path(f"{outdir}", "PDOS_FILE") file_dir.mkdir(exist_ok=True) if isinstance(species, (list, tuple)): for elem in dos.keys(): - header_list = [''] + header_list = [""] data = np.hstack((self.energy.reshape(-1, 1), dos[elem])) - with open(file_dir/f"{keyname}-{elem}.dat", 'w') as f: - header_list.append( - f"Partial DOS for {keyname}: {elem}") - header_list.append('') + with open(file_dir / f"{keyname}-{elem}.dat", "w") as f: + header_list.append(f"Partial DOS for {keyname}: {elem}") + header_list.append("") for orb in self.orbitals: if orb[keyname] == elem: header_list.append( - f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}") - header_list.append('') - header_list.append('\tEnergy'+10*' ' + - 'spin 1'+8*' '+'spin 2') - header_list.append('') - header = '\n'.join(header_list) + f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}" + ) + header_list.append("") + header_list.append( + "\tEnergy" + 10 * " " + "spin 1" + 8 * " " + "spin 2" + ) + header_list.append("") + header = "\n".join(header_list) np.savetxt(f, data, fmt=fmt, header=header) elif isinstance(species, dict): for elem in dos.keys(): - elem_file_dir = file_dir/f"{keyname}-{elem}" + elem_file_dir = file_dir / f"{keyname}-{elem}" elem_file_dir.mkdir(exist_ok=True) for ang in dos[elem].keys(): l_index = int(ang) if isinstance(dos[elem][ang], dict): for mag in dos[elem][ang].keys(): - header_list = [''] + header_list = [""] data = np.hstack( - (self.energy.reshape(-1, 1), dos[elem][ang][mag])) + (self.energy.reshape(-1, 1), dos[elem][ang][mag]) + ) m_index = int(mag) - with open(elem_file_dir/f"{keyname}-{elem}_{ang}_{mag}.dat", 'w') as f: - header_list.append( - f"Partial DOS for {keyname}: {elem}") - header_list.append('') + with open( + elem_file_dir / f"{keyname}-{elem}_{ang}_{mag}.dat", "w" + ) as f: + header_list.append(f"Partial DOS for {keyname}: {elem}") + header_list.append("") for orb in self.orbitals: - if orb[keyname] == elem and orb["l"] == l_index and orb["m"] == m_index: + if ( + orb[keyname] == elem + and orb["l"] == l_index + and orb["m"] == m_index + ): header_list.append( - f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}") - header_list.append('') + f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}" + ) + header_list.append("") header_list.append( - '\tEnergy'+10*' '+'spin 1'+8*' '+'spin 2') - header_list.append('') - header = '\n'.join(header_list) + "\tEnergy" + + 10 * " " + + "spin 1" + + 8 * " " + + "spin 2" + ) + header_list.append("") + header = "\n".join(header_list) np.savetxt(f, data, fmt=fmt, header=header) else: - header_list = [''] - data = np.hstack( - (self.energy.reshape(-1, 1), dos[elem][ang])) - with open(elem_file_dir/f"{keyname}-{elem}_{ang}.dat", 'w') as f: - header_list.append( - f"Partial DOS for {keyname}: {elem}") - header_list.append('') + header_list = [""] + data = np.hstack((self.energy.reshape(-1, 1), dos[elem][ang])) + with open( + elem_file_dir / f"{keyname}-{elem}_{ang}.dat", "w" + ) as f: + header_list.append(f"Partial DOS for {keyname}: {elem}") + header_list.append("") for orb in self.orbitals: if orb[keyname] == elem and orb["l"] == l_index: header_list.append( - f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}") - header_list.append('') + f"\tAdd data for index ={orb['index']:4d}, atom_index ={orb['atom_index']:4d}, element ={orb['species']:4s}, l,m,z={orb['l']:3d}, {orb['m']:3d}, {orb['z']:3d}" + ) + header_list.append("") header_list.append( - '\tEnergy'+10*' '+'spin 1'+8*' '+'spin 2') - header_list.append('') - header = '\n'.join(header_list) + "\tEnergy" + 10 * " " + "spin 1" + 8 * " " + "spin 2" + ) + header_list.append("") + header = "\n".join(header_list) np.savetxt(f, data, fmt=fmt, header=header) - def write(self, - index: Union[Sequence[int], Dict[int, List[int]], - Dict[int, Dict[int, List[int]]]] = [], - atom_index: Union[Sequence[int], Dict[int, List[int]], - Dict[int, Dict[int, List[int]]]] = [], - species: Union[Sequence[str], Dict[str, List[int]], - Dict[str, Dict[int, List[int]]]] = [], - outdir: PathLike = './' - ): + def write( + self, + index: Union[ + Sequence[int], Dict[int, List[int]], Dict[int, Dict[int, List[int]]] + ] = [], + atom_index: Union[ + Sequence[int], Dict[int, List[int]], Dict[int, Dict[int, List[int]]] + ] = [], + species: Union[ + Sequence[str], Dict[str, List[int]], Dict[str, Dict[int, List[int]]] + ] = [], + outdir: PathLike = "./", + ): """Write parsed partial dos data to files Args: @@ -353,17 +423,18 @@ def write(self, outdir (PathLike, optional): directory of parsed PDOS files. Defaults to './'. """ if index: - self._write(index, keyname='index', outdir=outdir) + self._write(index, keyname="index", outdir=outdir) if atom_index: - self._write(atom_index, keyname='atom_index', outdir=outdir) + self._write(atom_index, keyname="atom_index", outdir=outdir) if species: - self._write(species, keyname='species', outdir=outdir) + self._write(species, keyname="species", outdir=outdir) def _shift_energy(self, efermi: float = 0, shift: bool = False, prec: float = 0.01): tdos = self._all_sum() if shift: vb, cb = self.set_vcband( - energy_minus_efermi(self.energy, efermi), tdos, prec) + energy_minus_efermi(self.energy, efermi), tdos, prec + ) self.info(vb, cb) energy_f = np.concatenate((vb.band, cb.band)) else: @@ -371,18 +442,21 @@ def _shift_energy(self, efermi: float = 0, shift: bool = False, prec: float = 0. return energy_f, tdos - def _parial_plot(self, - fig: Figure, - ax: Union[axes.Axes, Sequence[axes.Axes]], - species: Union[Sequence[Any], Dict[Any, List[int]], - Dict[Any, Dict[int, List[int]]]] = [], - efermi: float = 0, - energy_range: Sequence[float] = [], - dos_range: Sequence[float] = [], - shift: bool = False, - prec: float = 0.01, - keyname: str = '', - **kwargs): + def _parial_plot( + self, + fig: Figure, + ax: Union[axes.Axes, Sequence[axes.Axes]], + species: Union[ + Sequence[Any], Dict[Any, List[int]], Dict[Any, Dict[int, List[int]]] + ] = [], + efermi: float = 0, + energy_range: Sequence[float] = [], + dos_range: Sequence[float] = [], + shift: bool = False, + prec: float = 0.01, + keyname: str = "", + **kwargs, + ): """Plot parsed partial dos data Args: @@ -397,7 +471,7 @@ def _parial_plot(self, keyname (str, optional): the keyword that extracts the PDOS. Defaults to ''. Returns: - DOSPlot object: for manually plotting picture with dosplot.ax + DOSPlot object: for manually plotting picture with dosplot.ax """ if isinstance(ax, axes.Axes): ax = [ax] @@ -409,8 +483,9 @@ def _parial_plot(self, dosplot = DOSPlot(fig, ax, self.nspin, **kwargs) dosplot.ax = self._plot(dosplot, energy_f, tdos, "TDOS") if "notes" in dosplot.plot_params.keys(): - dosplot._set_figure(energy_range, dos_range, - notes=dosplot.plot_params["notes"]) + dosplot._set_figure( + energy_range, dos_range, notes=dosplot.plot_params["notes"] + ) else: dosplot._set_figure(energy_range, dos_range) @@ -419,16 +494,18 @@ def _parial_plot(self, if isinstance(species, (list, tuple)): dosplot = DOSPlot(fig, ax, self.nspin, **kwargs) if "xlabel_params" in dosplot.plot_params.keys(): - dosplot.ax.set_xlabel("Energy(eV)", ** - dosplot.plot_params["xlabel_params"]) + dosplot.ax.set_xlabel( + "Energy(eV)", **dosplot.plot_params["xlabel_params"] + ) else: dosplot.ax.set_xlabel("Energy(eV)", size=25) dosplot.ax = self._plot(dosplot, energy_f, tdos, "TDOS") for elem in dos.keys(): dosplot.ax = self._plot(dosplot, energy_f, dos[elem], elem) if "notes" in dosplot.plot_params.keys(): - dosplot._set_figure(energy_range, dos_range, - notes=dosplot.plot_params["notes"]) + dosplot._set_figure( + energy_range, dos_range, notes=dosplot.plot_params["notes"] + ) else: dosplot._set_figure(energy_range, dos_range) @@ -436,8 +513,7 @@ def _parial_plot(self, elif isinstance(species, dict): dosplots = [] - assert len(ax) >= len( - dos.keys()), "There must be enough `axes` to plot." + assert len(ax) >= len(dos.keys()), "There must be enough `axes` to plot." for i, elem in enumerate(dos.keys()): dosplot = DOSPlot(fig, ax[i], self.nspin, **kwargs) for ang in dos[elem].keys(): @@ -446,40 +522,55 @@ def _parial_plot(self, for mag in dos[elem][ang].keys(): m_index = int(mag) dosplot.ax = self._plot( - dosplot, energy_f, dos[elem][ang][mag], f"{elem}-{get_angular_momentum_name(l_index, m_index)}") + dosplot, + energy_f, + dos[elem][ang][mag], + f"{elem}-{get_angular_momentum_name(l_index, m_index)}", + ) else: dosplot.ax = self._plot( - dosplot, energy_f, dos[elem][ang], f"{elem}-{get_angular_momentum_label(l_index)}") + dosplot, + energy_f, + dos[elem][ang], + f"{elem}-{get_angular_momentum_label(l_index)}", + ) if "notes" in dosplot.plot_params.keys(): - dosplot._set_figure(energy_range, dos_range, - notes=dosplot.plot_params["notes"][i]) + dosplot._set_figure( + energy_range, dos_range, notes=dosplot.plot_params["notes"][i] + ) else: dosplot._set_figure(energy_range, dos_range) dosplots.append(dosplot) if "xlabel_params" in dosplot.plot_params.keys(): - dosplot.ax.set_xlabel("Energy(eV)", ** - dosplot.plot_params["xlabel_params"]) + dosplot.ax.set_xlabel( + "Energy(eV)", **dosplot.plot_params["xlabel_params"] + ) else: dosplot.ax.set_xlabel("Energy(eV)", size=25) return dosplots - def plot(self, - fig: Figure, - ax: Union[axes.Axes, Sequence[axes.Axes]], - index: Union[Sequence[int], Dict[int, List[int]], - Dict[int, Dict[int, List[int]]]] = [], - atom_index: Union[Sequence[int], Dict[int, List[int]], - Dict[int, Dict[int, List[int]]]] = [], - species: Union[Sequence[str], Dict[str, List[int]], - Dict[str, Dict[int, List[int]]]] = [], - efermi: float = 0, - energy_range: Sequence[float] = [], - dos_range: Sequence[float] = [], - shift: bool = False, - prec: float = 0.01, - **kwargs): + def plot( + self, + fig: Figure, + ax: Union[axes.Axes, Sequence[axes.Axes]], + index: Union[ + Sequence[int], Dict[int, List[int]], Dict[int, Dict[int, List[int]]] + ] = [], + atom_index: Union[ + Sequence[int], Dict[int, List[int]], Dict[int, Dict[int, List[int]]] + ] = [], + species: Union[ + Sequence[str], Dict[str, List[int]], Dict[str, Dict[int, List[int]]] + ] = [], + efermi: float = 0, + energy_range: Sequence[float] = [], + dos_range: Sequence[float] = [], + shift: bool = False, + prec: float = 0.01, + **kwargs, + ): """Plot parsed partial dos data Args: @@ -495,39 +586,80 @@ def plot(self, prec (float, optional): precision for treating dos as zero. Defaults to 0.01. Returns: - DOSPlot object: for manually plotting picture with dosplot.ax + DOSPlot object: for manually plotting picture with dosplot.ax """ if not index and not atom_index and not species: - dosplot = self._parial_plot(fig=fig, ax=ax, species=[ - ], efermi=efermi, energy_range=energy_range, dos_range=dos_range, shift=shift, prec=prec, keyname='', **kwargs) + dosplot = self._parial_plot( + fig=fig, + ax=ax, + species=[], + efermi=efermi, + energy_range=energy_range, + dos_range=dos_range, + shift=shift, + prec=prec, + keyname="", + **kwargs, + ) if index: - dosplot = self._parial_plot(fig=fig, ax=ax, species=index, efermi=efermi, energy_range=energy_range, - dos_range=dos_range, shift=shift, prec=prec, keyname='index', **kwargs) + dosplot = self._parial_plot( + fig=fig, + ax=ax, + species=index, + efermi=efermi, + energy_range=energy_range, + dos_range=dos_range, + shift=shift, + prec=prec, + keyname="index", + **kwargs, + ) if atom_index: - dosplot = self._parial_plot(fig=fig, ax=ax, species=atom_index, efermi=efermi, energy_range=energy_range, - dos_range=dos_range, shift=shift, prec=prec, keyname='atom_index', **kwargs) + dosplot = self._parial_plot( + fig=fig, + ax=ax, + species=atom_index, + efermi=efermi, + energy_range=energy_range, + dos_range=dos_range, + shift=shift, + prec=prec, + keyname="atom_index", + **kwargs, + ) if species: - dosplot = self._parial_plot(fig=fig, ax=ax, species=species, efermi=efermi, energy_range=energy_range, - dos_range=dos_range, shift=shift, prec=prec, keyname='species', **kwargs) + dosplot = self._parial_plot( + fig=fig, + ax=ax, + species=species, + efermi=efermi, + energy_range=energy_range, + dos_range=dos_range, + shift=shift, + prec=prec, + keyname="species", + **kwargs, + ) return dosplot if __name__ == "__main__": import matplotlib.pyplot as plt - #tdosfile = r"C:\Users\YY.Ji\Desktop\TDOS" - #tdos = TDOS(tdosfile) - #fig, ax = plt.subplots() - #energy_range = [-6, 10] - #dos_range = [0, 5] + + # tdosfile = r"C:\Users\YY.Ji\Desktop\TDOS" + # tdos = TDOS(tdosfile) + # fig, ax = plt.subplots() + # energy_range = [-6, 10] + # dos_range = [0, 5] # dosplots = tdos.plot(fig, ax, efermi=5, shift=True, # energy_range=energy_range, dos_range=dos_range, notes={'s': '(a)'}) # fig.savefig("tdos.png") pdosfile = r"../examples/Si/PDOS" pdos = PDOS(pdosfile) - #species = {"Ag": [2], "Cl": [1], "In": [0]} + # species = {"Ag": [2], "Cl": [1], "In": [0]} atom_index = {1: {1: [0, 1]}} fig, ax = plt.subplots(1, 1, sharex=True) energy_range = [-5, 7] @@ -536,7 +668,15 @@ def plot(self, # if you want to specify `species` or `index`, you need to # set `species=species` or `index=index` in the following two functions - dosplots = pdos.plot(fig, ax, atom_index=atom_index, efermi=efermi, shift=True, - energy_range=energy_range, dos_range=dos_range, notes=[{'s': '(a)'}]) + dosplots = pdos.plot( + fig, + ax, + atom_index=atom_index, + efermi=efermi, + shift=True, + energy_range=energy_range, + dos_range=dos_range, + notes=[{"s": "(a)"}], + ) fig.savefig("pdos.png") pdos.write(atom_index=atom_index) diff --git a/tools/plot-tools/abacus_plot/main.py b/tools/plot-tools/abacus_plot/main.py index 123f62b1149..abf885c5bb0 100644 --- a/tools/plot-tools/abacus_plot/main.py +++ b/tools/plot-tools/abacus_plot/main.py @@ -1,9 +1,9 @@ -''' +""" Date: 2022-01-03 15:03:54 LastEditors: jiyuyang LastEditTime: 2022-01-03 17:10:52 Mail: jiyuyang@mail.ustc.edu.cn, 1041176461@qq.com -''' +""" import argparse import matplotlib.pyplot as plt @@ -28,7 +28,14 @@ def show_cmdline(cls, args): figsize = text.pop("figsize", (12, 10)) fig, ax = plt.subplots(figsize=figsize) band = Band(bandfile, kptfile) - band.plot(fig=fig, ax=ax, efermi=efermi, energy_range=energy_range, shift=shift, **text) + band.plot( + fig=fig, + ax=ax, + efermi=efermi, + energy_range=energy_range, + shift=shift, + **text + ) dpi = text.pop("dpi", 400) fig.savefig(text.pop("outfile", "band.png"), dpi=dpi) @@ -41,13 +48,27 @@ def show_cmdline(cls, args): shift = text.pop("shift", False) figsize = text.pop("figsize", (12, 10)) fig, ax = plt.subplots(figsize=figsize) - index = key2int(text.pop("index", None)) # keys of json must be dict, I convert them to int for `index` and `atom_index` + index = key2int( + text.pop("index", None) + ) # keys of json must be dict, I convert them to int for `index` and `atom_index` atom_index = key2int(text.pop("atom_index", None)) species = text.pop("species", None) - outdir = text.pop("outdir", './') - cmapname = text.pop("cmapname", 'jet') + outdir = text.pop("outdir", "./") + cmapname = text.pop("cmapname", "jet") pband = PBand(bandfile, kptfile) - pband.plot(fig=fig, ax=ax, index=index, atom_index=atom_index, species=species, efermi=efermi, energy_range=energy_range, shift=shift, outdir=outdir, cmapname=cmapname, **text) + pband.plot( + fig=fig, + ax=ax, + index=index, + atom_index=atom_index, + species=species, + efermi=efermi, + energy_range=energy_range, + shift=shift, + outdir=outdir, + cmapname=cmapname, + **text + ) if args.band and args.out: text = read_json(args.file) @@ -56,13 +77,15 @@ def show_cmdline(cls, args): index = key2int(text.pop("index", None)) atom_index = key2int(text.pop("atom_index", None)) species = text.pop("species", None) - outdir = text.pop("outdir", './') + outdir = text.pop("outdir", "./") pdos = PBand(bandfile, kptfile) - pdos.write(index=index, atom_index=atom_index, species=species, outdir=outdir) + pdos.write( + index=index, atom_index=atom_index, species=species, outdir=outdir + ) if args.dos and not args.projected and not args.out: text = read_json(args.file) - tdosfile = text.pop("tdosfile", '') + tdosfile = text.pop("tdosfile", "") efermi = text.pop("efermi", 0.0) energy_range = text.pop("energy_range", []) dos_range = text.pop("dos_range", []) @@ -71,14 +94,22 @@ def show_cmdline(cls, args): fig, ax = plt.subplots(figsize=figsize) prec = text.pop("prec", 0.01) tdos = TDOS(tdosfile) - tdos.plot(fig, ax, efermi=efermi, shift=shift, - energy_range=energy_range, dos_range=dos_range, prec=prec, **text) + tdos.plot( + fig, + ax, + efermi=efermi, + shift=shift, + energy_range=energy_range, + dos_range=dos_range, + prec=prec, + **text + ) dpi = text.pop("dpi", 400) fig.savefig(text.pop("tdosfig", "tdos.png"), dpi=dpi) if args.dos and args.projected: text = read_json(args.file) - pdosfile = text.pop("pdosfile", '') + pdosfile = text.pop("pdosfile", "") efermi = text.pop("efermi", 0.0) energy_range = text.pop("energy_range", []) dos_range = text.pop("dos_range", []) @@ -88,46 +119,98 @@ def show_cmdline(cls, args): species = text.pop("species", None) figsize = text.pop("figsize", (12, 10)) if index: - fig, ax = plt.subplots( - len(index), 1, sharex=True, figsize=figsize) + fig, ax = plt.subplots(len(index), 1, sharex=True, figsize=figsize) if atom_index: - fig, ax = plt.subplots( - len(atom_index), 1, sharex=True, figsize=figsize) + fig, ax = plt.subplots(len(atom_index), 1, sharex=True, figsize=figsize) if species: - fig, ax = plt.subplots( - len(species), 1, sharex=True, figsize=figsize) + fig, ax = plt.subplots(len(species), 1, sharex=True, figsize=figsize) prec = text.pop("prec", 0.01) pdos = PDOS(pdosfile) - pdos.plot(fig=fig, ax=ax, index=index, atom_index=atom_index, species=species, efermi=efermi, shift=shift, - energy_range=energy_range, dos_range=dos_range, prec=prec, **text) + pdos.plot( + fig=fig, + ax=ax, + index=index, + atom_index=atom_index, + species=species, + efermi=efermi, + shift=shift, + energy_range=energy_range, + dos_range=dos_range, + prec=prec, + **text + ) dpi = text.pop("dpi", 400) fig.savefig(text.pop("pdosfig", "pdos.png"), dpi=dpi) if args.dos and args.out: text = read_json(args.file) - pdosfile = text.pop("pdosfile", '') + pdosfile = text.pop("pdosfile", "") index = key2int(text.pop("index", None)) atom_index = key2int(text.pop("atom_index", None)) species = text.pop("species", None) - outdir = text.pop("outdir", './') + outdir = text.pop("outdir", "./") pdos = PDOS(pdosfile) - pdos.write(index=index, atom_index=atom_index, species=species, outdir=outdir) + pdos.write( + index=index, atom_index=atom_index, species=species, outdir=outdir + ) + def main(): parser = argparse.ArgumentParser( - prog='abacus-plot', description='Plotting tools for ABACUS') + prog="abacus-plot", description="Plotting tools for ABACUS" + ) # Show - parser.add_argument('-f', '--file', dest='file', type=str, nargs='?', const='config.json', - default='config.json', help='profile with format json') - parser.add_argument('-b', '--band', dest='band', nargs='?', const=1, type=int, - default=None, help='plot band structure and show band information.') - parser.add_argument('-d', '--dos', dest='dos', nargs='?', const=1, type=int, - default=None, help='plot density of state(DOS).') - parser.add_argument('-p', '--projected', dest='projected', nargs='?', const=1, type=int, - default=None, help='plot projected band structure or partial density of state(PDOS), should be used with `-b` or `-d`.') - parser.add_argument('-o', '--out_parsed_data', dest='out', nargs='?', const=1, type=int, - default=None, help='output projected band structure or partial density of state(PDOS) to files, should be used with `-b` or `-d`.') + parser.add_argument( + "-f", + "--file", + dest="file", + type=str, + nargs="?", + const="config.json", + default="config.json", + help="profile with format json", + ) + parser.add_argument( + "-b", + "--band", + dest="band", + nargs="?", + const=1, + type=int, + default=None, + help="plot band structure and show band information.", + ) + parser.add_argument( + "-d", + "--dos", + dest="dos", + nargs="?", + const=1, + type=int, + default=None, + help="plot density of state(DOS).", + ) + parser.add_argument( + "-p", + "--projected", + dest="projected", + nargs="?", + const=1, + type=int, + default=None, + help="plot projected band structure or partial density of state(PDOS), should be used with `-b` or `-d`.", + ) + parser.add_argument( + "-o", + "--out_parsed_data", + dest="out", + nargs="?", + const=1, + type=int, + default=None, + help="output projected band structure or partial density of state(PDOS) to files, should be used with `-b` or `-d`.", + ) parser.set_defaults(func=Show().show_cmdline) args = parser.parse_args() diff --git a/tools/plot-tools/abacus_plot/utils.py b/tools/plot-tools/abacus_plot/utils.py index 36ba1315048..1e8298b5783 100644 --- a/tools/plot-tools/abacus_plot/utils.py +++ b/tools/plot-tools/abacus_plot/utils.py @@ -1,9 +1,9 @@ -''' +""" Date: 2021-08-18 11:05:39 LastEditors: jiyuyang LastEditTime: 2021-11-08 15:16:35 Mail: jiyuyang@mail.ustc.edu.cn, 1041176461@qq.com -''' +""" import json import re @@ -17,26 +17,27 @@ def remove_empty(a: list) -> list: """Remove '' and [] in `a`""" - while '' in a: - a.remove('') + while "" in a: + a.remove("") while [] in a: a.remove([]) def handle_data(data): - data.remove('') + data.remove("") def handle_elem(elem): - elist = elem.split(' ') + elist = elem.split(" ") remove_empty(elist) # `list` will be modified in function return elist + return list(map(handle_elem, data)) def skip_notes(line: str) -> str: """Delete comments lines with '#' or '//' - :params line: line will be handled + :params line: line will be handled """ line = re.compile(r"#.*").sub("", line) line = re.compile(r"//.*").sub("", line) @@ -46,8 +47,10 @@ def skip_notes(line: str) -> str: def list_elem2strip(a: List[str], ds=string.whitespace) -> List[str]: """Strip element of list with `str` type""" + def list_strip(s): return s.strip(ds) + return list(map(list_strip, a)) @@ -90,13 +93,21 @@ def list_elem_2float(a: List[str]) -> List[float]: """ return list(map(float, a)) + # KPT class Kpt: """K-points information""" - def __init__(self, mode: str, numbers: list = [], special_k: list = [], offset: list = [0.0, 0.0, 0.0], klabel: list = []) -> None: + def __init__( + self, + mode: str, + numbers: list = [], + special_k: list = [], + offset: list = [0.0, 0.0, 0.0], + klabel: list = [], + ) -> None: """Initialize Kpt object :params mode: 'sGamma', 'MP' or 'Line' @@ -119,18 +130,21 @@ def get_kpt(self) -> str: if self.mode in ["Gamma", "MP"]: line.append("0") line.append(self.mode) - line.append(" ".join(list_elem2str(self.numbers+self.offset))) + line.append(" ".join(list_elem2str(self.numbers + self.offset))) elif self.mode == "Line": line.append(str(len(self.special_k))) line.append(self.mode) for i, k in enumerate(self.special_k): if self.klabel: - line.append(" ".join(list_elem2str( - k+[self.numbers[i]]))+'\t#'+self.klabel[i]) + line.append( + " ".join(list_elem2str(k + [self.numbers[i]])) + + "\t#" + + self.klabel[i] + ) else: - line.append(" ".join(list_elem2str(k+[self.numbers[i]]))) + line.append(" ".join(list_elem2str(k + [self.numbers[i]]))) - return '\n'.join(line) + return "\n".join(line) def write_kpt(self, filename: str): """Write k-points file @@ -138,7 +152,7 @@ def write_kpt(self, filename: str): :params filename: absolute path of k-points file """ - with open(filename, 'w') as file: + with open(filename, "w") as file: file.write(self.get_kpt()) @property @@ -147,8 +161,9 @@ def full_kpath(self): total_k = np.sum(self.numbers) spec_k_coor = np.array(self.special_k) - interval = (np.roll(spec_k_coor, -1, axis=0) - spec_k_coor) / \ - np.reshape(self.numbers, (-1, 1)) + interval = (np.roll(spec_k_coor, -1, axis=0) - spec_k_coor) / np.reshape( + self.numbers, (-1, 1) + ) max_num = np.max(self.numbers) len_num = len(self.numbers) k_coor_span = np.zeros((len_num, max_num), dtype=float) @@ -171,7 +186,8 @@ def label_special_k(self): """Label special k-points based on `numbers` list""" index = np.cumsum(np.concatenate(([1], self.numbers), axis=0))[ - :len(self.special_k)] + : len(self.special_k) + ] if self.klabel: return zip(self.klabel, index) else: @@ -206,16 +222,16 @@ def read_kpt(kpt_file: PathLike) -> Kpt: special_k.append(list_elem_2float(linesplit[:3])) numbers.append(int(linesplit[3])) if len(linesplit) == 5: - klabel.append(linesplit[4].strip('#\n ')) + klabel.append(linesplit[4].strip("#\n ")) return Kpt(mode, numbers, special_k, offset=[], klabel=klabel) def read_json(filename: PathLike) -> dict: - """ Read json file and return dict + """Read json file and return dict :params filename: json file """ - with open(filename, 'r') as file: + with open(filename, "r") as file: text = json.load(file) return text @@ -234,10 +250,10 @@ def energy_minus_efermi(energy: Sequence, efermi: float) -> np.ndarray: :params efermi: Fermi level in unit eV """ - return np.array(energy)-efermi + return np.array(energy) - efermi -angular_momentum_label = ['s', 'p', 'd', 'f', 'g'] +angular_momentum_label = ["s", "p", "d", "f", "g"] def get_angular_momentum_label(l_index: int) -> str: @@ -250,13 +266,19 @@ def get_angular_momentum_label(l_index: int) -> str: angular_momentum_name = [ - ['$s$'], - ['$p_z$', '$p_x$', '$p_y$'], - ['$d_{z^2}$', '$d_{xz}$', '$d_{yz}$', '$d_{x^2-y^2}$', '$d_{xy}$'], - ['$f_{z^3}$', '$f_{xz^2}$', '$f_{yz^2}$', '$f_{z(x^2-y^2)}$', - '$f_{xyz}$', '$f_{x(x^2-3y^2)}$', '$f_{y(3x^2-y^2)}$'], - ['$g_1$', '$g_2$', '$g_3$', '$g_4$', '$g_5$', - '$g_6$', '$g_7$', '$g_8$', '$g_9$'] + ["s"], + ["p_z", "p_x", "p_y"], + ["d_{z^2}", "d_{xz}", "d_{yz}", "d_{x^2-y^2}", "d_{xy}"], + [ + "f_{z^3}", + "f_{xz^2}", + "f_{yz^2}", + "f_{z(x^2-y^2)}", + "f_{xyz}", + "f_{x(x^2-3y^2)}", + "f_{y(3x^2-y^2)}", + ], + ["g_1", "g_2", "g_3", "g_4", "g_5", "g_6", "g_7", "g_8", "g_9"], ] @@ -270,7 +292,13 @@ def get_angular_momentum_name(l_index: int, m_index: int) -> str: return angular_momentum_name[l_index][m_index] -def parse_projected_data(orbitals, species: Union[Sequence[Any], Dict[Any, List[int]], Dict[Any, Dict[Any, List[int]]]], keyname=''): +def parse_projected_data( + orbitals, + species: Union[ + Sequence[Any], Dict[Any, List[int]], Dict[Any, Dict[Any, List[int]]] + ], + keyname="", +): """Extract projected data from file Args: @@ -306,10 +334,13 @@ def parse_projected_data(orbitals, species: Union[Sequence[Any], Dict[Any, List[ l_data = {} for m_index in mag: m_count = 0 - data_temp = np.zeros_like( - orbitals[0]["data"], dtype=float) + data_temp = np.zeros_like(orbitals[0]["data"], dtype=float) for orb in orbitals: - if orb[keyname] == elem and orb["l"] == l_index and orb["m"] == m_index: + if ( + orb[keyname] == elem + and orb["l"] == l_index + and orb["m"] == m_index + ): data_temp += orb["data"] m_count += 1 l_count += 1 @@ -322,8 +353,7 @@ def parse_projected_data(orbitals, species: Union[Sequence[Any], Dict[Any, List[ elif isinstance(l[i], list): for l_index in l[i]: count = 0 - data_temp = np.zeros_like( - orbitals[0]["data"], dtype=float) + data_temp = np.zeros_like(orbitals[0]["data"], dtype=float) for orb in orbitals: if orb[keyname] == elem and orb["l"] == l_index: data_temp += orb["data"] diff --git a/tools/plot-tools/cube_manipulator.py b/tools/plot-tools/cube_manipulator.py index aa9d3362c64..19358581c7a 100644 --- a/tools/plot-tools/cube_manipulator.py +++ b/tools/plot-tools/cube_manipulator.py @@ -3,7 +3,7 @@ def read_gaussian_cube(fcube: str): The detailed format information can be found here: https://paulbourke.net/dataformats/cube/ - In brief, + In brief, ``` [comment line1] @@ -20,18 +20,19 @@ def read_gaussian_cube(fcube: str): [data7] [data8] [data9] ... [data12] ... ``` - + Args: fcube (str): the file name of the cube file. - + Returns: data (dict): a dictionary containing the following """ import re import numpy as np - with open(fcube, 'r') as f: + + with open(fcube, "r") as f: lines = f.readlines() - + out = {} out["comment 1"] = lines[0].strip() out["comment 2"] = lines[1].strip() @@ -49,7 +50,7 @@ def read_gaussian_cube(fcube: str): out["R"] = np.array([[e11, e12, e13], [e21, e22, e23], [e31, e32, e33]]) atomz, chg, coords = [], [], [] - for line in lines[6:6+int(natom)]: + for line in lines[6 : 6 + int(natom)]: atomz.append(int(line.split()[0])) chg.append(float(line.split()[1])) coords.append(list(map(float, line.split()[2:]))) @@ -58,19 +59,20 @@ def read_gaussian_cube(fcube: str): out["coords"] = coords data = [] - for line in lines[6+int(natom):]: + for line in lines[6 + int(natom) :]: data.extend(list(map(float, line.split()))) - #out["data"] = np.array(data).reshape(int(nx), int(ny), int(nz)) # is it necessary to reshape? - out["data"] = np.array(data) # not reshaped + # out["data"] = np.array(data).reshape(int(nx), int(ny), int(nz)) # is it necessary to reshape? + out["data"] = np.array(data) # not reshaped return out + def write_gaussian_cube(data: dict, fcube: str, **kwargs): """write the Gaussian cube format volumetric data. Data should be organized as what is returned by read_cube(). - + (if present) the ndigits will be used to control the number of digits of volumetric data, while the coordination data in header of cube is fixed to 6 digits. - + format of each part is defined in the following with format string: ``` %s @@ -89,7 +91,7 @@ def write_gaussian_cube(data: dict, fcube: str, **kwargs): data (dict): the dictionary containing the cube data. fcube (str): the file name of the cube file. **kwargs: other optional arguments. - + Returns: None """ @@ -98,20 +100,44 @@ def write_gaussian_cube(data: dict, fcube: str, **kwargs): width = ndigits + 7 # temporarily there is no more format controlling options. - with open(fcube, 'w') as f: + with open(fcube, "w") as f: f.write(data["comment 1"] + "\n") f.write(data["comment 2"] + "\n") - f.write(" %4d %11.6f %11.6f %11.6f\n" % (data["natom"], data["origin"][0], data["origin"][1], data["origin"][2])) - f.write(" %4d %11.6f %11.6f %11.6f\n" % (data["nx"], data["R"][0][0], data["R"][0][1], data["R"][0][2])) - f.write(" %4d %11.6f %11.6f %11.6f\n" % (data["ny"], data["R"][1][0], data["R"][1][1], data["R"][1][2])) - f.write(" %4d %11.6f %11.6f %11.6f\n" % (data["nz"], data["R"][2][0], data["R"][2][1], data["R"][2][2])) + f.write( + " %4d %11.6f %11.6f %11.6f\n" + % (data["natom"], data["origin"][0], data["origin"][1], data["origin"][2]) + ) + f.write( + " %4d %11.6f %11.6f %11.6f\n" + % (data["nx"], data["R"][0][0], data["R"][0][1], data["R"][0][2]) + ) + f.write( + " %4d %11.6f %11.6f %11.6f\n" + % (data["ny"], data["R"][1][0], data["R"][1][1], data["R"][1][2]) + ) + f.write( + " %4d %11.6f %11.6f %11.6f\n" + % (data["nz"], data["R"][2][0], data["R"][2][1], data["R"][2][2]) + ) for i in range(int(data["natom"])): - f.write(" %4d %11.6f %11.6f %11.6f %11.6f\n" % (data["atomz"][i], data["chg"][i], data["coords"][i][0], data["coords"][i][1], data["coords"][i][2])) + f.write( + " %4d %11.6f %11.6f %11.6f %11.6f\n" + % ( + data["atomz"][i], + data["chg"][i], + data["coords"][i][0], + data["coords"][i][1], + data["coords"][i][2], + ) + ) for i in range(0, len(data["data"]), 6): - f.write(" ".join([f"%{width}.{ndigits}e" % x for x in data["data"][i:i+6]])) + f.write( + " ".join([f"%{width}.{ndigits}e" % x for x in data["data"][i : i + 6]]) + ) f.write("\n") return + def axpy(x, y=None, alpha=1.0, beta=1.0): """ Act like BLAS xAXPY function: Y = alpha * X + beta * Y. @@ -120,18 +146,19 @@ def axpy(x, y=None, alpha=1.0, beta=1.0): return alpha * x else: return alpha * x + beta * y - + + def profile1d(data: dict, axis: str): """integrate the 3D cube data to 2D plane. Args: data (dict): the dictionary containing the cube data. axis (str): the axis to be integrated. 'x' means integrate yz plane, 'y' means xz plane, 'z' means xy plane. - + Returns: data (dict): the dictionary containing the cube data. """ import numpy as np - + mat3d = data["data"].reshape(int(data["nx"]), int(data["ny"]), int(data["nz"])) if axis == "x": val = np.sum(mat3d, axis=2).sum(axis=1) @@ -146,12 +173,16 @@ def profile1d(data: dict, axis: str): data["data"] = np.vstack((var, val)).T return data + def slice2d(data: dict, prompt: str): import re import numpy as np - assert re.match(r"[xyz]=\d+(\.\d+)?", prompt), "the prompt should be like 'x=0.0', 'y=0.0', 'z=0.0'." + + assert re.match( + r"[xyz]=\d+(\.\d+)?", prompt + ), "the prompt should be like 'x=0.0', 'y=0.0', 'z=0.0'." axis, value = prompt.split("=") - value = float(value) # the fractional coordinate, between 0 and 1 + value = float(value) # the fractional coordinate, between 0 and 1 mat3d = data["data"].reshape(int(data["nx"]), int(data["ny"]), int(data["nz"])) if axis == "x": val = mat3d[int(value * data["nx"]), :, :] @@ -163,10 +194,11 @@ def slice2d(data: dict, prompt: str): data["data"] = val return data + def check(args): - """check the reasonability of the arguments. - """ + """check the reasonability of the arguments.""" import os, re + assert os.path.exists(args.inp), f"the input file {args.inp} does not exist." # no, the output file can be already existed, behavior would be overwrite. @@ -176,20 +208,29 @@ def check(args): # no, the scale can be negative. # if args.scale is not None: # assert args.scale > 0, "the scale factor should be positive." - + if args.p1d is not None: - assert args.p1d in ["x", "y", "z"], "the axis for 2D integration should be 'x', 'y' or 'z'." - + assert args.p1d in [ + "x", + "y", + "z", + ], "the axis for 2D integration should be 'x', 'y' or 'z'." + if args.s2d is not None: - assert re.match(r"[xyz]=\d+(\.\d+)?", args.s2d), "the prompt should be like 'x=0.0', 'y=0.0', 'z=0.0'." - + assert re.match( + r"[xyz]=\d+(\.\d+)?", args.s2d + ), "the prompt should be like 'x=0.0', 'y=0.0', 'z=0.0'." + if args.plus is not None: assert os.path.exists(args.plus), f"the input file {args.plus} does not exist." - + if args.minus is not None: - assert os.path.exists(args.minus), f"the input file {args.minus} does not exist." + assert os.path.exists( + args.minus + ), f"the input file {args.minus} does not exist." return + def op_init(args): """initialize the operations and fill the following dictionary. in: fcube1 @@ -220,33 +261,37 @@ def op_init(args): op["obj"] = args.minus return op + def write_profile1d(data, fprofile: str): """write the 1D profile data to a file. Args: data (dict): the dictionary returned by function profile1d. fprofile (str): the file name of the profile file. - + Returns: None """ import numpy as np - with open(fprofile, 'w') as f: + + with open(fprofile, "w") as f: f.write(f"{'# Direct coord':<13s} {'Value':<14s}\n") for i in range(len(data["data"])): f.write(f"{data['data'][i][0]:>14.8e} {data['data'][i][1]:>14.8e}\n") return + def write_slice2d(data: dict, fslice: str): """write the 2D slice data to a file. Args: data (dict): the dictionary returned by function slice2d. fslice (str): the file name of the slice file. - + Returns: None """ import numpy as np - with open(fslice, 'w') as f: + + with open(fslice, "w") as f: # first write the header: nrow, ncol = xxx, xxx shape = data["data"].shape f.write(f"# nrow, ncol = {shape[0]}, {shape[1]}\n") @@ -254,11 +299,12 @@ def write_slice2d(data: dict, fslice: str): # then write as 8 columns for i in range(len(src)): f.write(f"{src[i]:>14.8e} ") - if (i+1) % 8 == 0 and i != 0: + if (i + 1) % 8 == 0 and i != 0: f.write("\n") f.write("\n") return + def main(args): """main workflow function""" check(args) @@ -290,77 +336,140 @@ def main(args): raise ValueError("the dimension of the data is not supported") return + def _argparse(): """the interface of the script. Currently the following operations will be supported: - - basic: + + basic: -i, --inp: the input Gaussian cube file. -o, --out: the output Gaussian cube file. - - one-body operations: + + one-body operations: -s, --scale: scale the Gaussian cube file by a factor, therefore this flag is followed by a number. - advanced: + advanced: --profile1d: integrate the Gaussian cube file in 2D, therefore followed with the axis. 'x' means integrate yz plane, ... , useful for intergrating Hartree potential to get the work function. --slice: slice the Gaussian cube file along one axis, followed by string like 'x=0.0', 'y=0.0', 'z=0.0'. - - two-body operations: + + two-body operations: -p, --plus: plus the two Gaussian cube files, therefore this flag is followed by another cube file. -m, --minus: minus the two Gaussian cube files, therefore this flag is followed by another cube file. - + """ import argparse - parser = argparse.ArgumentParser(description="manipulate the Gaussian cube format volumetric data.") + + parser = argparse.ArgumentParser( + description="manipulate the Gaussian cube format volumetric data." + ) welcome = """Once meet any problem, please submit an issue at:\n https://github.com/deepmodeling/abacus-develop/issues\n """ parser.epilog = welcome parser.add_argument("-i", "--inp", type=str, help="the input Gaussian cube file.") parser.add_argument("-o", "--out", type=str, help="the output file.") - parser.add_argument("-s", "--scale", type=float, help="scale the Gaussian cube file by a factor.") - parser.add_argument("--p1d", type=str, help="integrate the Gaussian cube file in 2D, followed by the axis: 'x', ...") - parser.add_argument("--s2d", type=str, help="slice the Gaussian cube file along one axis, followed by string like 'x=0.0', 'y=0.0', 'z=0.0'. Note: should be fractional coodinate.") - parser.add_argument("-p", "--plus", type=str, help="plus the two Gaussian cube files.") - parser.add_argument("-m", "--minus", type=str, help="minus the two Gaussian cube files.") + parser.add_argument( + "-s", "--scale", type=float, help="scale the Gaussian cube file by a factor." + ) + parser.add_argument( + "--p1d", + type=str, + help="integrate the Gaussian cube file in 2D, followed by the axis: 'x', ...", + ) + parser.add_argument( + "--s2d", + type=str, + help="slice the Gaussian cube file along one axis, followed by string like 'x=0.0', 'y=0.0', 'z=0.0'. Note: should be fractional coodinate.", + ) + parser.add_argument( + "-p", "--plus", type=str, help="plus the two Gaussian cube files." + ) + parser.add_argument( + "-m", "--minus", type=str, help="minus the two Gaussian cube files." + ) # set the default value for --out parser.set_defaults(out="abacus_cube_manipulator.out") return parser.parse_args() + import unittest + + class TestCubeManipulator(unittest.TestCase): def test_argparse(self): # mock the stdin import sys + sys.argv = ["cube_manipulator.py", "-i", "test.cube", "-o", "test_out.cube"] args = _argparse() - + self.assertEqual(args.inp, "test.cube") self.assertEqual(args.out, "test_out.cube") - sys.argv = ["cube_manipulator.py", "-i", "test.cube", "-o", "test_out.cube", "-s", "2.0"] + sys.argv = [ + "cube_manipulator.py", + "-i", + "test.cube", + "-o", + "test_out.cube", + "-s", + "2.0", + ] args = _argparse() self.assertEqual(args.scale, 2.0) - sys.argv = ["cube_manipulator.py", "-i", "test.cube", "-o", "test_out.cube", "--p1d", "x"] + sys.argv = [ + "cube_manipulator.py", + "-i", + "test.cube", + "-o", + "test_out.cube", + "--p1d", + "x", + ] args = _argparse() self.assertEqual(args.p1d, "x") - sys.argv = ["cube_manipulator.py", "-i", "test.cube", "-o", "test_out.cube", "--s2d", "x=0.0"] + sys.argv = [ + "cube_manipulator.py", + "-i", + "test.cube", + "-o", + "test_out.cube", + "--s2d", + "x=0.0", + ] args = _argparse() self.assertEqual(args.s2d, "x=0.0") - sys.argv = ["cube_manipulator.py", "-i", "test.cube", "-o", "test_out.cube", "-p", "test2.cube"] + sys.argv = [ + "cube_manipulator.py", + "-i", + "test.cube", + "-o", + "test_out.cube", + "-p", + "test2.cube", + ] args = _argparse() self.assertEqual(args.plus, "test2.cube") - sys.argv = ["cube_manipulator.py", "-i", "test.cube", "-o", "test_out.cube", "-m", "test2.cube"] + sys.argv = [ + "cube_manipulator.py", + "-i", + "test.cube", + "-o", + "test_out.cube", + "-m", + "test2.cube", + ] args = _argparse() self.assertEqual(args.minus, "test2.cube") + if __name__ == "__main__": # uncomment the following line to run the unittest - #unittest.main() + # unittest.main() args = _argparse() - main(args) \ No newline at end of file + main(args) diff --git a/tools/plot-tools/examples/Si/KLINES b/tools/plot-tools/examples/Si/KLINES index 30d0e5d4cfd..200b9abf720 100644 --- a/tools/plot-tools/examples/Si/KLINES +++ b/tools/plot-tools/examples/Si/KLINES @@ -1,9 +1,9 @@ K_POINTS 6 Line -0.5 0.0 0.5 20 #X -0.0 0.0 0.0 20 #G -0.5 0.5 0.5 20 #L -0.5 0.25 0.75 20 #W -0.375 0.375 0.75 20 #K -0.0 0.0 0.0 1 #G +0.5 0.0 0.5 20 #X +0.0 0.0 0.0 20 #G +0.5 0.5 0.5 20 #L +0.5 0.25 0.75 20 #W +0.375 0.375 0.75 20 #K +0.0 0.0 0.0 1 #G diff --git a/tools/plot-tools/examples/Si/PBAND1_FIG/atom_index-1/atom_index-1-$p_x$.pdf b/tools/plot-tools/examples/Si/PBAND1_FIG/atom_index-1/atom_index-1-p_x.pdf similarity index 100% rename from tools/plot-tools/examples/Si/PBAND1_FIG/atom_index-1/atom_index-1-$p_x$.pdf rename to tools/plot-tools/examples/Si/PBAND1_FIG/atom_index-1/atom_index-1-p_x.pdf diff --git a/tools/plot-tools/examples/Si/PBAND1_FIG/atom_index-1/atom_index-1-$p_y$.pdf b/tools/plot-tools/examples/Si/PBAND1_FIG/atom_index-1/atom_index-1-p_y.pdf similarity index 100% rename from tools/plot-tools/examples/Si/PBAND1_FIG/atom_index-1/atom_index-1-$p_y$.pdf rename to tools/plot-tools/examples/Si/PBAND1_FIG/atom_index-1/atom_index-1-p_y.pdf diff --git a/tools/plot-tools/setup.py b/tools/plot-tools/setup.py index f834ab62fe2..f42a23ceee9 100644 --- a/tools/plot-tools/setup.py +++ b/tools/plot-tools/setup.py @@ -1,22 +1,22 @@ -''' +""" Date: 2021-08-21 13:28:51 LastEditors: jiyuyang LastEditTime: 2022-01-03 17:08:06 Mail: jiyuyang@mail.ustc.edu.cn, 1041176461@qq.com -''' +""" from setuptools import setup, find_packages if __name__ == "__main__": setup( - name='abacus_plot', - version='1.2.0', + name="abacus_plot", + version="1.2.0", packages=find_packages(), - description='Ploting tools for ABACUS', - author='jiyuyang', - author_email='jiyuyang@mail.ustc.edu.cn', - url='None', - entry_points={'console_scripts': ['abacus-plot=abacus_plot.main:main']}, - install_requires=['matplotlib', 'numpy', 'setuptools', 'lxml'], - python_requires='>=3.4' + description="Ploting tools for ABACUS", + author="jiyuyang", + author_email="jiyuyang@mail.ustc.edu.cn", + url="None", + entry_points={"console_scripts": ["abacus-plot=abacus_plot.main:main"]}, + install_requires=["matplotlib", "numpy", "setuptools", "lxml"], + python_requires=">=3.4", ) diff --git a/tools/qo/README.md b/tools/qo/README.md index a99c1aa4921..6d4faacc468 100644 --- a/tools/qo/README.md +++ b/tools/qo/README.md @@ -1,25 +1,52 @@ *Use Markdown render to convert this document into directly human-readable version* + # ABACUS LCAO2QO Hands-on + ## Introduction -This document is a hands-on tutorial for the ABACUS LCAO2QO tool. For basic information about QO (Quasiatomic Orbital) method, please refer to *Quasiatomic orbitals for ab initio tight-binding analysis* by *Qian et al.*: https://journals.aps.org/prb/abstract/10.1103/PhysRevB.78.245112. + +This document is a hands-on tutorial for the ABACUS LCAO2QO tool. For basic information about QO +(Quasiatomic Orbital) method, please refer to *Quasiatomic orbitals for ab initio tight-binding +analysis* by *Qian et al.*: https://journals.aps.org/prb/abstract/10.1103/PhysRevB.78.245112. + ### Basic ideas -QO is for projecting as many as possible eigenstates of a system onto a atom-centered basis set, unlike MLWFs (Maximally Localized Wannier Functions) that would produce bond-like Wannier functions for some systems. The QO is defined from an optimization problem that maximal the norm of the projection of atom-centered orbitals onto the super-plane spanned by eigenstates and constructed unoccupied states: -$\max\mathcal{L}:=\max \sum_{\mu}{\left\|\left(\sum_{n\mathbf{k}}{\hat{P}_{\psi_{n\mathbf{k}}}}+\sum_{m\mathbf{k}}{\hat{P}_{c_{m\mathbf{k}}}}\right)|A_{\mu}\rangle\right\|^2}$ -where $\hat{P}_{\psi_{n\mathbf{k}}}$ and $\hat{P}_{c_{m\mathbf{k}}}$ are the projection operators for occupied and unoccupied states, respectively. $A_{\mu}$ is the atom-centered orbital. -The former part of projection is fixed once the occupied states are determined, and the latter part is determined by selection of $Nq-Nb$ from $\sum_{m\mathbf{k}}{\hat{P}_{c_{m\mathbf{k}}}}|A_{\mu}\rangle$ states, with total number of $Nq$ and number of occupied states $Nb$. + +QO is for projecting as many as possible eigenstates of a system onto a atom-centered basis set, +unlike MLWFs (Maximally Localized Wannier Functions) that would produce bond-like Wannier functions +for some systems. The QO is defined from an optimization problem that maximal the norm of the +projection of atom-centered orbitals onto the super-plane spanned by eigenstates and constructed +unoccupied states:\ +$\max\mathcal{L}:=\max \sum_{\mu}{\left\|\left(\sum_{n\mathbf{k}}{\hat{P}_{\psi_{n\mathbf{k}}}}+\sum_{m\mathbf{k}}{\hat{P}_{c_{m\mathbf{k}}}}\right)|A_{\mu}\rangle\right\|^2}$\ +where $\hat{P}_{\psi_{n\mathbf{k}}}$ and $\hat{P}_{c_{m\mathbf{k}}}$ are the projection operators +for occupied and unoccupied states, respectively. $A_{\mu}$ is the atom-centered orbital.\ +The former part of projection is fixed once the occupied states are determined, and the latter part +is determined by selection of $Nq-Nb$ from +$\sum_{m\mathbf{k}}{\hat{P}_{c_{m\mathbf{k}}}}|A_{\mu}\rangle$ states, with total number of $Nq$ and +number of occupied states $Nb$. + ### Formulation -See Github issue #3640 for details: https://github.com/deepmodeling/abacus-develop/issues/3640 + +See Github issue #3640 for details: https://github.com/deepmodeling/abacus-develop/issues/3640 + ## Prerequisites + - ABACUS - Python3 - Numpy - Scipy - Matplotlib (optional) + ## Usage + ### Basis set selection -ABACUS provides various kinds of atom-centered orbitals construction, such as hydrogen-like orbitals, exponentially decay scaled pseudowavefunctions, single zeta (not implemented, develop up to user actual needs). Select orbitals that fit most to the system you are interested in. + +ABACUS provides various kinds of atom-centered orbitals construction, such as hydrogen-like +orbitals, exponentially decay scaled pseudowavefunctions, single zeta (not implemented, develop up +to user actual needs). Select orbitals that fit most to the system you are interested in. + ### Input file of ABACUS + To run QO analysis, in ABACUS INPUT file, following keywords are needed to be set: + ```bash qo_switch 1 qo_basis hydrogen @@ -27,13 +54,27 @@ qo_strategy energy-valence qo_thr 1.0e-10 #qo_screening_coeff 0.1 ``` + - `qo_switch` is a switch to turn on QO analysis. -- `qo_basis` is the basis set selection, parameters above define the hydrogen-like orbital construction -- `qo_strategy` is the strategy to set what orbitals needed to construct. For hydrogen-like orbitals, for example if element is Cu (1s2 2s2 2p6 3s2 3p6 3d10 4s1), `energy-valence` corresponds to construct only 3p 3d and 4s orbitals, `energy-full` corresponds to construct all orbitals, `minimal-nodeless` corresponds to construct 1s, 2p, 3d and 4f orbitals, `minimal-valence` corresponds to construct 4s 4p 4d 4f orbitals. For more information about this keyword, please refer to ABACUS manual: https://abacus.deepmodeling.com/en/latest/advanced/input_files/input-main.html#qo-strategy -- `qo_thr` is the threshold to determine the realspace tailing of orbitals, which is used to determine the cutoff radius of orbitals. Default value is 1.0e-10. -- `qo_screening_coeff`, for `qo_basis hydrogen` it controls whether use Slater screening coefficients to include many-electron effect into the orbitals. Any float number as value will turn on this feature. Default value is off. +- `qo_basis` is the basis set selection, parameters above define the hydrogen-like orbital + construction +- `qo_strategy` is the strategy to set what orbitals needed to construct. For hydrogen-like + orbitals, for example if element is Cu (1s2 2s2 2p6 3s2 3p6 3d10 4s1), `energy-valence` + corresponds to construct only 3p 3d and 4s orbitals, `energy-full` corresponds to construct all + orbitals, `minimal-nodeless` corresponds to construct 1s, 2p, 3d and 4f orbitals, + `minimal-valence` corresponds to construct 4s 4p 4d 4f orbitals. For more information about this + keyword, please refer to ABACUS manual: + https://abacus.deepmodeling.com/en/latest/advanced/input_files/input-main.html#qo-strategy +- `qo_thr` is the threshold to determine the realspace tailing of orbitals, which is used to + determine the cutoff radius of orbitals. Default value is 1.0e-10. +- `qo_screening_coeff`, for `qo_basis hydrogen` it controls whether use Slater screening + coefficients to include many-electron effect into the orbitals. Any float number as value will + turn on this feature. Default value is off. + +For some systems, pseudowavefunction works better than hydrogen-like orbitals (but not all +pseudopotential has pseudowavefunction in file, check your pseudopotential file before run). To use +pseudowavefunction as `qo_basis`, set as following: -For some systems, pseudowavefunction works better than hydrogen-like orbitals (but not all pseudopotential has pseudowavefunction in file, check your pseudopotential file before run). To use pseudowavefunction as `qo_basis`, set as following: ```bash qo_switch 1 qo_basis pswfc @@ -41,35 +82,62 @@ qo_strategy all qo_thr 1.0e-10 qo_screening_coeff 0.5 ``` -For `qo_basis pswfc`, `qo_screening_coeff` is necessary and for Si single crystal the optimal value is tested to be `0.5`. Test on this parameter should be done for different systems. A larger value will result in more localized orbitals. + +For `qo_basis pswfc`, `qo_screening_coeff` is necessary and for Si single crystal the optimal value +is tested to be `0.5`. Test on this parameter should be done for different systems. A larger value +will result in more localized orbitals. + ### Output file of ABACUS -Once the calculation is done, the output file will contain the QO analysis results. The QO analysis results are stored in `OUT.${suffix}` directory, where `${suffix}` is set in `INPUT` and default is `ABACUS`. You will find following files: + +Once the calculation is done, the output file will contain the QO analysis results. The QO analysis +results are stored in `OUT.${suffix}` directory, where `${suffix}` is set in `INPUT` and default is +`ABACUS`. You will find following files: + ```bash data-0-H ... data-0-S ... ``` -These files are Hamiltonian and overlap matrix of numerical atomic orbitals basis sets. For each kpoint a pair of these files will be generated, and different spin channels are defined as different kpoints. + +These files are Hamiltonian and overlap matrix of numerical atomic orbitals basis sets. For each +kpoint a pair of these files will be generated, and different spin channels are defined as different +kpoints. + ```bash WFC_NAO_K1.txt ... ``` -These files are eigenstates represented by numerical atomic orbital basis sets. For each kpoint a file will be generated. + +These files are eigenstates represented by numerical atomic orbital basis sets. For each kpoint a +file will be generated. + ```bash QO_ovlp_0.dat ... ``` -This file contains information of $\langle A_\mu(\mathbf{k})|\phi_\nu(\mathbf{k})\rangle$, file name indiced by kpoint. + +This file contains information of $\langle A_\mu(\mathbf{k})|\phi_\nu(\mathbf{k})\rangle$, file name +indiced by kpoint. + ```bash QO_supercells.dat ``` -This file stores information of supercell considered when calculating two-center-integrals, will be usefull in kpoint extrapolation. + +This file stores information of supercell considered when calculating two-center-integrals, will be +usefull in kpoint extrapolation. + ```bash kpoints istate.info running_scf.log ... ``` + Basic output files of ABACUS. + ### Run `postprocess.py` -After the calculation is done, run `postprocess.py` to generate QO analysis results. The script will read the output files of ABACUS and generate the QO analysis results. Following defines an example of `postprocess.py`: + +After the calculation is done, run `postprocess.py` to generate QO analysis results. The script will +read the output files of ABACUS and generate the QO analysis results. Following defines an example +of `postprocess.py`: + ```python if __name__ == "__main__": @@ -91,7 +159,19 @@ if __name__ == "__main__": elif run_type == "unittest": unittest.main() ``` -The `production` function will read the output files of ABACUS and generate the QO analysis results. The `path` is the path to the output files of ABACUS. `nkpts` is the number of kpoints. `ib_min` and `ib_max` are the range of orbitals to be considered. `eig_thr` is the threshold to determine the eigenstates to be considered. `error_estimation_with_lcao` is a switch to turn on error estimation with LCAO. If set to `True`, the script will calculate the error estimation with LCAO. Collect information output by `production(...)` function. The `hqos_k` and `sqos_k` are the Hamiltonian and overlap matrix of QO basis sets. The `kvecs_d` is the direct coordinates of kpoints. -QO postprocess is programmed with unittest, therefore to run the script, set `run_type` to `production` and run the script (but mostly you don't need this). + +The `production` function will read the output files of ABACUS and generate the QO analysis results. +The `path` is the path to the output files of ABACUS. `nkpts` is the number of kpoints. `ib_min` and +`ib_max` are the range of orbitals to be considered. `eig_thr` is the threshold to determine the +eigenstates to be considered. `error_estimation_with_lcao` is a switch to turn on error estimation +with LCAO. If set to `True`, the script will calculate the error estimation with LCAO. Collect +information output by `production(...)` function. The `hqos_k` and `sqos_k` are the Hamiltonian and +overlap matrix of QO basis sets. The `kvecs_d` is the direct coordinates of kpoints.\ +QO postprocess is programmed with unittest, therefore to run the script, set `run_type` to +`production` and run the script (but mostly you don't need this). + ## Acknowledgement -ABACUS LCAO2QO module uses two-center-integrator module refactored by @jinzx10, who also helps in code debugging. @mohanchen, @dyzheng, @WHUweiqingzhou and @QG-phys provide suggestions on code maintainance and participate discussion in technical aspects. \ No newline at end of file + +ABACUS LCAO2QO module uses two-center-integrator module refactored by @jinzx10, who also helps in +code debugging. @mohanchen, @dyzheng, @WHUweiqingzhou and @QG-phys provide suggestions on code +maintainance and participate discussion in technical aspects. diff --git a/tools/qo/examples/STRU b/tools/qo/examples/STRU index 069387c4550..3a303d8924f 100644 --- a/tools/qo/examples/STRU +++ b/tools/qo/examples/STRU @@ -7,7 +7,7 @@ NUMERICAL_ORBITAL ./Si_gga_8au_100Ry_2s2p1d.orb LATTICE_CONSTANT -1.8897261258369282 #Lattice constant +1.8897261258369282 #Lattice constant LATTICE_VECTORS 0.0000000000 2.7218510000 2.7218510000 @@ -15,9 +15,9 @@ LATTICE_VECTORS 2.7218510000 2.7218510000 0.0000000000 ATOMIC_POSITIONS -Direct #Cartesian(Unit is LATTICE_CONSTANT) -Si #Name of element -0.0 #Magnetic for this element. -2 #Number of atoms -0.00 0.00 0.00 1 1 1 #x,y,z, move_x, move_y, move_z +Direct #Cartesian(Unit is LATTICE_CONSTANT) +Si #Name of element +0.0 #Magnetic for this element. +2 #Number of atoms +0.00 0.00 0.00 1 1 1 #x,y,z, move_x, move_y, move_z 0.25 0.25 0.25 1 1 1 diff --git a/tools/qo/examples/reference/band/STRU b/tools/qo/examples/reference/band/STRU index 069387c4550..3a303d8924f 100644 --- a/tools/qo/examples/reference/band/STRU +++ b/tools/qo/examples/reference/band/STRU @@ -7,7 +7,7 @@ NUMERICAL_ORBITAL ./Si_gga_8au_100Ry_2s2p1d.orb LATTICE_CONSTANT -1.8897261258369282 #Lattice constant +1.8897261258369282 #Lattice constant LATTICE_VECTORS 0.0000000000 2.7218510000 2.7218510000 @@ -15,9 +15,9 @@ LATTICE_VECTORS 2.7218510000 2.7218510000 0.0000000000 ATOMIC_POSITIONS -Direct #Cartesian(Unit is LATTICE_CONSTANT) -Si #Name of element -0.0 #Magnetic for this element. -2 #Number of atoms -0.00 0.00 0.00 1 1 1 #x,y,z, move_x, move_y, move_z +Direct #Cartesian(Unit is LATTICE_CONSTANT) +Si #Name of element +0.0 #Magnetic for this element. +2 #Number of atoms +0.00 0.00 0.00 1 1 1 #x,y,z, move_x, move_y, move_z 0.25 0.25 0.25 1 1 1 diff --git a/tools/qo/examples/reference/scf/STRU b/tools/qo/examples/reference/scf/STRU index 069387c4550..3a303d8924f 100644 --- a/tools/qo/examples/reference/scf/STRU +++ b/tools/qo/examples/reference/scf/STRU @@ -7,7 +7,7 @@ NUMERICAL_ORBITAL ./Si_gga_8au_100Ry_2s2p1d.orb LATTICE_CONSTANT -1.8897261258369282 #Lattice constant +1.8897261258369282 #Lattice constant LATTICE_VECTORS 0.0000000000 2.7218510000 2.7218510000 @@ -15,9 +15,9 @@ LATTICE_VECTORS 2.7218510000 2.7218510000 0.0000000000 ATOMIC_POSITIONS -Direct #Cartesian(Unit is LATTICE_CONSTANT) -Si #Name of element -0.0 #Magnetic for this element. -2 #Number of atoms -0.00 0.00 0.00 1 1 1 #x,y,z, move_x, move_y, move_z +Direct #Cartesian(Unit is LATTICE_CONSTANT) +Si #Name of element +0.0 #Magnetic for this element. +2 #Number of atoms +0.00 0.00 0.00 1 1 1 #x,y,z, move_x, move_y, move_z 0.25 0.25 0.25 1 1 1 diff --git a/tools/qo/postprocess.py b/tools/qo/postprocess.py index d4b7aeae615..1fb633292be 100644 --- a/tools/qo/postprocess.py +++ b/tools/qo/postprocess.py @@ -25,8 +25,8 @@ | the parameters in the `if __name__ == "__main__":` block. | 2. As a module: | - Import this script as a module in another script. -| - Call the function `production` with the appropriate parameters, the -| function `production` returns the Hamiltonian and overlap matrices in +| - Call the function `production` with the appropriate parameters, the +| function `production` returns the Hamiltonian and overlap matrices in | QO representation along with valid kpoints direct coordinates. | 9999. Unittest: | - Run the script with the command `python all_in_one.py` to perform @@ -37,17 +37,21 @@ """ import numpy as np + + # TESTED def cxx_topycomplex(num: str): """cxx prints complex numbers in the form (a,b)""" - num = num.replace('(', '').replace(')', '') - num = num.split(',') + num = num.replace("(", "").replace(")", "") + num = num.split(",") return complex(float(num[0]), float(num[1])) + + # TESTED def read_mat_hs(fhs): """""" - with open(fhs, 'r') as f: - data = "".join(f.readlines()).replace('\n', '').split() + with open(fhs, "r") as f: + data = "".join(f.readlines()).replace("\n", "").split() size = int(data[0]) indexing = [] for i in range(size): @@ -60,18 +64,20 @@ def read_mat_hs(fhs): for i in range(size): mat[i, i] = mat[i, i] / 2 return mat + + # TESTED def read_lowf(flowf): """read the lowf matrix in k-space, and the k-vector. - + Args: flowf (str): path to the file containing the lowf matrix - + Returns: np.ndarray: lowf matrix in k-space np.ndarray: k-vector """ - with open(flowf, 'r') as f: + with open(flowf, "r") as f: lines = [line.strip() for line in f.readlines()] for line in lines: if line.endswith("(number of bands)"): @@ -92,25 +98,30 @@ def read_lowf(flowf): if line.count(" ") != 2: # it means it is a band rather than coordinates of kpoint nums = line.split() - c = [complex(float(nums[i]), float(nums[i+1])) for i in range(0, len(nums), 2)] + c = [ + complex(float(nums[i]), float(nums[i + 1])) + for i in range(0, len(nums), 2) + ] for i in range(len(c)): lowf_k[ilocal, ib] = c[i] ilocal += 1 else: kvec_c = np.array([float(x) for x in line.split()]) return lowf_k, kvec_c + + # TESTED def read_ao_proj(fao_proj): """Read the atomic orbital projection matrix in k-space, and the k-vector. - + Args: fao_proj (str): path to the file containing the atomic orbital projection matrix - + Returns: np.ndarray: atomic orbital projection matrix in k-space np.ndarray: k-vector """ - with open(fao_proj, 'r') as f: + with open(fao_proj, "r") as f: lines = [line.strip() for line in f.readlines()] kvec_d = None if lines[0].startswith("KPOINT_COORDINATE"): @@ -125,16 +136,22 @@ def read_ao_proj(fao_proj): ao_proj[i, j] = nums[j] # because in ao_proj, the row index is AO, we need to dagger it return ao_proj.conj().T, kvec_d + + # TESTED import os -def read(path: str, - nk: int, - read_H: bool = True, - read_S: bool = True, - read_LOWF: bool = True, - read_QO: bool = True) -> tuple[list, list, list, list, list]: + + +def read( + path: str, + nk: int, + read_H: bool = True, + read_S: bool = True, + read_LOWF: bool = True, + read_QO: bool = True, +) -> tuple[list, list, list, list, list]: """Read H(k), S(k), LOWF(k), and <\phi(k)|A(k)> from ABACUS output files. - + Args: path (str): path to the directory containing the output files nk (int): number of kpoints @@ -142,7 +159,7 @@ def read(path: str, read_S (bool, optional): whether to read S(k). Defaults to True. read_LOWF (bool, optional): whether to read LOWF(k). Defaults to True. read_QO (bool, optional): whether to read <\phi(k)|A(k)>. Defaults to True. - + Returns: tuple[list, list, list, list, list]: H(k), S(k), LOWF(k), <\phi(k)|A(k)>, k-vectors """ @@ -169,28 +186,34 @@ def read(path: str, kvecs_d.append(kvec_d) return hs_k, ss_k, lowfs_k, aos_proj_k, kvecs_d + + # TESTED def cal_denmat(lowf_k: np.ndarray) -> np.ndarray: """calculate the density matrix from the lowf matrix. - + Args: lowf_k (np.ndarray): lowf matrix in k-space - + Returns: np.ndarray: density matrix in k-space """ - return lowf_k@lowf_k.conj().T + return lowf_k @ lowf_k.conj().T + + # TESTED import scipy as sp + + def lowdin_onW(s_k: np.ndarray, denmat_k: np.ndarray, ao_proj_k: np.ndarray, m: int): """Perform Lowdin orthogonalization on the W matrix, which is defined as W = A^+ * (S^-1 - D) * A. - + Args: s_k (np.ndarray): overlap matrix in k-space denmat_k (np.ndarray): density matrix in k-space ao_proj_k (np.ndarray): atomic orbital projection matrix in k-space m (int): number of bands wanted - + Returns: np.ndarray: the lowdin orthogonalized matrix in the quasi-atomic orbital basis, can check orthonormality with overlap matrix @@ -199,48 +222,58 @@ def lowdin_onW(s_k: np.ndarray, denmat_k: np.ndarray, ao_proj_k: np.ndarray, m: ncol = s_k.shape[1] assert nrow == ncol sinv_k = np.linalg.solve(s_k, np.eye(N=nrow, M=ncol, dtype=np.complex128)) - W_mat = ao_proj_k.conj().T@(sinv_k - denmat_k)@ao_proj_k + W_mat = ao_proj_k.conj().T @ (sinv_k - denmat_k) @ ao_proj_k # forcely let diagonal elements to be real W_mat = (W_mat + W_mat.conj().T) / 2 # diagonalize W and get only m largest eigenvalues and corresponding eigenvectors eigvals, eigvecs = sp.linalg.eigh(W_mat) eigvals = eigvals[-m:] eigvecs = eigvecs[:, -m:] - lambdas = np.diag(1.0/np.sqrt(eigvals)) - - return (sinv_k - denmat_k)@ao_proj_k@eigvecs@lambdas + lambdas = np.diag(1.0 / np.sqrt(eigvals)) + + return (sinv_k - denmat_k) @ ao_proj_k @ eigvecs @ lambdas # call return as lowf_k_bar + + # TESTED -def cal_tb_hs(h_k: np.ndarray, s_k: np.ndarray, denmat_k_tilde: np.ndarray, ao_proj_k: np.ndarray, norm_thr: float = 1e-10): +def cal_tb_hs( + h_k: np.ndarray, + s_k: np.ndarray, + denmat_k_tilde: np.ndarray, + ao_proj_k: np.ndarray, + norm_thr: float = 1e-10, +): """calculate the tight-binding Hamiltonian and overlap matrix in the quasi-atomic orbital basis. - + Args: h_k (np.ndarray): Hamiltonian matrix in k-space s_k (np.ndarray): overlap matrix in k-space denmat_k_tilde (np.ndarray): density matrix in k-space ao_proj_k (np.ndarray): atomic orbital projection matrix in k-space norm_thr (float, optional): threshold for the norm of quasi-atomic orbitals. Defaults to 1e-10. - + Returns: tuple: tight-binding Hamiltonian and overlap matrix in the quasi-atomic orbital basis. """ - qo_k = denmat_k_tilde@ao_proj_k + qo_k = denmat_k_tilde @ ao_proj_k # normalize qo_k nqo = qo_k.shape[1] for iqo in range(nqo): - norm_qo = np.sqrt(qo_k[:, iqo].conj().T@s_k@qo_k[:, iqo]) + norm_qo = np.sqrt(qo_k[:, iqo].conj().T @ s_k @ qo_k[:, iqo]) if norm_qo < norm_thr: raise ValueError(f"Norm of qo_k is too small: norm < {norm_thr}.") qo_k[:, iqo] = qo_k[:, iqo] / norm_qo - - hqo_k = qo_k.conj().T@h_k@qo_k - sqo_k = qo_k.conj().T@s_k@qo_k + + hqo_k = qo_k.conj().T @ h_k @ qo_k + sqo_k = qo_k.conj().T @ s_k @ qo_k return hqo_k, sqo_k + + # TESTED def kR_transform(dst, mats_in: list, srcs: list, direction: str = "R->k"): """single-side transformation from k-space to R-space, or from R-space to k-space. - + Args: dst (np.ndarray): destination vector mats_in (list): input matrices @@ -252,51 +285,71 @@ def kR_transform(dst, mats_in: list, srcs: list, direction: str = "R->k"): """ mat_out = np.zeros_like(mats_in[0], dtype=np.complex128) if len(mats_in) != len(srcs): - print(f"Number of input matrices and source vectors are not equal: {len(mats_in)} (num of mats) != {len(srcs)} (num of srcs).") + print( + f"Number of input matrices and source vectors are not equal: {len(mats_in)} (num of mats) != {len(srcs)} (num of srcs)." + ) print(f"Shape of first matrix: {mats_in[0].shape}.") assert False - phase = 0.0+1.0j if direction == "R->k" else 0.0-1.0j + phase = 0.0 + 1.0j if direction == "R->k" else 0.0 - 1.0j for mat_in, src in zip(mats_in, srcs): arg = np.exp(phase * 2.0 * np.pi * np.dot(dst, src)) mat_out += arg * mat_in return mat_out / np.sqrt(len(mats_in)) + + # TESTED def k_extrapolation(mats_k: list, kvecs_in: list, Rs: list, kvecs_out: list): """for kpoint extrapolation, from k-space to R-space, and then back to k-space. - + Args: mats_k (list): input matrices in k-space kvecs_in (list): input k-vectors Rs (list): supercell vectors kvecs_out (list): output k-vectors - + Returns: list: output matrices in k-space """ - mats_R = [kR_transform(Rs[i], mats_k, kvecs_in, direction="k->R") for i in range(len(Rs))] - mats_kpath = [kR_transform(kvecs_out[i], mats_R, Rs, direction="R->k") for i in range(len(kvecs_out))] + mats_R = [ + kR_transform(Rs[i], mats_k, kvecs_in, direction="k->R") for i in range(len(Rs)) + ] + mats_kpath = [ + kR_transform(kvecs_out[i], mats_R, Rs, direction="R->k") + for i in range(len(kvecs_out)) + ] return mats_kpath -def norm_filter_k(denmat_k: np.ndarray, s_k: np.ndarray, ao_proj_k: np.ndarray, norm_thr: float = 1e-10): + +def norm_filter_k( + denmat_k: np.ndarray, + s_k: np.ndarray, + ao_proj_k: np.ndarray, + norm_thr: float = 1e-10, +): """filter out unbounded states represented by norms of atomic orbitals. - + Args: denmat_k (np.ndarray): density matrix in k-space s_k (np.ndarray): overlap matrix in k-space ao_proj_k (np.ndarray): atomic orbital projection matrix in k-space norm_thr (float, optional): threshold for the norm of atomic orbitals. Defaults to 1e-10. - + Returns: list: indices of unbounded states """ - ao_k = denmat_k@ao_proj_k - norms = [np.sqrt(ao_k[:, iao].conj().T@s_k@ao_k[:, iao]) for iao in range(ao_k.shape[1])] + ao_k = denmat_k @ ao_proj_k + norms = [ + np.sqrt(ao_k[:, iao].conj().T @ s_k @ ao_k[:, iao]) + for iao in range(ao_k.shape[1]) + ] unbounded_states = [iqo for iqo, norm in enumerate(norms) if norm < norm_thr] return unbounded_states + def nao_space_reduce(selected_indices: list, s_k: np.ndarray): return s_k[:, selected_indices] + """Expect a file contain information describing row and column indices, like @@ -307,8 +360,10 @@ def nao_space_reduce(selected_indices: list, s_k: np.ndarray): """ + + def read_matrix_index(findex: str): - with open(findex, 'r') as f: + with open(findex, "r") as f: lines = [line.strip() for line in f.readlines()] # return bidirectional maps, tuple to index and index to tuple # row index @@ -323,69 +378,99 @@ def read_matrix_index(findex: str): col_index_inv = {i: index for i, index in enumerate(col_index)} return row_index, row_index_inv, col_index, col_index_inv + import itertools as it + + def mats_hs_k(path: str, nk: int, ib_min: int, ib_max: int = -1, qo: bool = True): print("Number of kpoints: ", nk) hs_k, ss_k, lowfs_k, aos_proj_k, kvecs_d = read(path, nk) - lowfs_k = lowfs_k if ib_max == -1 else [lowfs_k[ik][:, ib_min:ib_max] for ik in range(nk)] + lowfs_k = ( + lowfs_k if ib_max == -1 else [lowfs_k[ik][:, ib_min:ib_max] for ik in range(nk)] + ) if not qo: return hs_k, ss_k, kvecs_d else: # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - # present is TZDP, 3s3p2d, arrange like [1s, 2s, 3s, 1p-1, 1p0, 1p1, 2p-1, 2p0, 2p1, 3p-1, 3p0, 3p1, 1d-2, 1d-1, 1d0, 1d1, 1d2, 2d-2, 2d-1, 2d0, 2d1, 2d2] + # present is TZDP, 3s3p2d, arrange like [1s, 2s, 3s, 1p-1, 1p0, 1p1, 2p-1, 2p0, 2p1, 3p-1, 3p0, 3p1, 1d-2, 1d-1, 1d0, 1d1, 1d2, 2d-2, 2d-1, 2d0, 2d1, 2d2] # 0 1 2 3 4 5 6 7 8 9 10 11 12 # for DZP, 2s2p1d, arrange like [1s, 2s, 1p-1, 1p0, 1p1, 2p-1, 2p0, 2p1, 1d-2, 1d-1, 1d0, 1d1, 1d2] # only want 1s1p # therefore the szv_indices from TZDP: - #szv_indices = [0, 3, 4, 5, 22, 25, 26, 27] + # szv_indices = [0, 3, 4, 5, 22, 25, 26, 27] # therefore the szv_indices from DZP: - #szv_indices = [0, 2, 3, 4, 13, 15, 16, 17] - #dzp_indices = [0, 1, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15, 16, 22, 23, 25, 26, 27, 28, 29, 30, 34, 35, 36, 37, 38] - #aos_proj_k = [ss_k[ik][:, szv_indices] for ik in range(nk)] - #print("Shape of ao_proj_k: ", aos_proj_k[0].shape) # (8, 44), 8 is the number of selected atomic orbitals, 44 is the number of numerical atomic orbitals - #aos_proj_k = ss_k - + # szv_indices = [0, 2, 3, 4, 13, 15, 16, 17] + # dzp_indices = [0, 1, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15, 16, 22, 23, 25, 26, 27, 28, 29, 30, 34, 35, 36, 37, 38] + # aos_proj_k = [ss_k[ik][:, szv_indices] for ik in range(nk)] + # print("Shape of ao_proj_k: ", aos_proj_k[0].shape) # (8, 44), 8 is the number of selected atomic orbitals, 44 is the number of numerical atomic orbitals + # aos_proj_k = ss_k + nband = lowfs_k[0].shape[1] print("Number of bands selected: ", nband) m = aos_proj_k[0].shape[1] - nband print("Calculating quasi-atomic orbitals, number of bands unoccupied: ", m) denmats_k = [cal_denmat(lowf_k) for lowf_k in lowfs_k] - ubsts_k = [norm_filter_k(denmat_k=denmats_k[ik], s_k=ss_k[ik], ao_proj_k=aos_proj_k[ik], norm_thr=1e-8) for ik in range(nk)] + ubsts_k = [ + norm_filter_k( + denmat_k=denmats_k[ik], + s_k=ss_k[ik], + ao_proj_k=aos_proj_k[ik], + norm_thr=1e-8, + ) + for ik in range(nk) + ] iks_ubsts = [ik for ik, ubsts in enumerate(ubsts_k) if len(ubsts) > 0] print("Kpoints with unbounded states: ", iks_ubsts) - lowfs_bar_k = [lowdin_onW(s_k=ss_k[ik], - denmat_k=denmats_k[ik], - ao_proj_k=aos_proj_k[ik], - m=m) for ik in range(nk)] - lowfs_tilde_k = [np.concatenate((lowfs_k[ik], lowfs_bar_k[ik]), axis=1) for ik in range(nk)] - _one = [lowf_tilde_k.conj().T@ss_k[ik]@lowf_tilde_k for ik, lowf_tilde_k in enumerate(lowfs_tilde_k)] + lowfs_bar_k = [ + lowdin_onW( + s_k=ss_k[ik], denmat_k=denmats_k[ik], ao_proj_k=aos_proj_k[ik], m=m + ) + for ik in range(nk) + ] + lowfs_tilde_k = [ + np.concatenate((lowfs_k[ik], lowfs_bar_k[ik]), axis=1) for ik in range(nk) + ] + _one = [ + lowf_tilde_k.conj().T @ ss_k[ik] @ lowf_tilde_k + for ik, lowf_tilde_k in enumerate(lowfs_tilde_k) + ] # immediate check of orthonormality for ik in range(nk): - for i, j in it.product(range(nband+m), repeat=2): + for i, j in it.product(range(nband + m), repeat=2): if i != j: - #print(_one[ik][i, j]) - assert abs(_one[ik][i, j].real) < 1e-6 and abs(_one[ik][i, j].imag) < 1e-6 + # print(_one[ik][i, j]) + assert ( + abs(_one[ik][i, j].real) < 1e-6 + and abs(_one[ik][i, j].imag) < 1e-6 + ) else: - #print(_one[ik][i, j]) - assert abs(_one[ik][i, j].real - 1) < 1e-5 and abs(_one[ik][i, j].imag) < 1e-6 + # print(_one[ik][i, j]) + assert ( + abs(_one[ik][i, j].real - 1) < 1e-5 + and abs(_one[ik][i, j].imag) < 1e-6 + ) # go on denmats_tilde_k = [cal_denmat(lowf_tilde_k) for lowf_tilde_k in lowfs_tilde_k] hqos_k, sqos_k = [], [] for ik in range(nk): - hqo_k, sqo_k = cal_tb_hs(hs_k[ik], ss_k[ik], denmats_tilde_k[ik], aos_proj_k[ik]) + hqo_k, sqo_k = cal_tb_hs( + hs_k[ik], ss_k[ik], denmats_tilde_k[ik], aos_proj_k[ik] + ) hqos_k.append(hqo_k) sqos_k.append(sqo_k) return hqos_k, sqos_k, kvecs_d + def monkhorst_pack(size): """Construct a uniform sampling of k-space of given size.""" if np.less_equal(size, 0).any(): - raise ValueError(f'Illegal size: {list(size)}') + raise ValueError(f"Illegal size: {list(size)}") kpts = np.indices(size).transpose((1, 2, 3, 0)).reshape((-1, 3)) - return (kpts - np.array(size)//2) + return kpts - np.array(size) // 2 -def bad_condition_diag(Hk, Sk, eig_thr = 1e-10): + +def bad_condition_diag(Hk, Sk, eig_thr=1e-10): """diagonalize the generalized eigenvalue problem Hk * x = e * Sk * x, and return the eigenvalues. Args: @@ -398,25 +483,28 @@ def bad_condition_diag(Hk, Sk, eig_thr = 1e-10): """ ndim = Hk.shape[0] s_eigvals, s_eigvecs = np.linalg.eigh(Sk) - #print("eigenvalues of sk:\n", s_eigvals) + # print("eigenvalues of sk:\n", s_eigvals) s_eigvecs = s_eigvecs[:, s_eigvals > eig_thr] s_eigvals = s_eigvals[s_eigvals > eig_thr] - s_eigvals = np.diag(1.0/np.sqrt(s_eigvals)) + s_eigvals = np.diag(1.0 / np.sqrt(s_eigvals)) s_eigvecs = np.dot(s_eigvecs, s_eigvals) Hk = np.dot(np.conj(s_eigvecs.T), np.dot(Hk, s_eigvecs)) eigs = np.linalg.eigvalsh(Hk) # fill in the missing eigenvalues with a large number - eigs = np.concatenate((eigs, np.ones(ndim-len(eigs))*1e6)) + eigs = np.concatenate((eigs, np.ones(ndim - len(eigs)) * 1e6)) return eigs -def production(path: str, # path of OUT.${suffix} folder - nkpts: int, # number of kpoints in KPT file - ib_min: int = 0, # minimum index of bands selected to reproduce - ib_max: int = -1, # maximum index of bands selected to reproduce - diag_thr: float = 1e-10, # threshold for filtering out linear dependent components - error_estimation_with_lcao: bool = False): # whether to estimate errors with LCAO + +def production( + path: str, # path of OUT.${suffix} folder + nkpts: int, # number of kpoints in KPT file + ib_min: int = 0, # minimum index of bands selected to reproduce + ib_max: int = -1, # maximum index of bands selected to reproduce + diag_thr: float = 1e-10, # threshold for filtering out linear dependent components + error_estimation_with_lcao: bool = False, +): # whether to estimate errors with LCAO """Production code for the whole process of calculating Hamiltonian and overlap matrices in QO basis. - + Args: path (str): path to the directory containing the output files nkpts (int): number of kpoints @@ -424,7 +512,7 @@ def production(path: str, # path of OUT.${suff ib_max (int, optional): maximum index of bands selected to reproduce. Defaults to -1. diag_thr (float, optional): threshold for filtering out linear dependent components. Defaults to 1e-10. error_estimation_with_lcao (bool, optional): whether to estimate errors with LCAO. Defaults to False. - + Returns: list: Hamiltonian matrices in QO basis list: overlap matrices in QO basis @@ -432,18 +520,29 @@ def production(path: str, # path of OUT.${suff """ # first calculate things repsented by QO basis hqos_k, sqos_k, kvecs_d = mats_hs_k(path, nkpts, ib_min, ib_max, qo=True) - eigs_qo = [bad_condition_diag(hqos_k[ik], sqos_k[ik], diag_thr) for ik in range(nkpts)] + eigs_qo = [ + bad_condition_diag(hqos_k[ik], sqos_k[ik], diag_thr) for ik in range(nkpts) + ] eigs_qo = np.asarray(eigs_qo) # then calculate things represented by AO basis, if necessary if error_estimation_with_lcao: haos_k, saos_k, kvecs_d = mats_hs_k(path, nkpts, ib_min, ib_max, qo=False) - eigs_ao = [bad_condition_diag(haos_k[ik], saos_k[ik], diag_thr) for ik in range(nkpts)] + eigs_ao = [ + bad_condition_diag(haos_k[ik], saos_k[ik], diag_thr) for ik in range(nkpts) + ] eigs_ao = np.asarray(eigs_ao) # calculate errors e_errors_k = eigs_qo[:, ib_min:ib_max] - eigs_ao[:, ib_min:ib_max] e_errors_k = [np.linalg.norm(e_errors_k[ik]) for ik in range(nkpts)] - exclude_kvecs = [ik for ik, e_error_k in enumerate(e_errors_k) if e_error_k > 1e-8] - print("Number of kpoints excluded due to large error:", len(exclude_kvecs), "\nTheir indices:", exclude_kvecs) + exclude_kvecs = [ + ik for ik, e_error_k in enumerate(e_errors_k) if e_error_k > 1e-8 + ] + print( + "Number of kpoints excluded due to large error:", + len(exclude_kvecs), + "\nTheir indices:", + exclude_kvecs, + ) for ik in exclude_kvecs: print("kpoint: ", kvecs_d[ik], "has an error of: ", e_errors_k[ik]) print("eigvals of sqos_k: ", sp.linalg.eigvalsh(sqos_k[ik])) @@ -476,12 +575,15 @@ def production(path: str, # path of OUT.${suff # plt.title(figure_title) # plt.savefig(fpic) + import unittest + + class QOUnittest(unittest.TestCase): def test_read_mat_hs(self): for ik in range(ndim**3): print("Unittest test_read_mat_hs on kpoint", ik) - fhs = path + f'/data-{ik}-S' + fhs = path + f"/data-{ik}-S" mat = read_mat_hs(fhs) nrows, ncols = mat.shape # check square matrix @@ -504,12 +606,14 @@ def test_read_lowf_k(self): # check dimension of space self.assertGreater(nlocal, nband) - fs = path + f'/data-{ik}-S' + fs = path + f"/data-{ik}-S" s_k = read_mat_hs(fs) nrows, ncols = s_k.shape - self.assertEqual(nrows, ncols) # should be a square matrix - self.assertEqual(nrows, nlocal) # should be overlap matrix of basis functions - _one = lowf_k.conj().T@s_k@lowf_k + self.assertEqual(nrows, ncols) # should be a square matrix + self.assertEqual( + nrows, nlocal + ) # should be overlap matrix of basis functions + _one = lowf_k.conj().T @ s_k @ lowf_k # orthonormality for i in range(nband): for j in range(nband): @@ -523,12 +627,12 @@ def test_read_lowf_k(self): def test_read_ao_proj(self): for ik in range(ndim**3): print("Unittest test_read_ao_proj on kpoint", ik) - fao_proj = path + f'/QO_ovlp_{ik}.dat' + fao_proj = path + f"/QO_ovlp_{ik}.dat" ao_proj, kvec_d = read_ao_proj(fao_proj) nrows, ncols = ao_proj.shape self.assertGreater(nrows, 0) self.assertGreater(ncols, 0) - self.assertGreater(nrows, ncols) # space dimension comparision + self.assertGreater(nrows, ncols) # space dimension comparision def test_cal_denmat(self): for ik in range(ndim**3): @@ -536,23 +640,25 @@ def test_cal_denmat(self): flowf = path + f"/WFC_NAO_K{ik+1}.txt" lowf_k, kvec_d = read_lowf(flowf) denmat_k = cal_denmat(lowf_k) - + nrows, ncols = denmat_k.shape self.assertEqual(nrows, ncols) nlocal, nband = lowf_k.shape self.assertEqual(nrows, nlocal) self.assertEqual(ncols, nlocal) - + denmat_dagger_k = denmat_k.conj().T # D = D^+ for i in range(nrows): for j in range(ncols): - self.assertAlmostEqual(denmat_k[i, j], denmat_dagger_k[i, j], delta=1e-5) - - fs = path + f'/data-{ik}-S' + self.assertAlmostEqual( + denmat_k[i, j], denmat_dagger_k[i, j], delta=1e-5 + ) + + fs = path + f"/data-{ik}-S" s_k = read_mat_hs(fs) D_k = denmat_k.tolist() - DSD_k = (denmat_k@s_k@denmat_k).tolist() + DSD_k = (denmat_k @ s_k @ denmat_k).tolist() self.assertEqual(len(D_k), len(DSD_k)) self.assertEqual(len(D_k[0]), len(DSD_k[0])) # D = DSD @@ -567,16 +673,15 @@ def test_lowdin_onW(self): flowf = path + f"/WFC_NAO_K{ik+1}.txt" lowf_k, kvec_d = read_lowf(flowf) denmat_k = cal_denmat(lowf_k) - fs = path + f'/data-{ik}-S' + fs = path + f"/data-{ik}-S" s_k = read_mat_hs(fs) - fao_proj = path + f'/QO_ovlp_{ik}.dat' + fao_proj = path + f"/QO_ovlp_{ik}.dat" ao_proj_k, kvec_d = read_ao_proj(fao_proj) - - lowf_bar = lowdin_onW(s_k=s_k, - denmat_k=denmat_k, - ao_proj_k=ao_proj_k, - m = ndim_test) - _one = lowf_bar.conj().T@s_k@lowf_bar + + lowf_bar = lowdin_onW( + s_k=s_k, denmat_k=denmat_k, ao_proj_k=ao_proj_k, m=ndim_test + ) + _one = lowf_bar.conj().T @ s_k @ lowf_bar self.assertEqual(_one.shape, (ndim_test, ndim_test)) # orthonormality for i in range(ndim_test): @@ -589,10 +694,12 @@ def test_lowdin_onW(self): lowf_tilde_k = np.concatenate((lowf_k, lowf_bar), axis=1) denmat_tilde_k = cal_denmat(lowf_tilde_k) D_tilde_k = denmat_tilde_k.tolist() - DSD_tilde_k = (denmat_tilde_k@s_k@denmat_tilde_k).tolist() + DSD_tilde_k = (denmat_tilde_k @ s_k @ denmat_tilde_k).tolist() for i in range(len(D_tilde_k)): for j in range(len(D_tilde_k[0])): - self.assertAlmostEqual(D_tilde_k[i][j], DSD_tilde_k[i][j], delta=1e-5) + self.assertAlmostEqual( + D_tilde_k[i][j], DSD_tilde_k[i][j], delta=1e-5 + ) def test_cal_tb_hs(self): print("Unittest test_cal_tb_hs") @@ -601,7 +708,7 @@ def test_cal_tb_hs(self): I = np.eye(nbasis, dtype=np.complex128) # CASE 1: the most ideal case # create an Hermite matrix as model Hamiltonian - H = np.random.rand(nbasis, nbasis) + 1.0j*np.random.rand(nbasis, nbasis) + H = np.random.rand(nbasis, nbasis) + 1.0j * np.random.rand(nbasis, nbasis) H = H + H.conj().T # eye as model overlap matrix S = I @@ -620,11 +727,11 @@ def test_cal_tb_hs(self): # check not-all-zero self.assertNotEqual(np.sum(np.abs(Htb)), 0) self.assertNotEqual(np.sum(np.abs(Stb)), 0) - # CASE 2: less ideal case + # CASE 2: less ideal case # directly truncate A, for the meaning the AO basis is not as many as original basis nAO = 3 A = A[:, :nAO] - D = I[:, :nAO]@I[:nAO, :] # usually D is not a full-rank matrix + D = I[:, :nAO] @ I[:nAO, :] # usually D is not a full-rank matrix Htb, Stb = cal_tb_hs(H, S, D, A) # check shape self.assertEqual(Htb.shape, (nAO, nAO)) @@ -638,53 +745,74 @@ def test_cal_tb_hs(self): def test_kR_transform(self): for nk in [1, 3, 5]: - kpoints = it.product(np.arange(-0.5+0.5/nk, 0.5, 1.0/nk), repeat=3) + kpoints = it.product(np.arange(-0.5 + 0.5 / nk, 0.5, 1.0 / nk), repeat=3) kpoints = np.array(list(kpoints)) - Rs = it.product(range(-int((nk-1)/2), int((nk+1)/2)), repeat=3) + Rs = it.product(range(-int((nk - 1) / 2), int((nk + 1) / 2)), repeat=3) Rs = np.array(list(Rs)) assert len(kpoints) == len(Rs) - ndim = 20 # square matrix dimension + ndim = 20 # square matrix dimension mats_0 = [np.random.rand(ndim, ndim) for i in range(len(kpoints))] - mats_k = [kR_transform(kpoints[i], mats_0, Rs, "R->k") for i in range(len(kpoints))] - mats_kR = [kR_transform(Rs[i], mats_k, kpoints, "k->R") for i in range(len(kpoints))] + mats_k = [ + kR_transform(kpoints[i], mats_0, Rs, "R->k") + for i in range(len(kpoints)) + ] + mats_kR = [ + kR_transform(Rs[i], mats_k, kpoints, "k->R") + for i in range(len(kpoints)) + ] for ik in range(len(kpoints)): for i in range(ndim): for j in range(ndim): - self.assertAlmostEqual(mats_kR[ik][i, j].real, mats_0[ik][i, j].real, delta=1e-12) - self.assertAlmostEqual(mats_kR[ik][i, j].imag, mats_0[ik][i, j].imag, delta=1e-12) + self.assertAlmostEqual( + mats_kR[ik][i, j].real, mats_0[ik][i, j].real, delta=1e-12 + ) + self.assertAlmostEqual( + mats_kR[ik][i, j].imag, mats_0[ik][i, j].imag, delta=1e-12 + ) def test_k_extrapolation(self): for nk in [1, 3, 5]: - kpoints = it.product(np.arange(-0.5+0.5/nk, 0.5, 1.0/nk), repeat=3) + kpoints = it.product(np.arange(-0.5 + 0.5 / nk, 0.5, 1.0 / nk), repeat=3) kpoints = np.array(list(kpoints)) - Rs = it.product(range(-int((nk-1)/2), int((nk+1)/2)), repeat=3) + Rs = it.product(range(-int((nk - 1) / 2), int((nk + 1) / 2)), repeat=3) Rs = np.array(list(Rs)) assert len(kpoints) == len(Rs) - ndim = 20 # square matrix dimension + ndim = 20 # square matrix dimension mats_0 = [np.random.rand(ndim, ndim) for i in range(len(kpoints))] mats_k2R2k = k_extrapolation(mats_0, kpoints, Rs, kpoints) for ik in range(len(kpoints)): for i in range(ndim): for j in range(ndim): - self.assertAlmostEqual(mats_k2R2k[ik][i, j].real, mats_0[ik][i, j].real, delta=1e-12) - self.assertAlmostEqual(mats_k2R2k[ik][i, j].imag, mats_0[ik][i, j].imag, delta=1e-12) + self.assertAlmostEqual( + mats_k2R2k[ik][i, j].real, + mats_0[ik][i, j].real, + delta=1e-12, + ) + self.assertAlmostEqual( + mats_k2R2k[ik][i, j].imag, + mats_0[ik][i, j].imag, + delta=1e-12, + ) + if __name__ == "__main__": # False to run unittest, True to run production - run_type = "production" # can be "unittest" or "production" - ndim = 7 # dimension of Monkhorst-Pack grid + run_type = "production" # can be "unittest" or "production" + ndim = 7 # dimension of Monkhorst-Pack grid qo_basis = "hydrogen" qo_strategy = "minimal-valence" path = f"./scf/{qo_basis}/{qo_strategy}/OUT.ABACUS-{ndim}{ndim}{ndim}/" - #fpic = f"{qo_basis}-{qo_strategy}-{ndim}{ndim}{ndim}.png" + # fpic = f"{qo_basis}-{qo_strategy}-{ndim}{ndim}{ndim}.png" # only for production eig_thr = 1e-10 ib_min, ib_max = 0, 4 if run_type == "production": - nkpts = ndim*ndim*ndim - hqos_k, sqos_k, kvecs_d = production(path, nkpts, ib_min, ib_max, eig_thr, error_estimation_with_lcao=True) + nkpts = ndim * ndim * ndim + hqos_k, sqos_k, kvecs_d = production( + path, nkpts, ib_min, ib_max, eig_thr, error_estimation_with_lcao=True + ) elif run_type == "unittest": unittest.main() diff --git a/tools/rt-tddft-tools/dipole.py b/tools/rt-tddft-tools/dipole.py index 91fcbdb53f8..b26e6ba01dd 100644 --- a/tools/rt-tddft-tools/dipole.py +++ b/tools/rt-tddft-tools/dipole.py @@ -4,7 +4,7 @@ from matplotlib import axes import scipy.constants as sc -Freq2eV = sc.h/sc.eV*1e15 # 1/fs to eV +Freq2eV = sc.h / sc.eV * 1e15 # 1/fs to eV class Dipole: @@ -25,7 +25,7 @@ def read(cls, filename: PathLike): indices = data[:, 0] dipole = data[:, 1:].transpose() for i in range(3): - dipole[i,:] = dipole[i,:] - dipole[i,0] + dipole[i, :] = dipole[i, :] - dipole[i, 0] return indices, dipole @@ -33,7 +33,13 @@ def read(cls, filename: PathLike): def dipole_data(self): return self.dipole - def plot_dipole(self, fig: Figure, ax: axes.Axes, directions: list = [0, 1, 2], time_range: list = []): + def plot_dipole( + self, + fig: Figure, + ax: axes.Axes, + directions: list = [0, 1, 2], + time_range: list = [], + ): """Plot dipole data in x,y,z directions :params fig: (matplotlib.figure.Figure) @@ -42,26 +48,29 @@ def plot_dipole(self, fig: Figure, ax: axes.Axes, directions: list = [0, 1, 2], :params time_range: (list) range of time (in unit fs) to plot """ - labels = {0: 'X', 1: 'Y', 2: 'Z'} + labels = {0: "X", 1: "Y", 2: "Z"} for direc in directions: - ax.plot(self._indices*self.dt, self.dipole_data[direc], label=labels[direc]) + ax.plot( + self._indices * self.dt, self.dipole_data[direc], label=labels[direc] + ) - ax.set_xlabel('Times (fs)') - ax.set_ylabel('Dipole') + ax.set_xlabel("Times (fs)") + ax.set_ylabel("Dipole") ax.legend() if time_range: ax.set_xlim(time_range) return fig, ax + class Efield: """Parse Efield Data""" - def __init__(self, Efile: list[list[PathLike]], dt: float, nstep:int) -> None: + def __init__(self, Efile: list[list[PathLike]], dt: float, nstep: int) -> None: self.Efile = Efile - self.dt=dt - self.efield=self.reade(self.Efile, nstep) + self.dt = dt + self.efield = self.reade(self.Efile, nstep) @classmethod def reade(cls, Efile: list[list[PathLike]], nstep: int): @@ -70,20 +79,24 @@ def reade(cls, Efile: list[list[PathLike]], nstep: int): :params Efile: string type 2D list of Efield data file, Efile[i][j] is the jth Efield data file in ith direction :params nstep: number of steps in simulation """ - Efield = np.zeros([3,nstep]) + Efield = np.zeros([3, nstep]) for i in range(len(Efile)): for file in Efile[i]: Edata = np.loadtxt(file, dtype=float) - Efield[i,0:(len(Edata))] += Edata[:, 1] + Efield[i, 0 : (len(Edata))] += Edata[:, 1] return Efield - + @property def efield_data(self): return self.efield - + + class Absorption(Dipole, Efield): """Calculate Absorption Spectrum under light field""" - def __init__(self, dipolefile: PathLike,Efile: list[list[PathLike]], dt: float) -> None: + + def __init__( + self, dipolefile: PathLike, Efile: list[list[PathLike]], dt: float + ) -> None: Dipole.__init__(self, dipolefile, dt) Efield.__init__(self, Efile, dt, len(self._indices)) @@ -92,80 +105,90 @@ def padding(self, data: np.ndarray): :params data: (np.ndarray) data to be padded """ - #mask part - Ndim=len(self._indices)*10 - index=np.linspace(0,Ndim-1,Ndim) - t=self._indices*self.dt - b=5 - mask=np.exp(-b*t/t[-1]) - #padding part - padding=np.zeros(Ndim-len(data)) - data_pass=np.concatenate((data*mask, padding)) + # mask part + Ndim = len(self._indices) * 10 + index = np.linspace(0, Ndim - 1, Ndim) + t = self._indices * self.dt + b = 5 + mask = np.exp(-b * t / t[-1]) + # padding part + padding = np.zeros(Ndim - len(data)) + data_pass = np.concatenate((data * mask, padding)) return data_pass - - def alpha(self,dirc: int): + + def alpha(self, dirc: int): """Calculate alpha :params dirc: (int) 0->X, 1->Y, 2->Z """ - #FFT part - dipole=self.padding(self.dipole_data[dirc]) - efield=self.padding(self.efield_data[dirc]) + # FFT part + dipole = self.padding(self.dipole_data[dirc]) + efield = self.padding(self.efield_data[dirc]) dipole_fft = np.fft.fft(dipole) efield_fft = np.fft.fft(efield) - alpha = np.abs((dipole_fft/efield_fft).imag) + alpha = np.abs((dipole_fft / efield_fft).imag) return alpha - - def plot_abs(self, fig: Figure, ax: axes.Axes, directions: list = [0, 1, 2], x_range: list = [], unit: str = 'eV'): + + def plot_abs( + self, + fig: Figure, + ax: axes.Axes, + directions: list = [0, 1, 2], + x_range: list = [], + unit: str = "eV", + ): """Plot Absportion Spectrum under Delta light field in x,y,z directions :params fig: (matplotlib.figure.Figure) :params ax: (matplotlib.axes.Axes) :params directions: (list) 0->X, 1->Y, 2->Z :params x_range: (list) range of energies (in unit eV) to plot - :params unit: (str) + :params unit: (str) """ - assert unit in ['eV', 'nm'] - labels = {0: 'X', 1: 'Y', 2: 'Z'} - Ndim=len(self._indices)*10 - index=np.linspace(0,Ndim-1,Ndim) - energies = Freq2eV*index/self.dt/len(index) - x_data = energies if unit == 'eV' else sc.nu2lambda( - sc.eV/sc.h*energies)*1e9 - - #plot the adsorption spectra and output the data + assert unit in ["eV", "nm"] + labels = {0: "X", 1: "Y", 2: "Z"} + Ndim = len(self._indices) * 10 + index = np.linspace(0, Ndim - 1, Ndim) + energies = Freq2eV * index / self.dt / len(index) + x_data = ( + energies if unit == "eV" else sc.nu2lambda(sc.eV / sc.h * energies) * 1e9 + ) + + # plot the adsorption spectra and output the data adsorption_spectra_data = x_data[:, np.newaxis] for direc in directions: alpha = self.alpha(direc) ax.plot(x_data, alpha, label=labels[direc]) - adsorption_spectra_data = np.concatenate((adsorption_spectra_data, alpha[:, np.newaxis]),axis=1) - np.savetxt('absorpation_spectra.dat', adsorption_spectra_data) + adsorption_spectra_data = np.concatenate( + (adsorption_spectra_data, alpha[:, np.newaxis]), axis=1 + ) + np.savetxt("absorpation_spectra.dat", adsorption_spectra_data) - xlabel = 'Energy (eV)' if unit == 'eV' else 'Wave Length (nm)' + xlabel = "Energy (eV)" if unit == "eV" else "Wave Length (nm)" ax.set_xlabel(xlabel) - ax.set_ylabel('Absportion') + ax.set_ylabel("Absportion") ax.legend() if x_range: ax.set_xlim(x_range) - lim_range=index[(x_data>x_range[0])&(x_data x_range[0]) & (x_data < x_range[1])] + ax.set_ylim([0, 1.2 * max(alpha[int(lim_range[0]) : int(lim_range[-1])])]) return fig, ax if __name__ == "__main__": - dipolefile = './dipole_s1.txt' + dipolefile = "./dipole_s1.txt" dipole = Dipole(dipolefile, dt=0.0024) - Efile=[[],[],["efield_0.txt"]] + Efile = [[], [], ["efield_0.txt"]] Abs = Absorption(dipolefile, Efile, dt=0.0024) import matplotlib.pyplot as plt + fig1, ax1 = plt.subplots() fig1, ax1 = dipole.plot_dipole(fig1, ax1) - fig1.savefig('dipole.png') - + fig1.savefig("dipole.png") + fig2, ax2 = plt.subplots() x_range = [0, 400] - fig2, ax2 = Abs.plot_abs( - fig2, ax2, x_range=x_range, unit='nm') - fig2.savefig('abs.png') + fig2, ax2 = Abs.plot_abs(fig2, ax2, x_range=x_range, unit="nm") + fig2.savefig("abs.png") diff --git a/tools/rt-tddft-tools/examples/Absorpation-N2/ABACUS-INPUT b/tools/rt-tddft-tools/examples/Absorpation-N2/ABACUS-INPUT index 1044cdf06ef..71b122a75f5 100644 --- a/tools/rt-tddft-tools/examples/Absorpation-N2/ABACUS-INPUT +++ b/tools/rt-tddft-tools/examples/Absorpation-N2/ABACUS-INPUT @@ -1,32 +1,32 @@ -INPUT_PARAMETERS -suffix tddft -basis_type lcao - -ecutwfc 60 -scf_nmax 100 -scf_thr 1e-6 - -calculation md -esolver_type tddft -md_type nve -md_nstep 10000 -md_dt 0.0024 -md_tfirst 0 - -td_vext 1 -td_vext_dire 3 3 -td_stype 0 -td_ttype 0 0 -td_tstart 1 -td_tend 2000 -td_lcut1 0.01 -td_lcut2 0.99 -td_gauss_freq 3.66 1.22 -td_gauss_phase 0.0 0.0 -td_gauss_sigma 0.2 0.2 -td_gauss_t0 800 800 -td_gauss_amp 0.6 0.6 - -out_chg 1 -out_efield 1 -out_dipole 1 +INPUT_PARAMETERS +suffix tddft +basis_type lcao + +ecutwfc 60 +scf_nmax 100 +scf_thr 1e-6 + +calculation md +esolver_type tddft +md_type nve +md_nstep 10000 +md_dt 0.0024 +md_tfirst 0 + +td_vext 1 +td_vext_dire 3 3 +td_stype 0 +td_ttype 0 0 +td_tstart 1 +td_tend 2000 +td_lcut1 0.01 +td_lcut2 0.99 +td_gauss_freq 3.66 1.22 +td_gauss_phase 0.0 0.0 +td_gauss_sigma 0.2 0.2 +td_gauss_t0 800 800 +td_gauss_amp 0.6 0.6 + +out_chg 1 +out_efield 1 +out_dipole 1 diff --git a/tools/rt-tddft-tools/examples/Absorpation-N2/Abs_plot.py b/tools/rt-tddft-tools/examples/Absorpation-N2/Abs_plot.py index d832badc0f6..1e3c7246799 100644 --- a/tools/rt-tddft-tools/examples/Absorpation-N2/Abs_plot.py +++ b/tools/rt-tddft-tools/examples/Absorpation-N2/Abs_plot.py @@ -2,17 +2,16 @@ from abacus_plot.dipole import Absorption import matplotlib.pyplot as plt -dipolefile = './dipole_s1.txt' +dipolefile = "./dipole_s1.txt" dipole = Dipole(dipolefile, dt=0.0024) -Efile=[[],[],["efield_0.txt","efield_1.txt"]] +Efile = [[], [], ["efield_0.txt", "efield_1.txt"]] Abs = Absorption(dipolefile, Efile, dt=0.0024) fig1, ax1 = plt.subplots() fig1, ax1 = dipole.plot_dipole(fig1, ax1) -fig1.savefig('dipole.png') +fig1.savefig("dipole.png") fig2, ax2 = plt.subplots() x_range = [0, 20] -fig2, ax2 = Abs.plot_abs( -fig2, ax2, x_range=x_range,directions=[2], unit='eV') -fig2.savefig('abs.png') \ No newline at end of file +fig2, ax2 = Abs.plot_abs(fig2, ax2, x_range=x_range, directions=[2], unit="eV") +fig2.savefig("abs.png") diff --git a/tools/rt-tddft-tools/examples/Absorpation-N2/efield_0.txt b/tools/rt-tddft-tools/examples/Absorpation-N2/efield_0.txt index 050585d1416..e9543d6674b 100644 --- a/tools/rt-tddft-tools/examples/Absorpation-N2/efield_0.txt +++ b/tools/rt-tddft-tools/examples/Absorpation-N2/efield_0.txt @@ -1,2000 +1,2000 @@ -0.0024 6.5005e-21 -0.0048 7.32828e-21 -0.0072 8.23505e-21 -0.0096 9.22452e-21 -0.012 1.02999e-20 -0.0144 1.14636e-20 -0.0168 1.27171e-20 -0.0192 1.40606e-20 -0.0216 1.54929e-20 -0.024 1.70108e-20 -0.0264 1.86088e-20 -0.0288 2.02785e-20 -0.0312 2.20084e-20 -0.0336 2.37829e-20 -0.036 2.55816e-20 -0.0384 2.73789e-20 -0.0408 2.91427e-20 -0.0432 3.08334e-20 -0.0456 3.24031e-20 -0.048 3.3794e-20 -0.0504 3.4937e-20 -0.0528 3.57507e-20 -0.0552 3.61387e-20 -0.0576 3.59886e-20 -0.06 3.51695e-20 -0.0624 3.353e-20 -0.0648 3.08954e-20 -0.0672 2.70654e-20 -0.0696 2.18112e-20 -0.072 1.48721e-20 -0.0744 5.95274e-21 -0.0768 -5.28066e-21 -0.0792 -1.92039e-20 -0.0816 -3.62386e-20 -0.084 -5.68562e-20 -0.0864 -8.15819e-20 -0.0888 -1.10999e-19 -0.0912 -1.45754e-19 -0.0936 -1.86558e-19 -0.096 -2.34195e-19 -0.0984 -2.89523e-19 -0.1008 -3.53476e-19 -0.1032 -4.27072e-19 -0.1056 -5.11413e-19 -0.108 -6.07687e-19 -0.1104 -7.17169e-19 -0.1128 -8.41221e-19 -0.1152 -9.81291e-19 -0.1176 -1.13891e-18 -0.12 -1.31568e-18 -0.1224 -1.51329e-18 -0.1248 -1.73347e-18 -0.1272 -1.978e-18 -0.1296 -2.24869e-18 -0.132 -2.54734e-18 -0.1344 -2.87576e-18 -0.1368 -3.23568e-18 -0.1392 -3.62873e-18 -0.1416 -4.05639e-18 -0.144 -4.51997e-18 -0.1464 -5.02048e-18 -0.1488 -5.55859e-18 -0.1512 -6.13454e-18 -0.1536 -6.74802e-18 -0.156 -7.39808e-18 -0.1584 -8.08295e-18 -0.1608 -8.79992e-18 -0.1632 -9.54517e-18 -0.1656 -1.03135e-17 -0.168 -1.10983e-17 -0.1704 -1.18911e-17 -0.1728 -1.26812e-17 -0.1752 -1.34558e-17 -0.1776 -1.41994e-17 -0.18 -1.4893e-17 -0.1824 -1.55147e-17 -0.1848 -1.60383e-17 -0.1872 -1.64332e-17 -0.1896 -1.6664e-17 -0.192 -1.66896e-17 -0.1944 -1.6463e-17 -0.1968 -1.593e-17 -0.1992 -1.50292e-17 -0.2016 -1.36909e-17 -0.204 -1.18363e-17 -0.2064 -9.37646e-18 -0.2088 -6.212e-18 -0.2112 -2.23163e-18 -0.2136 2.68855e-18 -0.216 8.68605e-18 -0.2184 1.5913e-17 -0.2208 2.45369e-17 -0.2232 3.47422e-17 -0.2256 4.67304e-17 -0.228 6.07215e-17 -0.2304 7.69546e-17 -0.2328 9.56889e-17 -0.2352 1.17204e-16 -0.2376 1.418e-16 -0.24 1.69798e-16 -0.2424 2.01541e-16 -0.2448 2.37392e-16 -0.2472 2.77734e-16 -0.2496 3.2297e-16 -0.252 3.73517e-16 -0.2544 4.29811e-16 -0.2568 4.92298e-16 -0.2592 5.6143e-16 -0.2616 6.37668e-16 -0.264 7.21466e-16 -0.2664 8.13273e-16 -0.2688 9.13517e-16 -0.2712 1.0226e-15 -0.2736 1.1409e-15 -0.276 1.26872e-15 -0.2784 1.40631e-15 -0.2808 1.55385e-15 -0.2832 1.7114e-15 -0.2856 1.87889e-15 -0.288 2.05612e-15 -0.2904 2.2427e-15 -0.2928 2.43802e-15 -0.2952 2.64125e-15 -0.2976 2.85126e-15 -0.3 3.06657e-15 -0.3024 3.28535e-15 -0.3048 3.50532e-15 -0.3072 3.72373e-15 -0.3096 3.93725e-15 -0.312 4.14194e-15 -0.3144 4.33316e-15 -0.3168 4.50548e-15 -0.3192 4.65259e-15 -0.3216 4.76725e-15 -0.324 4.84112e-15 -0.3264 4.8647e-15 -0.3288 4.8272e-15 -0.3312 4.71643e-15 -0.3336 4.51867e-15 -0.336 4.21853e-15 -0.3384 3.79882e-15 -0.3408 3.24044e-15 -0.3432 2.52217e-15 -0.3456 1.62062e-15 -0.348 5.09998e-16 -0.3504 -8.37972e-16 -0.3528 -2.45421e-15 -0.3552 -4.37241e-15 -0.3576 -6.62916e-15 -0.36 -9.26404e-15 -0.3624 -1.23197e-14 -0.3648 -1.5842e-14 -0.3672 -1.98801e-14 -0.3696 -2.4486e-14 -0.372 -2.97154e-14 -0.3744 -3.56268e-14 -0.3768 -4.22817e-14 -0.3792 -4.97447e-14 -0.3816 -5.80827e-14 -0.384 -6.7365e-14 -0.3864 -7.76626e-14 -0.3888 -8.90479e-14 -0.3912 -1.01594e-13 -0.3936 -1.15373e-13 -0.396 -1.30458e-13 -0.3984 -1.46918e-13 -0.4008 -1.6482e-13 -0.4032 -1.84224e-13 -0.4056 -2.05187e-13 -0.408 -2.27754e-13 -0.4104 -2.51961e-13 -0.4128 -2.77832e-13 -0.4152 -3.05372e-13 -0.4176 -3.34571e-13 -0.42 -3.65394e-13 -0.4224 -3.97779e-13 -0.4248 -4.31637e-13 -0.4272 -4.66841e-13 -0.4296 -5.03223e-13 -0.432 -5.40573e-13 -0.4344 -5.78624e-13 -0.4368 -6.17055e-13 -0.4392 -6.55476e-13 -0.4416 -6.93426e-13 -0.444 -7.30359e-13 -0.4464 -7.65641e-13 -0.4488 -7.98538e-13 -0.4512 -8.28205e-13 -0.4536 -8.53675e-13 -0.456 -8.73852e-13 -0.4584 -8.87496e-13 -0.4608 -8.93209e-13 -0.4632 -8.89429e-13 -0.4656 -8.7441e-13 -0.468 -8.46214e-13 -0.4704 -8.02696e-13 -0.4728 -7.41488e-13 -0.4752 -6.5999e-13 -0.4776 -5.55357e-13 -0.48 -4.24481e-13 -0.4824 -2.63986e-13 -0.4848 -7.02117e-14 -0.4872 1.60793e-13 -0.4896 4.3328e-13 -0.492 7.51808e-13 -0.4944 1.12125e-12 -0.4968 1.54678e-12 -0.4992 2.03389e-12 -0.5016 2.58838e-12 -0.504 3.21636e-12 -0.5064 3.92417e-12 -0.5088 4.71848e-12 -0.5112 5.60614e-12 -0.5136 6.59422e-12 -0.516 7.68996e-12 -0.5184 8.90069e-12 -0.5208 1.02338e-11 -0.5232 1.16966e-11 -0.5256 1.32965e-11 -0.528 1.50403e-11 -0.5304 1.6935e-11 -0.5328 1.89867e-11 -0.5352 2.12012e-11 -0.5376 2.35834e-11 -0.54 2.61374e-11 -0.5424 2.8866e-11 -0.5448 3.17708e-11 -0.5472 3.48517e-11 -0.5496 3.81068e-11 -0.552 4.15319e-11 -0.5544 4.51203e-11 -0.5568 4.88625e-11 -0.5592 5.27458e-11 -0.5616 5.67537e-11 -0.564 6.08655e-11 -0.5664 6.5056e-11 -0.5688 6.92949e-11 -0.5712 7.35462e-11 -0.5736 7.77675e-11 -0.576 8.19096e-11 -0.5784 8.59158e-11 -0.5808 8.97212e-11 -0.5832 9.32518e-11 -0.5856 9.64241e-11 -0.588 9.91442e-11 -0.5904 1.01307e-10 -0.5928 1.02795e-10 -0.5952 1.03479e-10 -0.5976 1.03216e-10 -0.6 1.01846e-10 -0.6024 9.91989e-11 -0.6048 9.5084e-11 -0.6072 8.92965e-11 -0.6096 8.16136e-11 -0.612 7.17949e-11 -0.6144 5.95812e-11 -0.6168 4.46949e-11 -0.6192 2.68389e-11 -0.6216 5.69693e-12 -0.624 -1.90666e-11 -0.6264 -4.78066e-11 -0.6288 -8.08967e-11 -0.6312 -1.18729e-10 -0.6336 -1.61712e-10 -0.636 -2.10272e-10 -0.6384 -2.64848e-10 -0.6408 -3.25893e-10 -0.6432 -3.9387e-10 -0.6456 -4.6925e-10 -0.648 -5.52507e-10 -0.6504 -6.44117e-10 -0.6528 -7.4455e-10 -0.6552 -8.5427e-10 -0.6576 -9.73724e-10 -0.66 -1.10334e-09 -0.6624 -1.24351e-09 -0.6648 -1.3946e-09 -0.6672 -1.55692e-09 -0.6696 -1.73073e-09 -0.672 -1.91623e-09 -0.6744 -2.11352e-09 -0.6768 -2.32263e-09 -0.6792 -2.54348e-09 -0.6816 -2.77584e-09 -0.684 -3.01939e-09 -0.6864 -3.27361e-09 -0.6888 -3.53784e-09 -0.6912 -3.81118e-09 -0.6936 -4.09256e-09 -0.696 -4.38065e-09 -0.6984 -4.67383e-09 -0.7008 -4.97024e-09 -0.7032 -5.26766e-09 -0.7056 -5.56356e-09 -0.708 -5.855e-09 -0.7104 -6.13868e-09 -0.7128 -6.41084e-09 -0.7152 -6.66727e-09 -0.7176 -6.90326e-09 -0.72 -7.11358e-09 -0.7224 -7.29245e-09 -0.7248 -7.4335e-09 -0.7272 -7.52975e-09 -0.7296 -7.57357e-09 -0.732 -7.55666e-09 -0.7344 -7.47003e-09 -0.7368 -7.30398e-09 -0.7392 -7.04805e-09 -0.7416 -6.69104e-09 -0.744 -6.22099e-09 -0.7464 -5.62516e-09 -0.7488 -4.89003e-09 -0.7512 -4.00132e-09 -0.7536 -2.944e-09 -0.756 -1.70229e-09 -0.7584 -2.5971e-10 -0.7608 1.40088e-09 -0.7632 3.29725e-09 -0.7656 5.44771e-09 -0.768 7.87105e-09 -0.7704 1.05864e-08 -0.7728 1.36133e-08 -0.7752 1.69713e-08 -0.7776 2.06801e-08 -0.78 2.4759e-08 -0.7824 2.92273e-08 -0.7848 3.41035e-08 -0.7872 3.94054e-08 -0.7896 4.515e-08 -0.792 5.13526e-08 -0.7944 5.80273e-08 -0.7968 6.51861e-08 -0.7992 7.28385e-08 -0.8016 8.09918e-08 -0.804 8.96497e-08 -0.8064 9.88126e-08 -0.8088 1.08477e-07 -0.8112 1.18634e-07 -0.8136 1.29272e-07 -0.816 1.40369e-07 -0.8184 1.51903e-07 -0.8208 1.6384e-07 -0.8232 1.7614e-07 -0.8256 1.88755e-07 -0.828 2.01629e-07 -0.8304 2.14694e-07 -0.8328 2.27873e-07 -0.8352 2.41078e-07 -0.8376 2.54207e-07 -0.84 2.67148e-07 -0.8424 2.79774e-07 -0.8448 2.91942e-07 -0.8472 3.03497e-07 -0.8496 3.14266e-07 -0.852 3.24059e-07 -0.8544 3.3267e-07 -0.8568 3.39875e-07 -0.8592 3.45429e-07 -0.8616 3.49073e-07 -0.864 3.50523e-07 -0.8664 3.49478e-07 -0.8688 3.45617e-07 -0.8712 3.38597e-07 -0.8736 3.28058e-07 -0.876 3.13618e-07 -0.8784 2.94875e-07 -0.8808 2.71409e-07 -0.8832 2.42782e-07 -0.8856 2.08538e-07 -0.888 1.68206e-07 -0.8904 1.213e-07 -0.8928 6.73205e-08 -0.8952 5.75981e-09 -0.8976 -6.38992e-08 -0.9 -1.42178e-07 -0.9024 -2.29602e-07 -0.9048 -3.26691e-07 -0.9072 -4.33964e-07 -0.9096 -5.51924e-07 -0.912 -6.81065e-07 -0.9144 -8.21855e-07 -0.9168 -9.7474e-07 -0.9192 -1.14013e-06 -0.9216 -1.3184e-06 -0.924 -1.50986e-06 -0.9264 -1.7148e-06 -0.9288 -1.93342e-06 -0.9312 -2.16584e-06 -0.9336 -2.41213e-06 -0.936 -2.67223e-06 -0.9384 -2.94601e-06 -0.9408 -3.23321e-06 -0.9432 -3.53344e-06 -0.9456 -3.84619e-06 -0.948 -4.17078e-06 -0.9504 -4.50639e-06 -0.9528 -4.85201e-06 -0.9552 -5.20645e-06 -0.9576 -5.5683e-06 -0.96 -5.93596e-06 -0.9624 -6.3076e-06 -0.9648 -6.68112e-06 -0.9672 -7.0542e-06 -0.9696 -7.42424e-06 -0.972 -7.78834e-06 -0.9744 -8.14334e-06 -0.9768 -8.48576e-06 -0.9792 -8.81181e-06 -0.9816 -9.11738e-06 -0.984 -9.39803e-06 -0.9864 -9.64897e-06 -0.9888 -9.86509e-06 -0.9912 -1.00409e-05 -0.9936 -1.01706e-05 -0.996 -1.02481e-05 -0.9984 -1.02668e-05 -1.0008 -1.02199e-05 -1.0032 -1.01002e-05 -1.0056 -9.90027e-06 -1.008 -9.61232e-06 -1.0104 -9.22827e-06 -1.0128 -8.73982e-06 -1.0152 -8.1384e-06 -1.0176 -7.41528e-06 -1.02 -6.56154e-06 -1.0224 -5.56814e-06 -1.0248 -4.42599e-06 -1.0272 -3.12593e-06 -1.0296 -1.65887e-06 -1.032 -1.58004e-08 -1.0344 1.81212e-06 -1.0368 3.83351e-06 -1.0392 6.05665e-06 -1.0416 8.48943e-06 -1.044 1.11393e-05 -1.0464 1.40129e-05 -1.0488 1.71165e-05 -1.0512 2.04553e-05 -1.0536 2.40337e-05 -1.056 2.7855e-05 -1.0584 3.19214e-05 -1.0608 3.62336e-05 -1.0632 4.07911e-05 -1.0656 4.55916e-05 -1.068 5.06312e-05 -1.0704 5.59042e-05 -1.0728 6.14026e-05 -1.0752 6.71163e-05 -1.0776 7.30331e-05 -1.08 7.9138e-05 -1.0824 8.54135e-05 -1.0848 9.18392e-05 -1.0872 9.83918e-05 -1.0896 0.000105045 -1.092 0.000111769 -1.0944 0.000118531 -1.0968 0.000125294 -1.0992 0.000132018 -1.1016 0.00013866 -1.104 0.000145171 -1.1064 0.000151501 -1.1088 0.000157593 -1.1112 0.000163388 -1.1136 0.000168824 -1.116 0.000173831 -1.1184 0.000178339 -1.1208 0.000182273 -1.1232 0.000185553 -1.1256 0.000188096 -1.128 0.000189816 -1.1304 0.000190624 -1.1328 0.000190425 -1.1352 0.000189125 -1.1376 0.000186625 -1.14 0.000182823 -1.1424 0.000177618 -1.1448 0.000170906 -1.1472 0.00016258 -1.1496 0.000152536 -1.152 0.000140668 -1.1544 0.000126872 -1.1568 0.000111045 -1.1592 9.3085e-05 -1.1616 7.28944e-05 -1.164 5.03788e-05 -1.1664 2.54485e-05 -1.1688 -1.98071e-06 -1.1712 -3.19866e-05 -1.1736 -6.46393e-05 -1.176 -0.0001 -1.1784 -0.000138122 -1.1808 -0.000179045 -1.1832 -0.000222799 -1.1856 -0.0002694 -1.188 -0.000318849 -1.1904 -0.000371133 -1.1928 -0.000426222 -1.1952 -0.000484066 -1.1976 -0.000544597 -1.2 -0.000607728 -1.2024 -0.000673348 -1.2048 -0.000741324 -1.2072 -0.000811498 -1.2096 -0.000883689 -1.212 -0.000957687 -1.2144 -0.00103326 -1.2168 -0.00111013 -1.2192 -0.00118802 -1.2216 -0.00126661 -1.224 -0.00134553 -1.2264 -0.0014244 -1.2288 -0.00150281 -1.2312 -0.00158032 -1.2336 -0.00165643 -1.236 -0.00173065 -1.2384 -0.00180243 -1.2408 -0.00187119 -1.2432 -0.00193635 -1.2456 -0.00199726 -1.248 -0.00205326 -1.2504 -0.00210368 -1.2528 -0.00214779 -1.2552 -0.00218487 -1.2576 -0.00221416 -1.26 -0.00223488 -1.2624 -0.00224625 -1.2648 -0.00224747 -1.2672 -0.00223772 -1.2696 -0.00221618 -1.272 -0.00218203 -1.2744 -0.00213445 -1.2768 -0.00207264 -1.2792 -0.00199579 -1.2816 -0.00190312 -1.284 -0.00179386 -1.2864 -0.00166728 -1.2888 -0.00152268 -1.2912 -0.00135938 -1.2936 -0.00117677 -1.296 -0.000974285 -1.2984 -0.000751412 -1.3008 -0.000507706 -1.3032 -0.000242794 -1.3056 4.36187e-05 -1.308 0.00035174 -1.3104 0.000681685 -1.3128 0.00103347 -1.3152 0.001407 -1.3176 0.00180208 -1.32 0.00221837 -1.3224 0.00265543 -1.3248 0.00311267 -1.3272 0.00358935 -1.3296 0.00408462 -1.332 0.00459743 -1.3344 0.00512662 -1.3368 0.00567085 -1.3392 0.00622861 -1.3416 0.00679823 -1.344 0.00737786 -1.3464 0.0079655 -1.3488 0.00855895 -1.3512 0.00915585 -1.3536 0.00975367 -1.356 0.0103497 -1.3584 0.0109411 -1.3608 0.0115247 -1.3632 0.0120974 -1.3656 0.0126559 -1.368 0.0131966 -1.3704 0.0137158 -1.3728 0.0142098 -1.3752 0.0146747 -1.3776 0.0151064 -1.38 0.0155009 -1.3824 0.0158538 -1.3848 0.0161611 -1.3872 0.0164183 -1.3896 0.0166211 -1.392 0.0167652 -1.3944 0.0168461 -1.3968 0.0168595 -1.3992 0.0168012 -1.4016 0.0166669 -1.404 0.0164525 -1.4064 0.016154 -1.4088 0.0157676 -1.4112 0.0152897 -1.4136 0.0147166 -1.416 0.0140453 -1.4184 0.0132727 -1.4208 0.0123962 -1.4232 0.0114134 -1.4256 0.0103222 -1.428 0.00912107 -1.4304 0.00780876 -1.4328 0.00638444 -1.4352 0.0048478 -1.4376 0.00319896 -1.44 0.0014386 -1.4424 -0.000432086 -1.4448 -0.00241133 -1.4472 -0.00449679 -1.4496 -0.00668552 -1.452 -0.00897394 -1.4544 -0.0113578 -1.4568 -0.0138324 -1.4592 -0.016392 -1.4616 -0.0190305 -1.464 -0.0217411 -1.4664 -0.0245161 -1.4688 -0.0273473 -1.4712 -0.0302259 -1.4736 -0.0331422 -1.476 -0.036086 -1.4784 -0.0390464 -1.4808 -0.0420119 -1.4832 -0.0449704 -1.4856 -0.0479091 -1.488 -0.0508149 -1.4904 -0.0536739 -1.4928 -0.056472 -1.4952 -0.0591944 -1.4976 -0.061826 -1.5 -0.0643516 -1.5024 -0.0667553 -1.5048 -0.0690213 -1.5072 -0.0711334 -1.5096 -0.0730755 -1.512 -0.0748314 -1.5144 -0.0763849 -1.5168 -0.0777199 -1.5192 -0.0788206 -1.5216 -0.0796713 -1.524 -0.0802569 -1.5264 -0.0805624 -1.5288 -0.0805736 -1.5312 -0.0802769 -1.5336 -0.0796592 -1.536 -0.0787084 -1.5384 -0.0774131 -1.5408 -0.075763 -1.5432 -0.0737488 -1.5456 -0.0713623 -1.548 -0.0685966 -1.5504 -0.0654459 -1.5528 -0.0619061 -1.5552 -0.0579742 -1.5576 -0.0536491 -1.56 -0.0489309 -1.5624 -0.0438216 -1.5648 -0.038325 -1.5672 -0.0324463 -1.5696 -0.0261929 -1.572 -0.0195738 -1.5744 -0.0125999 -1.5768 -0.00528426 -1.5792 0.0023585 -1.5816 0.0103116 -1.584 0.0185564 -1.5864 0.0270724 -1.5888 0.035837 -1.5912 0.044826 -1.5936 0.0540131 -1.596 0.0633704 -1.5984 0.0728683 -1.6008 0.0824752 -1.6032 0.0921584 -1.6056 0.101883 -1.608 0.111614 -1.6104 0.121313 -1.6128 0.130943 -1.6152 0.140464 -1.6176 0.149835 -1.62 0.159016 -1.6224 0.167964 -1.6248 0.176639 -1.6272 0.184996 -1.6296 0.192993 -1.632 0.200588 -1.6344 0.207738 -1.6368 0.214402 -1.6392 0.220538 -1.6416 0.226104 -1.644 0.231063 -1.6464 0.235375 -1.6488 0.239003 -1.6512 0.241913 -1.6536 0.24407 -1.656 0.245442 -1.6584 0.246001 -1.6608 0.245719 -1.6632 0.244572 -1.6656 0.242539 -1.668 0.239599 -1.6704 0.235738 -1.6728 0.230942 -1.6752 0.225203 -1.6776 0.218515 -1.68 0.210876 -1.6824 0.202286 -1.6848 0.192753 -1.6872 0.182283 -1.6896 0.170892 -1.692 0.158596 -1.6944 0.145416 -1.6968 0.131377 -1.6992 0.116508 -1.7016 0.100843 -1.704 0.0844184 -1.7064 0.0672756 -1.7088 0.0494592 -1.7112 0.0310178 -1.7136 0.0120033 -1.716 -0.00752867 -1.7184 -0.0275192 -1.7208 -0.0479063 -1.7232 -0.0686251 -1.7256 -0.0896079 -1.728 -0.110785 -1.7304 -0.132082 -1.7328 -0.153427 -1.7352 -0.174742 -1.7376 -0.19595 -1.74 -0.216972 -1.7424 -0.237728 -1.7448 -0.258137 -1.7472 -0.278119 -1.7496 -0.297593 -1.752 -0.31648 -1.7544 -0.334699 -1.7568 -0.352172 -1.7592 -0.368823 -1.7616 -0.384576 -1.764 -0.399358 -1.7664 -0.413098 -1.7688 -0.425729 -1.7712 -0.437186 -1.7736 -0.447407 -1.776 -0.456335 -1.7784 -0.463916 -1.7808 -0.470102 -1.7832 -0.474847 -1.7856 -0.478111 -1.788 -0.47986 -1.7904 -0.480064 -1.7928 -0.478699 -1.7952 -0.475747 -1.7976 -0.471195 -1.8 -0.465036 -1.8024 -0.457269 -1.8048 -0.447901 -1.8072 -0.436942 -1.8096 -0.424411 -1.812 -0.410332 -1.8144 -0.394734 -1.8168 -0.377655 -1.8192 -0.359136 -1.8216 -0.339227 -1.824 -0.317981 -1.8264 -0.295459 -1.8288 -0.271725 -1.8312 -0.24685 -1.8336 -0.220911 -1.836 -0.193986 -1.8384 -0.166163 -1.8408 -0.137529 -1.8432 -0.108178 -1.8456 -0.0782063 -1.848 -0.0477137 -1.8504 -0.0168028 -1.8528 0.0144215 -1.8552 0.0458521 -1.8576 0.0773807 -1.86 0.108897 -1.8624 0.140292 -1.8648 0.171453 -1.8672 0.202272 -1.8696 0.232637 -1.872 0.26244 -1.8744 0.291573 -1.8768 0.319932 -1.8792 0.347413 -1.8816 0.373916 -1.884 0.399344 -1.8864 0.423605 -1.8888 0.446608 -1.8912 0.468268 -1.8936 0.488507 -1.896 0.507248 -1.8984 0.524422 -1.9008 0.539965 -1.9032 0.553819 -1.9056 0.565933 -1.908 0.576261 -1.9104 0.584764 -1.9128 0.591411 -1.9152 0.596177 -1.9176 0.599043 -1.92 0.6 -1.9224 0.599043 -1.9248 0.596177 -1.9272 0.591411 -1.9296 0.584764 -1.932 0.576261 -1.9344 0.565933 -1.9368 0.553819 -1.9392 0.539965 -1.9416 0.524422 -1.944 0.507248 -1.9464 0.488507 -1.9488 0.468268 -1.9512 0.446608 -1.9536 0.423605 -1.956 0.399344 -1.9584 0.373916 -1.9608 0.347413 -1.9632 0.319932 -1.9656 0.291573 -1.968 0.26244 -1.9704 0.232637 -1.9728 0.202272 -1.9752 0.171453 -1.9776 0.140292 -1.98 0.108897 -1.9824 0.0773807 -1.9848 0.0458521 -1.9872 0.0144215 -1.9896 -0.0168028 -1.992 -0.0477137 -1.9944 -0.0782063 -1.9968 -0.108178 -1.9992 -0.137529 -2.0016 -0.166163 -2.004 -0.193986 -2.0064 -0.220911 -2.0088 -0.24685 -2.0112 -0.271725 -2.0136 -0.295459 -2.016 -0.317981 -2.0184 -0.339227 -2.0208 -0.359136 -2.0232 -0.377655 -2.0256 -0.394734 -2.028 -0.410332 -2.0304 -0.424411 -2.0328 -0.436942 -2.0352 -0.447901 -2.0376 -0.457269 -2.04 -0.465036 -2.0424 -0.471195 -2.0448 -0.475747 -2.0472 -0.478699 -2.0496 -0.480064 -2.052 -0.47986 -2.0544 -0.478111 -2.0568 -0.474847 -2.0592 -0.470102 -2.0616 -0.463916 -2.064 -0.456335 -2.0664 -0.447407 -2.0688 -0.437186 -2.0712 -0.425729 -2.0736 -0.413098 -2.076 -0.399358 -2.0784 -0.384576 -2.0808 -0.368823 -2.0832 -0.352172 -2.0856 -0.334699 -2.088 -0.31648 -2.0904 -0.297593 -2.0928 -0.278119 -2.0952 -0.258137 -2.0976 -0.237728 -2.1 -0.216972 -2.1024 -0.19595 -2.1048 -0.174742 -2.1072 -0.153427 -2.1096 -0.132082 -2.112 -0.110785 -2.1144 -0.0896079 -2.1168 -0.0686251 -2.1192 -0.0479063 -2.1216 -0.0275192 -2.124 -0.00752867 -2.1264 0.0120033 -2.1288 0.0310178 -2.1312 0.0494592 -2.1336 0.0672756 -2.136 0.0844184 -2.1384 0.100843 -2.1408 0.116508 -2.1432 0.131377 -2.1456 0.145416 -2.148 0.158596 -2.1504 0.170892 -2.1528 0.182283 -2.1552 0.192753 -2.1576 0.202286 -2.16 0.210876 -2.1624 0.218515 -2.1648 0.225203 -2.1672 0.230942 -2.1696 0.235738 -2.172 0.239599 -2.1744 0.242539 -2.1768 0.244572 -2.1792 0.245719 -2.1816 0.246001 -2.184 0.245442 -2.1864 0.24407 -2.1888 0.241913 -2.1912 0.239003 -2.1936 0.235375 -2.196 0.231063 -2.1984 0.226104 -2.2008 0.220538 -2.2032 0.214402 -2.2056 0.207738 -2.208 0.200588 -2.2104 0.192993 -2.2128 0.184996 -2.2152 0.176639 -2.2176 0.167964 -2.22 0.159016 -2.2224 0.149835 -2.2248 0.140464 -2.2272 0.130943 -2.2296 0.121313 -2.232 0.111614 -2.2344 0.101883 -2.2368 0.0921584 -2.2392 0.0824752 -2.2416 0.0728683 -2.244 0.0633704 -2.2464 0.0540131 -2.2488 0.044826 -2.2512 0.035837 -2.2536 0.0270724 -2.256 0.0185564 -2.2584 0.0103116 -2.2608 0.0023585 -2.2632 -0.00528426 -2.2656 -0.0125999 -2.268 -0.0195738 -2.2704 -0.0261929 -2.2728 -0.0324463 -2.2752 -0.038325 -2.2776 -0.0438216 -2.28 -0.0489309 -2.2824 -0.0536491 -2.2848 -0.0579742 -2.2872 -0.0619061 -2.2896 -0.0654459 -2.292 -0.0685966 -2.2944 -0.0713623 -2.2968 -0.0737488 -2.2992 -0.075763 -2.3016 -0.0774131 -2.304 -0.0787084 -2.3064 -0.0796592 -2.3088 -0.0802769 -2.3112 -0.0805736 -2.3136 -0.0805624 -2.316 -0.0802569 -2.3184 -0.0796713 -2.3208 -0.0788206 -2.3232 -0.0777199 -2.3256 -0.0763849 -2.328 -0.0748314 -2.3304 -0.0730755 -2.3328 -0.0711334 -2.3352 -0.0690213 -2.3376 -0.0667553 -2.34 -0.0643516 -2.3424 -0.061826 -2.3448 -0.0591944 -2.3472 -0.056472 -2.3496 -0.0536739 -2.352 -0.0508149 -2.3544 -0.0479091 -2.3568 -0.0449704 -2.3592 -0.0420119 -2.3616 -0.0390464 -2.364 -0.036086 -2.3664 -0.0331422 -2.3688 -0.0302259 -2.3712 -0.0273473 -2.3736 -0.0245161 -2.376 -0.0217411 -2.3784 -0.0190305 -2.3808 -0.016392 -2.3832 -0.0138324 -2.3856 -0.0113578 -2.388 -0.00897394 -2.3904 -0.00668552 -2.3928 -0.00449679 -2.3952 -0.00241133 -2.3976 -0.000432086 -2.4 0.0014386 -2.4024 0.00319896 -2.4048 0.0048478 -2.4072 0.00638444 -2.4096 0.00780876 -2.412 0.00912107 -2.4144 0.0103222 -2.4168 0.0114134 -2.4192 0.0123962 -2.4216 0.0132727 -2.424 0.0140453 -2.4264 0.0147166 -2.4288 0.0152897 -2.4312 0.0157676 -2.4336 0.016154 -2.436 0.0164525 -2.4384 0.0166669 -2.4408 0.0168012 -2.4432 0.0168595 -2.4456 0.0168461 -2.448 0.0167652 -2.4504 0.0166211 -2.4528 0.0164183 -2.4552 0.0161611 -2.4576 0.0158538 -2.46 0.0155009 -2.4624 0.0151064 -2.4648 0.0146747 -2.4672 0.0142098 -2.4696 0.0137158 -2.472 0.0131966 -2.4744 0.0126559 -2.4768 0.0120974 -2.4792 0.0115247 -2.4816 0.0109411 -2.484 0.0103497 -2.4864 0.00975367 -2.4888 0.00915585 -2.4912 0.00855895 -2.4936 0.0079655 -2.496 0.00737786 -2.4984 0.00679823 -2.5008 0.00622861 -2.5032 0.00567085 -2.5056 0.00512662 -2.508 0.00459743 -2.5104 0.00408462 -2.5128 0.00358935 -2.5152 0.00311267 -2.5176 0.00265543 -2.52 0.00221837 -2.5224 0.00180208 -2.5248 0.001407 -2.5272 0.00103347 -2.5296 0.000681685 -2.532 0.00035174 -2.5344 4.36187e-05 -2.5368 -0.000242794 -2.5392 -0.000507706 -2.5416 -0.000751412 -2.544 -0.000974285 -2.5464 -0.00117677 -2.5488 -0.00135938 -2.5512 -0.00152268 -2.5536 -0.00166728 -2.556 -0.00179386 -2.5584 -0.00190312 -2.5608 -0.00199579 -2.5632 -0.00207264 -2.5656 -0.00213445 -2.568 -0.00218203 -2.5704 -0.00221618 -2.5728 -0.00223772 -2.5752 -0.00224747 -2.5776 -0.00224625 -2.58 -0.00223488 -2.5824 -0.00221416 -2.5848 -0.00218487 -2.5872 -0.00214779 -2.5896 -0.00210368 -2.592 -0.00205326 -2.5944 -0.00199726 -2.5968 -0.00193635 -2.5992 -0.00187119 -2.6016 -0.00180243 -2.604 -0.00173065 -2.6064 -0.00165643 -2.6088 -0.00158032 -2.6112 -0.00150281 -2.6136 -0.0014244 -2.616 -0.00134553 -2.6184 -0.00126661 -2.6208 -0.00118802 -2.6232 -0.00111013 -2.6256 -0.00103326 -2.628 -0.000957687 -2.6304 -0.000883689 -2.6328 -0.000811498 -2.6352 -0.000741324 -2.6376 -0.000673348 -2.64 -0.000607728 -2.6424 -0.000544597 -2.6448 -0.000484066 -2.6472 -0.000426222 -2.6496 -0.000371133 -2.652 -0.000318849 -2.6544 -0.0002694 -2.6568 -0.000222799 -2.6592 -0.000179045 -2.6616 -0.000138122 -2.664 -0.0001 -2.6664 -6.46393e-05 -2.6688 -3.19866e-05 -2.6712 -1.98071e-06 -2.6736 2.54485e-05 -2.676 5.03788e-05 -2.6784 7.28944e-05 -2.6808 9.3085e-05 -2.6832 0.000111045 -2.6856 0.000126872 -2.688 0.000140668 -2.6904 0.000152536 -2.6928 0.00016258 -2.6952 0.000170906 -2.6976 0.000177618 -2.7 0.000182823 -2.7024 0.000186625 -2.7048 0.000189125 -2.7072 0.000190425 -2.7096 0.000190624 -2.712 0.000189816 -2.7144 0.000188096 -2.7168 0.000185553 -2.7192 0.000182273 -2.7216 0.000178339 -2.724 0.000173831 -2.7264 0.000168824 -2.7288 0.000163388 -2.7312 0.000157593 -2.7336 0.000151501 -2.736 0.000145171 -2.7384 0.00013866 -2.7408 0.000132018 -2.7432 0.000125294 -2.7456 0.000118531 -2.748 0.000111769 -2.7504 0.000105045 -2.7528 9.83918e-05 -2.7552 9.18392e-05 -2.7576 8.54135e-05 -2.76 7.9138e-05 -2.7624 7.30331e-05 -2.7648 6.71163e-05 -2.7672 6.14026e-05 -2.7696 5.59042e-05 -2.772 5.06312e-05 -2.7744 4.55916e-05 -2.7768 4.07911e-05 -2.7792 3.62336e-05 -2.7816 3.19214e-05 -2.784 2.7855e-05 -2.7864 2.40337e-05 -2.7888 2.04553e-05 -2.7912 1.71165e-05 -2.7936 1.40129e-05 -2.796 1.11393e-05 -2.7984 8.48943e-06 -2.8008 6.05665e-06 -2.8032 3.83351e-06 -2.8056 1.81212e-06 -2.808 -1.58004e-08 -2.8104 -1.65887e-06 -2.8128 -3.12593e-06 -2.8152 -4.42599e-06 -2.8176 -5.56814e-06 -2.82 -6.56154e-06 -2.8224 -7.41528e-06 -2.8248 -8.1384e-06 -2.8272 -8.73982e-06 -2.8296 -9.22827e-06 -2.832 -9.61232e-06 -2.8344 -9.90027e-06 -2.8368 -1.01002e-05 -2.8392 -1.02199e-05 -2.8416 -1.02668e-05 -2.844 -1.02481e-05 -2.8464 -1.01706e-05 -2.8488 -1.00409e-05 -2.8512 -9.86509e-06 -2.8536 -9.64897e-06 -2.856 -9.39803e-06 -2.8584 -9.11738e-06 -2.8608 -8.81181e-06 -2.8632 -8.48576e-06 -2.8656 -8.14334e-06 -2.868 -7.78834e-06 -2.8704 -7.42424e-06 -2.8728 -7.0542e-06 -2.8752 -6.68112e-06 -2.8776 -6.3076e-06 -2.88 -5.93596e-06 -2.8824 -5.5683e-06 -2.8848 -5.20645e-06 -2.8872 -4.85201e-06 -2.8896 -4.50639e-06 -2.892 -4.17078e-06 -2.8944 -3.84619e-06 -2.8968 -3.53344e-06 -2.8992 -3.23321e-06 -2.9016 -2.94601e-06 -2.904 -2.67223e-06 -2.9064 -2.41213e-06 -2.9088 -2.16584e-06 -2.9112 -1.93342e-06 -2.9136 -1.7148e-06 -2.916 -1.50986e-06 -2.9184 -1.3184e-06 -2.9208 -1.14013e-06 -2.9232 -9.7474e-07 -2.9256 -8.21855e-07 -2.928 -6.81065e-07 -2.9304 -5.51924e-07 -2.9328 -4.33964e-07 -2.9352 -3.26691e-07 -2.9376 -2.29602e-07 -2.94 -1.42178e-07 -2.9424 -6.38992e-08 -2.9448 5.75981e-09 -2.9472 6.73205e-08 -2.9496 1.213e-07 -2.952 1.68206e-07 -2.9544 2.08538e-07 -2.9568 2.42782e-07 -2.9592 2.71409e-07 -2.9616 2.94875e-07 -2.964 3.13618e-07 -2.9664 3.28058e-07 -2.9688 3.38597e-07 -2.9712 3.45617e-07 -2.9736 3.49478e-07 -2.976 3.50523e-07 -2.9784 3.49073e-07 -2.9808 3.45429e-07 -2.9832 3.39875e-07 -2.9856 3.3267e-07 -2.988 3.24059e-07 -2.9904 3.14266e-07 -2.9928 3.03497e-07 -2.9952 2.91942e-07 -2.9976 2.79774e-07 -3 2.67148e-07 -3.0024 2.54207e-07 -3.0048 2.41078e-07 -3.0072 2.27873e-07 -3.0096 2.14694e-07 -3.012 2.01629e-07 -3.0144 1.88755e-07 -3.0168 1.7614e-07 -3.0192 1.6384e-07 -3.0216 1.51903e-07 -3.024 1.40369e-07 -3.0264 1.29272e-07 -3.0288 1.18634e-07 -3.0312 1.08477e-07 -3.0336 9.88126e-08 -3.036 8.96497e-08 -3.0384 8.09918e-08 -3.0408 7.28385e-08 -3.0432 6.51861e-08 -3.0456 5.80273e-08 -3.048 5.13526e-08 -3.0504 4.515e-08 -3.0528 3.94054e-08 -3.0552 3.41035e-08 -3.0576 2.92273e-08 -3.06 2.4759e-08 -3.0624 2.06801e-08 -3.0648 1.69713e-08 -3.0672 1.36133e-08 -3.0696 1.05864e-08 -3.072 7.87105e-09 -3.0744 5.44771e-09 -3.0768 3.29725e-09 -3.0792 1.40088e-09 -3.0816 -2.5971e-10 -3.084 -1.70229e-09 -3.0864 -2.944e-09 -3.0888 -4.00132e-09 -3.0912 -4.89003e-09 -3.0936 -5.62516e-09 -3.096 -6.22099e-09 -3.0984 -6.69104e-09 -3.1008 -7.04805e-09 -3.1032 -7.30398e-09 -3.1056 -7.47003e-09 -3.108 -7.55666e-09 -3.1104 -7.57357e-09 -3.1128 -7.52975e-09 -3.1152 -7.4335e-09 -3.1176 -7.29245e-09 -3.12 -7.11358e-09 -3.1224 -6.90326e-09 -3.1248 -6.66727e-09 -3.1272 -6.41084e-09 -3.1296 -6.13868e-09 -3.132 -5.855e-09 -3.1344 -5.56356e-09 -3.1368 -5.26766e-09 -3.1392 -4.97024e-09 -3.1416 -4.67383e-09 -3.144 -4.38065e-09 -3.1464 -4.09256e-09 -3.1488 -3.81118e-09 -3.1512 -3.53784e-09 -3.1536 -3.27361e-09 -3.156 -3.01939e-09 -3.1584 -2.77584e-09 -3.1608 -2.54348e-09 -3.1632 -2.32263e-09 -3.1656 -2.11352e-09 -3.168 -1.91623e-09 -3.1704 -1.73073e-09 -3.1728 -1.55692e-09 -3.1752 -1.3946e-09 -3.1776 -1.24351e-09 -3.18 -1.10334e-09 -3.1824 -9.73724e-10 -3.1848 -8.5427e-10 -3.1872 -7.4455e-10 -3.1896 -6.44117e-10 -3.192 -5.52507e-10 -3.1944 -4.6925e-10 -3.1968 -3.9387e-10 -3.1992 -3.25893e-10 -3.2016 -2.64848e-10 -3.204 -2.10272e-10 -3.2064 -1.61712e-10 -3.2088 -1.18729e-10 -3.2112 -8.08967e-11 -3.2136 -4.78066e-11 -3.216 -1.90666e-11 -3.2184 5.69693e-12 -3.2208 2.68389e-11 -3.2232 4.46949e-11 -3.2256 5.95812e-11 -3.228 7.17949e-11 -3.2304 8.16136e-11 -3.2328 8.92965e-11 -3.2352 9.5084e-11 -3.2376 9.91989e-11 -3.24 1.01846e-10 -3.2424 1.03216e-10 -3.2448 1.03479e-10 -3.2472 1.02795e-10 -3.2496 1.01307e-10 -3.252 9.91442e-11 -3.2544 9.64241e-11 -3.2568 9.32518e-11 -3.2592 8.97212e-11 -3.2616 8.59158e-11 -3.264 8.19096e-11 -3.2664 7.77675e-11 -3.2688 7.35462e-11 -3.2712 6.92949e-11 -3.2736 6.5056e-11 -3.276 6.08655e-11 -3.2784 5.67537e-11 -3.2808 5.27458e-11 -3.2832 4.88625e-11 -3.2856 4.51203e-11 -3.288 4.15319e-11 -3.2904 3.81068e-11 -3.2928 3.48517e-11 -3.2952 3.17708e-11 -3.2976 2.8866e-11 -3.3 2.61374e-11 -3.3024 2.35834e-11 -3.3048 2.12012e-11 -3.3072 1.89867e-11 -3.3096 1.6935e-11 -3.312 1.50403e-11 -3.3144 1.32965e-11 -3.3168 1.16966e-11 -3.3192 1.02338e-11 -3.3216 8.90069e-12 -3.324 7.68996e-12 -3.3264 6.59422e-12 -3.3288 5.60614e-12 -3.3312 4.71848e-12 -3.3336 3.92417e-12 -3.336 3.21636e-12 -3.3384 2.58838e-12 -3.3408 2.03389e-12 -3.3432 1.54678e-12 -3.3456 1.12125e-12 -3.348 7.51808e-13 -3.3504 4.3328e-13 -3.3528 1.60793e-13 -3.3552 -7.02117e-14 -3.3576 -2.63986e-13 -3.36 -4.24481e-13 -3.3624 -5.55357e-13 -3.3648 -6.5999e-13 -3.3672 -7.41488e-13 -3.3696 -8.02696e-13 -3.372 -8.46214e-13 -3.3744 -8.7441e-13 -3.3768 -8.89429e-13 -3.3792 -8.93209e-13 -3.3816 -8.87496e-13 -3.384 -8.73852e-13 -3.3864 -8.53675e-13 -3.3888 -8.28205e-13 -3.3912 -7.98538e-13 -3.3936 -7.65641e-13 -3.396 -7.30359e-13 -3.3984 -6.93426e-13 -3.4008 -6.55476e-13 -3.4032 -6.17055e-13 -3.4056 -5.78624e-13 -3.408 -5.40573e-13 -3.4104 -5.03223e-13 -3.4128 -4.66841e-13 -3.4152 -4.31637e-13 -3.4176 -3.97779e-13 -3.42 -3.65394e-13 -3.4224 -3.34571e-13 -3.4248 -3.05372e-13 -3.4272 -2.77832e-13 -3.4296 -2.51961e-13 -3.432 -2.27754e-13 -3.4344 -2.05187e-13 -3.4368 -1.84224e-13 -3.4392 -1.6482e-13 -3.4416 -1.46918e-13 -3.444 -1.30458e-13 -3.4464 -1.15373e-13 -3.4488 -1.01594e-13 -3.4512 -8.90479e-14 -3.4536 -7.76626e-14 -3.456 -6.7365e-14 -3.4584 -5.80827e-14 -3.4608 -4.97447e-14 -3.4632 -4.22817e-14 -3.4656 -3.56268e-14 -3.468 -2.97154e-14 -3.4704 -2.4486e-14 -3.4728 -1.98801e-14 -3.4752 -1.5842e-14 -3.4776 -1.23197e-14 -3.48 -9.26404e-15 -3.4824 -6.62916e-15 -3.4848 -4.37241e-15 -3.4872 -2.45421e-15 -3.4896 -8.37972e-16 -3.492 5.09998e-16 -3.4944 1.62062e-15 -3.4968 2.52217e-15 -3.4992 3.24044e-15 -3.5016 3.79882e-15 -3.504 4.21853e-15 -3.5064 4.51867e-15 -3.5088 4.71643e-15 -3.5112 4.8272e-15 -3.5136 4.8647e-15 -3.516 4.84112e-15 -3.5184 4.76725e-15 -3.5208 4.65259e-15 -3.5232 4.50548e-15 -3.5256 4.33316e-15 -3.528 4.14194e-15 -3.5304 3.93725e-15 -3.5328 3.72373e-15 -3.5352 3.50532e-15 -3.5376 3.28535e-15 -3.54 3.06657e-15 -3.5424 2.85126e-15 -3.5448 2.64125e-15 -3.5472 2.43802e-15 -3.5496 2.2427e-15 -3.552 2.05612e-15 -3.5544 1.87889e-15 -3.5568 1.7114e-15 -3.5592 1.55385e-15 -3.5616 1.40631e-15 -3.564 1.26872e-15 -3.5664 1.1409e-15 -3.5688 1.0226e-15 -3.5712 9.13517e-16 -3.5736 8.13273e-16 -3.576 7.21466e-16 -3.5784 6.37668e-16 -3.5808 5.6143e-16 -3.5832 4.92298e-16 -3.5856 4.29811e-16 -3.588 3.73517e-16 -3.5904 3.2297e-16 -3.5928 2.77734e-16 -3.5952 2.37392e-16 -3.5976 2.01541e-16 -3.6 1.69798e-16 -3.6024 1.418e-16 -3.6048 1.17204e-16 -3.6072 9.56889e-17 -3.6096 7.69546e-17 -3.612 6.07215e-17 -3.6144 4.67304e-17 -3.6168 3.47422e-17 -3.6192 2.45369e-17 -3.6216 1.5913e-17 -3.624 8.68605e-18 -3.6264 2.68855e-18 -3.6288 -2.23163e-18 -3.6312 -6.212e-18 -3.6336 -9.37646e-18 -3.636 -1.18363e-17 -3.6384 -1.36909e-17 -3.6408 -1.50292e-17 -3.6432 -1.593e-17 -3.6456 -1.6463e-17 -3.648 -1.66896e-17 -3.6504 -1.6664e-17 -3.6528 -1.64332e-17 -3.6552 -1.60383e-17 -3.6576 -1.55147e-17 -3.66 -1.4893e-17 -3.6624 -1.41994e-17 -3.6648 -1.34558e-17 -3.6672 -1.26812e-17 -3.6696 -1.18911e-17 -3.672 -1.10983e-17 -3.6744 -1.03135e-17 -3.6768 -9.54517e-18 -3.6792 -8.79992e-18 -3.6816 -8.08295e-18 -3.684 -7.39808e-18 -3.6864 -6.74802e-18 -3.6888 -6.13454e-18 -3.6912 -5.55859e-18 -3.6936 -5.02048e-18 -3.696 -4.51997e-18 -3.6984 -4.05639e-18 -3.7008 -3.62873e-18 -3.7032 -3.23568e-18 -3.7056 -2.87576e-18 -3.708 -2.54734e-18 -3.7104 -2.24869e-18 -3.7128 -1.978e-18 -3.7152 -1.73347e-18 -3.7176 -1.51329e-18 -3.72 -1.31568e-18 -3.7224 -1.13891e-18 -3.7248 -9.81291e-19 -3.7272 -8.41221e-19 -3.7296 -7.17169e-19 -3.732 -6.07687e-19 -3.7344 -5.11413e-19 -3.7368 -4.27072e-19 -3.7392 -3.53476e-19 -3.7416 -2.89523e-19 -3.744 -2.34195e-19 -3.7464 -1.86558e-19 -3.7488 -1.45754e-19 -3.7512 -1.10999e-19 -3.7536 -8.15819e-20 -3.756 -5.68562e-20 -3.7584 -3.62386e-20 -3.7608 -1.92039e-20 -3.7632 -5.28066e-21 -3.7656 5.95274e-21 -3.768 1.48721e-20 -3.7704 2.18112e-20 -3.7728 2.70654e-20 -3.7752 3.08954e-20 -3.7776 3.353e-20 -3.78 3.51695e-20 -3.7824 3.59886e-20 -3.7848 3.61387e-20 -3.7872 3.57507e-20 -3.7896 3.4937e-20 -3.792 3.3794e-20 -3.7944 3.24031e-20 -3.7968 3.08334e-20 -3.7992 2.91427e-20 -3.8016 2.73789e-20 -3.804 2.55816e-20 -3.8064 2.37829e-20 -3.8088 2.20084e-20 -3.8112 2.02785e-20 -3.8136 1.86088e-20 -3.816 1.70108e-20 -3.8184 1.54929e-20 -3.8208 1.40606e-20 -3.8232 1.27171e-20 -3.8256 1.14636e-20 -3.828 1.02999e-20 -3.8304 9.22452e-21 -3.8328 8.23505e-21 -3.8352 7.32828e-21 -3.8376 6.5005e-21 -3.84 5.74762e-21 -3.8424 5.06528e-21 -3.8448 4.449e-21 -3.8472 3.89426e-21 -3.8496 3.39656e-21 -3.852 2.95148e-21 -3.8544 2.55477e-21 -3.8568 2.2023e-21 -3.8592 1.89017e-21 -3.8616 1.61467e-21 -3.864 1.37232e-21 -3.8664 1.15987e-21 -3.8688 9.74292e-22 -3.8712 8.12781e-22 -3.8736 6.72759e-22 -3.876 5.5186e-22 -3.8784 4.47923e-22 -3.8808 3.58978e-22 -3.8832 2.83241e-22 -3.8856 2.19101e-22 -3.888 1.65105e-22 -3.8904 1.19951e-22 -3.8928 8.24745e-23 -3.8952 5.16363e-23 -3.8976 2.65146e-23 -3.9 6.2929e-24 -3.9024 -9.74902e-24 -3.9048 -2.22445e-23 -3.9072 -3.17484e-23 -3.9096 -3.8745e-23 -3.912 -4.36553e-23 -3.9144 -4.6844e-23 -3.9168 -4.86257e-23 -3.9192 -4.92702e-23 -3.9216 -4.90084e-23 -3.924 -4.80363e-23 -3.9264 -4.65195e-23 -3.9288 -4.45974e-23 -3.9312 -4.23859e-23 -3.9336 -3.99811e-23 -3.936 -3.74617e-23 -3.9384 -3.48915e-23 -3.9408 -3.23217e-23 -3.9432 -2.97926e-23 -3.9456 -2.73351e-23 -3.948 -2.49728e-23 -3.9504 -2.27224e-23 -3.9528 -2.05956e-23 -3.9552 -1.85995e-23 -3.9576 -1.67376e-23 -3.96 -1.50107e-23 -3.9624 -1.34172e-23 -3.9648 -1.19538e-23 -3.9672 -1.06157e-23 -3.9696 -9.39726e-24 -3.972 -8.29218e-24 -3.9744 -7.29364e-24 -3.9768 -6.39462e-24 -3.9792 -5.58802e-24 -3.9816 -4.86678e-24 -3.984 -4.22401e-24 -3.9864 -3.65304e-24 -3.9888 -3.14751e-24 -3.9912 -2.70136e-24 -3.9936 -2.30889e-24 -3.996 -1.96478e-24 -3.9984 -1.66407e-24 -4.0008 -1.40217e-24 -4.0032 -1.17489e-24 -4.0056 -9.78347e-25 -4.008 -8.09034e-25 -4.0104 -6.63754e-25 -4.0128 -5.39615e-25 -4.0152 -4.34014e-25 -4.0176 -3.44611e-25 -4.02 -2.69314e-25 -4.0224 -2.06259e-25 -4.0248 -1.53787e-25 -4.0272 -1.1043e-25 -4.0296 -7.48921e-26 -4.032 -4.60332e-26 -4.0344 -2.28536e-26 -4.0368 -4.47991e-27 -4.0392 9.84853e-27 -4.0416 2.07915e-26 -4.044 2.89195e-26 -4.0464 3.47235e-26 -4.0488 3.86247e-26 -4.0512 4.09827e-26 -4.0536 4.21031e-26 -4.056 4.22444e-26 -4.0584 4.16239e-26 -4.0608 4.04236e-26 -4.0632 3.87945e-26 -4.0656 3.68612e-26 -4.068 3.47255e-26 -4.0704 3.247e-26 -4.0728 3.01607e-26 -4.0752 2.78498e-26 -4.0776 2.55777e-26 -4.08 2.33751e-26 -4.0824 2.12645e-26 -4.0848 1.92619e-26 -4.0872 1.73778e-26 -4.0896 1.56181e-26 -4.092 1.39853e-26 -4.0944 1.24792e-26 -4.0968 1.10974e-26 -4.0992 9.83579e-27 -4.1016 8.68924e-27 -4.104 7.65166e-27 -4.1064 6.71647e-27 -4.1088 5.87679e-27 -4.1112 5.12562e-27 -4.1136 4.45601e-27 -4.116 3.86114e-27 -4.1184 3.33445e-27 -4.1208 2.86964e-27 -4.1232 2.46079e-27 -4.1256 2.10231e-27 -4.128 1.78902e-27 -4.1304 1.51611e-27 -4.1328 1.27917e-27 -4.1352 1.07413e-27 -4.1376 8.97315e-28 -4.14 7.45381e-28 -4.1424 6.15306e-28 -4.1448 5.04374e-28 -4.1472 4.10151e-28 -4.1496 3.30464e-28 -4.152 2.6338e-28 -4.1544 2.07186e-28 -4.1568 1.6037e-28 -4.1592 1.21597e-28 -4.1616 8.97e-29 -4.164 6.36552e-29 -4.1664 4.25712e-29 -4.1688 2.56737e-29 -4.1712 1.2292e-29 -4.1736 1.84771e-30 -4.176 -6.15651e-30 -4.1784 -1.21465e-29 -4.1808 -1.64857e-29 -4.1832 -1.94827e-29 -4.1856 -2.13985e-29 -4.188 -2.24531e-29 -4.1904 -2.28304e-29 -4.1928 -2.26839e-29 -4.1952 -2.21407e-29 -4.1976 -2.13051e-29 -4.2 -2.02625e-29 -4.2024 -1.90818e-29 -4.2048 -1.78185e-29 -4.2072 -1.65161e-29 -4.2096 -1.52088e-29 -4.212 -1.39227e-29 -4.2144 -1.26773e-29 -4.2168 -1.14868e-29 -4.2192 -1.03608e-29 -4.2216 -9.30542e-30 -4.224 -8.32409e-30 -4.2264 -7.41793e-30 -4.2288 -6.58636e-30 -4.2312 -5.82752e-30 -4.2336 -5.13858e-30 -4.236 -4.51607e-30 -4.2384 -3.95606e-30 -4.2408 -3.45436e-30 -4.2432 -3.00667e-30 -4.2456 -2.60865e-30 -4.248 -2.25607e-30 -4.2504 -1.94483e-30 -4.2528 -1.67101e-30 -4.2552 -1.4309e-30 -4.2576 -1.22105e-30 -4.26 -1.03824e-30 -4.2624 -8.79487e-31 -4.2648 -7.4208e-31 -4.2672 -6.23536e-31 -4.2696 -5.21603e-31 -4.272 -4.34251e-31 -4.2744 -3.59655e-31 -4.2768 -2.96181e-31 -4.2792 -2.42373e-31 -4.2816 -1.96938e-31 -4.284 -1.58734e-31 -4.2864 -1.2675e-31 -4.2888 -1.00101e-31 -4.2912 -7.80124e-32 -4.2936 -5.98058e-32 -4.296 -4.48927e-32 -4.2984 -3.27625e-32 -4.3008 -2.29742e-32 -4.3032 -1.51477e-32 -4.3056 -8.9571e-33 -4.308 -4.12353e-33 -4.3104 -4.09408e-34 -4.3128 2.38695e-33 -4.3152 4.43607e-33 -4.3176 5.88157e-33 -4.32 6.84383e-33 -4.3224 7.4233e-33 -4.3248 7.70338e-33 -4.3272 7.75291e-33 -4.3296 7.6284e-33 -4.332 7.37587e-33 -4.3344 7.03255e-33 -4.3368 6.62829e-33 -4.3392 6.18674e-33 -4.3416 5.72644e-33 -4.344 5.2617e-33 -4.3464 4.80335e-33 -4.3488 4.35937e-33 -4.3512 3.93545e-33 -4.3536 3.53546e-33 -4.356 3.16177e-33 -4.3584 2.81562e-33 -4.3608 2.49737e-33 -4.3632 2.20669e-33 -4.3656 1.94278e-33 -4.368 1.70445e-33 -4.3704 1.49029e-33 -4.3728 1.29872e-33 -4.3752 1.1281e-33 -4.3776 9.76754e-34 -4.38 8.43013e-34 -4.3824 7.25264e-34 -4.3848 6.21962e-34 -4.3872 5.31645e-34 -4.3896 4.52945e-34 -4.392 3.84593e-34 -4.3944 3.25421e-34 -4.3968 2.74361e-34 -4.3992 2.30444e-34 -4.4016 1.92792e-34 -4.404 1.60617e-34 -4.4064 1.33215e-34 -4.4088 1.09958e-34 -4.4112 9.0287e-35 -4.4136 7.37109e-35 -4.416 5.97959e-35 -4.4184 4.81615e-35 -4.4208 3.84753e-35 -4.4232 3.04477e-35 -4.4256 2.38273e-35 -4.428 1.83965e-35 -4.4304 1.39676e-35 -4.4328 1.03793e-35 -4.4352 7.49326e-36 -4.4376 5.19158e-36 -4.44 3.37377e-36 -4.4424 1.95465e-36 -4.4448 8.62247e-37 -4.4472 3.59778e-38 -4.4496 -5.74953e-37 -4.452 -1.01296e-36 -4.4544 -1.3133e-36 -4.4568 -1.50515e-36 -4.4592 -1.61253e-36 -4.4616 -1.65508e-36 -4.464 -1.64881e-36 -4.4664 -1.60663e-36 -4.4688 -1.53891e-36 -4.4712 -1.45387e-36 -4.4736 -1.35799e-36 -4.476 -1.2563e-36 -4.4784 -1.15264e-36 -4.4808 -1.04988e-36 -4.4832 -9.50148e-37 -4.4856 -8.54914e-37 -4.488 -7.65177e-37 -4.4904 -6.81543e-37 -4.4928 -6.04323e-37 -4.4952 -5.33598e-37 -4.4976 -4.69279e-37 -4.5 -4.11155e-37 -4.5024 -3.58927e-37 -4.5048 -3.12241e-37 -4.5072 -2.70708e-37 -4.5096 -2.33925e-37 -4.512 -2.01484e-37 -4.5144 -1.72984e-37 -4.5168 -1.48043e-37 -4.5192 -1.26293e-37 -4.5216 -1.07394e-37 -4.524 -9.10261e-38 -4.5264 -7.68982e-38 -4.5288 -6.47434e-38 -4.5312 -5.43199e-38 -4.5336 -4.541e-38 -4.536 -3.78183e-38 -4.5384 -3.13709e-38 -4.5408 -2.59134e-38 -4.5432 -2.13092e-38 -4.5456 -1.74385e-38 -4.548 -1.41959e-38 -4.5504 -1.14896e-38 -4.5528 -9.23958e-39 -4.5552 -7.37667e-39 -4.5576 -5.84095e-39 -4.56 -4.58085e-39 -4.5624 -3.55213e-39 -4.5648 -2.71692e-39 -4.5672 -2.04294e-39 -4.5696 -1.50278e-39 -4.572 -1.07317e-39 -4.5744 -7.34526e-40 -4.5768 -4.70336e-40 -4.5792 -2.66776e-40 -4.5816 -1.12301e-40 -4.584 2.69003e-42 -4.5864 8.61517e-41 -4.5888 1.44642e-40 -4.5912 1.83544e-40 -4.5936 2.07254e-40 -4.596 2.1934e-40 -4.5984 2.22686e-40 -4.6008 2.19599e-40 -4.6032 2.11917e-40 -4.6056 2.01089e-40 -4.608 1.88244e-40 -4.6104 1.74253e-40 -4.6128 1.59778e-40 -4.6152 1.4531e-40 -4.6176 1.31206e-40 -4.62 1.17716e-40 -4.6224 1.05008e-40 -4.6248 9.31813e-41 -4.6272 8.22891e-41 -4.6296 7.23454e-41 -4.632 6.3337e-41 -4.6344 5.5231e-41 -4.6368 4.79812e-41 -4.6392 4.15328e-41 -4.6416 3.58261e-41 -4.644 3.07991e-41 -4.6464 2.63901e-41 -4.6488 2.2539e-41 -4.6512 1.91882e-41 -4.6536 1.62834e-41 -4.656 1.37743e-41 -4.6584 1.16145e-41 -4.6608 9.76145e-42 -4.6632 8.17694e-42 -4.6656 6.82643e-42 -4.668 5.67906e-42 -4.6704 4.70742e-42 -4.6728 3.88725e-42 -4.6752 3.19719e-42 -4.6776 2.61853e-42 -4.68 2.13492e-42 -4.6824 1.73217e-42 -4.6848 1.39797e-42 -4.6872 1.12168e-42 -4.6896 8.94185e-43 -4.692 7.0764e-43 -4.6944 5.55357e-43 -4.6968 4.31639e-43 -4.6992 3.31648e-43 -4.7016 2.51296e-43 -4.704 1.87131e-43 -4.7064 1.36256e-43 -4.7088 9.62434e-44 -4.7112 6.50662e-44 -4.7136 4.10401e-44 -4.716 2.27693e-44 -4.7184 9.10173e-45 -4.7208 -9.09271e-46 -4.7232 -8.03847e-45 -4.7256 -1.29169e-44 -4.728 -1.60559e-44 -4.7304 -1.78677e-44 -4.7328 -1.86825e-44 -4.7352 -1.8763e-44 -4.7376 -1.83166e-44 -4.74 -1.75059e-44 -4.7424 -1.64566e-44 -4.7448 -1.52651e-44 -4.7472 -1.4004e-44 -4.7496 -1.27272e-44 -4.752 -1.14734e-44 -4.7544 -1.02698e-44 -4.7568 -9.13438e-45 -4.7592 -8.07826e-45 -4.7616 -7.10716e-45 -4.764 -6.2229e-45 -4.7664 -5.42443e-45 -4.7688 -4.70872e-45 -4.7712 -4.07134e-45 -4.7736 -3.50704e-45 -4.776 -3.0101e-45 -4.7784 -2.57462e-45 -4.7808 -2.19471e-45 -4.7832 -1.86471e-45 -4.7856 -1.57919e-45 -4.788 -1.33311e-45 -4.7904 -1.12178e-45 -4.7928 -9.40945e-46 -4.7952 -7.86725e-46 -4.7976 -6.55643e-46 -4.8 -5.4459e-46 +0.0024 6.5005e-21 +0.0048 7.32828e-21 +0.0072 8.23505e-21 +0.0096 9.22452e-21 +0.012 1.02999e-20 +0.0144 1.14636e-20 +0.0168 1.27171e-20 +0.0192 1.40606e-20 +0.0216 1.54929e-20 +0.024 1.70108e-20 +0.0264 1.86088e-20 +0.0288 2.02785e-20 +0.0312 2.20084e-20 +0.0336 2.37829e-20 +0.036 2.55816e-20 +0.0384 2.73789e-20 +0.0408 2.91427e-20 +0.0432 3.08334e-20 +0.0456 3.24031e-20 +0.048 3.3794e-20 +0.0504 3.4937e-20 +0.0528 3.57507e-20 +0.0552 3.61387e-20 +0.0576 3.59886e-20 +0.06 3.51695e-20 +0.0624 3.353e-20 +0.0648 3.08954e-20 +0.0672 2.70654e-20 +0.0696 2.18112e-20 +0.072 1.48721e-20 +0.0744 5.95274e-21 +0.0768 -5.28066e-21 +0.0792 -1.92039e-20 +0.0816 -3.62386e-20 +0.084 -5.68562e-20 +0.0864 -8.15819e-20 +0.0888 -1.10999e-19 +0.0912 -1.45754e-19 +0.0936 -1.86558e-19 +0.096 -2.34195e-19 +0.0984 -2.89523e-19 +0.1008 -3.53476e-19 +0.1032 -4.27072e-19 +0.1056 -5.11413e-19 +0.108 -6.07687e-19 +0.1104 -7.17169e-19 +0.1128 -8.41221e-19 +0.1152 -9.81291e-19 +0.1176 -1.13891e-18 +0.12 -1.31568e-18 +0.1224 -1.51329e-18 +0.1248 -1.73347e-18 +0.1272 -1.978e-18 +0.1296 -2.24869e-18 +0.132 -2.54734e-18 +0.1344 -2.87576e-18 +0.1368 -3.23568e-18 +0.1392 -3.62873e-18 +0.1416 -4.05639e-18 +0.144 -4.51997e-18 +0.1464 -5.02048e-18 +0.1488 -5.55859e-18 +0.1512 -6.13454e-18 +0.1536 -6.74802e-18 +0.156 -7.39808e-18 +0.1584 -8.08295e-18 +0.1608 -8.79992e-18 +0.1632 -9.54517e-18 +0.1656 -1.03135e-17 +0.168 -1.10983e-17 +0.1704 -1.18911e-17 +0.1728 -1.26812e-17 +0.1752 -1.34558e-17 +0.1776 -1.41994e-17 +0.18 -1.4893e-17 +0.1824 -1.55147e-17 +0.1848 -1.60383e-17 +0.1872 -1.64332e-17 +0.1896 -1.6664e-17 +0.192 -1.66896e-17 +0.1944 -1.6463e-17 +0.1968 -1.593e-17 +0.1992 -1.50292e-17 +0.2016 -1.36909e-17 +0.204 -1.18363e-17 +0.2064 -9.37646e-18 +0.2088 -6.212e-18 +0.2112 -2.23163e-18 +0.2136 2.68855e-18 +0.216 8.68605e-18 +0.2184 1.5913e-17 +0.2208 2.45369e-17 +0.2232 3.47422e-17 +0.2256 4.67304e-17 +0.228 6.07215e-17 +0.2304 7.69546e-17 +0.2328 9.56889e-17 +0.2352 1.17204e-16 +0.2376 1.418e-16 +0.24 1.69798e-16 +0.2424 2.01541e-16 +0.2448 2.37392e-16 +0.2472 2.77734e-16 +0.2496 3.2297e-16 +0.252 3.73517e-16 +0.2544 4.29811e-16 +0.2568 4.92298e-16 +0.2592 5.6143e-16 +0.2616 6.37668e-16 +0.264 7.21466e-16 +0.2664 8.13273e-16 +0.2688 9.13517e-16 +0.2712 1.0226e-15 +0.2736 1.1409e-15 +0.276 1.26872e-15 +0.2784 1.40631e-15 +0.2808 1.55385e-15 +0.2832 1.7114e-15 +0.2856 1.87889e-15 +0.288 2.05612e-15 +0.2904 2.2427e-15 +0.2928 2.43802e-15 +0.2952 2.64125e-15 +0.2976 2.85126e-15 +0.3 3.06657e-15 +0.3024 3.28535e-15 +0.3048 3.50532e-15 +0.3072 3.72373e-15 +0.3096 3.93725e-15 +0.312 4.14194e-15 +0.3144 4.33316e-15 +0.3168 4.50548e-15 +0.3192 4.65259e-15 +0.3216 4.76725e-15 +0.324 4.84112e-15 +0.3264 4.8647e-15 +0.3288 4.8272e-15 +0.3312 4.71643e-15 +0.3336 4.51867e-15 +0.336 4.21853e-15 +0.3384 3.79882e-15 +0.3408 3.24044e-15 +0.3432 2.52217e-15 +0.3456 1.62062e-15 +0.348 5.09998e-16 +0.3504 -8.37972e-16 +0.3528 -2.45421e-15 +0.3552 -4.37241e-15 +0.3576 -6.62916e-15 +0.36 -9.26404e-15 +0.3624 -1.23197e-14 +0.3648 -1.5842e-14 +0.3672 -1.98801e-14 +0.3696 -2.4486e-14 +0.372 -2.97154e-14 +0.3744 -3.56268e-14 +0.3768 -4.22817e-14 +0.3792 -4.97447e-14 +0.3816 -5.80827e-14 +0.384 -6.7365e-14 +0.3864 -7.76626e-14 +0.3888 -8.90479e-14 +0.3912 -1.01594e-13 +0.3936 -1.15373e-13 +0.396 -1.30458e-13 +0.3984 -1.46918e-13 +0.4008 -1.6482e-13 +0.4032 -1.84224e-13 +0.4056 -2.05187e-13 +0.408 -2.27754e-13 +0.4104 -2.51961e-13 +0.4128 -2.77832e-13 +0.4152 -3.05372e-13 +0.4176 -3.34571e-13 +0.42 -3.65394e-13 +0.4224 -3.97779e-13 +0.4248 -4.31637e-13 +0.4272 -4.66841e-13 +0.4296 -5.03223e-13 +0.432 -5.40573e-13 +0.4344 -5.78624e-13 +0.4368 -6.17055e-13 +0.4392 -6.55476e-13 +0.4416 -6.93426e-13 +0.444 -7.30359e-13 +0.4464 -7.65641e-13 +0.4488 -7.98538e-13 +0.4512 -8.28205e-13 +0.4536 -8.53675e-13 +0.456 -8.73852e-13 +0.4584 -8.87496e-13 +0.4608 -8.93209e-13 +0.4632 -8.89429e-13 +0.4656 -8.7441e-13 +0.468 -8.46214e-13 +0.4704 -8.02696e-13 +0.4728 -7.41488e-13 +0.4752 -6.5999e-13 +0.4776 -5.55357e-13 +0.48 -4.24481e-13 +0.4824 -2.63986e-13 +0.4848 -7.02117e-14 +0.4872 1.60793e-13 +0.4896 4.3328e-13 +0.492 7.51808e-13 +0.4944 1.12125e-12 +0.4968 1.54678e-12 +0.4992 2.03389e-12 +0.5016 2.58838e-12 +0.504 3.21636e-12 +0.5064 3.92417e-12 +0.5088 4.71848e-12 +0.5112 5.60614e-12 +0.5136 6.59422e-12 +0.516 7.68996e-12 +0.5184 8.90069e-12 +0.5208 1.02338e-11 +0.5232 1.16966e-11 +0.5256 1.32965e-11 +0.528 1.50403e-11 +0.5304 1.6935e-11 +0.5328 1.89867e-11 +0.5352 2.12012e-11 +0.5376 2.35834e-11 +0.54 2.61374e-11 +0.5424 2.8866e-11 +0.5448 3.17708e-11 +0.5472 3.48517e-11 +0.5496 3.81068e-11 +0.552 4.15319e-11 +0.5544 4.51203e-11 +0.5568 4.88625e-11 +0.5592 5.27458e-11 +0.5616 5.67537e-11 +0.564 6.08655e-11 +0.5664 6.5056e-11 +0.5688 6.92949e-11 +0.5712 7.35462e-11 +0.5736 7.77675e-11 +0.576 8.19096e-11 +0.5784 8.59158e-11 +0.5808 8.97212e-11 +0.5832 9.32518e-11 +0.5856 9.64241e-11 +0.588 9.91442e-11 +0.5904 1.01307e-10 +0.5928 1.02795e-10 +0.5952 1.03479e-10 +0.5976 1.03216e-10 +0.6 1.01846e-10 +0.6024 9.91989e-11 +0.6048 9.5084e-11 +0.6072 8.92965e-11 +0.6096 8.16136e-11 +0.612 7.17949e-11 +0.6144 5.95812e-11 +0.6168 4.46949e-11 +0.6192 2.68389e-11 +0.6216 5.69693e-12 +0.624 -1.90666e-11 +0.6264 -4.78066e-11 +0.6288 -8.08967e-11 +0.6312 -1.18729e-10 +0.6336 -1.61712e-10 +0.636 -2.10272e-10 +0.6384 -2.64848e-10 +0.6408 -3.25893e-10 +0.6432 -3.9387e-10 +0.6456 -4.6925e-10 +0.648 -5.52507e-10 +0.6504 -6.44117e-10 +0.6528 -7.4455e-10 +0.6552 -8.5427e-10 +0.6576 -9.73724e-10 +0.66 -1.10334e-09 +0.6624 -1.24351e-09 +0.6648 -1.3946e-09 +0.6672 -1.55692e-09 +0.6696 -1.73073e-09 +0.672 -1.91623e-09 +0.6744 -2.11352e-09 +0.6768 -2.32263e-09 +0.6792 -2.54348e-09 +0.6816 -2.77584e-09 +0.684 -3.01939e-09 +0.6864 -3.27361e-09 +0.6888 -3.53784e-09 +0.6912 -3.81118e-09 +0.6936 -4.09256e-09 +0.696 -4.38065e-09 +0.6984 -4.67383e-09 +0.7008 -4.97024e-09 +0.7032 -5.26766e-09 +0.7056 -5.56356e-09 +0.708 -5.855e-09 +0.7104 -6.13868e-09 +0.7128 -6.41084e-09 +0.7152 -6.66727e-09 +0.7176 -6.90326e-09 +0.72 -7.11358e-09 +0.7224 -7.29245e-09 +0.7248 -7.4335e-09 +0.7272 -7.52975e-09 +0.7296 -7.57357e-09 +0.732 -7.55666e-09 +0.7344 -7.47003e-09 +0.7368 -7.30398e-09 +0.7392 -7.04805e-09 +0.7416 -6.69104e-09 +0.744 -6.22099e-09 +0.7464 -5.62516e-09 +0.7488 -4.89003e-09 +0.7512 -4.00132e-09 +0.7536 -2.944e-09 +0.756 -1.70229e-09 +0.7584 -2.5971e-10 +0.7608 1.40088e-09 +0.7632 3.29725e-09 +0.7656 5.44771e-09 +0.768 7.87105e-09 +0.7704 1.05864e-08 +0.7728 1.36133e-08 +0.7752 1.69713e-08 +0.7776 2.06801e-08 +0.78 2.4759e-08 +0.7824 2.92273e-08 +0.7848 3.41035e-08 +0.7872 3.94054e-08 +0.7896 4.515e-08 +0.792 5.13526e-08 +0.7944 5.80273e-08 +0.7968 6.51861e-08 +0.7992 7.28385e-08 +0.8016 8.09918e-08 +0.804 8.96497e-08 +0.8064 9.88126e-08 +0.8088 1.08477e-07 +0.8112 1.18634e-07 +0.8136 1.29272e-07 +0.816 1.40369e-07 +0.8184 1.51903e-07 +0.8208 1.6384e-07 +0.8232 1.7614e-07 +0.8256 1.88755e-07 +0.828 2.01629e-07 +0.8304 2.14694e-07 +0.8328 2.27873e-07 +0.8352 2.41078e-07 +0.8376 2.54207e-07 +0.84 2.67148e-07 +0.8424 2.79774e-07 +0.8448 2.91942e-07 +0.8472 3.03497e-07 +0.8496 3.14266e-07 +0.852 3.24059e-07 +0.8544 3.3267e-07 +0.8568 3.39875e-07 +0.8592 3.45429e-07 +0.8616 3.49073e-07 +0.864 3.50523e-07 +0.8664 3.49478e-07 +0.8688 3.45617e-07 +0.8712 3.38597e-07 +0.8736 3.28058e-07 +0.876 3.13618e-07 +0.8784 2.94875e-07 +0.8808 2.71409e-07 +0.8832 2.42782e-07 +0.8856 2.08538e-07 +0.888 1.68206e-07 +0.8904 1.213e-07 +0.8928 6.73205e-08 +0.8952 5.75981e-09 +0.8976 -6.38992e-08 +0.9 -1.42178e-07 +0.9024 -2.29602e-07 +0.9048 -3.26691e-07 +0.9072 -4.33964e-07 +0.9096 -5.51924e-07 +0.912 -6.81065e-07 +0.9144 -8.21855e-07 +0.9168 -9.7474e-07 +0.9192 -1.14013e-06 +0.9216 -1.3184e-06 +0.924 -1.50986e-06 +0.9264 -1.7148e-06 +0.9288 -1.93342e-06 +0.9312 -2.16584e-06 +0.9336 -2.41213e-06 +0.936 -2.67223e-06 +0.9384 -2.94601e-06 +0.9408 -3.23321e-06 +0.9432 -3.53344e-06 +0.9456 -3.84619e-06 +0.948 -4.17078e-06 +0.9504 -4.50639e-06 +0.9528 -4.85201e-06 +0.9552 -5.20645e-06 +0.9576 -5.5683e-06 +0.96 -5.93596e-06 +0.9624 -6.3076e-06 +0.9648 -6.68112e-06 +0.9672 -7.0542e-06 +0.9696 -7.42424e-06 +0.972 -7.78834e-06 +0.9744 -8.14334e-06 +0.9768 -8.48576e-06 +0.9792 -8.81181e-06 +0.9816 -9.11738e-06 +0.984 -9.39803e-06 +0.9864 -9.64897e-06 +0.9888 -9.86509e-06 +0.9912 -1.00409e-05 +0.9936 -1.01706e-05 +0.996 -1.02481e-05 +0.9984 -1.02668e-05 +1.0008 -1.02199e-05 +1.0032 -1.01002e-05 +1.0056 -9.90027e-06 +1.008 -9.61232e-06 +1.0104 -9.22827e-06 +1.0128 -8.73982e-06 +1.0152 -8.1384e-06 +1.0176 -7.41528e-06 +1.02 -6.56154e-06 +1.0224 -5.56814e-06 +1.0248 -4.42599e-06 +1.0272 -3.12593e-06 +1.0296 -1.65887e-06 +1.032 -1.58004e-08 +1.0344 1.81212e-06 +1.0368 3.83351e-06 +1.0392 6.05665e-06 +1.0416 8.48943e-06 +1.044 1.11393e-05 +1.0464 1.40129e-05 +1.0488 1.71165e-05 +1.0512 2.04553e-05 +1.0536 2.40337e-05 +1.056 2.7855e-05 +1.0584 3.19214e-05 +1.0608 3.62336e-05 +1.0632 4.07911e-05 +1.0656 4.55916e-05 +1.068 5.06312e-05 +1.0704 5.59042e-05 +1.0728 6.14026e-05 +1.0752 6.71163e-05 +1.0776 7.30331e-05 +1.08 7.9138e-05 +1.0824 8.54135e-05 +1.0848 9.18392e-05 +1.0872 9.83918e-05 +1.0896 0.000105045 +1.092 0.000111769 +1.0944 0.000118531 +1.0968 0.000125294 +1.0992 0.000132018 +1.1016 0.00013866 +1.104 0.000145171 +1.1064 0.000151501 +1.1088 0.000157593 +1.1112 0.000163388 +1.1136 0.000168824 +1.116 0.000173831 +1.1184 0.000178339 +1.1208 0.000182273 +1.1232 0.000185553 +1.1256 0.000188096 +1.128 0.000189816 +1.1304 0.000190624 +1.1328 0.000190425 +1.1352 0.000189125 +1.1376 0.000186625 +1.14 0.000182823 +1.1424 0.000177618 +1.1448 0.000170906 +1.1472 0.00016258 +1.1496 0.000152536 +1.152 0.000140668 +1.1544 0.000126872 +1.1568 0.000111045 +1.1592 9.3085e-05 +1.1616 7.28944e-05 +1.164 5.03788e-05 +1.1664 2.54485e-05 +1.1688 -1.98071e-06 +1.1712 -3.19866e-05 +1.1736 -6.46393e-05 +1.176 -0.0001 +1.1784 -0.000138122 +1.1808 -0.000179045 +1.1832 -0.000222799 +1.1856 -0.0002694 +1.188 -0.000318849 +1.1904 -0.000371133 +1.1928 -0.000426222 +1.1952 -0.000484066 +1.1976 -0.000544597 +1.2 -0.000607728 +1.2024 -0.000673348 +1.2048 -0.000741324 +1.2072 -0.000811498 +1.2096 -0.000883689 +1.212 -0.000957687 +1.2144 -0.00103326 +1.2168 -0.00111013 +1.2192 -0.00118802 +1.2216 -0.00126661 +1.224 -0.00134553 +1.2264 -0.0014244 +1.2288 -0.00150281 +1.2312 -0.00158032 +1.2336 -0.00165643 +1.236 -0.00173065 +1.2384 -0.00180243 +1.2408 -0.00187119 +1.2432 -0.00193635 +1.2456 -0.00199726 +1.248 -0.00205326 +1.2504 -0.00210368 +1.2528 -0.00214779 +1.2552 -0.00218487 +1.2576 -0.00221416 +1.26 -0.00223488 +1.2624 -0.00224625 +1.2648 -0.00224747 +1.2672 -0.00223772 +1.2696 -0.00221618 +1.272 -0.00218203 +1.2744 -0.00213445 +1.2768 -0.00207264 +1.2792 -0.00199579 +1.2816 -0.00190312 +1.284 -0.00179386 +1.2864 -0.00166728 +1.2888 -0.00152268 +1.2912 -0.00135938 +1.2936 -0.00117677 +1.296 -0.000974285 +1.2984 -0.000751412 +1.3008 -0.000507706 +1.3032 -0.000242794 +1.3056 4.36187e-05 +1.308 0.00035174 +1.3104 0.000681685 +1.3128 0.00103347 +1.3152 0.001407 +1.3176 0.00180208 +1.32 0.00221837 +1.3224 0.00265543 +1.3248 0.00311267 +1.3272 0.00358935 +1.3296 0.00408462 +1.332 0.00459743 +1.3344 0.00512662 +1.3368 0.00567085 +1.3392 0.00622861 +1.3416 0.00679823 +1.344 0.00737786 +1.3464 0.0079655 +1.3488 0.00855895 +1.3512 0.00915585 +1.3536 0.00975367 +1.356 0.0103497 +1.3584 0.0109411 +1.3608 0.0115247 +1.3632 0.0120974 +1.3656 0.0126559 +1.368 0.0131966 +1.3704 0.0137158 +1.3728 0.0142098 +1.3752 0.0146747 +1.3776 0.0151064 +1.38 0.0155009 +1.3824 0.0158538 +1.3848 0.0161611 +1.3872 0.0164183 +1.3896 0.0166211 +1.392 0.0167652 +1.3944 0.0168461 +1.3968 0.0168595 +1.3992 0.0168012 +1.4016 0.0166669 +1.404 0.0164525 +1.4064 0.016154 +1.4088 0.0157676 +1.4112 0.0152897 +1.4136 0.0147166 +1.416 0.0140453 +1.4184 0.0132727 +1.4208 0.0123962 +1.4232 0.0114134 +1.4256 0.0103222 +1.428 0.00912107 +1.4304 0.00780876 +1.4328 0.00638444 +1.4352 0.0048478 +1.4376 0.00319896 +1.44 0.0014386 +1.4424 -0.000432086 +1.4448 -0.00241133 +1.4472 -0.00449679 +1.4496 -0.00668552 +1.452 -0.00897394 +1.4544 -0.0113578 +1.4568 -0.0138324 +1.4592 -0.016392 +1.4616 -0.0190305 +1.464 -0.0217411 +1.4664 -0.0245161 +1.4688 -0.0273473 +1.4712 -0.0302259 +1.4736 -0.0331422 +1.476 -0.036086 +1.4784 -0.0390464 +1.4808 -0.0420119 +1.4832 -0.0449704 +1.4856 -0.0479091 +1.488 -0.0508149 +1.4904 -0.0536739 +1.4928 -0.056472 +1.4952 -0.0591944 +1.4976 -0.061826 +1.5 -0.0643516 +1.5024 -0.0667553 +1.5048 -0.0690213 +1.5072 -0.0711334 +1.5096 -0.0730755 +1.512 -0.0748314 +1.5144 -0.0763849 +1.5168 -0.0777199 +1.5192 -0.0788206 +1.5216 -0.0796713 +1.524 -0.0802569 +1.5264 -0.0805624 +1.5288 -0.0805736 +1.5312 -0.0802769 +1.5336 -0.0796592 +1.536 -0.0787084 +1.5384 -0.0774131 +1.5408 -0.075763 +1.5432 -0.0737488 +1.5456 -0.0713623 +1.548 -0.0685966 +1.5504 -0.0654459 +1.5528 -0.0619061 +1.5552 -0.0579742 +1.5576 -0.0536491 +1.56 -0.0489309 +1.5624 -0.0438216 +1.5648 -0.038325 +1.5672 -0.0324463 +1.5696 -0.0261929 +1.572 -0.0195738 +1.5744 -0.0125999 +1.5768 -0.00528426 +1.5792 0.0023585 +1.5816 0.0103116 +1.584 0.0185564 +1.5864 0.0270724 +1.5888 0.035837 +1.5912 0.044826 +1.5936 0.0540131 +1.596 0.0633704 +1.5984 0.0728683 +1.6008 0.0824752 +1.6032 0.0921584 +1.6056 0.101883 +1.608 0.111614 +1.6104 0.121313 +1.6128 0.130943 +1.6152 0.140464 +1.6176 0.149835 +1.62 0.159016 +1.6224 0.167964 +1.6248 0.176639 +1.6272 0.184996 +1.6296 0.192993 +1.632 0.200588 +1.6344 0.207738 +1.6368 0.214402 +1.6392 0.220538 +1.6416 0.226104 +1.644 0.231063 +1.6464 0.235375 +1.6488 0.239003 +1.6512 0.241913 +1.6536 0.24407 +1.656 0.245442 +1.6584 0.246001 +1.6608 0.245719 +1.6632 0.244572 +1.6656 0.242539 +1.668 0.239599 +1.6704 0.235738 +1.6728 0.230942 +1.6752 0.225203 +1.6776 0.218515 +1.68 0.210876 +1.6824 0.202286 +1.6848 0.192753 +1.6872 0.182283 +1.6896 0.170892 +1.692 0.158596 +1.6944 0.145416 +1.6968 0.131377 +1.6992 0.116508 +1.7016 0.100843 +1.704 0.0844184 +1.7064 0.0672756 +1.7088 0.0494592 +1.7112 0.0310178 +1.7136 0.0120033 +1.716 -0.00752867 +1.7184 -0.0275192 +1.7208 -0.0479063 +1.7232 -0.0686251 +1.7256 -0.0896079 +1.728 -0.110785 +1.7304 -0.132082 +1.7328 -0.153427 +1.7352 -0.174742 +1.7376 -0.19595 +1.74 -0.216972 +1.7424 -0.237728 +1.7448 -0.258137 +1.7472 -0.278119 +1.7496 -0.297593 +1.752 -0.31648 +1.7544 -0.334699 +1.7568 -0.352172 +1.7592 -0.368823 +1.7616 -0.384576 +1.764 -0.399358 +1.7664 -0.413098 +1.7688 -0.425729 +1.7712 -0.437186 +1.7736 -0.447407 +1.776 -0.456335 +1.7784 -0.463916 +1.7808 -0.470102 +1.7832 -0.474847 +1.7856 -0.478111 +1.788 -0.47986 +1.7904 -0.480064 +1.7928 -0.478699 +1.7952 -0.475747 +1.7976 -0.471195 +1.8 -0.465036 +1.8024 -0.457269 +1.8048 -0.447901 +1.8072 -0.436942 +1.8096 -0.424411 +1.812 -0.410332 +1.8144 -0.394734 +1.8168 -0.377655 +1.8192 -0.359136 +1.8216 -0.339227 +1.824 -0.317981 +1.8264 -0.295459 +1.8288 -0.271725 +1.8312 -0.24685 +1.8336 -0.220911 +1.836 -0.193986 +1.8384 -0.166163 +1.8408 -0.137529 +1.8432 -0.108178 +1.8456 -0.0782063 +1.848 -0.0477137 +1.8504 -0.0168028 +1.8528 0.0144215 +1.8552 0.0458521 +1.8576 0.0773807 +1.86 0.108897 +1.8624 0.140292 +1.8648 0.171453 +1.8672 0.202272 +1.8696 0.232637 +1.872 0.26244 +1.8744 0.291573 +1.8768 0.319932 +1.8792 0.347413 +1.8816 0.373916 +1.884 0.399344 +1.8864 0.423605 +1.8888 0.446608 +1.8912 0.468268 +1.8936 0.488507 +1.896 0.507248 +1.8984 0.524422 +1.9008 0.539965 +1.9032 0.553819 +1.9056 0.565933 +1.908 0.576261 +1.9104 0.584764 +1.9128 0.591411 +1.9152 0.596177 +1.9176 0.599043 +1.92 0.6 +1.9224 0.599043 +1.9248 0.596177 +1.9272 0.591411 +1.9296 0.584764 +1.932 0.576261 +1.9344 0.565933 +1.9368 0.553819 +1.9392 0.539965 +1.9416 0.524422 +1.944 0.507248 +1.9464 0.488507 +1.9488 0.468268 +1.9512 0.446608 +1.9536 0.423605 +1.956 0.399344 +1.9584 0.373916 +1.9608 0.347413 +1.9632 0.319932 +1.9656 0.291573 +1.968 0.26244 +1.9704 0.232637 +1.9728 0.202272 +1.9752 0.171453 +1.9776 0.140292 +1.98 0.108897 +1.9824 0.0773807 +1.9848 0.0458521 +1.9872 0.0144215 +1.9896 -0.0168028 +1.992 -0.0477137 +1.9944 -0.0782063 +1.9968 -0.108178 +1.9992 -0.137529 +2.0016 -0.166163 +2.004 -0.193986 +2.0064 -0.220911 +2.0088 -0.24685 +2.0112 -0.271725 +2.0136 -0.295459 +2.016 -0.317981 +2.0184 -0.339227 +2.0208 -0.359136 +2.0232 -0.377655 +2.0256 -0.394734 +2.028 -0.410332 +2.0304 -0.424411 +2.0328 -0.436942 +2.0352 -0.447901 +2.0376 -0.457269 +2.04 -0.465036 +2.0424 -0.471195 +2.0448 -0.475747 +2.0472 -0.478699 +2.0496 -0.480064 +2.052 -0.47986 +2.0544 -0.478111 +2.0568 -0.474847 +2.0592 -0.470102 +2.0616 -0.463916 +2.064 -0.456335 +2.0664 -0.447407 +2.0688 -0.437186 +2.0712 -0.425729 +2.0736 -0.413098 +2.076 -0.399358 +2.0784 -0.384576 +2.0808 -0.368823 +2.0832 -0.352172 +2.0856 -0.334699 +2.088 -0.31648 +2.0904 -0.297593 +2.0928 -0.278119 +2.0952 -0.258137 +2.0976 -0.237728 +2.1 -0.216972 +2.1024 -0.19595 +2.1048 -0.174742 +2.1072 -0.153427 +2.1096 -0.132082 +2.112 -0.110785 +2.1144 -0.0896079 +2.1168 -0.0686251 +2.1192 -0.0479063 +2.1216 -0.0275192 +2.124 -0.00752867 +2.1264 0.0120033 +2.1288 0.0310178 +2.1312 0.0494592 +2.1336 0.0672756 +2.136 0.0844184 +2.1384 0.100843 +2.1408 0.116508 +2.1432 0.131377 +2.1456 0.145416 +2.148 0.158596 +2.1504 0.170892 +2.1528 0.182283 +2.1552 0.192753 +2.1576 0.202286 +2.16 0.210876 +2.1624 0.218515 +2.1648 0.225203 +2.1672 0.230942 +2.1696 0.235738 +2.172 0.239599 +2.1744 0.242539 +2.1768 0.244572 +2.1792 0.245719 +2.1816 0.246001 +2.184 0.245442 +2.1864 0.24407 +2.1888 0.241913 +2.1912 0.239003 +2.1936 0.235375 +2.196 0.231063 +2.1984 0.226104 +2.2008 0.220538 +2.2032 0.214402 +2.2056 0.207738 +2.208 0.200588 +2.2104 0.192993 +2.2128 0.184996 +2.2152 0.176639 +2.2176 0.167964 +2.22 0.159016 +2.2224 0.149835 +2.2248 0.140464 +2.2272 0.130943 +2.2296 0.121313 +2.232 0.111614 +2.2344 0.101883 +2.2368 0.0921584 +2.2392 0.0824752 +2.2416 0.0728683 +2.244 0.0633704 +2.2464 0.0540131 +2.2488 0.044826 +2.2512 0.035837 +2.2536 0.0270724 +2.256 0.0185564 +2.2584 0.0103116 +2.2608 0.0023585 +2.2632 -0.00528426 +2.2656 -0.0125999 +2.268 -0.0195738 +2.2704 -0.0261929 +2.2728 -0.0324463 +2.2752 -0.038325 +2.2776 -0.0438216 +2.28 -0.0489309 +2.2824 -0.0536491 +2.2848 -0.0579742 +2.2872 -0.0619061 +2.2896 -0.0654459 +2.292 -0.0685966 +2.2944 -0.0713623 +2.2968 -0.0737488 +2.2992 -0.075763 +2.3016 -0.0774131 +2.304 -0.0787084 +2.3064 -0.0796592 +2.3088 -0.0802769 +2.3112 -0.0805736 +2.3136 -0.0805624 +2.316 -0.0802569 +2.3184 -0.0796713 +2.3208 -0.0788206 +2.3232 -0.0777199 +2.3256 -0.0763849 +2.328 -0.0748314 +2.3304 -0.0730755 +2.3328 -0.0711334 +2.3352 -0.0690213 +2.3376 -0.0667553 +2.34 -0.0643516 +2.3424 -0.061826 +2.3448 -0.0591944 +2.3472 -0.056472 +2.3496 -0.0536739 +2.352 -0.0508149 +2.3544 -0.0479091 +2.3568 -0.0449704 +2.3592 -0.0420119 +2.3616 -0.0390464 +2.364 -0.036086 +2.3664 -0.0331422 +2.3688 -0.0302259 +2.3712 -0.0273473 +2.3736 -0.0245161 +2.376 -0.0217411 +2.3784 -0.0190305 +2.3808 -0.016392 +2.3832 -0.0138324 +2.3856 -0.0113578 +2.388 -0.00897394 +2.3904 -0.00668552 +2.3928 -0.00449679 +2.3952 -0.00241133 +2.3976 -0.000432086 +2.4 0.0014386 +2.4024 0.00319896 +2.4048 0.0048478 +2.4072 0.00638444 +2.4096 0.00780876 +2.412 0.00912107 +2.4144 0.0103222 +2.4168 0.0114134 +2.4192 0.0123962 +2.4216 0.0132727 +2.424 0.0140453 +2.4264 0.0147166 +2.4288 0.0152897 +2.4312 0.0157676 +2.4336 0.016154 +2.436 0.0164525 +2.4384 0.0166669 +2.4408 0.0168012 +2.4432 0.0168595 +2.4456 0.0168461 +2.448 0.0167652 +2.4504 0.0166211 +2.4528 0.0164183 +2.4552 0.0161611 +2.4576 0.0158538 +2.46 0.0155009 +2.4624 0.0151064 +2.4648 0.0146747 +2.4672 0.0142098 +2.4696 0.0137158 +2.472 0.0131966 +2.4744 0.0126559 +2.4768 0.0120974 +2.4792 0.0115247 +2.4816 0.0109411 +2.484 0.0103497 +2.4864 0.00975367 +2.4888 0.00915585 +2.4912 0.00855895 +2.4936 0.0079655 +2.496 0.00737786 +2.4984 0.00679823 +2.5008 0.00622861 +2.5032 0.00567085 +2.5056 0.00512662 +2.508 0.00459743 +2.5104 0.00408462 +2.5128 0.00358935 +2.5152 0.00311267 +2.5176 0.00265543 +2.52 0.00221837 +2.5224 0.00180208 +2.5248 0.001407 +2.5272 0.00103347 +2.5296 0.000681685 +2.532 0.00035174 +2.5344 4.36187e-05 +2.5368 -0.000242794 +2.5392 -0.000507706 +2.5416 -0.000751412 +2.544 -0.000974285 +2.5464 -0.00117677 +2.5488 -0.00135938 +2.5512 -0.00152268 +2.5536 -0.00166728 +2.556 -0.00179386 +2.5584 -0.00190312 +2.5608 -0.00199579 +2.5632 -0.00207264 +2.5656 -0.00213445 +2.568 -0.00218203 +2.5704 -0.00221618 +2.5728 -0.00223772 +2.5752 -0.00224747 +2.5776 -0.00224625 +2.58 -0.00223488 +2.5824 -0.00221416 +2.5848 -0.00218487 +2.5872 -0.00214779 +2.5896 -0.00210368 +2.592 -0.00205326 +2.5944 -0.00199726 +2.5968 -0.00193635 +2.5992 -0.00187119 +2.6016 -0.00180243 +2.604 -0.00173065 +2.6064 -0.00165643 +2.6088 -0.00158032 +2.6112 -0.00150281 +2.6136 -0.0014244 +2.616 -0.00134553 +2.6184 -0.00126661 +2.6208 -0.00118802 +2.6232 -0.00111013 +2.6256 -0.00103326 +2.628 -0.000957687 +2.6304 -0.000883689 +2.6328 -0.000811498 +2.6352 -0.000741324 +2.6376 -0.000673348 +2.64 -0.000607728 +2.6424 -0.000544597 +2.6448 -0.000484066 +2.6472 -0.000426222 +2.6496 -0.000371133 +2.652 -0.000318849 +2.6544 -0.0002694 +2.6568 -0.000222799 +2.6592 -0.000179045 +2.6616 -0.000138122 +2.664 -0.0001 +2.6664 -6.46393e-05 +2.6688 -3.19866e-05 +2.6712 -1.98071e-06 +2.6736 2.54485e-05 +2.676 5.03788e-05 +2.6784 7.28944e-05 +2.6808 9.3085e-05 +2.6832 0.000111045 +2.6856 0.000126872 +2.688 0.000140668 +2.6904 0.000152536 +2.6928 0.00016258 +2.6952 0.000170906 +2.6976 0.000177618 +2.7 0.000182823 +2.7024 0.000186625 +2.7048 0.000189125 +2.7072 0.000190425 +2.7096 0.000190624 +2.712 0.000189816 +2.7144 0.000188096 +2.7168 0.000185553 +2.7192 0.000182273 +2.7216 0.000178339 +2.724 0.000173831 +2.7264 0.000168824 +2.7288 0.000163388 +2.7312 0.000157593 +2.7336 0.000151501 +2.736 0.000145171 +2.7384 0.00013866 +2.7408 0.000132018 +2.7432 0.000125294 +2.7456 0.000118531 +2.748 0.000111769 +2.7504 0.000105045 +2.7528 9.83918e-05 +2.7552 9.18392e-05 +2.7576 8.54135e-05 +2.76 7.9138e-05 +2.7624 7.30331e-05 +2.7648 6.71163e-05 +2.7672 6.14026e-05 +2.7696 5.59042e-05 +2.772 5.06312e-05 +2.7744 4.55916e-05 +2.7768 4.07911e-05 +2.7792 3.62336e-05 +2.7816 3.19214e-05 +2.784 2.7855e-05 +2.7864 2.40337e-05 +2.7888 2.04553e-05 +2.7912 1.71165e-05 +2.7936 1.40129e-05 +2.796 1.11393e-05 +2.7984 8.48943e-06 +2.8008 6.05665e-06 +2.8032 3.83351e-06 +2.8056 1.81212e-06 +2.808 -1.58004e-08 +2.8104 -1.65887e-06 +2.8128 -3.12593e-06 +2.8152 -4.42599e-06 +2.8176 -5.56814e-06 +2.82 -6.56154e-06 +2.8224 -7.41528e-06 +2.8248 -8.1384e-06 +2.8272 -8.73982e-06 +2.8296 -9.22827e-06 +2.832 -9.61232e-06 +2.8344 -9.90027e-06 +2.8368 -1.01002e-05 +2.8392 -1.02199e-05 +2.8416 -1.02668e-05 +2.844 -1.02481e-05 +2.8464 -1.01706e-05 +2.8488 -1.00409e-05 +2.8512 -9.86509e-06 +2.8536 -9.64897e-06 +2.856 -9.39803e-06 +2.8584 -9.11738e-06 +2.8608 -8.81181e-06 +2.8632 -8.48576e-06 +2.8656 -8.14334e-06 +2.868 -7.78834e-06 +2.8704 -7.42424e-06 +2.8728 -7.0542e-06 +2.8752 -6.68112e-06 +2.8776 -6.3076e-06 +2.88 -5.93596e-06 +2.8824 -5.5683e-06 +2.8848 -5.20645e-06 +2.8872 -4.85201e-06 +2.8896 -4.50639e-06 +2.892 -4.17078e-06 +2.8944 -3.84619e-06 +2.8968 -3.53344e-06 +2.8992 -3.23321e-06 +2.9016 -2.94601e-06 +2.904 -2.67223e-06 +2.9064 -2.41213e-06 +2.9088 -2.16584e-06 +2.9112 -1.93342e-06 +2.9136 -1.7148e-06 +2.916 -1.50986e-06 +2.9184 -1.3184e-06 +2.9208 -1.14013e-06 +2.9232 -9.7474e-07 +2.9256 -8.21855e-07 +2.928 -6.81065e-07 +2.9304 -5.51924e-07 +2.9328 -4.33964e-07 +2.9352 -3.26691e-07 +2.9376 -2.29602e-07 +2.94 -1.42178e-07 +2.9424 -6.38992e-08 +2.9448 5.75981e-09 +2.9472 6.73205e-08 +2.9496 1.213e-07 +2.952 1.68206e-07 +2.9544 2.08538e-07 +2.9568 2.42782e-07 +2.9592 2.71409e-07 +2.9616 2.94875e-07 +2.964 3.13618e-07 +2.9664 3.28058e-07 +2.9688 3.38597e-07 +2.9712 3.45617e-07 +2.9736 3.49478e-07 +2.976 3.50523e-07 +2.9784 3.49073e-07 +2.9808 3.45429e-07 +2.9832 3.39875e-07 +2.9856 3.3267e-07 +2.988 3.24059e-07 +2.9904 3.14266e-07 +2.9928 3.03497e-07 +2.9952 2.91942e-07 +2.9976 2.79774e-07 +3 2.67148e-07 +3.0024 2.54207e-07 +3.0048 2.41078e-07 +3.0072 2.27873e-07 +3.0096 2.14694e-07 +3.012 2.01629e-07 +3.0144 1.88755e-07 +3.0168 1.7614e-07 +3.0192 1.6384e-07 +3.0216 1.51903e-07 +3.024 1.40369e-07 +3.0264 1.29272e-07 +3.0288 1.18634e-07 +3.0312 1.08477e-07 +3.0336 9.88126e-08 +3.036 8.96497e-08 +3.0384 8.09918e-08 +3.0408 7.28385e-08 +3.0432 6.51861e-08 +3.0456 5.80273e-08 +3.048 5.13526e-08 +3.0504 4.515e-08 +3.0528 3.94054e-08 +3.0552 3.41035e-08 +3.0576 2.92273e-08 +3.06 2.4759e-08 +3.0624 2.06801e-08 +3.0648 1.69713e-08 +3.0672 1.36133e-08 +3.0696 1.05864e-08 +3.072 7.87105e-09 +3.0744 5.44771e-09 +3.0768 3.29725e-09 +3.0792 1.40088e-09 +3.0816 -2.5971e-10 +3.084 -1.70229e-09 +3.0864 -2.944e-09 +3.0888 -4.00132e-09 +3.0912 -4.89003e-09 +3.0936 -5.62516e-09 +3.096 -6.22099e-09 +3.0984 -6.69104e-09 +3.1008 -7.04805e-09 +3.1032 -7.30398e-09 +3.1056 -7.47003e-09 +3.108 -7.55666e-09 +3.1104 -7.57357e-09 +3.1128 -7.52975e-09 +3.1152 -7.4335e-09 +3.1176 -7.29245e-09 +3.12 -7.11358e-09 +3.1224 -6.90326e-09 +3.1248 -6.66727e-09 +3.1272 -6.41084e-09 +3.1296 -6.13868e-09 +3.132 -5.855e-09 +3.1344 -5.56356e-09 +3.1368 -5.26766e-09 +3.1392 -4.97024e-09 +3.1416 -4.67383e-09 +3.144 -4.38065e-09 +3.1464 -4.09256e-09 +3.1488 -3.81118e-09 +3.1512 -3.53784e-09 +3.1536 -3.27361e-09 +3.156 -3.01939e-09 +3.1584 -2.77584e-09 +3.1608 -2.54348e-09 +3.1632 -2.32263e-09 +3.1656 -2.11352e-09 +3.168 -1.91623e-09 +3.1704 -1.73073e-09 +3.1728 -1.55692e-09 +3.1752 -1.3946e-09 +3.1776 -1.24351e-09 +3.18 -1.10334e-09 +3.1824 -9.73724e-10 +3.1848 -8.5427e-10 +3.1872 -7.4455e-10 +3.1896 -6.44117e-10 +3.192 -5.52507e-10 +3.1944 -4.6925e-10 +3.1968 -3.9387e-10 +3.1992 -3.25893e-10 +3.2016 -2.64848e-10 +3.204 -2.10272e-10 +3.2064 -1.61712e-10 +3.2088 -1.18729e-10 +3.2112 -8.08967e-11 +3.2136 -4.78066e-11 +3.216 -1.90666e-11 +3.2184 5.69693e-12 +3.2208 2.68389e-11 +3.2232 4.46949e-11 +3.2256 5.95812e-11 +3.228 7.17949e-11 +3.2304 8.16136e-11 +3.2328 8.92965e-11 +3.2352 9.5084e-11 +3.2376 9.91989e-11 +3.24 1.01846e-10 +3.2424 1.03216e-10 +3.2448 1.03479e-10 +3.2472 1.02795e-10 +3.2496 1.01307e-10 +3.252 9.91442e-11 +3.2544 9.64241e-11 +3.2568 9.32518e-11 +3.2592 8.97212e-11 +3.2616 8.59158e-11 +3.264 8.19096e-11 +3.2664 7.77675e-11 +3.2688 7.35462e-11 +3.2712 6.92949e-11 +3.2736 6.5056e-11 +3.276 6.08655e-11 +3.2784 5.67537e-11 +3.2808 5.27458e-11 +3.2832 4.88625e-11 +3.2856 4.51203e-11 +3.288 4.15319e-11 +3.2904 3.81068e-11 +3.2928 3.48517e-11 +3.2952 3.17708e-11 +3.2976 2.8866e-11 +3.3 2.61374e-11 +3.3024 2.35834e-11 +3.3048 2.12012e-11 +3.3072 1.89867e-11 +3.3096 1.6935e-11 +3.312 1.50403e-11 +3.3144 1.32965e-11 +3.3168 1.16966e-11 +3.3192 1.02338e-11 +3.3216 8.90069e-12 +3.324 7.68996e-12 +3.3264 6.59422e-12 +3.3288 5.60614e-12 +3.3312 4.71848e-12 +3.3336 3.92417e-12 +3.336 3.21636e-12 +3.3384 2.58838e-12 +3.3408 2.03389e-12 +3.3432 1.54678e-12 +3.3456 1.12125e-12 +3.348 7.51808e-13 +3.3504 4.3328e-13 +3.3528 1.60793e-13 +3.3552 -7.02117e-14 +3.3576 -2.63986e-13 +3.36 -4.24481e-13 +3.3624 -5.55357e-13 +3.3648 -6.5999e-13 +3.3672 -7.41488e-13 +3.3696 -8.02696e-13 +3.372 -8.46214e-13 +3.3744 -8.7441e-13 +3.3768 -8.89429e-13 +3.3792 -8.93209e-13 +3.3816 -8.87496e-13 +3.384 -8.73852e-13 +3.3864 -8.53675e-13 +3.3888 -8.28205e-13 +3.3912 -7.98538e-13 +3.3936 -7.65641e-13 +3.396 -7.30359e-13 +3.3984 -6.93426e-13 +3.4008 -6.55476e-13 +3.4032 -6.17055e-13 +3.4056 -5.78624e-13 +3.408 -5.40573e-13 +3.4104 -5.03223e-13 +3.4128 -4.66841e-13 +3.4152 -4.31637e-13 +3.4176 -3.97779e-13 +3.42 -3.65394e-13 +3.4224 -3.34571e-13 +3.4248 -3.05372e-13 +3.4272 -2.77832e-13 +3.4296 -2.51961e-13 +3.432 -2.27754e-13 +3.4344 -2.05187e-13 +3.4368 -1.84224e-13 +3.4392 -1.6482e-13 +3.4416 -1.46918e-13 +3.444 -1.30458e-13 +3.4464 -1.15373e-13 +3.4488 -1.01594e-13 +3.4512 -8.90479e-14 +3.4536 -7.76626e-14 +3.456 -6.7365e-14 +3.4584 -5.80827e-14 +3.4608 -4.97447e-14 +3.4632 -4.22817e-14 +3.4656 -3.56268e-14 +3.468 -2.97154e-14 +3.4704 -2.4486e-14 +3.4728 -1.98801e-14 +3.4752 -1.5842e-14 +3.4776 -1.23197e-14 +3.48 -9.26404e-15 +3.4824 -6.62916e-15 +3.4848 -4.37241e-15 +3.4872 -2.45421e-15 +3.4896 -8.37972e-16 +3.492 5.09998e-16 +3.4944 1.62062e-15 +3.4968 2.52217e-15 +3.4992 3.24044e-15 +3.5016 3.79882e-15 +3.504 4.21853e-15 +3.5064 4.51867e-15 +3.5088 4.71643e-15 +3.5112 4.8272e-15 +3.5136 4.8647e-15 +3.516 4.84112e-15 +3.5184 4.76725e-15 +3.5208 4.65259e-15 +3.5232 4.50548e-15 +3.5256 4.33316e-15 +3.528 4.14194e-15 +3.5304 3.93725e-15 +3.5328 3.72373e-15 +3.5352 3.50532e-15 +3.5376 3.28535e-15 +3.54 3.06657e-15 +3.5424 2.85126e-15 +3.5448 2.64125e-15 +3.5472 2.43802e-15 +3.5496 2.2427e-15 +3.552 2.05612e-15 +3.5544 1.87889e-15 +3.5568 1.7114e-15 +3.5592 1.55385e-15 +3.5616 1.40631e-15 +3.564 1.26872e-15 +3.5664 1.1409e-15 +3.5688 1.0226e-15 +3.5712 9.13517e-16 +3.5736 8.13273e-16 +3.576 7.21466e-16 +3.5784 6.37668e-16 +3.5808 5.6143e-16 +3.5832 4.92298e-16 +3.5856 4.29811e-16 +3.588 3.73517e-16 +3.5904 3.2297e-16 +3.5928 2.77734e-16 +3.5952 2.37392e-16 +3.5976 2.01541e-16 +3.6 1.69798e-16 +3.6024 1.418e-16 +3.6048 1.17204e-16 +3.6072 9.56889e-17 +3.6096 7.69546e-17 +3.612 6.07215e-17 +3.6144 4.67304e-17 +3.6168 3.47422e-17 +3.6192 2.45369e-17 +3.6216 1.5913e-17 +3.624 8.68605e-18 +3.6264 2.68855e-18 +3.6288 -2.23163e-18 +3.6312 -6.212e-18 +3.6336 -9.37646e-18 +3.636 -1.18363e-17 +3.6384 -1.36909e-17 +3.6408 -1.50292e-17 +3.6432 -1.593e-17 +3.6456 -1.6463e-17 +3.648 -1.66896e-17 +3.6504 -1.6664e-17 +3.6528 -1.64332e-17 +3.6552 -1.60383e-17 +3.6576 -1.55147e-17 +3.66 -1.4893e-17 +3.6624 -1.41994e-17 +3.6648 -1.34558e-17 +3.6672 -1.26812e-17 +3.6696 -1.18911e-17 +3.672 -1.10983e-17 +3.6744 -1.03135e-17 +3.6768 -9.54517e-18 +3.6792 -8.79992e-18 +3.6816 -8.08295e-18 +3.684 -7.39808e-18 +3.6864 -6.74802e-18 +3.6888 -6.13454e-18 +3.6912 -5.55859e-18 +3.6936 -5.02048e-18 +3.696 -4.51997e-18 +3.6984 -4.05639e-18 +3.7008 -3.62873e-18 +3.7032 -3.23568e-18 +3.7056 -2.87576e-18 +3.708 -2.54734e-18 +3.7104 -2.24869e-18 +3.7128 -1.978e-18 +3.7152 -1.73347e-18 +3.7176 -1.51329e-18 +3.72 -1.31568e-18 +3.7224 -1.13891e-18 +3.7248 -9.81291e-19 +3.7272 -8.41221e-19 +3.7296 -7.17169e-19 +3.732 -6.07687e-19 +3.7344 -5.11413e-19 +3.7368 -4.27072e-19 +3.7392 -3.53476e-19 +3.7416 -2.89523e-19 +3.744 -2.34195e-19 +3.7464 -1.86558e-19 +3.7488 -1.45754e-19 +3.7512 -1.10999e-19 +3.7536 -8.15819e-20 +3.756 -5.68562e-20 +3.7584 -3.62386e-20 +3.7608 -1.92039e-20 +3.7632 -5.28066e-21 +3.7656 5.95274e-21 +3.768 1.48721e-20 +3.7704 2.18112e-20 +3.7728 2.70654e-20 +3.7752 3.08954e-20 +3.7776 3.353e-20 +3.78 3.51695e-20 +3.7824 3.59886e-20 +3.7848 3.61387e-20 +3.7872 3.57507e-20 +3.7896 3.4937e-20 +3.792 3.3794e-20 +3.7944 3.24031e-20 +3.7968 3.08334e-20 +3.7992 2.91427e-20 +3.8016 2.73789e-20 +3.804 2.55816e-20 +3.8064 2.37829e-20 +3.8088 2.20084e-20 +3.8112 2.02785e-20 +3.8136 1.86088e-20 +3.816 1.70108e-20 +3.8184 1.54929e-20 +3.8208 1.40606e-20 +3.8232 1.27171e-20 +3.8256 1.14636e-20 +3.828 1.02999e-20 +3.8304 9.22452e-21 +3.8328 8.23505e-21 +3.8352 7.32828e-21 +3.8376 6.5005e-21 +3.84 5.74762e-21 +3.8424 5.06528e-21 +3.8448 4.449e-21 +3.8472 3.89426e-21 +3.8496 3.39656e-21 +3.852 2.95148e-21 +3.8544 2.55477e-21 +3.8568 2.2023e-21 +3.8592 1.89017e-21 +3.8616 1.61467e-21 +3.864 1.37232e-21 +3.8664 1.15987e-21 +3.8688 9.74292e-22 +3.8712 8.12781e-22 +3.8736 6.72759e-22 +3.876 5.5186e-22 +3.8784 4.47923e-22 +3.8808 3.58978e-22 +3.8832 2.83241e-22 +3.8856 2.19101e-22 +3.888 1.65105e-22 +3.8904 1.19951e-22 +3.8928 8.24745e-23 +3.8952 5.16363e-23 +3.8976 2.65146e-23 +3.9 6.2929e-24 +3.9024 -9.74902e-24 +3.9048 -2.22445e-23 +3.9072 -3.17484e-23 +3.9096 -3.8745e-23 +3.912 -4.36553e-23 +3.9144 -4.6844e-23 +3.9168 -4.86257e-23 +3.9192 -4.92702e-23 +3.9216 -4.90084e-23 +3.924 -4.80363e-23 +3.9264 -4.65195e-23 +3.9288 -4.45974e-23 +3.9312 -4.23859e-23 +3.9336 -3.99811e-23 +3.936 -3.74617e-23 +3.9384 -3.48915e-23 +3.9408 -3.23217e-23 +3.9432 -2.97926e-23 +3.9456 -2.73351e-23 +3.948 -2.49728e-23 +3.9504 -2.27224e-23 +3.9528 -2.05956e-23 +3.9552 -1.85995e-23 +3.9576 -1.67376e-23 +3.96 -1.50107e-23 +3.9624 -1.34172e-23 +3.9648 -1.19538e-23 +3.9672 -1.06157e-23 +3.9696 -9.39726e-24 +3.972 -8.29218e-24 +3.9744 -7.29364e-24 +3.9768 -6.39462e-24 +3.9792 -5.58802e-24 +3.9816 -4.86678e-24 +3.984 -4.22401e-24 +3.9864 -3.65304e-24 +3.9888 -3.14751e-24 +3.9912 -2.70136e-24 +3.9936 -2.30889e-24 +3.996 -1.96478e-24 +3.9984 -1.66407e-24 +4.0008 -1.40217e-24 +4.0032 -1.17489e-24 +4.0056 -9.78347e-25 +4.008 -8.09034e-25 +4.0104 -6.63754e-25 +4.0128 -5.39615e-25 +4.0152 -4.34014e-25 +4.0176 -3.44611e-25 +4.02 -2.69314e-25 +4.0224 -2.06259e-25 +4.0248 -1.53787e-25 +4.0272 -1.1043e-25 +4.0296 -7.48921e-26 +4.032 -4.60332e-26 +4.0344 -2.28536e-26 +4.0368 -4.47991e-27 +4.0392 9.84853e-27 +4.0416 2.07915e-26 +4.044 2.89195e-26 +4.0464 3.47235e-26 +4.0488 3.86247e-26 +4.0512 4.09827e-26 +4.0536 4.21031e-26 +4.056 4.22444e-26 +4.0584 4.16239e-26 +4.0608 4.04236e-26 +4.0632 3.87945e-26 +4.0656 3.68612e-26 +4.068 3.47255e-26 +4.0704 3.247e-26 +4.0728 3.01607e-26 +4.0752 2.78498e-26 +4.0776 2.55777e-26 +4.08 2.33751e-26 +4.0824 2.12645e-26 +4.0848 1.92619e-26 +4.0872 1.73778e-26 +4.0896 1.56181e-26 +4.092 1.39853e-26 +4.0944 1.24792e-26 +4.0968 1.10974e-26 +4.0992 9.83579e-27 +4.1016 8.68924e-27 +4.104 7.65166e-27 +4.1064 6.71647e-27 +4.1088 5.87679e-27 +4.1112 5.12562e-27 +4.1136 4.45601e-27 +4.116 3.86114e-27 +4.1184 3.33445e-27 +4.1208 2.86964e-27 +4.1232 2.46079e-27 +4.1256 2.10231e-27 +4.128 1.78902e-27 +4.1304 1.51611e-27 +4.1328 1.27917e-27 +4.1352 1.07413e-27 +4.1376 8.97315e-28 +4.14 7.45381e-28 +4.1424 6.15306e-28 +4.1448 5.04374e-28 +4.1472 4.10151e-28 +4.1496 3.30464e-28 +4.152 2.6338e-28 +4.1544 2.07186e-28 +4.1568 1.6037e-28 +4.1592 1.21597e-28 +4.1616 8.97e-29 +4.164 6.36552e-29 +4.1664 4.25712e-29 +4.1688 2.56737e-29 +4.1712 1.2292e-29 +4.1736 1.84771e-30 +4.176 -6.15651e-30 +4.1784 -1.21465e-29 +4.1808 -1.64857e-29 +4.1832 -1.94827e-29 +4.1856 -2.13985e-29 +4.188 -2.24531e-29 +4.1904 -2.28304e-29 +4.1928 -2.26839e-29 +4.1952 -2.21407e-29 +4.1976 -2.13051e-29 +4.2 -2.02625e-29 +4.2024 -1.90818e-29 +4.2048 -1.78185e-29 +4.2072 -1.65161e-29 +4.2096 -1.52088e-29 +4.212 -1.39227e-29 +4.2144 -1.26773e-29 +4.2168 -1.14868e-29 +4.2192 -1.03608e-29 +4.2216 -9.30542e-30 +4.224 -8.32409e-30 +4.2264 -7.41793e-30 +4.2288 -6.58636e-30 +4.2312 -5.82752e-30 +4.2336 -5.13858e-30 +4.236 -4.51607e-30 +4.2384 -3.95606e-30 +4.2408 -3.45436e-30 +4.2432 -3.00667e-30 +4.2456 -2.60865e-30 +4.248 -2.25607e-30 +4.2504 -1.94483e-30 +4.2528 -1.67101e-30 +4.2552 -1.4309e-30 +4.2576 -1.22105e-30 +4.26 -1.03824e-30 +4.2624 -8.79487e-31 +4.2648 -7.4208e-31 +4.2672 -6.23536e-31 +4.2696 -5.21603e-31 +4.272 -4.34251e-31 +4.2744 -3.59655e-31 +4.2768 -2.96181e-31 +4.2792 -2.42373e-31 +4.2816 -1.96938e-31 +4.284 -1.58734e-31 +4.2864 -1.2675e-31 +4.2888 -1.00101e-31 +4.2912 -7.80124e-32 +4.2936 -5.98058e-32 +4.296 -4.48927e-32 +4.2984 -3.27625e-32 +4.3008 -2.29742e-32 +4.3032 -1.51477e-32 +4.3056 -8.9571e-33 +4.308 -4.12353e-33 +4.3104 -4.09408e-34 +4.3128 2.38695e-33 +4.3152 4.43607e-33 +4.3176 5.88157e-33 +4.32 6.84383e-33 +4.3224 7.4233e-33 +4.3248 7.70338e-33 +4.3272 7.75291e-33 +4.3296 7.6284e-33 +4.332 7.37587e-33 +4.3344 7.03255e-33 +4.3368 6.62829e-33 +4.3392 6.18674e-33 +4.3416 5.72644e-33 +4.344 5.2617e-33 +4.3464 4.80335e-33 +4.3488 4.35937e-33 +4.3512 3.93545e-33 +4.3536 3.53546e-33 +4.356 3.16177e-33 +4.3584 2.81562e-33 +4.3608 2.49737e-33 +4.3632 2.20669e-33 +4.3656 1.94278e-33 +4.368 1.70445e-33 +4.3704 1.49029e-33 +4.3728 1.29872e-33 +4.3752 1.1281e-33 +4.3776 9.76754e-34 +4.38 8.43013e-34 +4.3824 7.25264e-34 +4.3848 6.21962e-34 +4.3872 5.31645e-34 +4.3896 4.52945e-34 +4.392 3.84593e-34 +4.3944 3.25421e-34 +4.3968 2.74361e-34 +4.3992 2.30444e-34 +4.4016 1.92792e-34 +4.404 1.60617e-34 +4.4064 1.33215e-34 +4.4088 1.09958e-34 +4.4112 9.0287e-35 +4.4136 7.37109e-35 +4.416 5.97959e-35 +4.4184 4.81615e-35 +4.4208 3.84753e-35 +4.4232 3.04477e-35 +4.4256 2.38273e-35 +4.428 1.83965e-35 +4.4304 1.39676e-35 +4.4328 1.03793e-35 +4.4352 7.49326e-36 +4.4376 5.19158e-36 +4.44 3.37377e-36 +4.4424 1.95465e-36 +4.4448 8.62247e-37 +4.4472 3.59778e-38 +4.4496 -5.74953e-37 +4.452 -1.01296e-36 +4.4544 -1.3133e-36 +4.4568 -1.50515e-36 +4.4592 -1.61253e-36 +4.4616 -1.65508e-36 +4.464 -1.64881e-36 +4.4664 -1.60663e-36 +4.4688 -1.53891e-36 +4.4712 -1.45387e-36 +4.4736 -1.35799e-36 +4.476 -1.2563e-36 +4.4784 -1.15264e-36 +4.4808 -1.04988e-36 +4.4832 -9.50148e-37 +4.4856 -8.54914e-37 +4.488 -7.65177e-37 +4.4904 -6.81543e-37 +4.4928 -6.04323e-37 +4.4952 -5.33598e-37 +4.4976 -4.69279e-37 +4.5 -4.11155e-37 +4.5024 -3.58927e-37 +4.5048 -3.12241e-37 +4.5072 -2.70708e-37 +4.5096 -2.33925e-37 +4.512 -2.01484e-37 +4.5144 -1.72984e-37 +4.5168 -1.48043e-37 +4.5192 -1.26293e-37 +4.5216 -1.07394e-37 +4.524 -9.10261e-38 +4.5264 -7.68982e-38 +4.5288 -6.47434e-38 +4.5312 -5.43199e-38 +4.5336 -4.541e-38 +4.536 -3.78183e-38 +4.5384 -3.13709e-38 +4.5408 -2.59134e-38 +4.5432 -2.13092e-38 +4.5456 -1.74385e-38 +4.548 -1.41959e-38 +4.5504 -1.14896e-38 +4.5528 -9.23958e-39 +4.5552 -7.37667e-39 +4.5576 -5.84095e-39 +4.56 -4.58085e-39 +4.5624 -3.55213e-39 +4.5648 -2.71692e-39 +4.5672 -2.04294e-39 +4.5696 -1.50278e-39 +4.572 -1.07317e-39 +4.5744 -7.34526e-40 +4.5768 -4.70336e-40 +4.5792 -2.66776e-40 +4.5816 -1.12301e-40 +4.584 2.69003e-42 +4.5864 8.61517e-41 +4.5888 1.44642e-40 +4.5912 1.83544e-40 +4.5936 2.07254e-40 +4.596 2.1934e-40 +4.5984 2.22686e-40 +4.6008 2.19599e-40 +4.6032 2.11917e-40 +4.6056 2.01089e-40 +4.608 1.88244e-40 +4.6104 1.74253e-40 +4.6128 1.59778e-40 +4.6152 1.4531e-40 +4.6176 1.31206e-40 +4.62 1.17716e-40 +4.6224 1.05008e-40 +4.6248 9.31813e-41 +4.6272 8.22891e-41 +4.6296 7.23454e-41 +4.632 6.3337e-41 +4.6344 5.5231e-41 +4.6368 4.79812e-41 +4.6392 4.15328e-41 +4.6416 3.58261e-41 +4.644 3.07991e-41 +4.6464 2.63901e-41 +4.6488 2.2539e-41 +4.6512 1.91882e-41 +4.6536 1.62834e-41 +4.656 1.37743e-41 +4.6584 1.16145e-41 +4.6608 9.76145e-42 +4.6632 8.17694e-42 +4.6656 6.82643e-42 +4.668 5.67906e-42 +4.6704 4.70742e-42 +4.6728 3.88725e-42 +4.6752 3.19719e-42 +4.6776 2.61853e-42 +4.68 2.13492e-42 +4.6824 1.73217e-42 +4.6848 1.39797e-42 +4.6872 1.12168e-42 +4.6896 8.94185e-43 +4.692 7.0764e-43 +4.6944 5.55357e-43 +4.6968 4.31639e-43 +4.6992 3.31648e-43 +4.7016 2.51296e-43 +4.704 1.87131e-43 +4.7064 1.36256e-43 +4.7088 9.62434e-44 +4.7112 6.50662e-44 +4.7136 4.10401e-44 +4.716 2.27693e-44 +4.7184 9.10173e-45 +4.7208 -9.09271e-46 +4.7232 -8.03847e-45 +4.7256 -1.29169e-44 +4.728 -1.60559e-44 +4.7304 -1.78677e-44 +4.7328 -1.86825e-44 +4.7352 -1.8763e-44 +4.7376 -1.83166e-44 +4.74 -1.75059e-44 +4.7424 -1.64566e-44 +4.7448 -1.52651e-44 +4.7472 -1.4004e-44 +4.7496 -1.27272e-44 +4.752 -1.14734e-44 +4.7544 -1.02698e-44 +4.7568 -9.13438e-45 +4.7592 -8.07826e-45 +4.7616 -7.10716e-45 +4.764 -6.2229e-45 +4.7664 -5.42443e-45 +4.7688 -4.70872e-45 +4.7712 -4.07134e-45 +4.7736 -3.50704e-45 +4.776 -3.0101e-45 +4.7784 -2.57462e-45 +4.7808 -2.19471e-45 +4.7832 -1.86471e-45 +4.7856 -1.57919e-45 +4.788 -1.33311e-45 +4.7904 -1.12178e-45 +4.7928 -9.40945e-46 +4.7952 -7.86725e-46 +4.7976 -6.55643e-46 +4.8 -5.4459e-46 diff --git a/tools/rt-tddft-tools/examples/Absorpation-N2/efield_1.txt b/tools/rt-tddft-tools/examples/Absorpation-N2/efield_1.txt index c847977cb31..782bd846f4e 100644 --- a/tools/rt-tddft-tools/examples/Absorpation-N2/efield_1.txt +++ b/tools/rt-tddft-tools/examples/Absorpation-N2/efield_1.txt @@ -1,2000 +1,2000 @@ -0.0024 -3.48824e-21 -0.0048 -3.79837e-21 -0.0072 -4.13024e-21 -0.0096 -4.48442e-21 -0.012 -4.86129e-21 -0.0144 -5.26097e-21 -0.0168 -5.68331e-21 -0.0192 -6.12777e-21 -0.0216 -6.59336e-21 -0.024 -7.07854e-21 -0.0264 -7.58109e-21 -0.0288 -8.098e-21 -0.0312 -8.6253e-21 -0.0336 -9.15788e-21 -0.036 -9.6893e-21 -0.0384 -1.02115e-20 -0.0408 -1.07146e-20 -0.0432 -1.11866e-20 -0.0456 -1.16128e-20 -0.048 -1.19757e-20 -0.0504 -1.22543e-20 -0.0528 -1.24238e-20 -0.0552 -1.24544e-20 -0.0576 -1.23115e-20 -0.06 -1.1954e-20 -0.0624 -1.13341e-20 -0.0648 -1.03957e-20 -0.0672 -9.07356e-21 -0.0696 -7.2919e-21 -0.072 -4.96279e-21 -0.0744 -1.98453e-21 -0.0768 1.76037e-21 -0.0792 6.40731e-21 -0.0816 1.21121e-20 -0.084 1.90538e-20 -0.0864 2.74378e-20 -0.0888 3.74994e-20 -0.0912 4.95077e-20 -0.0936 6.37703e-20 -0.096 8.06381e-20 -0.0984 1.00511e-19 -0.1008 1.23845e-19 -0.1032 1.51158e-19 -0.1056 1.83037e-19 -0.108 2.20152e-19 -0.1104 2.6326e-19 -0.1128 3.13217e-19 -0.1152 3.70997e-19 -0.1176 4.37697e-19 -0.12 5.14557e-19 -0.1224 6.02979e-19 -0.1248 7.04544e-19 -0.1272 8.21033e-19 -0.1296 9.54452e-19 -0.132 1.10706e-18 -0.1344 1.2814e-18 -0.1368 1.48032e-18 -0.1392 1.70704e-18 -0.1416 1.96514e-18 -0.144 2.25867e-18 -0.1464 2.59216e-18 -0.1488 2.97067e-18 -0.1512 3.39988e-18 -0.1536 3.88613e-18 -0.156 4.43654e-18 -0.1584 5.05902e-18 -0.1608 5.76245e-18 -0.1632 6.5567e-18 -0.1656 7.45282e-18 -0.168 8.46309e-18 -0.1704 9.60123e-18 -0.1728 1.08825e-17 -0.1752 1.23239e-17 -0.1776 1.39442e-17 -0.18 1.57646e-17 -0.1824 1.78083e-17 -0.1848 2.01012e-17 -0.1872 2.26722e-17 -0.1896 2.55532e-17 -0.192 2.87794e-17 -0.1944 3.23902e-17 -0.1968 3.64289e-17 -0.1992 4.09438e-17 -0.2016 4.59878e-17 -0.204 5.162e-17 -0.2064 5.79053e-17 -0.2088 6.49156e-17 -0.2112 7.27302e-17 -0.2136 8.14366e-17 -0.216 9.11315e-17 -0.2184 1.01921e-16 -0.2208 1.13923e-16 -0.2232 1.27266e-16 -0.2256 1.42093e-16 -0.228 1.5856e-16 -0.2304 1.76839e-16 -0.2328 1.97119e-16 -0.2352 2.19608e-16 -0.2376 2.44533e-16 -0.24 2.72146e-16 -0.2424 3.02719e-16 -0.2448 3.36555e-16 -0.2472 3.73982e-16 -0.2496 4.1536e-16 -0.252 4.61086e-16 -0.2544 5.11589e-16 -0.2568 5.67343e-16 -0.2592 6.28862e-16 -0.2616 6.96709e-16 -0.264 7.71498e-16 -0.2664 8.53898e-16 -0.2688 9.44639e-16 -0.2712 1.04452e-15 -0.2736 1.15439e-15 -0.276 1.27521e-15 -0.2784 1.408e-15 -0.2808 1.55386e-15 -0.2832 1.714e-15 -0.2856 1.88974e-15 -0.288 2.08249e-15 -0.2904 2.29379e-15 -0.2928 2.52531e-15 -0.2952 2.77884e-15 -0.2976 3.05635e-15 -0.3 3.35992e-15 -0.3024 3.69183e-15 -0.3048 4.05454e-15 -0.3072 4.45068e-15 -0.3096 4.8831e-15 -0.312 5.35486e-15 -0.3144 5.86924e-15 -0.3168 6.42977e-15 -0.3192 7.04025e-15 -0.3216 7.70473e-15 -0.324 8.42756e-15 -0.3264 9.21339e-15 -0.3288 1.00672e-14 -0.3312 1.09942e-14 -0.3336 1.20001e-14 -0.336 1.3091e-14 -0.3384 1.42731e-14 -0.3408 1.55533e-14 -0.3432 1.69387e-14 -0.3456 1.8437e-14 -0.348 2.0056e-14 -0.3504 2.18044e-14 -0.3528 2.36909e-14 -0.3552 2.57249e-14 -0.3576 2.79162e-14 -0.36 3.02749e-14 -0.3624 3.28116e-14 -0.3648 3.55375e-14 -0.3672 3.84639e-14 -0.3696 4.16026e-14 -0.372 4.49656e-14 -0.3744 4.85654e-14 -0.3768 5.24145e-14 -0.3792 5.65257e-14 -0.3816 6.09115e-14 -0.384 6.55849e-14 -0.3864 7.05581e-14 -0.3888 7.58435e-14 -0.3912 8.14526e-14 -0.3936 8.73964e-14 -0.396 9.36849e-14 -0.3984 1.00327e-13 -0.4008 1.07329e-13 -0.4032 1.14698e-13 -0.4056 1.22436e-13 -0.408 1.30544e-13 -0.4104 1.39018e-13 -0.4128 1.47853e-13 -0.4152 1.57036e-13 -0.4176 1.66552e-13 -0.42 1.76378e-13 -0.4224 1.86484e-13 -0.4248 1.96833e-13 -0.4272 2.07379e-13 -0.4296 2.18062e-13 -0.432 2.28815e-13 -0.4344 2.39554e-13 -0.4368 2.5018e-13 -0.4392 2.60577e-13 -0.4416 2.70609e-13 -0.444 2.80117e-13 -0.4464 2.88919e-13 -0.4488 2.96801e-13 -0.4512 3.03521e-13 -0.4536 3.088e-13 -0.456 3.12321e-13 -0.4584 3.1372e-13 -0.4608 3.12587e-13 -0.4632 3.08455e-13 -0.4656 3.00799e-13 -0.468 2.89022e-13 -0.4704 2.72458e-13 -0.4728 2.50353e-13 -0.4752 2.21863e-13 -0.4776 1.86045e-13 -0.48 1.41839e-13 -0.4824 8.80648e-14 -0.4848 2.3405e-14 -0.4872 -5.36088e-14 -0.4896 -1.4461e-13 -0.492 -2.51415e-13 -0.4944 -3.7604e-13 -0.4968 -5.20721e-13 -0.4992 -6.87934e-13 -0.5016 -8.80422e-13 -0.504 -1.10122e-12 -0.5064 -1.35367e-12 -0.5088 -1.64147e-12 -0.5112 -1.96871e-12 -0.5136 -2.33986e-12 -0.516 -2.75989e-12 -0.5184 -3.23422e-12 -0.5208 -3.76885e-12 -0.5232 -4.37033e-12 -0.5256 -5.04588e-12 -0.528 -5.8034e-12 -0.5304 -6.65157e-12 -0.5328 -7.59987e-12 -0.5352 -8.65869e-12 -0.5376 -9.8394e-12 -0.54 -1.11544e-11 -0.5424 -1.26173e-11 -0.5448 -1.42428e-11 -0.5472 -1.60472e-11 -0.5496 -1.8048e-11 -0.552 -2.02644e-11 -0.5544 -2.27174e-11 -0.5568 -2.54296e-11 -0.5592 -2.84258e-11 -0.5616 -3.17329e-11 -0.564 -3.53801e-11 -0.5664 -3.9399e-11 -0.5688 -4.38241e-11 -0.5712 -4.86927e-11 -0.5736 -5.40452e-11 -0.576 -5.99254e-11 -0.5784 -6.63808e-11 -0.5808 -7.34626e-11 -0.5832 -8.12264e-11 -0.5856 -8.97322e-11 -0.588 -9.90446e-11 -0.5904 -1.09234e-10 -0.5928 -1.20375e-10 -0.5952 -1.3255e-10 -0.5976 -1.45846e-10 -0.6 -1.60359e-10 -0.6024 -1.76189e-10 -0.6048 -1.93446e-10 -0.6072 -2.12248e-10 -0.6096 -2.32722e-10 -0.612 -2.55004e-10 -0.6144 -2.7924e-10 -0.6168 -3.05587e-10 -0.6192 -3.34213e-10 -0.6216 -3.65299e-10 -0.624 -3.99037e-10 -0.6264 -4.35635e-10 -0.6288 -4.75315e-10 -0.6312 -5.18312e-10 -0.6336 -5.6488e-10 -0.636 -6.15291e-10 -0.6384 -6.69832e-10 -0.6408 -7.28812e-10 -0.6432 -7.92559e-10 -0.6456 -8.61425e-10 -0.648 -9.35783e-10 -0.6504 -1.01603e-09 -0.6528 -1.10259e-09 -0.6552 -1.19591e-09 -0.6576 -1.29646e-09 -0.66 -1.40477e-09 -0.6624 -1.52136e-09 -0.6648 -1.6468e-09 -0.6672 -1.7817e-09 -0.6696 -1.9267e-09 -0.672 -2.08248e-09 -0.6744 -2.24975e-09 -0.6768 -2.42928e-09 -0.6792 -2.62185e-09 -0.6816 -2.82832e-09 -0.684 -3.04957e-09 -0.6864 -3.28654e-09 -0.6888 -3.54022e-09 -0.6912 -3.81163e-09 -0.6936 -4.10188e-09 -0.696 -4.41209e-09 -0.6984 -4.74347e-09 -0.7008 -5.09728e-09 -0.7032 -5.47482e-09 -0.7056 -5.87747e-09 -0.708 -6.30667e-09 -0.7104 -6.76389e-09 -0.7128 -7.25071e-09 -0.7152 -7.76874e-09 -0.7176 -8.31966e-09 -0.72 -8.90521e-09 -0.7224 -9.52722e-09 -0.7248 -1.01875e-08 -0.7272 -1.08881e-08 -0.7296 -1.16309e-08 -0.732 -1.24179e-08 -0.7344 -1.32514e-08 -0.7368 -1.41334e-08 -0.7392 -1.50661e-08 -0.7416 -1.60518e-08 -0.744 -1.70927e-08 -0.7464 -1.81912e-08 -0.7488 -1.93496e-08 -0.7512 -2.05702e-08 -0.7536 -2.18554e-08 -0.756 -2.32075e-08 -0.7584 -2.46289e-08 -0.7608 -2.61219e-08 -0.7632 -2.76886e-08 -0.7656 -2.93312e-08 -0.768 -3.10519e-08 -0.7704 -3.28526e-08 -0.7728 -3.47352e-08 -0.7752 -3.67012e-08 -0.7776 -3.87523e-08 -0.78 -4.08897e-08 -0.7824 -4.31144e-08 -0.7848 -4.54271e-08 -0.7872 -4.78281e-08 -0.7896 -5.03174e-08 -0.792 -5.28947e-08 -0.7944 -5.55588e-08 -0.7968 -5.83083e-08 -0.7992 -6.11411e-08 -0.8016 -6.40543e-08 -0.804 -6.70443e-08 -0.8064 -7.01066e-08 -0.8088 -7.32359e-08 -0.8112 -7.64257e-08 -0.8136 -7.96683e-08 -0.816 -8.2955e-08 -0.8184 -8.62754e-08 -0.8208 -8.96179e-08 -0.8232 -9.29689e-08 -0.8256 -9.63132e-08 -0.828 -9.96336e-08 -0.8304 -1.02911e-07 -0.8328 -1.06123e-07 -0.8352 -1.09246e-07 -0.8376 -1.12253e-07 -0.84 -1.15114e-07 -0.8424 -1.17795e-07 -0.8448 -1.2026e-07 -0.8472 -1.22469e-07 -0.8496 -1.24378e-07 -0.852 -1.25936e-07 -0.8544 -1.27092e-07 -0.8568 -1.27785e-07 -0.8592 -1.27953e-07 -0.8616 -1.27525e-07 -0.864 -1.26426e-07 -0.8664 -1.24572e-07 -0.8688 -1.21873e-07 -0.8712 -1.18233e-07 -0.8736 -1.13545e-07 -0.876 -1.07695e-07 -0.8784 -1.00558e-07 -0.8808 -9.20018e-08 -0.8832 -8.18809e-08 -0.8856 -7.00398e-08 -0.888 -5.63106e-08 -0.8904 -4.05128e-08 -0.8928 -2.24521e-08 -0.8952 -1.91994e-09 -0.8976 2.13077e-08 -0.9 4.74712e-08 -0.9024 7.68278e-08 -0.9048 1.09653e-07 -0.9072 1.46243e-07 -0.9096 1.86912e-07 -0.912 2.31997e-07 -0.9144 2.81859e-07 -0.9168 3.36881e-07 -0.9192 3.97473e-07 -0.9216 4.64071e-07 -0.924 5.37139e-07 -0.9264 6.17172e-07 -0.9288 7.04694e-07 -0.9312 8.00264e-07 -0.9336 9.04475e-07 -0.936 1.01796e-06 -0.9384 1.14137e-06 -0.9408 1.27543e-06 -0.9432 1.42089e-06 -0.9456 1.57853e-06 -0.948 1.74919e-06 -0.9504 1.93376e-06 -0.9528 2.13319e-06 -0.9552 2.34844e-06 -0.9576 2.58058e-06 -0.96 2.8307e-06 -0.9624 3.09996e-06 -0.9648 3.38958e-06 -0.9672 3.70086e-06 -0.9696 4.03514e-06 -0.972 4.39384e-06 -0.9744 4.77847e-06 -0.9768 5.19059e-06 -0.9792 5.63185e-06 -0.9816 6.10398e-06 -0.984 6.60879e-06 -0.9864 7.14819e-06 -0.9888 7.72416e-06 -0.9912 8.33877e-06 -0.9936 8.99421e-06 -0.996 9.69275e-06 -0.9984 1.04368e-05 -1.0008 1.12287e-05 -1.0032 1.20712e-05 -1.0056 1.29669e-05 -1.008 1.39187e-05 -1.0104 1.49293e-05 -1.0128 1.6002e-05 -1.0152 1.71398e-05 -1.0176 1.83461e-05 -1.02 1.96241e-05 -1.0224 2.09775e-05 -1.0248 2.241e-05 -1.0272 2.39252e-05 -1.0296 2.55271e-05 -1.032 2.72199e-05 -1.0344 2.90076e-05 -1.0368 3.08946e-05 -1.0392 3.28853e-05 -1.0416 3.49844e-05 -1.044 3.71966e-05 -1.0464 3.95268e-05 -1.0488 4.198e-05 -1.0512 4.45613e-05 -1.0536 4.72759e-05 -1.056 5.01294e-05 -1.0584 5.31273e-05 -1.0608 5.62751e-05 -1.0632 5.95787e-05 -1.0656 6.3044e-05 -1.068 6.66771e-05 -1.0704 7.04839e-05 -1.0728 7.44707e-05 -1.0752 7.86439e-05 -1.0776 8.30098e-05 -1.08 8.7575e-05 -1.0824 9.23458e-05 -1.0848 9.73289e-05 -1.0872 0.000102531 -1.0896 0.000107959 -1.092 0.000113618 -1.0944 0.000119517 -1.0968 0.000125661 -1.0992 0.000132058 -1.1016 0.000138713 -1.104 0.000145633 -1.1064 0.000152824 -1.1088 0.000160294 -1.1112 0.000168046 -1.1136 0.000176089 -1.116 0.000184427 -1.1184 0.000193065 -1.1208 0.000202009 -1.1232 0.000211264 -1.1256 0.000220834 -1.128 0.000230723 -1.1304 0.000240934 -1.1328 0.000251472 -1.1352 0.000262338 -1.1376 0.000273535 -1.14 0.000285064 -1.1424 0.000296926 -1.1448 0.00030912 -1.1472 0.000321646 -1.1496 0.000334502 -1.152 0.000347686 -1.1544 0.000361193 -1.1568 0.00037502 -1.1592 0.000389161 -1.1616 0.000403607 -1.164 0.000418351 -1.1664 0.000433384 -1.1688 0.000448693 -1.1712 0.000464267 -1.1736 0.00048009 -1.176 0.000496146 -1.1784 0.000512417 -1.1808 0.000528884 -1.1832 0.000545523 -1.1856 0.000562311 -1.188 0.000579221 -1.1904 0.000596224 -1.1928 0.000613288 -1.1952 0.00063038 -1.1976 0.000647461 -1.2 0.000664493 -1.2024 0.000681432 -1.2048 0.000698232 -1.2072 0.000714843 -1.2096 0.000731214 -1.212 0.000747286 -1.2144 0.000763 -1.2168 0.000778292 -1.2192 0.000793093 -1.2216 0.000807331 -1.224 0.000820929 -1.2264 0.000833806 -1.2288 0.000845875 -1.2312 0.000857046 -1.2336 0.000867223 -1.236 0.000876305 -1.2384 0.000884185 -1.2408 0.000890751 -1.2432 0.000895887 -1.2456 0.000899469 -1.248 0.000901366 -1.2504 0.000901445 -1.2528 0.000899562 -1.2552 0.00089557 -1.2576 0.000889314 -1.26 0.000880632 -1.2624 0.000869356 -1.2648 0.000855309 -1.2672 0.000838309 -1.2696 0.000818166 -1.272 0.000794681 -1.2744 0.00076765 -1.2768 0.000736859 -1.2792 0.000702087 -1.2816 0.000663105 -1.284 0.000619676 -1.2864 0.000571555 -1.2888 0.000518487 -1.2912 0.000460212 -1.2936 0.000396458 -1.296 0.000326948 -1.2984 0.000251393 -1.3008 0.000169498 -1.3032 8.09577e-05 -1.3056 -1.45397e-05 -1.308 -0.000117316 -1.3104 -0.000227702 -1.3128 -0.000346035 -1.3152 -0.000472663 -1.3176 -0.000607941 -1.32 -0.000752233 -1.3224 -0.000905909 -1.3248 -0.00106935 -1.3272 -0.00124294 -1.3296 -0.00142709 -1.332 -0.00162218 -1.3344 -0.00182863 -1.3368 -0.00204686 -1.3392 -0.00227729 -1.3416 -0.00252036 -1.344 -0.00277649 -1.3464 -0.00304613 -1.3488 -0.00332973 -1.3512 -0.00362774 -1.3536 -0.00394062 -1.356 -0.00426883 -1.3584 -0.00461283 -1.3608 -0.00497309 -1.3632 -0.00535009 -1.3656 -0.0057443 -1.368 -0.00615619 -1.3704 -0.00658623 -1.3728 -0.00703491 -1.3752 -0.00750269 -1.3776 -0.00799005 -1.38 -0.00849747 -1.3824 -0.0090254 -1.3848 -0.00957432 -1.3872 -0.0101447 -1.3896 -0.0107369 -1.392 -0.0113516 -1.3944 -0.011989 -1.3968 -0.0126496 -1.3992 -0.0133338 -1.4016 -0.0140422 -1.404 -0.014775 -1.4064 -0.0155326 -1.4088 -0.0163154 -1.4112 -0.0171239 -1.4136 -0.0179582 -1.416 -0.0188189 -1.4184 -0.019706 -1.4208 -0.0206201 -1.4232 -0.0215612 -1.4256 -0.0225297 -1.428 -0.0235258 -1.4304 -0.0245496 -1.4328 -0.0256014 -1.4352 -0.0266813 -1.4376 -0.0277894 -1.44 -0.0289257 -1.4424 -0.0300903 -1.4448 -0.0312833 -1.4472 -0.0325046 -1.4496 -0.0337542 -1.452 -0.0350318 -1.4544 -0.0363376 -1.4568 -0.0376711 -1.4592 -0.0390323 -1.4616 -0.0404208 -1.464 -0.0418364 -1.4664 -0.0432786 -1.4688 -0.0447472 -1.4712 -0.0462415 -1.4736 -0.0477612 -1.476 -0.0493057 -1.4784 -0.0508743 -1.4808 -0.0524664 -1.4832 -0.0540812 -1.4856 -0.0557181 -1.488 -0.0573761 -1.4904 -0.0590543 -1.4928 -0.0607518 -1.4952 -0.0624676 -1.4976 -0.0642006 -1.5 -0.0659496 -1.5024 -0.0677135 -1.5048 -0.0694909 -1.5072 -0.0712806 -1.5096 -0.073081 -1.512 -0.0748908 -1.5144 -0.0767083 -1.5168 -0.0785321 -1.5192 -0.0803603 -1.5216 -0.0821914 -1.524 -0.0840233 -1.5264 -0.0858544 -1.5288 -0.0876826 -1.5312 -0.0895058 -1.5336 -0.0913221 -1.536 -0.0931293 -1.5384 -0.0949251 -1.5408 -0.0967074 -1.5432 -0.0984736 -1.5456 -0.100221 -1.548 -0.101948 -1.5504 -0.103652 -1.5528 -0.10533 -1.5552 -0.106979 -1.5576 -0.108596 -1.56 -0.11018 -1.5624 -0.111726 -1.5648 -0.113233 -1.5672 -0.114697 -1.5696 -0.116116 -1.572 -0.117485 -1.5744 -0.118803 -1.5768 -0.120066 -1.5792 -0.121271 -1.5816 -0.122415 -1.584 -0.123494 -1.5864 -0.124506 -1.5888 -0.125447 -1.5912 -0.126314 -1.5936 -0.127104 -1.596 -0.127813 -1.5984 -0.128437 -1.6008 -0.128975 -1.6032 -0.129422 -1.6056 -0.129775 -1.608 -0.13003 -1.6104 -0.130185 -1.6128 -0.130236 -1.6152 -0.13018 -1.6176 -0.130014 -1.62 -0.129733 -1.6224 -0.129337 -1.6248 -0.12882 -1.6272 -0.12818 -1.6296 -0.127414 -1.632 -0.126519 -1.6344 -0.125492 -1.6368 -0.12433 -1.6392 -0.123031 -1.6416 -0.121591 -1.644 -0.120008 -1.6464 -0.118279 -1.6488 -0.116402 -1.6512 -0.114375 -1.6536 -0.112195 -1.656 -0.10986 -1.6584 -0.107368 -1.6608 -0.104717 -1.6632 -0.101905 -1.6656 -0.0989311 -1.668 -0.0957929 -1.6704 -0.0924891 -1.6728 -0.0890186 -1.6752 -0.0853801 -1.6776 -0.0815726 -1.68 -0.0775953 -1.6824 -0.0734475 -1.6848 -0.0691287 -1.6872 -0.0646385 -1.6896 -0.0599766 -1.692 -0.0551431 -1.6944 -0.050138 -1.6968 -0.0449618 -1.6992 -0.039615 -1.7016 -0.0340981 -1.704 -0.0284122 -1.7064 -0.0225582 -1.7088 -0.0165375 -1.7112 -0.0103515 -1.7136 -0.00400178 -1.716 0.00250972 -1.7184 0.00918099 -1.7208 0.0160098 -1.7232 0.0229936 -1.7256 0.0301299 -1.728 0.0374157 -1.7304 0.0448481 -1.7328 0.0524238 -1.7352 0.0601393 -1.7376 0.067991 -1.74 0.0759751 -1.7424 0.0840875 -1.7448 0.092324 -1.7472 0.10068 -1.7496 0.109151 -1.752 0.117733 -1.7544 0.12642 -1.7568 0.135207 -1.7592 0.144089 -1.7616 0.15306 -1.764 0.162114 -1.7664 0.171247 -1.7688 0.180451 -1.7712 0.189722 -1.7736 0.199051 -1.776 0.208434 -1.7784 0.217863 -1.7808 0.227331 -1.7832 0.236833 -1.7856 0.24636 -1.788 0.255907 -1.7904 0.265465 -1.7928 0.275028 -1.7952 0.284588 -1.7976 0.294138 -1.8 0.303671 -1.8024 0.313178 -1.8048 0.322652 -1.8072 0.332086 -1.8096 0.341472 -1.812 0.350803 -1.8144 0.36007 -1.8168 0.369265 -1.8192 0.378382 -1.8216 0.387412 -1.824 0.396348 -1.8264 0.405182 -1.8288 0.413906 -1.8312 0.422513 -1.8336 0.430996 -1.836 0.439346 -1.8384 0.447556 -1.8408 0.455619 -1.8432 0.463528 -1.8456 0.471276 -1.848 0.478856 -1.8504 0.48626 -1.8528 0.493483 -1.8552 0.500516 -1.8576 0.507355 -1.86 0.513992 -1.8624 0.520422 -1.8648 0.526638 -1.8672 0.532635 -1.8696 0.538407 -1.872 0.543948 -1.8744 0.549254 -1.8768 0.554318 -1.8792 0.559138 -1.8816 0.563707 -1.884 0.568022 -1.8864 0.572078 -1.8888 0.575872 -1.8912 0.5794 -1.8936 0.582658 -1.896 0.585643 -1.8984 0.588353 -1.9008 0.590785 -1.9032 0.592936 -1.9056 0.594805 -1.908 0.596389 -1.9104 0.597687 -1.9128 0.598698 -1.9152 0.599421 -1.9176 0.599855 -1.92 0.6 -1.9224 0.599855 -1.9248 0.599421 -1.9272 0.598698 -1.9296 0.597687 -1.932 0.596389 -1.9344 0.594805 -1.9368 0.592936 -1.9392 0.590785 -1.9416 0.588353 -1.944 0.585643 -1.9464 0.582658 -1.9488 0.5794 -1.9512 0.575872 -1.9536 0.572078 -1.956 0.568022 -1.9584 0.563707 -1.9608 0.559138 -1.9632 0.554318 -1.9656 0.549254 -1.968 0.543948 -1.9704 0.538407 -1.9728 0.532635 -1.9752 0.526638 -1.9776 0.520422 -1.98 0.513992 -1.9824 0.507355 -1.9848 0.500516 -1.9872 0.493483 -1.9896 0.48626 -1.992 0.478856 -1.9944 0.471276 -1.9968 0.463528 -1.9992 0.455619 -2.0016 0.447556 -2.004 0.439346 -2.0064 0.430996 -2.0088 0.422513 -2.0112 0.413906 -2.0136 0.405182 -2.016 0.396348 -2.0184 0.387412 -2.0208 0.378382 -2.0232 0.369265 -2.0256 0.36007 -2.028 0.350803 -2.0304 0.341472 -2.0328 0.332086 -2.0352 0.322652 -2.0376 0.313178 -2.04 0.303671 -2.0424 0.294138 -2.0448 0.284588 -2.0472 0.275028 -2.0496 0.265465 -2.052 0.255907 -2.0544 0.24636 -2.0568 0.236833 -2.0592 0.227331 -2.0616 0.217863 -2.064 0.208434 -2.0664 0.199051 -2.0688 0.189722 -2.0712 0.180451 -2.0736 0.171247 -2.076 0.162114 -2.0784 0.15306 -2.0808 0.144089 -2.0832 0.135207 -2.0856 0.12642 -2.088 0.117733 -2.0904 0.109151 -2.0928 0.10068 -2.0952 0.092324 -2.0976 0.0840875 -2.1 0.0759751 -2.1024 0.067991 -2.1048 0.0601393 -2.1072 0.0524238 -2.1096 0.0448481 -2.112 0.0374157 -2.1144 0.0301299 -2.1168 0.0229936 -2.1192 0.0160098 -2.1216 0.00918099 -2.124 0.00250972 -2.1264 -0.00400178 -2.1288 -0.0103515 -2.1312 -0.0165375 -2.1336 -0.0225582 -2.136 -0.0284122 -2.1384 -0.0340981 -2.1408 -0.039615 -2.1432 -0.0449618 -2.1456 -0.050138 -2.148 -0.0551431 -2.1504 -0.0599766 -2.1528 -0.0646385 -2.1552 -0.0691287 -2.1576 -0.0734475 -2.16 -0.0775953 -2.1624 -0.0815726 -2.1648 -0.0853801 -2.1672 -0.0890186 -2.1696 -0.0924891 -2.172 -0.0957929 -2.1744 -0.0989311 -2.1768 -0.101905 -2.1792 -0.104717 -2.1816 -0.107368 -2.184 -0.10986 -2.1864 -0.112195 -2.1888 -0.114375 -2.1912 -0.116402 -2.1936 -0.118279 -2.196 -0.120008 -2.1984 -0.121591 -2.2008 -0.123031 -2.2032 -0.12433 -2.2056 -0.125492 -2.208 -0.126519 -2.2104 -0.127414 -2.2128 -0.12818 -2.2152 -0.12882 -2.2176 -0.129337 -2.22 -0.129733 -2.2224 -0.130014 -2.2248 -0.13018 -2.2272 -0.130236 -2.2296 -0.130185 -2.232 -0.13003 -2.2344 -0.129775 -2.2368 -0.129422 -2.2392 -0.128975 -2.2416 -0.128437 -2.244 -0.127813 -2.2464 -0.127104 -2.2488 -0.126314 -2.2512 -0.125447 -2.2536 -0.124506 -2.256 -0.123494 -2.2584 -0.122415 -2.2608 -0.121271 -2.2632 -0.120066 -2.2656 -0.118803 -2.268 -0.117485 -2.2704 -0.116116 -2.2728 -0.114697 -2.2752 -0.113233 -2.2776 -0.111726 -2.28 -0.11018 -2.2824 -0.108596 -2.2848 -0.106979 -2.2872 -0.10533 -2.2896 -0.103652 -2.292 -0.101948 -2.2944 -0.100221 -2.2968 -0.0984736 -2.2992 -0.0967074 -2.3016 -0.0949251 -2.304 -0.0931293 -2.3064 -0.0913221 -2.3088 -0.0895058 -2.3112 -0.0876826 -2.3136 -0.0858544 -2.316 -0.0840233 -2.3184 -0.0821914 -2.3208 -0.0803603 -2.3232 -0.0785321 -2.3256 -0.0767083 -2.328 -0.0748908 -2.3304 -0.073081 -2.3328 -0.0712806 -2.3352 -0.0694909 -2.3376 -0.0677135 -2.34 -0.0659496 -2.3424 -0.0642006 -2.3448 -0.0624676 -2.3472 -0.0607518 -2.3496 -0.0590543 -2.352 -0.0573761 -2.3544 -0.0557181 -2.3568 -0.0540812 -2.3592 -0.0524664 -2.3616 -0.0508743 -2.364 -0.0493057 -2.3664 -0.0477612 -2.3688 -0.0462415 -2.3712 -0.0447472 -2.3736 -0.0432786 -2.376 -0.0418364 -2.3784 -0.0404208 -2.3808 -0.0390323 -2.3832 -0.0376711 -2.3856 -0.0363376 -2.388 -0.0350318 -2.3904 -0.0337542 -2.3928 -0.0325046 -2.3952 -0.0312833 -2.3976 -0.0300903 -2.4 -0.0289257 -2.4024 -0.0277894 -2.4048 -0.0266813 -2.4072 -0.0256014 -2.4096 -0.0245496 -2.412 -0.0235258 -2.4144 -0.0225297 -2.4168 -0.0215612 -2.4192 -0.0206201 -2.4216 -0.019706 -2.424 -0.0188189 -2.4264 -0.0179582 -2.4288 -0.0171239 -2.4312 -0.0163154 -2.4336 -0.0155326 -2.436 -0.014775 -2.4384 -0.0140422 -2.4408 -0.0133338 -2.4432 -0.0126496 -2.4456 -0.011989 -2.448 -0.0113516 -2.4504 -0.0107369 -2.4528 -0.0101447 -2.4552 -0.00957432 -2.4576 -0.0090254 -2.46 -0.00849747 -2.4624 -0.00799005 -2.4648 -0.00750269 -2.4672 -0.00703491 -2.4696 -0.00658623 -2.472 -0.00615619 -2.4744 -0.0057443 -2.4768 -0.00535009 -2.4792 -0.00497309 -2.4816 -0.00461283 -2.484 -0.00426883 -2.4864 -0.00394062 -2.4888 -0.00362774 -2.4912 -0.00332973 -2.4936 -0.00304613 -2.496 -0.00277649 -2.4984 -0.00252036 -2.5008 -0.00227729 -2.5032 -0.00204686 -2.5056 -0.00182863 -2.508 -0.00162218 -2.5104 -0.00142709 -2.5128 -0.00124294 -2.5152 -0.00106935 -2.5176 -0.000905909 -2.52 -0.000752233 -2.5224 -0.000607941 -2.5248 -0.000472663 -2.5272 -0.000346035 -2.5296 -0.000227702 -2.532 -0.000117316 -2.5344 -1.45397e-05 -2.5368 8.09577e-05 -2.5392 0.000169498 -2.5416 0.000251393 -2.544 0.000326948 -2.5464 0.000396458 -2.5488 0.000460212 -2.5512 0.000518487 -2.5536 0.000571555 -2.556 0.000619676 -2.5584 0.000663105 -2.5608 0.000702087 -2.5632 0.000736859 -2.5656 0.00076765 -2.568 0.000794681 -2.5704 0.000818166 -2.5728 0.000838309 -2.5752 0.000855309 -2.5776 0.000869356 -2.58 0.000880632 -2.5824 0.000889314 -2.5848 0.00089557 -2.5872 0.000899562 -2.5896 0.000901445 -2.592 0.000901366 -2.5944 0.000899469 -2.5968 0.000895887 -2.5992 0.000890751 -2.6016 0.000884185 -2.604 0.000876305 -2.6064 0.000867223 -2.6088 0.000857046 -2.6112 0.000845875 -2.6136 0.000833806 -2.616 0.000820929 -2.6184 0.000807331 -2.6208 0.000793093 -2.6232 0.000778292 -2.6256 0.000763 -2.628 0.000747286 -2.6304 0.000731214 -2.6328 0.000714843 -2.6352 0.000698232 -2.6376 0.000681432 -2.64 0.000664493 -2.6424 0.000647461 -2.6448 0.00063038 -2.6472 0.000613288 -2.6496 0.000596224 -2.652 0.000579221 -2.6544 0.000562311 -2.6568 0.000545523 -2.6592 0.000528884 -2.6616 0.000512417 -2.664 0.000496146 -2.6664 0.00048009 -2.6688 0.000464267 -2.6712 0.000448693 -2.6736 0.000433384 -2.676 0.000418351 -2.6784 0.000403607 -2.6808 0.000389161 -2.6832 0.00037502 -2.6856 0.000361193 -2.688 0.000347686 -2.6904 0.000334502 -2.6928 0.000321646 -2.6952 0.00030912 -2.6976 0.000296926 -2.7 0.000285064 -2.7024 0.000273535 -2.7048 0.000262338 -2.7072 0.000251472 -2.7096 0.000240934 -2.712 0.000230723 -2.7144 0.000220834 -2.7168 0.000211264 -2.7192 0.000202009 -2.7216 0.000193065 -2.724 0.000184427 -2.7264 0.000176089 -2.7288 0.000168046 -2.7312 0.000160294 -2.7336 0.000152824 -2.736 0.000145633 -2.7384 0.000138713 -2.7408 0.000132058 -2.7432 0.000125661 -2.7456 0.000119517 -2.748 0.000113618 -2.7504 0.000107959 -2.7528 0.000102531 -2.7552 9.73289e-05 -2.7576 9.23458e-05 -2.76 8.7575e-05 -2.7624 8.30098e-05 -2.7648 7.86439e-05 -2.7672 7.44707e-05 -2.7696 7.04839e-05 -2.772 6.66771e-05 -2.7744 6.3044e-05 -2.7768 5.95787e-05 -2.7792 5.62751e-05 -2.7816 5.31273e-05 -2.784 5.01294e-05 -2.7864 4.72759e-05 -2.7888 4.45613e-05 -2.7912 4.198e-05 -2.7936 3.95268e-05 -2.796 3.71966e-05 -2.7984 3.49844e-05 -2.8008 3.28853e-05 -2.8032 3.08946e-05 -2.8056 2.90076e-05 -2.808 2.72199e-05 -2.8104 2.55271e-05 -2.8128 2.39252e-05 -2.8152 2.241e-05 -2.8176 2.09775e-05 -2.82 1.96241e-05 -2.8224 1.83461e-05 -2.8248 1.71398e-05 -2.8272 1.6002e-05 -2.8296 1.49293e-05 -2.832 1.39187e-05 -2.8344 1.29669e-05 -2.8368 1.20712e-05 -2.8392 1.12287e-05 -2.8416 1.04368e-05 -2.844 9.69275e-06 -2.8464 8.99421e-06 -2.8488 8.33877e-06 -2.8512 7.72416e-06 -2.8536 7.14819e-06 -2.856 6.60879e-06 -2.8584 6.10398e-06 -2.8608 5.63185e-06 -2.8632 5.19059e-06 -2.8656 4.77847e-06 -2.868 4.39384e-06 -2.8704 4.03514e-06 -2.8728 3.70086e-06 -2.8752 3.38958e-06 -2.8776 3.09996e-06 -2.88 2.8307e-06 -2.8824 2.58058e-06 -2.8848 2.34844e-06 -2.8872 2.13319e-06 -2.8896 1.93376e-06 -2.892 1.74919e-06 -2.8944 1.57853e-06 -2.8968 1.42089e-06 -2.8992 1.27543e-06 -2.9016 1.14137e-06 -2.904 1.01796e-06 -2.9064 9.04475e-07 -2.9088 8.00264e-07 -2.9112 7.04694e-07 -2.9136 6.17172e-07 -2.916 5.37139e-07 -2.9184 4.64071e-07 -2.9208 3.97473e-07 -2.9232 3.36881e-07 -2.9256 2.81859e-07 -2.928 2.31997e-07 -2.9304 1.86912e-07 -2.9328 1.46243e-07 -2.9352 1.09653e-07 -2.9376 7.68278e-08 -2.94 4.74712e-08 -2.9424 2.13077e-08 -2.9448 -1.91994e-09 -2.9472 -2.24521e-08 -2.9496 -4.05128e-08 -2.952 -5.63106e-08 -2.9544 -7.00398e-08 -2.9568 -8.18809e-08 -2.9592 -9.20018e-08 -2.9616 -1.00558e-07 -2.964 -1.07695e-07 -2.9664 -1.13545e-07 -2.9688 -1.18233e-07 -2.9712 -1.21873e-07 -2.9736 -1.24572e-07 -2.976 -1.26426e-07 -2.9784 -1.27525e-07 -2.9808 -1.27953e-07 -2.9832 -1.27785e-07 -2.9856 -1.27092e-07 -2.988 -1.25936e-07 -2.9904 -1.24378e-07 -2.9928 -1.22469e-07 -2.9952 -1.2026e-07 -2.9976 -1.17795e-07 -3 -1.15114e-07 -3.0024 -1.12253e-07 -3.0048 -1.09246e-07 -3.0072 -1.06123e-07 -3.0096 -1.02911e-07 -3.012 -9.96336e-08 -3.0144 -9.63132e-08 -3.0168 -9.29689e-08 -3.0192 -8.96179e-08 -3.0216 -8.62754e-08 -3.024 -8.2955e-08 -3.0264 -7.96683e-08 -3.0288 -7.64257e-08 -3.0312 -7.32359e-08 -3.0336 -7.01066e-08 -3.036 -6.70443e-08 -3.0384 -6.40543e-08 -3.0408 -6.11411e-08 -3.0432 -5.83083e-08 -3.0456 -5.55588e-08 -3.048 -5.28947e-08 -3.0504 -5.03174e-08 -3.0528 -4.78281e-08 -3.0552 -4.54271e-08 -3.0576 -4.31144e-08 -3.06 -4.08897e-08 -3.0624 -3.87523e-08 -3.0648 -3.67012e-08 -3.0672 -3.47352e-08 -3.0696 -3.28526e-08 -3.072 -3.10519e-08 -3.0744 -2.93312e-08 -3.0768 -2.76886e-08 -3.0792 -2.61219e-08 -3.0816 -2.46289e-08 -3.084 -2.32075e-08 -3.0864 -2.18554e-08 -3.0888 -2.05702e-08 -3.0912 -1.93496e-08 -3.0936 -1.81912e-08 -3.096 -1.70927e-08 -3.0984 -1.60518e-08 -3.1008 -1.50661e-08 -3.1032 -1.41334e-08 -3.1056 -1.32514e-08 -3.108 -1.24179e-08 -3.1104 -1.16309e-08 -3.1128 -1.08881e-08 -3.1152 -1.01875e-08 -3.1176 -9.52722e-09 -3.12 -8.90521e-09 -3.1224 -8.31966e-09 -3.1248 -7.76874e-09 -3.1272 -7.25071e-09 -3.1296 -6.76389e-09 -3.132 -6.30667e-09 -3.1344 -5.87747e-09 -3.1368 -5.47482e-09 -3.1392 -5.09728e-09 -3.1416 -4.74347e-09 -3.144 -4.41209e-09 -3.1464 -4.10188e-09 -3.1488 -3.81163e-09 -3.1512 -3.54022e-09 -3.1536 -3.28654e-09 -3.156 -3.04957e-09 -3.1584 -2.82832e-09 -3.1608 -2.62185e-09 -3.1632 -2.42928e-09 -3.1656 -2.24975e-09 -3.168 -2.08248e-09 -3.1704 -1.9267e-09 -3.1728 -1.7817e-09 -3.1752 -1.6468e-09 -3.1776 -1.52136e-09 -3.18 -1.40477e-09 -3.1824 -1.29646e-09 -3.1848 -1.19591e-09 -3.1872 -1.10259e-09 -3.1896 -1.01603e-09 -3.192 -9.35783e-10 -3.1944 -8.61425e-10 -3.1968 -7.92559e-10 -3.1992 -7.28812e-10 -3.2016 -6.69832e-10 -3.204 -6.15291e-10 -3.2064 -5.6488e-10 -3.2088 -5.18312e-10 -3.2112 -4.75315e-10 -3.2136 -4.35635e-10 -3.216 -3.99037e-10 -3.2184 -3.65299e-10 -3.2208 -3.34213e-10 -3.2232 -3.05587e-10 -3.2256 -2.7924e-10 -3.228 -2.55004e-10 -3.2304 -2.32722e-10 -3.2328 -2.12248e-10 -3.2352 -1.93446e-10 -3.2376 -1.76189e-10 -3.24 -1.60359e-10 -3.2424 -1.45846e-10 -3.2448 -1.3255e-10 -3.2472 -1.20375e-10 -3.2496 -1.09234e-10 -3.252 -9.90446e-11 -3.2544 -8.97322e-11 -3.2568 -8.12264e-11 -3.2592 -7.34626e-11 -3.2616 -6.63808e-11 -3.264 -5.99254e-11 -3.2664 -5.40452e-11 -3.2688 -4.86927e-11 -3.2712 -4.38241e-11 -3.2736 -3.9399e-11 -3.276 -3.53801e-11 -3.2784 -3.17329e-11 -3.2808 -2.84258e-11 -3.2832 -2.54296e-11 -3.2856 -2.27174e-11 -3.288 -2.02644e-11 -3.2904 -1.8048e-11 -3.2928 -1.60472e-11 -3.2952 -1.42428e-11 -3.2976 -1.26173e-11 -3.3 -1.11544e-11 -3.3024 -9.8394e-12 -3.3048 -8.65869e-12 -3.3072 -7.59987e-12 -3.3096 -6.65157e-12 -3.312 -5.8034e-12 -3.3144 -5.04588e-12 -3.3168 -4.37033e-12 -3.3192 -3.76885e-12 -3.3216 -3.23422e-12 -3.324 -2.75989e-12 -3.3264 -2.33986e-12 -3.3288 -1.96871e-12 -3.3312 -1.64147e-12 -3.3336 -1.35367e-12 -3.336 -1.10122e-12 -3.3384 -8.80422e-13 -3.3408 -6.87934e-13 -3.3432 -5.20721e-13 -3.3456 -3.7604e-13 -3.348 -2.51415e-13 -3.3504 -1.4461e-13 -3.3528 -5.36088e-14 -3.3552 2.3405e-14 -3.3576 8.80648e-14 -3.36 1.41839e-13 -3.3624 1.86045e-13 -3.3648 2.21863e-13 -3.3672 2.50353e-13 -3.3696 2.72458e-13 -3.372 2.89022e-13 -3.3744 3.00799e-13 -3.3768 3.08455e-13 -3.3792 3.12587e-13 -3.3816 3.1372e-13 -3.384 3.12321e-13 -3.3864 3.088e-13 -3.3888 3.03521e-13 -3.3912 2.96801e-13 -3.3936 2.88919e-13 -3.396 2.80117e-13 -3.3984 2.70609e-13 -3.4008 2.60577e-13 -3.4032 2.5018e-13 -3.4056 2.39554e-13 -3.408 2.28815e-13 -3.4104 2.18062e-13 -3.4128 2.07379e-13 -3.4152 1.96833e-13 -3.4176 1.86484e-13 -3.42 1.76378e-13 -3.4224 1.66552e-13 -3.4248 1.57036e-13 -3.4272 1.47853e-13 -3.4296 1.39018e-13 -3.432 1.30544e-13 -3.4344 1.22436e-13 -3.4368 1.14698e-13 -3.4392 1.07329e-13 -3.4416 1.00327e-13 -3.444 9.36849e-14 -3.4464 8.73964e-14 -3.4488 8.14526e-14 -3.4512 7.58435e-14 -3.4536 7.05581e-14 -3.456 6.55849e-14 -3.4584 6.09115e-14 -3.4608 5.65257e-14 -3.4632 5.24145e-14 -3.4656 4.85654e-14 -3.468 4.49656e-14 -3.4704 4.16026e-14 -3.4728 3.84639e-14 -3.4752 3.55375e-14 -3.4776 3.28116e-14 -3.48 3.02749e-14 -3.4824 2.79162e-14 -3.4848 2.57249e-14 -3.4872 2.36909e-14 -3.4896 2.18044e-14 -3.492 2.0056e-14 -3.4944 1.8437e-14 -3.4968 1.69387e-14 -3.4992 1.55533e-14 -3.5016 1.42731e-14 -3.504 1.3091e-14 -3.5064 1.20001e-14 -3.5088 1.09942e-14 -3.5112 1.00672e-14 -3.5136 9.21339e-15 -3.516 8.42756e-15 -3.5184 7.70473e-15 -3.5208 7.04025e-15 -3.5232 6.42977e-15 -3.5256 5.86924e-15 -3.528 5.35486e-15 -3.5304 4.8831e-15 -3.5328 4.45068e-15 -3.5352 4.05454e-15 -3.5376 3.69183e-15 -3.54 3.35992e-15 -3.5424 3.05635e-15 -3.5448 2.77884e-15 -3.5472 2.52531e-15 -3.5496 2.29379e-15 -3.552 2.08249e-15 -3.5544 1.88974e-15 -3.5568 1.714e-15 -3.5592 1.55386e-15 -3.5616 1.408e-15 -3.564 1.27521e-15 -3.5664 1.15439e-15 -3.5688 1.04452e-15 -3.5712 9.44639e-16 -3.5736 8.53898e-16 -3.576 7.71498e-16 -3.5784 6.96709e-16 -3.5808 6.28862e-16 -3.5832 5.67343e-16 -3.5856 5.11589e-16 -3.588 4.61086e-16 -3.5904 4.1536e-16 -3.5928 3.73982e-16 -3.5952 3.36555e-16 -3.5976 3.02719e-16 -3.6 2.72146e-16 -3.6024 2.44533e-16 -3.6048 2.19608e-16 -3.6072 1.97119e-16 -3.6096 1.76839e-16 -3.612 1.5856e-16 -3.6144 1.42093e-16 -3.6168 1.27266e-16 -3.6192 1.13923e-16 -3.6216 1.01921e-16 -3.624 9.11315e-17 -3.6264 8.14366e-17 -3.6288 7.27302e-17 -3.6312 6.49156e-17 -3.6336 5.79053e-17 -3.636 5.162e-17 -3.6384 4.59878e-17 -3.6408 4.09438e-17 -3.6432 3.64289e-17 -3.6456 3.23902e-17 -3.648 2.87794e-17 -3.6504 2.55532e-17 -3.6528 2.26722e-17 -3.6552 2.01012e-17 -3.6576 1.78083e-17 -3.66 1.57646e-17 -3.6624 1.39442e-17 -3.6648 1.23239e-17 -3.6672 1.08825e-17 -3.6696 9.60123e-18 -3.672 8.46309e-18 -3.6744 7.45282e-18 -3.6768 6.5567e-18 -3.6792 5.76245e-18 -3.6816 5.05902e-18 -3.684 4.43654e-18 -3.6864 3.88613e-18 -3.6888 3.39988e-18 -3.6912 2.97067e-18 -3.6936 2.59216e-18 -3.696 2.25867e-18 -3.6984 1.96514e-18 -3.7008 1.70704e-18 -3.7032 1.48032e-18 -3.7056 1.2814e-18 -3.708 1.10706e-18 -3.7104 9.54452e-19 -3.7128 8.21033e-19 -3.7152 7.04544e-19 -3.7176 6.02979e-19 -3.72 5.14557e-19 -3.7224 4.37697e-19 -3.7248 3.70997e-19 -3.7272 3.13217e-19 -3.7296 2.6326e-19 -3.732 2.20152e-19 -3.7344 1.83037e-19 -3.7368 1.51158e-19 -3.7392 1.23845e-19 -3.7416 1.00511e-19 -3.744 8.06381e-20 -3.7464 6.37703e-20 -3.7488 4.95077e-20 -3.7512 3.74994e-20 -3.7536 2.74378e-20 -3.756 1.90538e-20 -3.7584 1.21121e-20 -3.7608 6.40731e-21 -3.7632 1.76037e-21 -3.7656 -1.98453e-21 -3.768 -4.96279e-21 -3.7704 -7.2919e-21 -3.7728 -9.07356e-21 -3.7752 -1.03957e-20 -3.7776 -1.13341e-20 -3.78 -1.1954e-20 -3.7824 -1.23115e-20 -3.7848 -1.24544e-20 -3.7872 -1.24238e-20 -3.7896 -1.22543e-20 -3.792 -1.19757e-20 -3.7944 -1.16128e-20 -3.7968 -1.11866e-20 -3.7992 -1.07146e-20 -3.8016 -1.02115e-20 -3.804 -9.6893e-21 -3.8064 -9.15788e-21 -3.8088 -8.6253e-21 -3.8112 -8.098e-21 -3.8136 -7.58109e-21 -3.816 -7.07854e-21 -3.8184 -6.59336e-21 -3.8208 -6.12777e-21 -3.8232 -5.68331e-21 -3.8256 -5.26097e-21 -3.828 -4.86129e-21 -3.8304 -4.48442e-21 -3.8328 -4.13024e-21 -3.8352 -3.79837e-21 -3.8376 -3.48824e-21 -3.84 -3.19916e-21 -3.8424 -2.93032e-21 -3.8448 -2.68082e-21 -3.8472 -2.44973e-21 -3.8496 -2.2361e-21 -3.852 -2.03893e-21 -3.8544 -1.85727e-21 -3.8568 -1.69013e-21 -3.8592 -1.53659e-21 -3.8616 -1.39573e-21 -3.864 -1.26666e-21 -3.8664 -1.14856e-21 -3.8688 -1.04061e-21 -3.8712 -9.42046e-22 -3.8736 -8.52158e-22 -3.876 -7.70264e-22 -3.8784 -6.95728e-22 -3.8808 -6.27953e-22 -3.8832 -5.66382e-22 -3.8856 -5.10499e-22 -3.888 -4.5982e-22 -3.8904 -4.13901e-22 -3.8928 -3.72328e-22 -3.8952 -3.34719e-22 -3.8976 -3.00723e-22 -3.9 -2.70015e-22 -3.9024 -2.42297e-22 -3.9048 -2.17297e-22 -3.9072 -1.94763e-22 -3.9096 -1.74466e-22 -3.912 -1.56196e-22 -3.9144 -1.39762e-22 -3.9168 -1.24988e-22 -3.9192 -1.11715e-22 -3.9216 -9.97975e-23 -3.924 -8.91042e-23 -3.9264 -7.95148e-23 -3.9288 -7.09204e-23 -3.9312 -6.32222e-23 -3.9336 -5.63307e-23 -3.936 -5.01649e-23 -3.9384 -4.46515e-23 -3.9408 -3.9724e-23 -3.9432 -3.53227e-23 -3.9456 -3.13934e-23 -3.948 -2.78875e-23 -3.9504 -2.47609e-23 -3.9528 -2.19741e-23 -3.9552 -1.94914e-23 -3.9576 -1.72809e-23 -3.96 -1.53136e-23 -3.9624 -1.35636e-23 -3.9648 -1.20079e-23 -3.9672 -1.06255e-23 -3.9696 -9.39765e-24 -3.972 -8.3077e-24 -3.9744 -7.34062e-24 -3.9768 -6.48299e-24 -3.9792 -5.72279e-24 -3.9816 -5.04928e-24 -3.984 -4.45288e-24 -3.9864 -3.925e-24 -3.9888 -3.45802e-24 -3.9912 -3.0451e-24 -3.9936 -2.68017e-24 -3.996 -2.35781e-24 -3.9984 -2.07319e-24 -4.0008 -1.82201e-24 -4.0032 -1.60046e-24 -4.0056 -1.40514e-24 -4.008 -1.23303e-24 -4.0104 -1.08144e-24 -4.0128 -9.47996e-25 -4.0152 -8.30583e-25 -4.0176 -7.27328e-25 -4.02 -6.3657e-25 -4.0224 -5.56836e-25 -4.0248 -4.86823e-25 -4.0272 -4.25379e-25 -4.0296 -3.71481e-25 -4.032 -3.24229e-25 -4.0344 -2.82825e-25 -4.0368 -2.46564e-25 -4.0392 -2.14825e-25 -4.0416 -1.87059e-25 -4.044 -1.62781e-25 -4.0464 -1.41567e-25 -4.0488 -1.23039e-25 -4.0512 -1.06866e-25 -4.0536 -9.2758e-26 -4.056 -8.0458e-26 -4.0584 -6.97408e-26 -4.0608 -6.04084e-26 -4.0632 -5.22869e-26 -4.0656 -4.52237e-26 -4.068 -3.90847e-26 -4.0704 -3.37526e-26 -4.0728 -2.91243e-26 -4.0752 -2.51098e-26 -4.0776 -2.163e-26 -4.08 -1.86159e-26 -4.0824 -1.6007e-26 -4.0848 -1.37507e-26 -4.0872 -1.18007e-26 -4.0896 -1.01168e-26 -4.092 -8.66386e-27 -4.0944 -7.41128e-27 -4.0968 -6.33236e-27 -4.0992 -5.40386e-27 -4.1016 -4.60555e-27 -4.104 -3.91984e-27 -4.1064 -3.33143e-27 -4.1088 -2.82704e-27 -4.1112 -2.39515e-27 -4.1136 -2.02576e-27 -4.116 -1.71019e-27 -4.1184 -1.44094e-27 -4.1208 -1.21151e-27 -4.1232 -1.01628e-27 -4.1256 -8.50391e-28 -4.128 -7.09655e-28 -4.1304 -5.90451e-28 -4.1328 -4.89662e-28 -4.1352 -4.04601e-28 -4.1376 -3.32958e-28 -4.14 -2.72745e-28 -4.1424 -2.22257e-28 -4.1448 -1.8003e-28 -4.1472 -1.4481e-28 -4.1496 -1.15523e-28 -4.152 -9.12512e-29 -4.1544 -7.12105e-29 -4.1568 -5.47322e-29 -4.1592 -4.12466e-29 -4.1616 -3.02693e-29 -4.164 -2.13889e-29 -4.1664 -1.42565e-29 -4.1688 -8.57674e-30 -4.1712 -4.10003e-30 -4.1736 -6.15915e-31 -4.176 2.05275e-30 -4.1784 4.05472e-30 -4.1808 5.51463e-30 -4.1832 6.53659e-30 -4.1856 7.20735e-30 -4.188 7.59897e-30 -4.1904 7.77108e-30 -4.1928 7.77284e-30 -4.1952 7.64459e-30 -4.1976 7.41929e-30 -4.2 7.1237e-30 -4.2024 6.77942e-30 -4.2048 6.40372e-30 -4.2072 6.01034e-30 -4.2096 5.61001e-30 -4.212 5.21107e-30 -4.2144 4.81985e-30 -4.2168 4.44104e-30 -4.2192 4.07801e-30 -4.2216 3.73309e-30 -4.224 3.40773e-30 -4.2264 3.10273e-30 -4.2288 2.81834e-30 -4.2312 2.55442e-30 -4.2336 2.31053e-30 -4.236 2.08597e-30 -4.2384 1.87992e-30 -4.2408 1.69141e-30 -4.2432 1.51944e-30 -4.2456 1.36295e-30 -4.248 1.22087e-30 -4.2504 1.09216e-30 -4.2528 9.75801e-31 -4.2552 8.70793e-31 -4.2576 7.76198e-31 -4.26 6.91123e-31 -4.2624 6.14728e-31 -4.2648 5.46228e-31 -4.2672 4.8489e-31 -4.2696 4.30038e-31 -4.272 3.81048e-31 -4.2744 3.37344e-31 -4.2768 2.98401e-31 -4.2792 2.63737e-31 -4.2816 2.32915e-31 -4.284 2.05536e-31 -4.2864 1.81239e-31 -4.2888 1.59698e-31 -4.2912 1.40616e-31 -4.2936 1.23728e-31 -4.296 1.08794e-31 -4.2984 9.55985e-32 -4.3008 8.39487e-32 -4.3032 7.36713e-32 -4.3056 6.46116e-32 -4.308 5.6631e-32 -4.3104 4.9606e-32 -4.3128 4.34266e-32 -4.3152 3.79946e-32 -4.3176 3.32228e-32 -4.32 2.90338e-32 -4.3224 2.53587e-32 -4.3248 2.21365e-32 -4.3272 1.93131e-32 -4.3296 1.68407e-32 -4.332 1.4677e-32 -4.3344 1.27844e-32 -4.3368 1.11301e-32 -4.3392 9.68478e-33 -4.3416 8.4228e-33 -4.344 7.32152e-33 -4.3464 6.36099e-33 -4.3488 5.52369e-33 -4.3512 4.7942e-33 -4.3536 4.15898e-33 -4.356 3.60614e-33 -4.3584 3.12524e-33 -4.3608 2.70714e-33 -4.3632 2.34383e-33 -4.3656 2.02829e-33 -4.368 1.75437e-33 -4.3704 1.51672e-33 -4.3728 1.31062e-33 -4.3752 1.13198e-33 -4.3776 9.77215e-34 -4.38 8.43204e-34 -4.3824 7.2722e-34 -4.3848 6.26887e-34 -4.3872 5.40136e-34 -4.3896 4.65165e-34 -4.392 4.00405e-34 -4.3944 3.44494e-34 -4.3968 2.96246e-34 -4.3992 2.5463e-34 -4.4016 2.18754e-34 -4.404 1.87839e-34 -4.4064 1.61214e-34 -4.4088 1.38294e-34 -4.4112 1.18573e-34 -4.4136 1.01613e-34 -4.416 8.70343e-35 -4.4184 7.45095e-35 -4.4208 6.37542e-35 -4.4232 5.4523e-35 -4.4256 4.66041e-35 -4.428 3.98142e-35 -4.4304 3.39953e-35 -4.4328 2.90112e-35 -4.4352 2.47442e-35 -4.4376 2.10932e-35 -4.44 1.79708e-35 -4.4424 1.53019e-35 -4.4448 1.30218e-35 -4.4472 1.1075e-35 -4.4496 9.41364e-36 -4.452 7.99668e-36 -4.4544 6.78881e-36 -4.4568 5.75979e-36 -4.4592 4.88362e-36 -4.4616 4.13803e-36 -4.464 3.50395e-36 -4.4664 2.96501e-36 -4.4688 2.50722e-36 -4.4712 2.11861e-36 -4.4736 1.78893e-36 -4.476 1.50941e-36 -4.4784 1.2726e-36 -4.4808 1.07209e-36 -4.4832 9.02434e-37 -4.4856 7.5899e-37 -4.488 6.37794e-37 -4.4904 5.35471e-37 -4.4928 4.49147e-37 -4.4952 3.76376e-37 -4.4976 3.15081e-37 -4.5 2.63494e-37 -4.5024 2.20114e-37 -4.5048 1.83668e-37 -4.5072 1.53074e-37 -4.5096 1.27418e-37 -4.512 1.05924e-37 -4.5144 8.79341e-38 -4.5168 7.28935e-38 -4.5192 6.03324e-38 -4.5216 4.98541e-38 -4.524 4.11238e-38 -4.5264 3.38591e-38 -4.5288 2.78219e-38 -4.5312 2.28119e-38 -4.5336 1.86605e-38 -4.536 1.52259e-38 -4.5384 1.23891e-38 -4.5408 1.00502e-38 -4.5432 8.12551e-39 -4.5456 6.54492e-39 -4.548 5.24977e-39 -4.5504 4.19104e-39 -4.5528 3.32783e-39 -4.5552 2.62603e-39 -4.5576 2.05725e-39 -4.56 1.59786e-39 -4.5624 1.22826e-39 -4.5648 9.32187e-40 -4.5672 6.96172e-40 -4.5696 5.09088e-40 -4.572 3.6175e-40 -4.5744 2.46595e-40 -4.5768 1.57406e-40 -4.5792 8.90817e-41 -4.5816 3.74498e-41 -4.584 -8.96678e-43 -4.5864 -2.87309e-41 -4.5888 -4.83036e-41 -4.5912 -6.14352e-41 -4.5936 -6.9593e-41 -4.596 -7.39546e-41 -4.5984 -7.54606e-41 -4.6008 -7.48585e-41 -4.6032 -7.27388e-41 -4.6056 -6.95644e-41 -4.608 -6.56951e-41 -4.6104 -6.14083e-41 -4.6128 -5.69145e-41 -4.6152 -5.23713e-41 -4.6176 -4.78945e-41 -4.62 -4.35665e-41 -4.6224 -3.94439e-41 -4.6248 -3.55632e-41 -4.6272 -3.19455e-41 -4.6296 -2.86e-41 -4.632 -2.55276e-41 -4.6344 -2.27225e-41 -4.6368 -2.01746e-41 -4.6392 -1.78708e-41 -4.6416 -1.57962e-41 -4.644 -1.39346e-41 -4.6464 -1.22695e-41 -4.6488 -1.07846e-41 -4.6512 -9.46396e-42 -4.6536 -8.29228e-42 -4.656 -7.25513e-42 -4.6584 -6.33898e-42 -4.6608 -5.53131e-42 -4.6632 -4.82056e-42 -4.6656 -4.19617e-42 -4.668 -3.64853e-42 -4.6704 -3.16893e-42 -4.6728 -2.74952e-42 -4.6752 -2.38324e-42 -4.6776 -2.06377e-42 -4.68 -1.78547e-42 -4.6824 -1.54332e-42 -4.6848 -1.33285e-42 -4.6872 -1.15013e-42 -4.6896 -9.91643e-43 -4.692 -8.54324e-43 -4.6944 -7.35456e-43 -4.6968 -6.32654e-43 -4.6992 -5.43825e-43 -4.7016 -4.67137e-43 -4.704 -4.00984e-43 -4.7064 -3.43966e-43 -4.7088 -2.9486e-43 -4.7112 -2.526e-43 -4.7136 -2.16259e-43 -4.716 -1.8503e-43 -4.7184 -1.58214e-43 -4.7208 -1.35203e-43 -4.7232 -1.15469e-43 -4.7256 -9.85585e-44 -4.728 -8.40758e-44 -4.7304 -7.16805e-44 -4.7328 -6.10785e-44 -4.7352 -5.20157e-44 -4.7376 -4.42734e-44 -4.74 -3.76632e-44 -4.7424 -3.20228e-44 -4.7448 -2.72127e-44 -4.7472 -2.3113e-44 -4.7496 -1.96207e-44 -4.752 -1.66475e-44 -4.7544 -1.41176e-44 -4.7568 -1.19662e-44 -4.7592 -1.01375e-44 -4.7616 -8.58392e-45 -4.764 -7.26484e-45 -4.7664 -6.14542e-45 -4.7688 -5.19593e-45 -4.7712 -4.39098e-45 -4.7736 -3.70892e-45 -4.776 -3.13128e-45 -4.7784 -2.64232e-45 -4.7808 -2.22864e-45 -4.7832 -1.87881e-45 -4.7856 -1.58312e-45 -4.788 -1.33333e-45 -4.7904 -1.12241e-45 -4.7928 -9.44403e-46 -4.7952 -7.94241e-46 -4.7976 -6.67632e-46 -4.8 -5.60934e-46 +0.0024 -3.48824e-21 +0.0048 -3.79837e-21 +0.0072 -4.13024e-21 +0.0096 -4.48442e-21 +0.012 -4.86129e-21 +0.0144 -5.26097e-21 +0.0168 -5.68331e-21 +0.0192 -6.12777e-21 +0.0216 -6.59336e-21 +0.024 -7.07854e-21 +0.0264 -7.58109e-21 +0.0288 -8.098e-21 +0.0312 -8.6253e-21 +0.0336 -9.15788e-21 +0.036 -9.6893e-21 +0.0384 -1.02115e-20 +0.0408 -1.07146e-20 +0.0432 -1.11866e-20 +0.0456 -1.16128e-20 +0.048 -1.19757e-20 +0.0504 -1.22543e-20 +0.0528 -1.24238e-20 +0.0552 -1.24544e-20 +0.0576 -1.23115e-20 +0.06 -1.1954e-20 +0.0624 -1.13341e-20 +0.0648 -1.03957e-20 +0.0672 -9.07356e-21 +0.0696 -7.2919e-21 +0.072 -4.96279e-21 +0.0744 -1.98453e-21 +0.0768 1.76037e-21 +0.0792 6.40731e-21 +0.0816 1.21121e-20 +0.084 1.90538e-20 +0.0864 2.74378e-20 +0.0888 3.74994e-20 +0.0912 4.95077e-20 +0.0936 6.37703e-20 +0.096 8.06381e-20 +0.0984 1.00511e-19 +0.1008 1.23845e-19 +0.1032 1.51158e-19 +0.1056 1.83037e-19 +0.108 2.20152e-19 +0.1104 2.6326e-19 +0.1128 3.13217e-19 +0.1152 3.70997e-19 +0.1176 4.37697e-19 +0.12 5.14557e-19 +0.1224 6.02979e-19 +0.1248 7.04544e-19 +0.1272 8.21033e-19 +0.1296 9.54452e-19 +0.132 1.10706e-18 +0.1344 1.2814e-18 +0.1368 1.48032e-18 +0.1392 1.70704e-18 +0.1416 1.96514e-18 +0.144 2.25867e-18 +0.1464 2.59216e-18 +0.1488 2.97067e-18 +0.1512 3.39988e-18 +0.1536 3.88613e-18 +0.156 4.43654e-18 +0.1584 5.05902e-18 +0.1608 5.76245e-18 +0.1632 6.5567e-18 +0.1656 7.45282e-18 +0.168 8.46309e-18 +0.1704 9.60123e-18 +0.1728 1.08825e-17 +0.1752 1.23239e-17 +0.1776 1.39442e-17 +0.18 1.57646e-17 +0.1824 1.78083e-17 +0.1848 2.01012e-17 +0.1872 2.26722e-17 +0.1896 2.55532e-17 +0.192 2.87794e-17 +0.1944 3.23902e-17 +0.1968 3.64289e-17 +0.1992 4.09438e-17 +0.2016 4.59878e-17 +0.204 5.162e-17 +0.2064 5.79053e-17 +0.2088 6.49156e-17 +0.2112 7.27302e-17 +0.2136 8.14366e-17 +0.216 9.11315e-17 +0.2184 1.01921e-16 +0.2208 1.13923e-16 +0.2232 1.27266e-16 +0.2256 1.42093e-16 +0.228 1.5856e-16 +0.2304 1.76839e-16 +0.2328 1.97119e-16 +0.2352 2.19608e-16 +0.2376 2.44533e-16 +0.24 2.72146e-16 +0.2424 3.02719e-16 +0.2448 3.36555e-16 +0.2472 3.73982e-16 +0.2496 4.1536e-16 +0.252 4.61086e-16 +0.2544 5.11589e-16 +0.2568 5.67343e-16 +0.2592 6.28862e-16 +0.2616 6.96709e-16 +0.264 7.71498e-16 +0.2664 8.53898e-16 +0.2688 9.44639e-16 +0.2712 1.04452e-15 +0.2736 1.15439e-15 +0.276 1.27521e-15 +0.2784 1.408e-15 +0.2808 1.55386e-15 +0.2832 1.714e-15 +0.2856 1.88974e-15 +0.288 2.08249e-15 +0.2904 2.29379e-15 +0.2928 2.52531e-15 +0.2952 2.77884e-15 +0.2976 3.05635e-15 +0.3 3.35992e-15 +0.3024 3.69183e-15 +0.3048 4.05454e-15 +0.3072 4.45068e-15 +0.3096 4.8831e-15 +0.312 5.35486e-15 +0.3144 5.86924e-15 +0.3168 6.42977e-15 +0.3192 7.04025e-15 +0.3216 7.70473e-15 +0.324 8.42756e-15 +0.3264 9.21339e-15 +0.3288 1.00672e-14 +0.3312 1.09942e-14 +0.3336 1.20001e-14 +0.336 1.3091e-14 +0.3384 1.42731e-14 +0.3408 1.55533e-14 +0.3432 1.69387e-14 +0.3456 1.8437e-14 +0.348 2.0056e-14 +0.3504 2.18044e-14 +0.3528 2.36909e-14 +0.3552 2.57249e-14 +0.3576 2.79162e-14 +0.36 3.02749e-14 +0.3624 3.28116e-14 +0.3648 3.55375e-14 +0.3672 3.84639e-14 +0.3696 4.16026e-14 +0.372 4.49656e-14 +0.3744 4.85654e-14 +0.3768 5.24145e-14 +0.3792 5.65257e-14 +0.3816 6.09115e-14 +0.384 6.55849e-14 +0.3864 7.05581e-14 +0.3888 7.58435e-14 +0.3912 8.14526e-14 +0.3936 8.73964e-14 +0.396 9.36849e-14 +0.3984 1.00327e-13 +0.4008 1.07329e-13 +0.4032 1.14698e-13 +0.4056 1.22436e-13 +0.408 1.30544e-13 +0.4104 1.39018e-13 +0.4128 1.47853e-13 +0.4152 1.57036e-13 +0.4176 1.66552e-13 +0.42 1.76378e-13 +0.4224 1.86484e-13 +0.4248 1.96833e-13 +0.4272 2.07379e-13 +0.4296 2.18062e-13 +0.432 2.28815e-13 +0.4344 2.39554e-13 +0.4368 2.5018e-13 +0.4392 2.60577e-13 +0.4416 2.70609e-13 +0.444 2.80117e-13 +0.4464 2.88919e-13 +0.4488 2.96801e-13 +0.4512 3.03521e-13 +0.4536 3.088e-13 +0.456 3.12321e-13 +0.4584 3.1372e-13 +0.4608 3.12587e-13 +0.4632 3.08455e-13 +0.4656 3.00799e-13 +0.468 2.89022e-13 +0.4704 2.72458e-13 +0.4728 2.50353e-13 +0.4752 2.21863e-13 +0.4776 1.86045e-13 +0.48 1.41839e-13 +0.4824 8.80648e-14 +0.4848 2.3405e-14 +0.4872 -5.36088e-14 +0.4896 -1.4461e-13 +0.492 -2.51415e-13 +0.4944 -3.7604e-13 +0.4968 -5.20721e-13 +0.4992 -6.87934e-13 +0.5016 -8.80422e-13 +0.504 -1.10122e-12 +0.5064 -1.35367e-12 +0.5088 -1.64147e-12 +0.5112 -1.96871e-12 +0.5136 -2.33986e-12 +0.516 -2.75989e-12 +0.5184 -3.23422e-12 +0.5208 -3.76885e-12 +0.5232 -4.37033e-12 +0.5256 -5.04588e-12 +0.528 -5.8034e-12 +0.5304 -6.65157e-12 +0.5328 -7.59987e-12 +0.5352 -8.65869e-12 +0.5376 -9.8394e-12 +0.54 -1.11544e-11 +0.5424 -1.26173e-11 +0.5448 -1.42428e-11 +0.5472 -1.60472e-11 +0.5496 -1.8048e-11 +0.552 -2.02644e-11 +0.5544 -2.27174e-11 +0.5568 -2.54296e-11 +0.5592 -2.84258e-11 +0.5616 -3.17329e-11 +0.564 -3.53801e-11 +0.5664 -3.9399e-11 +0.5688 -4.38241e-11 +0.5712 -4.86927e-11 +0.5736 -5.40452e-11 +0.576 -5.99254e-11 +0.5784 -6.63808e-11 +0.5808 -7.34626e-11 +0.5832 -8.12264e-11 +0.5856 -8.97322e-11 +0.588 -9.90446e-11 +0.5904 -1.09234e-10 +0.5928 -1.20375e-10 +0.5952 -1.3255e-10 +0.5976 -1.45846e-10 +0.6 -1.60359e-10 +0.6024 -1.76189e-10 +0.6048 -1.93446e-10 +0.6072 -2.12248e-10 +0.6096 -2.32722e-10 +0.612 -2.55004e-10 +0.6144 -2.7924e-10 +0.6168 -3.05587e-10 +0.6192 -3.34213e-10 +0.6216 -3.65299e-10 +0.624 -3.99037e-10 +0.6264 -4.35635e-10 +0.6288 -4.75315e-10 +0.6312 -5.18312e-10 +0.6336 -5.6488e-10 +0.636 -6.15291e-10 +0.6384 -6.69832e-10 +0.6408 -7.28812e-10 +0.6432 -7.92559e-10 +0.6456 -8.61425e-10 +0.648 -9.35783e-10 +0.6504 -1.01603e-09 +0.6528 -1.10259e-09 +0.6552 -1.19591e-09 +0.6576 -1.29646e-09 +0.66 -1.40477e-09 +0.6624 -1.52136e-09 +0.6648 -1.6468e-09 +0.6672 -1.7817e-09 +0.6696 -1.9267e-09 +0.672 -2.08248e-09 +0.6744 -2.24975e-09 +0.6768 -2.42928e-09 +0.6792 -2.62185e-09 +0.6816 -2.82832e-09 +0.684 -3.04957e-09 +0.6864 -3.28654e-09 +0.6888 -3.54022e-09 +0.6912 -3.81163e-09 +0.6936 -4.10188e-09 +0.696 -4.41209e-09 +0.6984 -4.74347e-09 +0.7008 -5.09728e-09 +0.7032 -5.47482e-09 +0.7056 -5.87747e-09 +0.708 -6.30667e-09 +0.7104 -6.76389e-09 +0.7128 -7.25071e-09 +0.7152 -7.76874e-09 +0.7176 -8.31966e-09 +0.72 -8.90521e-09 +0.7224 -9.52722e-09 +0.7248 -1.01875e-08 +0.7272 -1.08881e-08 +0.7296 -1.16309e-08 +0.732 -1.24179e-08 +0.7344 -1.32514e-08 +0.7368 -1.41334e-08 +0.7392 -1.50661e-08 +0.7416 -1.60518e-08 +0.744 -1.70927e-08 +0.7464 -1.81912e-08 +0.7488 -1.93496e-08 +0.7512 -2.05702e-08 +0.7536 -2.18554e-08 +0.756 -2.32075e-08 +0.7584 -2.46289e-08 +0.7608 -2.61219e-08 +0.7632 -2.76886e-08 +0.7656 -2.93312e-08 +0.768 -3.10519e-08 +0.7704 -3.28526e-08 +0.7728 -3.47352e-08 +0.7752 -3.67012e-08 +0.7776 -3.87523e-08 +0.78 -4.08897e-08 +0.7824 -4.31144e-08 +0.7848 -4.54271e-08 +0.7872 -4.78281e-08 +0.7896 -5.03174e-08 +0.792 -5.28947e-08 +0.7944 -5.55588e-08 +0.7968 -5.83083e-08 +0.7992 -6.11411e-08 +0.8016 -6.40543e-08 +0.804 -6.70443e-08 +0.8064 -7.01066e-08 +0.8088 -7.32359e-08 +0.8112 -7.64257e-08 +0.8136 -7.96683e-08 +0.816 -8.2955e-08 +0.8184 -8.62754e-08 +0.8208 -8.96179e-08 +0.8232 -9.29689e-08 +0.8256 -9.63132e-08 +0.828 -9.96336e-08 +0.8304 -1.02911e-07 +0.8328 -1.06123e-07 +0.8352 -1.09246e-07 +0.8376 -1.12253e-07 +0.84 -1.15114e-07 +0.8424 -1.17795e-07 +0.8448 -1.2026e-07 +0.8472 -1.22469e-07 +0.8496 -1.24378e-07 +0.852 -1.25936e-07 +0.8544 -1.27092e-07 +0.8568 -1.27785e-07 +0.8592 -1.27953e-07 +0.8616 -1.27525e-07 +0.864 -1.26426e-07 +0.8664 -1.24572e-07 +0.8688 -1.21873e-07 +0.8712 -1.18233e-07 +0.8736 -1.13545e-07 +0.876 -1.07695e-07 +0.8784 -1.00558e-07 +0.8808 -9.20018e-08 +0.8832 -8.18809e-08 +0.8856 -7.00398e-08 +0.888 -5.63106e-08 +0.8904 -4.05128e-08 +0.8928 -2.24521e-08 +0.8952 -1.91994e-09 +0.8976 2.13077e-08 +0.9 4.74712e-08 +0.9024 7.68278e-08 +0.9048 1.09653e-07 +0.9072 1.46243e-07 +0.9096 1.86912e-07 +0.912 2.31997e-07 +0.9144 2.81859e-07 +0.9168 3.36881e-07 +0.9192 3.97473e-07 +0.9216 4.64071e-07 +0.924 5.37139e-07 +0.9264 6.17172e-07 +0.9288 7.04694e-07 +0.9312 8.00264e-07 +0.9336 9.04475e-07 +0.936 1.01796e-06 +0.9384 1.14137e-06 +0.9408 1.27543e-06 +0.9432 1.42089e-06 +0.9456 1.57853e-06 +0.948 1.74919e-06 +0.9504 1.93376e-06 +0.9528 2.13319e-06 +0.9552 2.34844e-06 +0.9576 2.58058e-06 +0.96 2.8307e-06 +0.9624 3.09996e-06 +0.9648 3.38958e-06 +0.9672 3.70086e-06 +0.9696 4.03514e-06 +0.972 4.39384e-06 +0.9744 4.77847e-06 +0.9768 5.19059e-06 +0.9792 5.63185e-06 +0.9816 6.10398e-06 +0.984 6.60879e-06 +0.9864 7.14819e-06 +0.9888 7.72416e-06 +0.9912 8.33877e-06 +0.9936 8.99421e-06 +0.996 9.69275e-06 +0.9984 1.04368e-05 +1.0008 1.12287e-05 +1.0032 1.20712e-05 +1.0056 1.29669e-05 +1.008 1.39187e-05 +1.0104 1.49293e-05 +1.0128 1.6002e-05 +1.0152 1.71398e-05 +1.0176 1.83461e-05 +1.02 1.96241e-05 +1.0224 2.09775e-05 +1.0248 2.241e-05 +1.0272 2.39252e-05 +1.0296 2.55271e-05 +1.032 2.72199e-05 +1.0344 2.90076e-05 +1.0368 3.08946e-05 +1.0392 3.28853e-05 +1.0416 3.49844e-05 +1.044 3.71966e-05 +1.0464 3.95268e-05 +1.0488 4.198e-05 +1.0512 4.45613e-05 +1.0536 4.72759e-05 +1.056 5.01294e-05 +1.0584 5.31273e-05 +1.0608 5.62751e-05 +1.0632 5.95787e-05 +1.0656 6.3044e-05 +1.068 6.66771e-05 +1.0704 7.04839e-05 +1.0728 7.44707e-05 +1.0752 7.86439e-05 +1.0776 8.30098e-05 +1.08 8.7575e-05 +1.0824 9.23458e-05 +1.0848 9.73289e-05 +1.0872 0.000102531 +1.0896 0.000107959 +1.092 0.000113618 +1.0944 0.000119517 +1.0968 0.000125661 +1.0992 0.000132058 +1.1016 0.000138713 +1.104 0.000145633 +1.1064 0.000152824 +1.1088 0.000160294 +1.1112 0.000168046 +1.1136 0.000176089 +1.116 0.000184427 +1.1184 0.000193065 +1.1208 0.000202009 +1.1232 0.000211264 +1.1256 0.000220834 +1.128 0.000230723 +1.1304 0.000240934 +1.1328 0.000251472 +1.1352 0.000262338 +1.1376 0.000273535 +1.14 0.000285064 +1.1424 0.000296926 +1.1448 0.00030912 +1.1472 0.000321646 +1.1496 0.000334502 +1.152 0.000347686 +1.1544 0.000361193 +1.1568 0.00037502 +1.1592 0.000389161 +1.1616 0.000403607 +1.164 0.000418351 +1.1664 0.000433384 +1.1688 0.000448693 +1.1712 0.000464267 +1.1736 0.00048009 +1.176 0.000496146 +1.1784 0.000512417 +1.1808 0.000528884 +1.1832 0.000545523 +1.1856 0.000562311 +1.188 0.000579221 +1.1904 0.000596224 +1.1928 0.000613288 +1.1952 0.00063038 +1.1976 0.000647461 +1.2 0.000664493 +1.2024 0.000681432 +1.2048 0.000698232 +1.2072 0.000714843 +1.2096 0.000731214 +1.212 0.000747286 +1.2144 0.000763 +1.2168 0.000778292 +1.2192 0.000793093 +1.2216 0.000807331 +1.224 0.000820929 +1.2264 0.000833806 +1.2288 0.000845875 +1.2312 0.000857046 +1.2336 0.000867223 +1.236 0.000876305 +1.2384 0.000884185 +1.2408 0.000890751 +1.2432 0.000895887 +1.2456 0.000899469 +1.248 0.000901366 +1.2504 0.000901445 +1.2528 0.000899562 +1.2552 0.00089557 +1.2576 0.000889314 +1.26 0.000880632 +1.2624 0.000869356 +1.2648 0.000855309 +1.2672 0.000838309 +1.2696 0.000818166 +1.272 0.000794681 +1.2744 0.00076765 +1.2768 0.000736859 +1.2792 0.000702087 +1.2816 0.000663105 +1.284 0.000619676 +1.2864 0.000571555 +1.2888 0.000518487 +1.2912 0.000460212 +1.2936 0.000396458 +1.296 0.000326948 +1.2984 0.000251393 +1.3008 0.000169498 +1.3032 8.09577e-05 +1.3056 -1.45397e-05 +1.308 -0.000117316 +1.3104 -0.000227702 +1.3128 -0.000346035 +1.3152 -0.000472663 +1.3176 -0.000607941 +1.32 -0.000752233 +1.3224 -0.000905909 +1.3248 -0.00106935 +1.3272 -0.00124294 +1.3296 -0.00142709 +1.332 -0.00162218 +1.3344 -0.00182863 +1.3368 -0.00204686 +1.3392 -0.00227729 +1.3416 -0.00252036 +1.344 -0.00277649 +1.3464 -0.00304613 +1.3488 -0.00332973 +1.3512 -0.00362774 +1.3536 -0.00394062 +1.356 -0.00426883 +1.3584 -0.00461283 +1.3608 -0.00497309 +1.3632 -0.00535009 +1.3656 -0.0057443 +1.368 -0.00615619 +1.3704 -0.00658623 +1.3728 -0.00703491 +1.3752 -0.00750269 +1.3776 -0.00799005 +1.38 -0.00849747 +1.3824 -0.0090254 +1.3848 -0.00957432 +1.3872 -0.0101447 +1.3896 -0.0107369 +1.392 -0.0113516 +1.3944 -0.011989 +1.3968 -0.0126496 +1.3992 -0.0133338 +1.4016 -0.0140422 +1.404 -0.014775 +1.4064 -0.0155326 +1.4088 -0.0163154 +1.4112 -0.0171239 +1.4136 -0.0179582 +1.416 -0.0188189 +1.4184 -0.019706 +1.4208 -0.0206201 +1.4232 -0.0215612 +1.4256 -0.0225297 +1.428 -0.0235258 +1.4304 -0.0245496 +1.4328 -0.0256014 +1.4352 -0.0266813 +1.4376 -0.0277894 +1.44 -0.0289257 +1.4424 -0.0300903 +1.4448 -0.0312833 +1.4472 -0.0325046 +1.4496 -0.0337542 +1.452 -0.0350318 +1.4544 -0.0363376 +1.4568 -0.0376711 +1.4592 -0.0390323 +1.4616 -0.0404208 +1.464 -0.0418364 +1.4664 -0.0432786 +1.4688 -0.0447472 +1.4712 -0.0462415 +1.4736 -0.0477612 +1.476 -0.0493057 +1.4784 -0.0508743 +1.4808 -0.0524664 +1.4832 -0.0540812 +1.4856 -0.0557181 +1.488 -0.0573761 +1.4904 -0.0590543 +1.4928 -0.0607518 +1.4952 -0.0624676 +1.4976 -0.0642006 +1.5 -0.0659496 +1.5024 -0.0677135 +1.5048 -0.0694909 +1.5072 -0.0712806 +1.5096 -0.073081 +1.512 -0.0748908 +1.5144 -0.0767083 +1.5168 -0.0785321 +1.5192 -0.0803603 +1.5216 -0.0821914 +1.524 -0.0840233 +1.5264 -0.0858544 +1.5288 -0.0876826 +1.5312 -0.0895058 +1.5336 -0.0913221 +1.536 -0.0931293 +1.5384 -0.0949251 +1.5408 -0.0967074 +1.5432 -0.0984736 +1.5456 -0.100221 +1.548 -0.101948 +1.5504 -0.103652 +1.5528 -0.10533 +1.5552 -0.106979 +1.5576 -0.108596 +1.56 -0.11018 +1.5624 -0.111726 +1.5648 -0.113233 +1.5672 -0.114697 +1.5696 -0.116116 +1.572 -0.117485 +1.5744 -0.118803 +1.5768 -0.120066 +1.5792 -0.121271 +1.5816 -0.122415 +1.584 -0.123494 +1.5864 -0.124506 +1.5888 -0.125447 +1.5912 -0.126314 +1.5936 -0.127104 +1.596 -0.127813 +1.5984 -0.128437 +1.6008 -0.128975 +1.6032 -0.129422 +1.6056 -0.129775 +1.608 -0.13003 +1.6104 -0.130185 +1.6128 -0.130236 +1.6152 -0.13018 +1.6176 -0.130014 +1.62 -0.129733 +1.6224 -0.129337 +1.6248 -0.12882 +1.6272 -0.12818 +1.6296 -0.127414 +1.632 -0.126519 +1.6344 -0.125492 +1.6368 -0.12433 +1.6392 -0.123031 +1.6416 -0.121591 +1.644 -0.120008 +1.6464 -0.118279 +1.6488 -0.116402 +1.6512 -0.114375 +1.6536 -0.112195 +1.656 -0.10986 +1.6584 -0.107368 +1.6608 -0.104717 +1.6632 -0.101905 +1.6656 -0.0989311 +1.668 -0.0957929 +1.6704 -0.0924891 +1.6728 -0.0890186 +1.6752 -0.0853801 +1.6776 -0.0815726 +1.68 -0.0775953 +1.6824 -0.0734475 +1.6848 -0.0691287 +1.6872 -0.0646385 +1.6896 -0.0599766 +1.692 -0.0551431 +1.6944 -0.050138 +1.6968 -0.0449618 +1.6992 -0.039615 +1.7016 -0.0340981 +1.704 -0.0284122 +1.7064 -0.0225582 +1.7088 -0.0165375 +1.7112 -0.0103515 +1.7136 -0.00400178 +1.716 0.00250972 +1.7184 0.00918099 +1.7208 0.0160098 +1.7232 0.0229936 +1.7256 0.0301299 +1.728 0.0374157 +1.7304 0.0448481 +1.7328 0.0524238 +1.7352 0.0601393 +1.7376 0.067991 +1.74 0.0759751 +1.7424 0.0840875 +1.7448 0.092324 +1.7472 0.10068 +1.7496 0.109151 +1.752 0.117733 +1.7544 0.12642 +1.7568 0.135207 +1.7592 0.144089 +1.7616 0.15306 +1.764 0.162114 +1.7664 0.171247 +1.7688 0.180451 +1.7712 0.189722 +1.7736 0.199051 +1.776 0.208434 +1.7784 0.217863 +1.7808 0.227331 +1.7832 0.236833 +1.7856 0.24636 +1.788 0.255907 +1.7904 0.265465 +1.7928 0.275028 +1.7952 0.284588 +1.7976 0.294138 +1.8 0.303671 +1.8024 0.313178 +1.8048 0.322652 +1.8072 0.332086 +1.8096 0.341472 +1.812 0.350803 +1.8144 0.36007 +1.8168 0.369265 +1.8192 0.378382 +1.8216 0.387412 +1.824 0.396348 +1.8264 0.405182 +1.8288 0.413906 +1.8312 0.422513 +1.8336 0.430996 +1.836 0.439346 +1.8384 0.447556 +1.8408 0.455619 +1.8432 0.463528 +1.8456 0.471276 +1.848 0.478856 +1.8504 0.48626 +1.8528 0.493483 +1.8552 0.500516 +1.8576 0.507355 +1.86 0.513992 +1.8624 0.520422 +1.8648 0.526638 +1.8672 0.532635 +1.8696 0.538407 +1.872 0.543948 +1.8744 0.549254 +1.8768 0.554318 +1.8792 0.559138 +1.8816 0.563707 +1.884 0.568022 +1.8864 0.572078 +1.8888 0.575872 +1.8912 0.5794 +1.8936 0.582658 +1.896 0.585643 +1.8984 0.588353 +1.9008 0.590785 +1.9032 0.592936 +1.9056 0.594805 +1.908 0.596389 +1.9104 0.597687 +1.9128 0.598698 +1.9152 0.599421 +1.9176 0.599855 +1.92 0.6 +1.9224 0.599855 +1.9248 0.599421 +1.9272 0.598698 +1.9296 0.597687 +1.932 0.596389 +1.9344 0.594805 +1.9368 0.592936 +1.9392 0.590785 +1.9416 0.588353 +1.944 0.585643 +1.9464 0.582658 +1.9488 0.5794 +1.9512 0.575872 +1.9536 0.572078 +1.956 0.568022 +1.9584 0.563707 +1.9608 0.559138 +1.9632 0.554318 +1.9656 0.549254 +1.968 0.543948 +1.9704 0.538407 +1.9728 0.532635 +1.9752 0.526638 +1.9776 0.520422 +1.98 0.513992 +1.9824 0.507355 +1.9848 0.500516 +1.9872 0.493483 +1.9896 0.48626 +1.992 0.478856 +1.9944 0.471276 +1.9968 0.463528 +1.9992 0.455619 +2.0016 0.447556 +2.004 0.439346 +2.0064 0.430996 +2.0088 0.422513 +2.0112 0.413906 +2.0136 0.405182 +2.016 0.396348 +2.0184 0.387412 +2.0208 0.378382 +2.0232 0.369265 +2.0256 0.36007 +2.028 0.350803 +2.0304 0.341472 +2.0328 0.332086 +2.0352 0.322652 +2.0376 0.313178 +2.04 0.303671 +2.0424 0.294138 +2.0448 0.284588 +2.0472 0.275028 +2.0496 0.265465 +2.052 0.255907 +2.0544 0.24636 +2.0568 0.236833 +2.0592 0.227331 +2.0616 0.217863 +2.064 0.208434 +2.0664 0.199051 +2.0688 0.189722 +2.0712 0.180451 +2.0736 0.171247 +2.076 0.162114 +2.0784 0.15306 +2.0808 0.144089 +2.0832 0.135207 +2.0856 0.12642 +2.088 0.117733 +2.0904 0.109151 +2.0928 0.10068 +2.0952 0.092324 +2.0976 0.0840875 +2.1 0.0759751 +2.1024 0.067991 +2.1048 0.0601393 +2.1072 0.0524238 +2.1096 0.0448481 +2.112 0.0374157 +2.1144 0.0301299 +2.1168 0.0229936 +2.1192 0.0160098 +2.1216 0.00918099 +2.124 0.00250972 +2.1264 -0.00400178 +2.1288 -0.0103515 +2.1312 -0.0165375 +2.1336 -0.0225582 +2.136 -0.0284122 +2.1384 -0.0340981 +2.1408 -0.039615 +2.1432 -0.0449618 +2.1456 -0.050138 +2.148 -0.0551431 +2.1504 -0.0599766 +2.1528 -0.0646385 +2.1552 -0.0691287 +2.1576 -0.0734475 +2.16 -0.0775953 +2.1624 -0.0815726 +2.1648 -0.0853801 +2.1672 -0.0890186 +2.1696 -0.0924891 +2.172 -0.0957929 +2.1744 -0.0989311 +2.1768 -0.101905 +2.1792 -0.104717 +2.1816 -0.107368 +2.184 -0.10986 +2.1864 -0.112195 +2.1888 -0.114375 +2.1912 -0.116402 +2.1936 -0.118279 +2.196 -0.120008 +2.1984 -0.121591 +2.2008 -0.123031 +2.2032 -0.12433 +2.2056 -0.125492 +2.208 -0.126519 +2.2104 -0.127414 +2.2128 -0.12818 +2.2152 -0.12882 +2.2176 -0.129337 +2.22 -0.129733 +2.2224 -0.130014 +2.2248 -0.13018 +2.2272 -0.130236 +2.2296 -0.130185 +2.232 -0.13003 +2.2344 -0.129775 +2.2368 -0.129422 +2.2392 -0.128975 +2.2416 -0.128437 +2.244 -0.127813 +2.2464 -0.127104 +2.2488 -0.126314 +2.2512 -0.125447 +2.2536 -0.124506 +2.256 -0.123494 +2.2584 -0.122415 +2.2608 -0.121271 +2.2632 -0.120066 +2.2656 -0.118803 +2.268 -0.117485 +2.2704 -0.116116 +2.2728 -0.114697 +2.2752 -0.113233 +2.2776 -0.111726 +2.28 -0.11018 +2.2824 -0.108596 +2.2848 -0.106979 +2.2872 -0.10533 +2.2896 -0.103652 +2.292 -0.101948 +2.2944 -0.100221 +2.2968 -0.0984736 +2.2992 -0.0967074 +2.3016 -0.0949251 +2.304 -0.0931293 +2.3064 -0.0913221 +2.3088 -0.0895058 +2.3112 -0.0876826 +2.3136 -0.0858544 +2.316 -0.0840233 +2.3184 -0.0821914 +2.3208 -0.0803603 +2.3232 -0.0785321 +2.3256 -0.0767083 +2.328 -0.0748908 +2.3304 -0.073081 +2.3328 -0.0712806 +2.3352 -0.0694909 +2.3376 -0.0677135 +2.34 -0.0659496 +2.3424 -0.0642006 +2.3448 -0.0624676 +2.3472 -0.0607518 +2.3496 -0.0590543 +2.352 -0.0573761 +2.3544 -0.0557181 +2.3568 -0.0540812 +2.3592 -0.0524664 +2.3616 -0.0508743 +2.364 -0.0493057 +2.3664 -0.0477612 +2.3688 -0.0462415 +2.3712 -0.0447472 +2.3736 -0.0432786 +2.376 -0.0418364 +2.3784 -0.0404208 +2.3808 -0.0390323 +2.3832 -0.0376711 +2.3856 -0.0363376 +2.388 -0.0350318 +2.3904 -0.0337542 +2.3928 -0.0325046 +2.3952 -0.0312833 +2.3976 -0.0300903 +2.4 -0.0289257 +2.4024 -0.0277894 +2.4048 -0.0266813 +2.4072 -0.0256014 +2.4096 -0.0245496 +2.412 -0.0235258 +2.4144 -0.0225297 +2.4168 -0.0215612 +2.4192 -0.0206201 +2.4216 -0.019706 +2.424 -0.0188189 +2.4264 -0.0179582 +2.4288 -0.0171239 +2.4312 -0.0163154 +2.4336 -0.0155326 +2.436 -0.014775 +2.4384 -0.0140422 +2.4408 -0.0133338 +2.4432 -0.0126496 +2.4456 -0.011989 +2.448 -0.0113516 +2.4504 -0.0107369 +2.4528 -0.0101447 +2.4552 -0.00957432 +2.4576 -0.0090254 +2.46 -0.00849747 +2.4624 -0.00799005 +2.4648 -0.00750269 +2.4672 -0.00703491 +2.4696 -0.00658623 +2.472 -0.00615619 +2.4744 -0.0057443 +2.4768 -0.00535009 +2.4792 -0.00497309 +2.4816 -0.00461283 +2.484 -0.00426883 +2.4864 -0.00394062 +2.4888 -0.00362774 +2.4912 -0.00332973 +2.4936 -0.00304613 +2.496 -0.00277649 +2.4984 -0.00252036 +2.5008 -0.00227729 +2.5032 -0.00204686 +2.5056 -0.00182863 +2.508 -0.00162218 +2.5104 -0.00142709 +2.5128 -0.00124294 +2.5152 -0.00106935 +2.5176 -0.000905909 +2.52 -0.000752233 +2.5224 -0.000607941 +2.5248 -0.000472663 +2.5272 -0.000346035 +2.5296 -0.000227702 +2.532 -0.000117316 +2.5344 -1.45397e-05 +2.5368 8.09577e-05 +2.5392 0.000169498 +2.5416 0.000251393 +2.544 0.000326948 +2.5464 0.000396458 +2.5488 0.000460212 +2.5512 0.000518487 +2.5536 0.000571555 +2.556 0.000619676 +2.5584 0.000663105 +2.5608 0.000702087 +2.5632 0.000736859 +2.5656 0.00076765 +2.568 0.000794681 +2.5704 0.000818166 +2.5728 0.000838309 +2.5752 0.000855309 +2.5776 0.000869356 +2.58 0.000880632 +2.5824 0.000889314 +2.5848 0.00089557 +2.5872 0.000899562 +2.5896 0.000901445 +2.592 0.000901366 +2.5944 0.000899469 +2.5968 0.000895887 +2.5992 0.000890751 +2.6016 0.000884185 +2.604 0.000876305 +2.6064 0.000867223 +2.6088 0.000857046 +2.6112 0.000845875 +2.6136 0.000833806 +2.616 0.000820929 +2.6184 0.000807331 +2.6208 0.000793093 +2.6232 0.000778292 +2.6256 0.000763 +2.628 0.000747286 +2.6304 0.000731214 +2.6328 0.000714843 +2.6352 0.000698232 +2.6376 0.000681432 +2.64 0.000664493 +2.6424 0.000647461 +2.6448 0.00063038 +2.6472 0.000613288 +2.6496 0.000596224 +2.652 0.000579221 +2.6544 0.000562311 +2.6568 0.000545523 +2.6592 0.000528884 +2.6616 0.000512417 +2.664 0.000496146 +2.6664 0.00048009 +2.6688 0.000464267 +2.6712 0.000448693 +2.6736 0.000433384 +2.676 0.000418351 +2.6784 0.000403607 +2.6808 0.000389161 +2.6832 0.00037502 +2.6856 0.000361193 +2.688 0.000347686 +2.6904 0.000334502 +2.6928 0.000321646 +2.6952 0.00030912 +2.6976 0.000296926 +2.7 0.000285064 +2.7024 0.000273535 +2.7048 0.000262338 +2.7072 0.000251472 +2.7096 0.000240934 +2.712 0.000230723 +2.7144 0.000220834 +2.7168 0.000211264 +2.7192 0.000202009 +2.7216 0.000193065 +2.724 0.000184427 +2.7264 0.000176089 +2.7288 0.000168046 +2.7312 0.000160294 +2.7336 0.000152824 +2.736 0.000145633 +2.7384 0.000138713 +2.7408 0.000132058 +2.7432 0.000125661 +2.7456 0.000119517 +2.748 0.000113618 +2.7504 0.000107959 +2.7528 0.000102531 +2.7552 9.73289e-05 +2.7576 9.23458e-05 +2.76 8.7575e-05 +2.7624 8.30098e-05 +2.7648 7.86439e-05 +2.7672 7.44707e-05 +2.7696 7.04839e-05 +2.772 6.66771e-05 +2.7744 6.3044e-05 +2.7768 5.95787e-05 +2.7792 5.62751e-05 +2.7816 5.31273e-05 +2.784 5.01294e-05 +2.7864 4.72759e-05 +2.7888 4.45613e-05 +2.7912 4.198e-05 +2.7936 3.95268e-05 +2.796 3.71966e-05 +2.7984 3.49844e-05 +2.8008 3.28853e-05 +2.8032 3.08946e-05 +2.8056 2.90076e-05 +2.808 2.72199e-05 +2.8104 2.55271e-05 +2.8128 2.39252e-05 +2.8152 2.241e-05 +2.8176 2.09775e-05 +2.82 1.96241e-05 +2.8224 1.83461e-05 +2.8248 1.71398e-05 +2.8272 1.6002e-05 +2.8296 1.49293e-05 +2.832 1.39187e-05 +2.8344 1.29669e-05 +2.8368 1.20712e-05 +2.8392 1.12287e-05 +2.8416 1.04368e-05 +2.844 9.69275e-06 +2.8464 8.99421e-06 +2.8488 8.33877e-06 +2.8512 7.72416e-06 +2.8536 7.14819e-06 +2.856 6.60879e-06 +2.8584 6.10398e-06 +2.8608 5.63185e-06 +2.8632 5.19059e-06 +2.8656 4.77847e-06 +2.868 4.39384e-06 +2.8704 4.03514e-06 +2.8728 3.70086e-06 +2.8752 3.38958e-06 +2.8776 3.09996e-06 +2.88 2.8307e-06 +2.8824 2.58058e-06 +2.8848 2.34844e-06 +2.8872 2.13319e-06 +2.8896 1.93376e-06 +2.892 1.74919e-06 +2.8944 1.57853e-06 +2.8968 1.42089e-06 +2.8992 1.27543e-06 +2.9016 1.14137e-06 +2.904 1.01796e-06 +2.9064 9.04475e-07 +2.9088 8.00264e-07 +2.9112 7.04694e-07 +2.9136 6.17172e-07 +2.916 5.37139e-07 +2.9184 4.64071e-07 +2.9208 3.97473e-07 +2.9232 3.36881e-07 +2.9256 2.81859e-07 +2.928 2.31997e-07 +2.9304 1.86912e-07 +2.9328 1.46243e-07 +2.9352 1.09653e-07 +2.9376 7.68278e-08 +2.94 4.74712e-08 +2.9424 2.13077e-08 +2.9448 -1.91994e-09 +2.9472 -2.24521e-08 +2.9496 -4.05128e-08 +2.952 -5.63106e-08 +2.9544 -7.00398e-08 +2.9568 -8.18809e-08 +2.9592 -9.20018e-08 +2.9616 -1.00558e-07 +2.964 -1.07695e-07 +2.9664 -1.13545e-07 +2.9688 -1.18233e-07 +2.9712 -1.21873e-07 +2.9736 -1.24572e-07 +2.976 -1.26426e-07 +2.9784 -1.27525e-07 +2.9808 -1.27953e-07 +2.9832 -1.27785e-07 +2.9856 -1.27092e-07 +2.988 -1.25936e-07 +2.9904 -1.24378e-07 +2.9928 -1.22469e-07 +2.9952 -1.2026e-07 +2.9976 -1.17795e-07 +3 -1.15114e-07 +3.0024 -1.12253e-07 +3.0048 -1.09246e-07 +3.0072 -1.06123e-07 +3.0096 -1.02911e-07 +3.012 -9.96336e-08 +3.0144 -9.63132e-08 +3.0168 -9.29689e-08 +3.0192 -8.96179e-08 +3.0216 -8.62754e-08 +3.024 -8.2955e-08 +3.0264 -7.96683e-08 +3.0288 -7.64257e-08 +3.0312 -7.32359e-08 +3.0336 -7.01066e-08 +3.036 -6.70443e-08 +3.0384 -6.40543e-08 +3.0408 -6.11411e-08 +3.0432 -5.83083e-08 +3.0456 -5.55588e-08 +3.048 -5.28947e-08 +3.0504 -5.03174e-08 +3.0528 -4.78281e-08 +3.0552 -4.54271e-08 +3.0576 -4.31144e-08 +3.06 -4.08897e-08 +3.0624 -3.87523e-08 +3.0648 -3.67012e-08 +3.0672 -3.47352e-08 +3.0696 -3.28526e-08 +3.072 -3.10519e-08 +3.0744 -2.93312e-08 +3.0768 -2.76886e-08 +3.0792 -2.61219e-08 +3.0816 -2.46289e-08 +3.084 -2.32075e-08 +3.0864 -2.18554e-08 +3.0888 -2.05702e-08 +3.0912 -1.93496e-08 +3.0936 -1.81912e-08 +3.096 -1.70927e-08 +3.0984 -1.60518e-08 +3.1008 -1.50661e-08 +3.1032 -1.41334e-08 +3.1056 -1.32514e-08 +3.108 -1.24179e-08 +3.1104 -1.16309e-08 +3.1128 -1.08881e-08 +3.1152 -1.01875e-08 +3.1176 -9.52722e-09 +3.12 -8.90521e-09 +3.1224 -8.31966e-09 +3.1248 -7.76874e-09 +3.1272 -7.25071e-09 +3.1296 -6.76389e-09 +3.132 -6.30667e-09 +3.1344 -5.87747e-09 +3.1368 -5.47482e-09 +3.1392 -5.09728e-09 +3.1416 -4.74347e-09 +3.144 -4.41209e-09 +3.1464 -4.10188e-09 +3.1488 -3.81163e-09 +3.1512 -3.54022e-09 +3.1536 -3.28654e-09 +3.156 -3.04957e-09 +3.1584 -2.82832e-09 +3.1608 -2.62185e-09 +3.1632 -2.42928e-09 +3.1656 -2.24975e-09 +3.168 -2.08248e-09 +3.1704 -1.9267e-09 +3.1728 -1.7817e-09 +3.1752 -1.6468e-09 +3.1776 -1.52136e-09 +3.18 -1.40477e-09 +3.1824 -1.29646e-09 +3.1848 -1.19591e-09 +3.1872 -1.10259e-09 +3.1896 -1.01603e-09 +3.192 -9.35783e-10 +3.1944 -8.61425e-10 +3.1968 -7.92559e-10 +3.1992 -7.28812e-10 +3.2016 -6.69832e-10 +3.204 -6.15291e-10 +3.2064 -5.6488e-10 +3.2088 -5.18312e-10 +3.2112 -4.75315e-10 +3.2136 -4.35635e-10 +3.216 -3.99037e-10 +3.2184 -3.65299e-10 +3.2208 -3.34213e-10 +3.2232 -3.05587e-10 +3.2256 -2.7924e-10 +3.228 -2.55004e-10 +3.2304 -2.32722e-10 +3.2328 -2.12248e-10 +3.2352 -1.93446e-10 +3.2376 -1.76189e-10 +3.24 -1.60359e-10 +3.2424 -1.45846e-10 +3.2448 -1.3255e-10 +3.2472 -1.20375e-10 +3.2496 -1.09234e-10 +3.252 -9.90446e-11 +3.2544 -8.97322e-11 +3.2568 -8.12264e-11 +3.2592 -7.34626e-11 +3.2616 -6.63808e-11 +3.264 -5.99254e-11 +3.2664 -5.40452e-11 +3.2688 -4.86927e-11 +3.2712 -4.38241e-11 +3.2736 -3.9399e-11 +3.276 -3.53801e-11 +3.2784 -3.17329e-11 +3.2808 -2.84258e-11 +3.2832 -2.54296e-11 +3.2856 -2.27174e-11 +3.288 -2.02644e-11 +3.2904 -1.8048e-11 +3.2928 -1.60472e-11 +3.2952 -1.42428e-11 +3.2976 -1.26173e-11 +3.3 -1.11544e-11 +3.3024 -9.8394e-12 +3.3048 -8.65869e-12 +3.3072 -7.59987e-12 +3.3096 -6.65157e-12 +3.312 -5.8034e-12 +3.3144 -5.04588e-12 +3.3168 -4.37033e-12 +3.3192 -3.76885e-12 +3.3216 -3.23422e-12 +3.324 -2.75989e-12 +3.3264 -2.33986e-12 +3.3288 -1.96871e-12 +3.3312 -1.64147e-12 +3.3336 -1.35367e-12 +3.336 -1.10122e-12 +3.3384 -8.80422e-13 +3.3408 -6.87934e-13 +3.3432 -5.20721e-13 +3.3456 -3.7604e-13 +3.348 -2.51415e-13 +3.3504 -1.4461e-13 +3.3528 -5.36088e-14 +3.3552 2.3405e-14 +3.3576 8.80648e-14 +3.36 1.41839e-13 +3.3624 1.86045e-13 +3.3648 2.21863e-13 +3.3672 2.50353e-13 +3.3696 2.72458e-13 +3.372 2.89022e-13 +3.3744 3.00799e-13 +3.3768 3.08455e-13 +3.3792 3.12587e-13 +3.3816 3.1372e-13 +3.384 3.12321e-13 +3.3864 3.088e-13 +3.3888 3.03521e-13 +3.3912 2.96801e-13 +3.3936 2.88919e-13 +3.396 2.80117e-13 +3.3984 2.70609e-13 +3.4008 2.60577e-13 +3.4032 2.5018e-13 +3.4056 2.39554e-13 +3.408 2.28815e-13 +3.4104 2.18062e-13 +3.4128 2.07379e-13 +3.4152 1.96833e-13 +3.4176 1.86484e-13 +3.42 1.76378e-13 +3.4224 1.66552e-13 +3.4248 1.57036e-13 +3.4272 1.47853e-13 +3.4296 1.39018e-13 +3.432 1.30544e-13 +3.4344 1.22436e-13 +3.4368 1.14698e-13 +3.4392 1.07329e-13 +3.4416 1.00327e-13 +3.444 9.36849e-14 +3.4464 8.73964e-14 +3.4488 8.14526e-14 +3.4512 7.58435e-14 +3.4536 7.05581e-14 +3.456 6.55849e-14 +3.4584 6.09115e-14 +3.4608 5.65257e-14 +3.4632 5.24145e-14 +3.4656 4.85654e-14 +3.468 4.49656e-14 +3.4704 4.16026e-14 +3.4728 3.84639e-14 +3.4752 3.55375e-14 +3.4776 3.28116e-14 +3.48 3.02749e-14 +3.4824 2.79162e-14 +3.4848 2.57249e-14 +3.4872 2.36909e-14 +3.4896 2.18044e-14 +3.492 2.0056e-14 +3.4944 1.8437e-14 +3.4968 1.69387e-14 +3.4992 1.55533e-14 +3.5016 1.42731e-14 +3.504 1.3091e-14 +3.5064 1.20001e-14 +3.5088 1.09942e-14 +3.5112 1.00672e-14 +3.5136 9.21339e-15 +3.516 8.42756e-15 +3.5184 7.70473e-15 +3.5208 7.04025e-15 +3.5232 6.42977e-15 +3.5256 5.86924e-15 +3.528 5.35486e-15 +3.5304 4.8831e-15 +3.5328 4.45068e-15 +3.5352 4.05454e-15 +3.5376 3.69183e-15 +3.54 3.35992e-15 +3.5424 3.05635e-15 +3.5448 2.77884e-15 +3.5472 2.52531e-15 +3.5496 2.29379e-15 +3.552 2.08249e-15 +3.5544 1.88974e-15 +3.5568 1.714e-15 +3.5592 1.55386e-15 +3.5616 1.408e-15 +3.564 1.27521e-15 +3.5664 1.15439e-15 +3.5688 1.04452e-15 +3.5712 9.44639e-16 +3.5736 8.53898e-16 +3.576 7.71498e-16 +3.5784 6.96709e-16 +3.5808 6.28862e-16 +3.5832 5.67343e-16 +3.5856 5.11589e-16 +3.588 4.61086e-16 +3.5904 4.1536e-16 +3.5928 3.73982e-16 +3.5952 3.36555e-16 +3.5976 3.02719e-16 +3.6 2.72146e-16 +3.6024 2.44533e-16 +3.6048 2.19608e-16 +3.6072 1.97119e-16 +3.6096 1.76839e-16 +3.612 1.5856e-16 +3.6144 1.42093e-16 +3.6168 1.27266e-16 +3.6192 1.13923e-16 +3.6216 1.01921e-16 +3.624 9.11315e-17 +3.6264 8.14366e-17 +3.6288 7.27302e-17 +3.6312 6.49156e-17 +3.6336 5.79053e-17 +3.636 5.162e-17 +3.6384 4.59878e-17 +3.6408 4.09438e-17 +3.6432 3.64289e-17 +3.6456 3.23902e-17 +3.648 2.87794e-17 +3.6504 2.55532e-17 +3.6528 2.26722e-17 +3.6552 2.01012e-17 +3.6576 1.78083e-17 +3.66 1.57646e-17 +3.6624 1.39442e-17 +3.6648 1.23239e-17 +3.6672 1.08825e-17 +3.6696 9.60123e-18 +3.672 8.46309e-18 +3.6744 7.45282e-18 +3.6768 6.5567e-18 +3.6792 5.76245e-18 +3.6816 5.05902e-18 +3.684 4.43654e-18 +3.6864 3.88613e-18 +3.6888 3.39988e-18 +3.6912 2.97067e-18 +3.6936 2.59216e-18 +3.696 2.25867e-18 +3.6984 1.96514e-18 +3.7008 1.70704e-18 +3.7032 1.48032e-18 +3.7056 1.2814e-18 +3.708 1.10706e-18 +3.7104 9.54452e-19 +3.7128 8.21033e-19 +3.7152 7.04544e-19 +3.7176 6.02979e-19 +3.72 5.14557e-19 +3.7224 4.37697e-19 +3.7248 3.70997e-19 +3.7272 3.13217e-19 +3.7296 2.6326e-19 +3.732 2.20152e-19 +3.7344 1.83037e-19 +3.7368 1.51158e-19 +3.7392 1.23845e-19 +3.7416 1.00511e-19 +3.744 8.06381e-20 +3.7464 6.37703e-20 +3.7488 4.95077e-20 +3.7512 3.74994e-20 +3.7536 2.74378e-20 +3.756 1.90538e-20 +3.7584 1.21121e-20 +3.7608 6.40731e-21 +3.7632 1.76037e-21 +3.7656 -1.98453e-21 +3.768 -4.96279e-21 +3.7704 -7.2919e-21 +3.7728 -9.07356e-21 +3.7752 -1.03957e-20 +3.7776 -1.13341e-20 +3.78 -1.1954e-20 +3.7824 -1.23115e-20 +3.7848 -1.24544e-20 +3.7872 -1.24238e-20 +3.7896 -1.22543e-20 +3.792 -1.19757e-20 +3.7944 -1.16128e-20 +3.7968 -1.11866e-20 +3.7992 -1.07146e-20 +3.8016 -1.02115e-20 +3.804 -9.6893e-21 +3.8064 -9.15788e-21 +3.8088 -8.6253e-21 +3.8112 -8.098e-21 +3.8136 -7.58109e-21 +3.816 -7.07854e-21 +3.8184 -6.59336e-21 +3.8208 -6.12777e-21 +3.8232 -5.68331e-21 +3.8256 -5.26097e-21 +3.828 -4.86129e-21 +3.8304 -4.48442e-21 +3.8328 -4.13024e-21 +3.8352 -3.79837e-21 +3.8376 -3.48824e-21 +3.84 -3.19916e-21 +3.8424 -2.93032e-21 +3.8448 -2.68082e-21 +3.8472 -2.44973e-21 +3.8496 -2.2361e-21 +3.852 -2.03893e-21 +3.8544 -1.85727e-21 +3.8568 -1.69013e-21 +3.8592 -1.53659e-21 +3.8616 -1.39573e-21 +3.864 -1.26666e-21 +3.8664 -1.14856e-21 +3.8688 -1.04061e-21 +3.8712 -9.42046e-22 +3.8736 -8.52158e-22 +3.876 -7.70264e-22 +3.8784 -6.95728e-22 +3.8808 -6.27953e-22 +3.8832 -5.66382e-22 +3.8856 -5.10499e-22 +3.888 -4.5982e-22 +3.8904 -4.13901e-22 +3.8928 -3.72328e-22 +3.8952 -3.34719e-22 +3.8976 -3.00723e-22 +3.9 -2.70015e-22 +3.9024 -2.42297e-22 +3.9048 -2.17297e-22 +3.9072 -1.94763e-22 +3.9096 -1.74466e-22 +3.912 -1.56196e-22 +3.9144 -1.39762e-22 +3.9168 -1.24988e-22 +3.9192 -1.11715e-22 +3.9216 -9.97975e-23 +3.924 -8.91042e-23 +3.9264 -7.95148e-23 +3.9288 -7.09204e-23 +3.9312 -6.32222e-23 +3.9336 -5.63307e-23 +3.936 -5.01649e-23 +3.9384 -4.46515e-23 +3.9408 -3.9724e-23 +3.9432 -3.53227e-23 +3.9456 -3.13934e-23 +3.948 -2.78875e-23 +3.9504 -2.47609e-23 +3.9528 -2.19741e-23 +3.9552 -1.94914e-23 +3.9576 -1.72809e-23 +3.96 -1.53136e-23 +3.9624 -1.35636e-23 +3.9648 -1.20079e-23 +3.9672 -1.06255e-23 +3.9696 -9.39765e-24 +3.972 -8.3077e-24 +3.9744 -7.34062e-24 +3.9768 -6.48299e-24 +3.9792 -5.72279e-24 +3.9816 -5.04928e-24 +3.984 -4.45288e-24 +3.9864 -3.925e-24 +3.9888 -3.45802e-24 +3.9912 -3.0451e-24 +3.9936 -2.68017e-24 +3.996 -2.35781e-24 +3.9984 -2.07319e-24 +4.0008 -1.82201e-24 +4.0032 -1.60046e-24 +4.0056 -1.40514e-24 +4.008 -1.23303e-24 +4.0104 -1.08144e-24 +4.0128 -9.47996e-25 +4.0152 -8.30583e-25 +4.0176 -7.27328e-25 +4.02 -6.3657e-25 +4.0224 -5.56836e-25 +4.0248 -4.86823e-25 +4.0272 -4.25379e-25 +4.0296 -3.71481e-25 +4.032 -3.24229e-25 +4.0344 -2.82825e-25 +4.0368 -2.46564e-25 +4.0392 -2.14825e-25 +4.0416 -1.87059e-25 +4.044 -1.62781e-25 +4.0464 -1.41567e-25 +4.0488 -1.23039e-25 +4.0512 -1.06866e-25 +4.0536 -9.2758e-26 +4.056 -8.0458e-26 +4.0584 -6.97408e-26 +4.0608 -6.04084e-26 +4.0632 -5.22869e-26 +4.0656 -4.52237e-26 +4.068 -3.90847e-26 +4.0704 -3.37526e-26 +4.0728 -2.91243e-26 +4.0752 -2.51098e-26 +4.0776 -2.163e-26 +4.08 -1.86159e-26 +4.0824 -1.6007e-26 +4.0848 -1.37507e-26 +4.0872 -1.18007e-26 +4.0896 -1.01168e-26 +4.092 -8.66386e-27 +4.0944 -7.41128e-27 +4.0968 -6.33236e-27 +4.0992 -5.40386e-27 +4.1016 -4.60555e-27 +4.104 -3.91984e-27 +4.1064 -3.33143e-27 +4.1088 -2.82704e-27 +4.1112 -2.39515e-27 +4.1136 -2.02576e-27 +4.116 -1.71019e-27 +4.1184 -1.44094e-27 +4.1208 -1.21151e-27 +4.1232 -1.01628e-27 +4.1256 -8.50391e-28 +4.128 -7.09655e-28 +4.1304 -5.90451e-28 +4.1328 -4.89662e-28 +4.1352 -4.04601e-28 +4.1376 -3.32958e-28 +4.14 -2.72745e-28 +4.1424 -2.22257e-28 +4.1448 -1.8003e-28 +4.1472 -1.4481e-28 +4.1496 -1.15523e-28 +4.152 -9.12512e-29 +4.1544 -7.12105e-29 +4.1568 -5.47322e-29 +4.1592 -4.12466e-29 +4.1616 -3.02693e-29 +4.164 -2.13889e-29 +4.1664 -1.42565e-29 +4.1688 -8.57674e-30 +4.1712 -4.10003e-30 +4.1736 -6.15915e-31 +4.176 2.05275e-30 +4.1784 4.05472e-30 +4.1808 5.51463e-30 +4.1832 6.53659e-30 +4.1856 7.20735e-30 +4.188 7.59897e-30 +4.1904 7.77108e-30 +4.1928 7.77284e-30 +4.1952 7.64459e-30 +4.1976 7.41929e-30 +4.2 7.1237e-30 +4.2024 6.77942e-30 +4.2048 6.40372e-30 +4.2072 6.01034e-30 +4.2096 5.61001e-30 +4.212 5.21107e-30 +4.2144 4.81985e-30 +4.2168 4.44104e-30 +4.2192 4.07801e-30 +4.2216 3.73309e-30 +4.224 3.40773e-30 +4.2264 3.10273e-30 +4.2288 2.81834e-30 +4.2312 2.55442e-30 +4.2336 2.31053e-30 +4.236 2.08597e-30 +4.2384 1.87992e-30 +4.2408 1.69141e-30 +4.2432 1.51944e-30 +4.2456 1.36295e-30 +4.248 1.22087e-30 +4.2504 1.09216e-30 +4.2528 9.75801e-31 +4.2552 8.70793e-31 +4.2576 7.76198e-31 +4.26 6.91123e-31 +4.2624 6.14728e-31 +4.2648 5.46228e-31 +4.2672 4.8489e-31 +4.2696 4.30038e-31 +4.272 3.81048e-31 +4.2744 3.37344e-31 +4.2768 2.98401e-31 +4.2792 2.63737e-31 +4.2816 2.32915e-31 +4.284 2.05536e-31 +4.2864 1.81239e-31 +4.2888 1.59698e-31 +4.2912 1.40616e-31 +4.2936 1.23728e-31 +4.296 1.08794e-31 +4.2984 9.55985e-32 +4.3008 8.39487e-32 +4.3032 7.36713e-32 +4.3056 6.46116e-32 +4.308 5.6631e-32 +4.3104 4.9606e-32 +4.3128 4.34266e-32 +4.3152 3.79946e-32 +4.3176 3.32228e-32 +4.32 2.90338e-32 +4.3224 2.53587e-32 +4.3248 2.21365e-32 +4.3272 1.93131e-32 +4.3296 1.68407e-32 +4.332 1.4677e-32 +4.3344 1.27844e-32 +4.3368 1.11301e-32 +4.3392 9.68478e-33 +4.3416 8.4228e-33 +4.344 7.32152e-33 +4.3464 6.36099e-33 +4.3488 5.52369e-33 +4.3512 4.7942e-33 +4.3536 4.15898e-33 +4.356 3.60614e-33 +4.3584 3.12524e-33 +4.3608 2.70714e-33 +4.3632 2.34383e-33 +4.3656 2.02829e-33 +4.368 1.75437e-33 +4.3704 1.51672e-33 +4.3728 1.31062e-33 +4.3752 1.13198e-33 +4.3776 9.77215e-34 +4.38 8.43204e-34 +4.3824 7.2722e-34 +4.3848 6.26887e-34 +4.3872 5.40136e-34 +4.3896 4.65165e-34 +4.392 4.00405e-34 +4.3944 3.44494e-34 +4.3968 2.96246e-34 +4.3992 2.5463e-34 +4.4016 2.18754e-34 +4.404 1.87839e-34 +4.4064 1.61214e-34 +4.4088 1.38294e-34 +4.4112 1.18573e-34 +4.4136 1.01613e-34 +4.416 8.70343e-35 +4.4184 7.45095e-35 +4.4208 6.37542e-35 +4.4232 5.4523e-35 +4.4256 4.66041e-35 +4.428 3.98142e-35 +4.4304 3.39953e-35 +4.4328 2.90112e-35 +4.4352 2.47442e-35 +4.4376 2.10932e-35 +4.44 1.79708e-35 +4.4424 1.53019e-35 +4.4448 1.30218e-35 +4.4472 1.1075e-35 +4.4496 9.41364e-36 +4.452 7.99668e-36 +4.4544 6.78881e-36 +4.4568 5.75979e-36 +4.4592 4.88362e-36 +4.4616 4.13803e-36 +4.464 3.50395e-36 +4.4664 2.96501e-36 +4.4688 2.50722e-36 +4.4712 2.11861e-36 +4.4736 1.78893e-36 +4.476 1.50941e-36 +4.4784 1.2726e-36 +4.4808 1.07209e-36 +4.4832 9.02434e-37 +4.4856 7.5899e-37 +4.488 6.37794e-37 +4.4904 5.35471e-37 +4.4928 4.49147e-37 +4.4952 3.76376e-37 +4.4976 3.15081e-37 +4.5 2.63494e-37 +4.5024 2.20114e-37 +4.5048 1.83668e-37 +4.5072 1.53074e-37 +4.5096 1.27418e-37 +4.512 1.05924e-37 +4.5144 8.79341e-38 +4.5168 7.28935e-38 +4.5192 6.03324e-38 +4.5216 4.98541e-38 +4.524 4.11238e-38 +4.5264 3.38591e-38 +4.5288 2.78219e-38 +4.5312 2.28119e-38 +4.5336 1.86605e-38 +4.536 1.52259e-38 +4.5384 1.23891e-38 +4.5408 1.00502e-38 +4.5432 8.12551e-39 +4.5456 6.54492e-39 +4.548 5.24977e-39 +4.5504 4.19104e-39 +4.5528 3.32783e-39 +4.5552 2.62603e-39 +4.5576 2.05725e-39 +4.56 1.59786e-39 +4.5624 1.22826e-39 +4.5648 9.32187e-40 +4.5672 6.96172e-40 +4.5696 5.09088e-40 +4.572 3.6175e-40 +4.5744 2.46595e-40 +4.5768 1.57406e-40 +4.5792 8.90817e-41 +4.5816 3.74498e-41 +4.584 -8.96678e-43 +4.5864 -2.87309e-41 +4.5888 -4.83036e-41 +4.5912 -6.14352e-41 +4.5936 -6.9593e-41 +4.596 -7.39546e-41 +4.5984 -7.54606e-41 +4.6008 -7.48585e-41 +4.6032 -7.27388e-41 +4.6056 -6.95644e-41 +4.608 -6.56951e-41 +4.6104 -6.14083e-41 +4.6128 -5.69145e-41 +4.6152 -5.23713e-41 +4.6176 -4.78945e-41 +4.62 -4.35665e-41 +4.6224 -3.94439e-41 +4.6248 -3.55632e-41 +4.6272 -3.19455e-41 +4.6296 -2.86e-41 +4.632 -2.55276e-41 +4.6344 -2.27225e-41 +4.6368 -2.01746e-41 +4.6392 -1.78708e-41 +4.6416 -1.57962e-41 +4.644 -1.39346e-41 +4.6464 -1.22695e-41 +4.6488 -1.07846e-41 +4.6512 -9.46396e-42 +4.6536 -8.29228e-42 +4.656 -7.25513e-42 +4.6584 -6.33898e-42 +4.6608 -5.53131e-42 +4.6632 -4.82056e-42 +4.6656 -4.19617e-42 +4.668 -3.64853e-42 +4.6704 -3.16893e-42 +4.6728 -2.74952e-42 +4.6752 -2.38324e-42 +4.6776 -2.06377e-42 +4.68 -1.78547e-42 +4.6824 -1.54332e-42 +4.6848 -1.33285e-42 +4.6872 -1.15013e-42 +4.6896 -9.91643e-43 +4.692 -8.54324e-43 +4.6944 -7.35456e-43 +4.6968 -6.32654e-43 +4.6992 -5.43825e-43 +4.7016 -4.67137e-43 +4.704 -4.00984e-43 +4.7064 -3.43966e-43 +4.7088 -2.9486e-43 +4.7112 -2.526e-43 +4.7136 -2.16259e-43 +4.716 -1.8503e-43 +4.7184 -1.58214e-43 +4.7208 -1.35203e-43 +4.7232 -1.15469e-43 +4.7256 -9.85585e-44 +4.728 -8.40758e-44 +4.7304 -7.16805e-44 +4.7328 -6.10785e-44 +4.7352 -5.20157e-44 +4.7376 -4.42734e-44 +4.74 -3.76632e-44 +4.7424 -3.20228e-44 +4.7448 -2.72127e-44 +4.7472 -2.3113e-44 +4.7496 -1.96207e-44 +4.752 -1.66475e-44 +4.7544 -1.41176e-44 +4.7568 -1.19662e-44 +4.7592 -1.01375e-44 +4.7616 -8.58392e-45 +4.764 -7.26484e-45 +4.7664 -6.14542e-45 +4.7688 -5.19593e-45 +4.7712 -4.39098e-45 +4.7736 -3.70892e-45 +4.776 -3.13128e-45 +4.7784 -2.64232e-45 +4.7808 -2.22864e-45 +4.7832 -1.87881e-45 +4.7856 -1.58312e-45 +4.788 -1.33333e-45 +4.7904 -1.12241e-45 +4.7928 -9.44403e-46 +4.7952 -7.94241e-46 +4.7976 -6.67632e-46 +4.8 -5.60934e-46 diff --git a/tools/rt-tddft-tools/examples/ground-state-projection-Si/On1.dat b/tools/rt-tddft-tools/examples/ground-state-projection-Si/On1.dat index d745542ce92..4aed610292e 100644 --- a/tools/rt-tddft-tools/examples/ground-state-projection-Si/On1.dat +++ b/tools/rt-tddft-tools/examples/ground-state-projection-Si/On1.dat @@ -1,101 +1,101 @@ -7.812499853032692752e-03 7.812500279798491667e-03 7.812350082550026734e-03 7.812350082567939488e-03 6.686717854768583909e-18 1.273966279961955695e-20 1.281536489683403687e-20 2.436224928051321290e-17 1.455721960673305505e-20 -7.812499853032699691e-03 7.812500279798476055e-03 7.812350082258740641e-03 7.812350082365753998e-03 1.490247763194331891e-17 1.077391542540353658e-17 9.648851966739274479e-18 2.698813529540607934e-17 3.969790221977746295e-20 -7.812499853032702293e-03 7.812500279798481259e-03 7.812350082258744978e-03 7.812350082365754865e-03 1.338629013537693114e-17 1.040157544868407331e-17 8.023705175726225935e-18 2.818645043139415115e-17 2.152965149171645697e-19 -7.812499853032704028e-03 7.812500279798481259e-03 7.812350082258739774e-03 7.812350082365751396e-03 1.050061327306201373e-17 1.018748243646475980e-17 1.255526088916916614e-17 2.884255147975228781e-17 9.256801281552135578e-19 -7.812499853032684079e-03 7.812500279798443095e-03 7.812350082258605333e-03 7.812350082365557974e-03 1.110234188146072923e-16 5.476475696791553340e-17 9.458349117056311261e-17 7.886970031758802209e-17 3.443302604107927034e-17 -7.812499853032585199e-03 7.812500279797884514e-03 7.812350082257480365e-03 7.812350082363527480e-03 1.221025990081458542e-15 5.277097822561900040e-16 8.042486056611601589e-16 6.609800012573974879e-16 3.388298157432289595e-16 -7.812499853032228714e-03 7.812500279794808850e-03 7.812350082251317759e-03 7.812350082352021927e-03 7.688773607708341558e-15 3.222952618985768202e-15 4.719067260205915655e-15 4.031146146161859528e-15 1.884039370417977416e-15 -7.812499853031174869e-03 7.812500279782960688e-03 7.812350082226447029e-03 7.812350082305783740e-03 3.459153926335484060e-14 1.423009475135000606e-14 2.065106717651520955e-14 1.758670007424376872e-14 7.474971242608616118e-15 -7.812499853028622224e-03 7.812500279747522022e-03 7.812350082146477144e-03 7.812350082159213484e-03 1.228145204190944378e-13 4.981559865801570222e-14 7.232334033967236660e-14 6.002620078048621925e-14 2.330673017550618989e-14 -7.812499853023407645e-03 7.812500279660945443e-03 7.812350081934199032e-03 7.812350081777151914e-03 3.610941462883710220e-13 1.446487842594735793e-13 2.106461858849508682e-13 1.682485411779086762e-13 5.969979759489234567e-14 -7.812499853014897092e-03 7.812500279486930127e-03 7.812350081463906824e-03 7.812350080947388573e-03 8.986578228190934686e-13 3.554742578353971945e-13 5.197792228478134614e-13 3.957470702999447474e-13 1.276867248607976924e-13 -7.812499853005088098e-03 7.812500279205564918e-03 7.812350080604125828e-03 7.812350079464436790e-03 1.902129002541687645e-12 7.419716841836609477e-13 1.090168097358521198e-12 7.836573236885160296e-13 2.269353059419004219e-13 -7.812499853000657614e-03 7.812500278866488929e-03 7.812350079367172580e-03 7.812350077389442968e-03 3.385603051914610680e-12 1.299293649069382529e-12 1.919379016255142377e-12 1.289038721443987301e-12 3.261388284048605778e-13 -7.812499853009330364e-03 7.812500278626734532e-03 7.812350078155607877e-03 7.812350075432913411e-03 4.901700794298826520e-12 1.845807442333131019e-12 2.742383323432933970e-12 1.711872500631155452e-12 3.618101175167228489e-13 -7.812499853018082911e-03 7.812500278590924635e-03 7.812350077802290675e-03 7.812350074866239967e-03 5.396993520182899994e-12 2.001504125631436744e-12 2.981955563864776735e-12 1.839553005394764809e-12 3.385082846655620411e-13 -7.812499852932987786e-03 7.812500278033927478e-03 7.812350078412555986e-03 7.812350075183738599e-03 4.315407145162125193e-12 1.703056079344719690e-12 2.468677803485621447e-12 2.361762504659291149e-12 6.950218203357612152e-13 -7.812499852466974273e-03 7.812500273374220830e-03 7.812350074989517223e-03 7.812350066099102777e-03 6.283159864873798714e-12 3.169681657633534525e-12 4.281083262384277953e-12 7.474396685349264012e-12 3.134461378552293558e-12 -7.812499851005201730e-03 7.812500254476032260e-03 7.812350047197313789e-03 7.812350009764495659e-03 3.267183280083109047e-11 1.552890608038603436e-11 2.153012832021432507e-11 2.999039571018929183e-11 1.192963004046087639e-11 -7.812499847572922963e-03 7.812500200162266970e-03 7.812349942262116105e-03 7.812349812582107186e-03 1.418939026414260175e-10 6.257923727216895362e-11 8.890829388137152469e-11 9.827167982682776205e-11 3.508698292183345656e-11 -7.812499841149679949e-03 7.812500076640842978e-03 7.812349656646455642e-03 7.812349297842300852e-03 4.531185304792351007e-10 1.911716241251917738e-10 2.754704942626815632e-10 2.605143014572550335e-10 8.366148061447493069e-11 -7.812499831578885272e-03 7.812499846019973354e-03 7.812349034944595511e-03 7.812348211501761626e-03 1.153088037609147093e-09 4.718569550809047194e-10 6.864440626384909332e-10 5.765652531795112974e-10 1.666204089618884149e-10 -7.812499820987390577e-03 7.812499492320172136e-03 7.812347918113238948e-03 7.812346312754753913e-03 2.447702082586668115e-09 9.771504459394998477e-10 1.432182592776262639e-09 1.085202190312603517e-09 2.797335493584696527e-10 -7.812499814740346896e-03 7.812499062254251760e-03 7.812346269952624885e-03 7.812343587535403380e-03 4.418222801594663738e-09 1.724018381710924485e-09 2.543369039502271716e-09 1.745678194287174871e-09 3.925477856832722905e-10 -7.812499819669653858e-03 7.812498690802675665e-03 7.812344360995931644e-03 7.812340529108604235e-03 6.791658385448597663e-09 2.589635535318124385e-09 3.843587174577796148e-09 2.388121726329547615e-09 4.486778634736386646e-10 -7.812499836541287289e-03 7.812498540333734538e-03 7.812342867626963228e-03 7.812338223696329957e-03 8.770998199078791133e-09 3.264672608722082367e-09 4.871569121144878528e-09 2.769177408961638509e-09 4.069975426300912668e-10 -7.812499844218311236e-03 7.812498550624985029e-03 7.812342564980947340e-03 7.812337706375470196e-03 9.284480356680769592e-09 3.391579366265826169e-09 5.070184887145676427e-09 2.882656183351129511e-09 3.547336710690416432e-10 -7.812499781849658459e-03 7.812497938502010325e-03 7.812343184217111422e-03 7.812337931984741912e-03 8.187553284667456409e-09 3.083966817157662608e-09 4.539467182508874874e-09 3.660704609143170800e-09 6.855413362771258625e-10 -7.812499539571283146e-03 7.812494543140142793e-03 7.812341152959785887e-03 7.812332057382916951e-03 8.841744470361763275e-09 3.960847677671831129e-09 5.566699818414017084e-09 7.988727728025107941e-09 2.269703900840955374e-09 -7.812498977478036198e-03 7.812484406984244664e-03 7.812326615005588636e-03 7.812302905420510403e-03 2.180228070163895656e-08 1.051910237351932575e-08 1.469509777326951620e-08 2.154800783639236158e-08 6.441336062768101019e-09 -7.812497994380795431e-03 7.812462264526452878e-03 7.812281302555792832e-03 7.812220353796601319e-03 6.797441971956459514e-08 3.112683845546636387e-08 4.428691811001559565e-08 5.250018216563952165e-08 1.458559667171380079e-08 -7.812496642031469159e-03 7.812423582450244049e-03 7.812180052545585236e-03 7.812045025095691250e-03 1.780202938069342282e-07 7.735204086169203320e-08 1.116600602934448646e-07 1.089078623714063587e-07 2.722494382585283444e-08 -7.812495230981619278e-03 7.812368096507126165e-03 7.811998844602665269e-03 7.811742231074614295e-03 3.842368801176499279e-07 1.602847291236858473e-07 2.337376488854461481e-07 1.935971465318801878e-07 4.285591415854843683e-08 -7.812494328139583770e-03 7.812303379348786367e-03 7.811729874197701103e-03 7.811305756875472177e-03 7.032546837354541918e-07 2.835793382204843004e-07 4.166897389954705580e-07 2.982177140607078031e-07 5.728193039849254671e-08 -7.812494550142056599e-03 7.812245427258719503e-03 7.811398810282921268e-03 7.810782527030078054e-03 1.113727748184818239e-06 4.354043797212895802e-07 6.437087438942030785e-07 4.008686263785850362e-07 6.449845579325761372e-08 -7.812496138080336598e-03 7.812212893856464342e-03 7.811072727768756351e-03 7.810279691796943348e-03 1.541461156476913746e-06 5.846309847418375274e-07 8.688045986117029490e-07 4.729147334166597758e-07 5.986995545985544601e-08 -7.812498445556872832e-03 7.812213704232950744e-03 7.810843583203532815e-03 7.809932136645577130e-03 1.870616030668633253e-06 6.884156571567480939e-07 1.027329365299366220e-06 4.981846542090092702e-07 4.512119076652669270e-08 -7.812499643314411817e-03 7.812227465998996048e-03 7.810777050788949953e-03 7.809818584425421741e-03 1.996915864576686549e-06 7.162014155120878158e-07 1.070908963295831547e-06 5.007358000999807850e-07 3.290430957355282637e-08 -7.812497004583882597e-03 7.812192420099366673e-03 7.810833005781974391e-03 7.809841229764222931e-03 1.921887432159646985e-06 6.874135529587402941e-07 1.023172530687733249e-06 5.684268623121463193e-07 4.737660114594148372e-08 -7.812487977686922644e-03 7.812008194689230509e-03 7.810787695955377988e-03 7.809619485122610769e-03 1.857942469276308112e-06 7.085479518432960039e-07 1.035821288261976948e-06 8.540461262419201573e-07 1.176737671272773021e-07 -7.812471748767348123e-03 7.811562352071302860e-03 7.810207234515143850e-03 7.808473164261869534e-03 2.285569265615626913e-06 9.854058759137348325e-07 1.409932401056303498e-06 1.539858543220769961e-06 2.640648030851998174e-07 -7.812450529143469789e-03 7.810779042843053223e-03 7.808519956579640028e-03 7.805560882451594018e-03 3.896605580814575925e-06 1.787075451064486949e-06 2.548005225924580296e-06 2.765201026029978535e-06 4.813926593788763635e-07 -7.812429661862023596e-03 7.809674641149721812e-03 7.805202887404326904e-03 7.800181116207064586e-03 7.390363320579293810e-06 3.354519377221000757e-06 4.824207063860702588e-06 4.537698916556045439e-06 7.287005859073173523e-07 -7.812416165084923141e-03 7.808393536111879127e-03 7.800038510484820671e-03 7.792149825718211638e-03 1.316122584248707086e-05 5.776773434575371999e-06 8.402178779544433807e-06 6.667369014382867723e-06 9.343828152441929552e-07 -7.812415835781623234e-03 7.807194132714686402e-03 7.793337863448148058e-03 7.782082517240840498e-03 2.099925837947448981e-05 8.887746642244384300e-06 1.307323485563547160e-05 8.770203536976671789e-06 1.021168349833567159e-06 -7.812430158111208570e-03 7.806368467992530306e-03 7.786000020659196962e-03 7.771393248244110735e-03 2.996771098010651084e-05 1.224706928486793432e-05 1.820790009944723024e-05 1.037469218978934016e-05 9.437824387095230784e-07 -7.812454690656026220e-03 7.806110337177065567e-03 7.779316215103107730e-03 7.761914895057454335e-03 3.858110769296473004e-05 1.524525220567434296e-05 2.288872843530340110e-05 1.112352046586807781e-05 7.209921399975341084e-07 -7.812480201788416824e-03 7.806386805941349476e-03 7.774529785912486640e-03 7.755223553030285953e-03 4.528347453745602184e-05 1.731960264508936400e-05 2.622053730063316743e-05 1.100113352190226156e-05 4.399041900332164704e-07 -7.812496176044654919e-03 7.806891664948079936e-03 7.772291495159932770e-03 7.751926368829008263e-03 4.907275643454239819e-05 1.820754084061740197e-05 2.772288834078687984e-05 1.046061247568982606e-05 2.225225911981681611e-07 -7.812495292061822673e-03 7.807139215375609106e-03 7.772241751786874986e-03 7.751242393952807209e-03 5.001574978626547913e-05 1.812741955189118513e-05 2.764027203504243102e-05 1.032613486388670125e-05 1.665620513368287718e-07 -7.812476894523122731e-03 7.806683943209593787e-03 7.772945300038862533e-03 7.751111453457110168e-03 4.940863028517055046e-05 1.778892355151607562e-05 2.700354558676601411e-05 1.144278173216673945e-05 2.931356705096467600e-07 -7.812447633371830819e-03 7.805360622923213781e-03 7.772280325110742481e-03 7.748841300394401430e-03 4.946498788292683508e-05 1.819664607815776332e-05 2.735932394244346047e-05 1.421182877230432772e-05 5.348146728831700359e-07 -7.812418676200951796e-03 7.803399072295380545e-03 7.768182598560221565e-03 7.742056677893807692e-03 5.260502689341779259e-05 2.029938517503130136e-05 3.022889388385826916e-05 1.827918656212739249e-05 7.737969837445373764e-07 -7.812400713050573174e-03 7.801328899352429937e-03 7.759458933900293363e-03 7.729571012333778281e-03 6.059554765283085880e-05 2.461554399679295580e-05 3.650070756930909251e-05 2.260937471593158608e-05 9.062974796379607276e-07 -7.812399402924678250e-03 7.799725111593778897e-03 7.746317787884777345e-03 7.711834931169255294e-03 7.387281172230948569e-05 3.099207090489362784e-05 4.602122468061838116e-05 2.595267368927323958e-05 8.916091203328781368e-07 -7.812413332542555815e-03 7.798951317677097449e-03 7.730372562608386205e-03 7.690803617564479985e-03 9.132598392869010779e-05 3.860912329843406692e-05 5.757879489393928250e-05 2.744243129201358010e-05 7.582080085956336064e-07 -7.812435655750508100e-03 7.799045564899258556e-03 7.714106581128725958e-03 7.669307408003667517e-03 1.106354824953435383e-04 4.624173039586804786e-05 6.930319478072197116e-05 2.696493794476126531e-05 5.706638856372884918e-07 -7.812458049977899846e-03 7.799779002849843365e-03 7.700032119112999729e-03 7.650185626982551265e-03 1.290317728818038228e-04 5.267491242189746055e-05 7.931021912472004868e-05 2.510498190276937440e-05 3.874743003157170213e-07 -7.812474472833470102e-03 7.800806553791946735e-03 7.689895100482323394e-03 7.635495440478613609e-03 1.441671433054891155e-04 5.710082886942940348e-05 8.631673803264112315e-05 2.275885910941017286e-05 2.386244849668603841e-07 -7.812482976849034755e-03 7.801806678970187037e-03 7.684226346611384290e-03 7.626043122362352773e-03 1.547629942338338998e-04 5.933866733362661114e-05 8.998326647379967301e-05 2.069121747385026391e-05 1.297730912415325758e-07 -7.812485232220344605e-03 7.802559641047198541e-03 7.682363107231317788e-03 7.621351204389437833e-03 1.608167121281512204e-04 5.980453704693076267e-05 9.088196765691194143e-05 1.927999912557097661e-05 5.844008953976879205e-08 -7.812484687099224487e-03 7.802969819103481100e-03 7.682863284657014818e-03 7.620020195549746453e-03 1.633555907751381572e-04 5.927321903152686335e-05 9.015594799946130046e-05 1.851857110723650212e-05 2.355680679308437475e-08 -7.812484528579055273e-03 7.803053725096873068e-03 7.684099485053701856e-03 7.620313644105695082e-03 1.639054050789472161e-04 5.855667006084784424e-05 8.904796951092744850e-05 1.818147643885591132e-05 2.259562066722161082e-08 -7.812486347732097020e-03 7.802906138662985686e-03 7.684792010505495964e-03 7.620734657771241656e-03 1.639180799370792388e-04 5.823836154829621197e-05 8.849453651262909287e-05 1.801056113072297418e-05 4.482718225915012074e-08 -7.812489966877368686e-03 7.802652857458577430e-03 7.684311301855815610e-03 7.620397450278489949e-03 1.643642387066439835e-04 5.854960502899452695e-05 8.891359154098924097e-05 1.782919431049579911e-05 7.161912630444491773e-08 -7.812494127122805894e-03 7.802404580937485380e-03 7.682698807419341414e-03 7.619109876382451629e-03 1.655862811202974880e-04 5.939615713527549305e-05 9.021286715380141135e-05 1.757035112025118347e-05 8.559997302272443172e-08 -7.812497470211249989e-03 7.802228932425433333e-03 7.680464665858448801e-03 7.617210995022639063e-03 1.673906019698739671e-04 6.048444806446939652e-05 9.196185539774789648e-05 1.725117344749978250e-05 8.071052106673271989e-08 -7.812499262283496664e-03 7.802147068445501599e-03 7.678284905384741635e-03 7.615288498122666817e-03 1.692825327983098758e-04 6.147641588181483141e-05 9.362872093630432619e-05 1.693047970507380231e-05 6.424811185473353517e-08 -7.812499556017950091e-03 7.802145493693739449e-03 7.676725520415324244e-03 7.613906859695971675e-03 1.707300961208414974e-04 6.211532079841483437e-05 9.478777861569192588e-05 1.666872075534763098e-05 4.957518521111539337e-08 -7.812498898940323407e-03 7.802189426919653448e-03 7.676076529785660213e-03 7.613428103579155878e-03 1.713654284443885114e-04 6.229347725606795285e-05 9.523952736898054429e-05 1.649883460424523220e-05 4.584613527028352739e-08 -7.812497920560946760e-03 7.802232495060661827e-03 7.676319544958354509e-03 7.613946242661542678e-03 1.710785375910244487e-04 6.205778441104415428e-05 9.502791401655731585e-05 1.641215865889956077e-05 5.255976528493730751e-08 -7.812497066894792501e-03 7.802227167898124344e-03 7.677201581430874618e-03 7.615314113993682313e-03 1.700042512425950004e-04 6.156635540337338387e-05 9.437552276658168148e-05 1.636184653588275881e-05 6.184665501771761686e-08 -7.812496511241781051e-03 7.802139573436450704e-03 7.678360934842314196e-03 7.617224476854871258e-03 1.684368934514004535e-04 6.102002790153284524e-05 9.357839679933613655e-05 1.628189975863044079e-05 6.526686105702234742e-08 -7.812496219646037840e-03 7.801963573583982695e-03 7.679448409179731941e-03 7.619307392520942475e-03 1.667211245983212084e-04 6.059647760585791217e-05 9.290647870527361698e-05 1.611438596915572326e-05 5.944474959016087870e-08 -7.812496067262236082e-03 7.801724521784449314e-03 7.680207555690407410e-03 7.621215867234738643e-03 1.651611118942663268e-04 6.040796446319642645e-05 9.254061247558314075e-05 1.583289243326745281e-05 4.721294373152034348e-08 -7.812495939725520519e-03 7.801468805562560005e-03 7.680500815485480186e-03 7.622682332336906674e-03 1.639704408479166744e-04 6.049154736383084284e-05 9.255705934859457618e-05 1.545276710389118145e-05 3.486730501181152877e-08 -7.812495810392372161e-03 7.801245471614342251e-03 7.680293265591961113e-03 7.623542163437857511e-03 1.632627294083275303e-04 6.082500272239638590e-05 9.294827781949960212e-05 1.502481172788627132e-05 2.836530457701504368e-08 -7.812495774057383324e-03 7.801090398214164875e-03 7.679617741755038161e-03 7.623730980268567277e-03 1.630687270832232910e-04 6.135328767953494530e-05 9.365818359531991294e-05 1.461705702769232774e-05 3.062975683152378586e-08 -7.812496004572946559e-03 7.801019097885079565e-03 7.678544236128501121e-03 7.623267186730509938e-03 1.633636498553494383e-04 6.201144366886053398e-05 9.461157972898225999e-05 1.429342797726595519e-05 4.043850989161355651e-08 -7.812496631779798119e-03 7.801027496962795009e-03 7.677165776783217294e-03 7.622229199252808160e-03 1.640937838916600819e-04 6.273706605913448688e-05 9.572723457634188516e-05 1.409693806672889080e-05 5.277965583598395105e-08 -7.812497593986529945e-03 7.801096856079874943e-03 7.675599630972139084e-03 7.620731771399200105e-03 1.651974699868906436e-04 6.347246017827182240e-05 9.691547544110199126e-05 1.404137420550190033e-05 6.090756096056601143e-08 -7.812498566204971115e-03 7.801199754440974084e-03 7.673992897753495815e-03 7.618903661828040075e-03 1.666176502970805691e-04 6.416043472906765414e-05 9.806960623076769253e-05 1.411294308233202020e-05 5.993589060455973356e-08 -7.812499053771074925e-03 7.801305349386283491e-03 7.672518875246725489e-03 7.616869257773883906e-03 1.683046089823451085e-04 6.473936921646154048e-05 9.906343259329801248e-05 1.428210110113845229e-05 5.027682857905558417e-08 -7.812498632159666813e-03 7.801382900472925326e-03 7.671356652224933619e-03 7.614739595271466377e-03 1.702096434999436484e-04 6.514310541558802512e-05 9.976321818125709177e-05 1.452125443129783517e-05 3.829448713707502261e-08 -7.812497201837249015e-03 7.801403862531090978e-03 7.670657640407920266e-03 7.612615855838451850e-03 1.722743768132731137e-04 6.530927069172183942e-05 1.000534417096700466e-04 1.481781435146641011e-05 3.294263590754535029e-08 -7.812495078364333281e-03 7.801344666489945685e-03 7.670510553714322832e-03 7.610600036568103931e-03 1.744227893749939232e-04 6.519571551979745270e-05 9.986799788108100028e-05 1.517179567317124298e-05 4.016604303805187084e-08 -7.812492900103195845e-03 7.801192644470767747e-03 7.670919899304099940e-03 7.608803560422339532e-03 1.765599991482183864e-04 6.479804001506211746e-05 9.921318396850725772e-05 1.557572355818140049e-05 5.876129580872593247e-08 -7.812491399909044648e-03 7.800954310441960901e-03 7.671806713972414808e-03 7.607344211055998458e-03 1.785775612115598305e-04 6.415814227891146265e-05 9.817148076228197353e-05 1.599052210317778022e-05 8.069995376715356099e-08 -7.812491115931742038e-03 7.800660131530765505e-03 7.673033286305866278e-03 7.606329970254107307e-03 1.803626974654734159e-04 6.335517272175504935e-05 9.688053494765318523e-05 1.633939801180696436e-05 9.591747241806178274e-08 -7.812492133591250783e-03 7.800359190254140332e-03 7.674441600347642854e-03 7.605837575408820259e-03 1.818080321303487473e-04 6.248181849103899717e-05 9.549537823929271684e-05 1.653082719052810295e-05 9.833364655358530313e-08 -7.812494031046210430e-03 7.800102179172256622e-03 7.675896495846616999e-03 7.605897118576439818e-03 1.828226666389231193e-04 6.161441159967244615e-05 9.414446198404529656e-05 1.650237702724804381e-05 8.885369315965530215e-08 -7.812496052543584438e-03 7.799921303838168625e-03 7.677317282524499797e-03 7.606490090774489093e-03 1.833430573543588750e-04 6.079269373977964908e-05 9.289859503958730949e-05 1.625765820792788300e-05 7.334301113257308106e-08 -7.812497439077231015e-03 7.799819160821133690e-03 7.678687734277541560e-03 7.607558169686876905e-03 1.833426694457979708e-04 6.001769729579950902e-05 9.176364274852043203e-05 1.587269546633251967e-05 5.755832196158116801e-08 -7.812497729013648771e-03 7.799773549843452315e-03 7.680039522150496067e-03 7.609017003352169274e-03 1.828346147238102306e-04 5.926707271268964972e-05 9.069961910013031267e-05 1.546620639546001242e-05 4.367983950618309385e-08 -7.812496926672149108e-03 7.799752994451267067e-03 7.681416702438653189e-03 7.610766790791871801e-03 1.818667647155675722e-04 5.851800025715518221e-05 8.965562716129177984e-05 1.515316230951711319e-05 3.122579787001255668e-08 -7.812495468274187685e-03 7.799731951055652486e-03 7.682835526327059031e-03 7.612698745924777015e-03 1.805102346395485047e-04 5.776728284319049658e-05 8.860630501187015645e-05 1.500776599250491295e-05 2.081738234097757612e-08 -7.812494016638638072e-03 7.799697603207485230e-03 7.684256601122156811e-03 7.614700518728856164e-03 1.788464912402624996e-04 5.704162388654450915e-05 8.757577061659674008e-05 1.505214344464923625e-05 1.619689641452411641e-08 -7.812493190330011515e-03 7.799648584005202875e-03 7.685580722774925863e-03 7.616663927961365814e-03 1.769587121590053330e-04 5.639621921786125067e-05 8.664108488644773742e-05 1.526756760774609803e-05 2.164868747164934285e-08 -7.812493299653834079e-03 7.799590748379032698e-03 7.686670407032592141e-03 7.618494928507740273e-03 1.749302970073336380e-04 5.590279367022501475e-05 8.591411849626973997e-05 1.561254289370475563e-05 3.696860078954675002e-08 -7.812494265631523410e-03 7.799534011930964357e-03 7.687386700992878373e-03 7.620121303322026016e-03 1.728492941645273838e-04 5.563158007306383187e-05 8.550992286051971704e-05 1.603327927725472439e-05 5.520836506281878338e-08 -7.812495719581083985e-03 7.799488670675083432e-03 7.687630571093129368e-03 7.621494785823084046e-03 1.708138484432252554e-04 5.563085091837701400e-05 8.551007496670540967e-05 1.646635384646213534e-05 6.626114818767479494e-08 -7.812497205244232044e-03 7.799460270436679374e-03 7.687372984260292669e-03 7.622586576308315945e-03 1.689329458115936781e-04 5.591130652985255368e-05 8.593512815630114645e-05 1.684156091513745103e-05 6.387890909022737881e-08 +7.812499853032692752e-03 7.812500279798491667e-03 7.812350082550026734e-03 7.812350082567939488e-03 6.686717854768583909e-18 1.273966279961955695e-20 1.281536489683403687e-20 2.436224928051321290e-17 1.455721960673305505e-20 +7.812499853032699691e-03 7.812500279798476055e-03 7.812350082258740641e-03 7.812350082365753998e-03 1.490247763194331891e-17 1.077391542540353658e-17 9.648851966739274479e-18 2.698813529540607934e-17 3.969790221977746295e-20 +7.812499853032702293e-03 7.812500279798481259e-03 7.812350082258744978e-03 7.812350082365754865e-03 1.338629013537693114e-17 1.040157544868407331e-17 8.023705175726225935e-18 2.818645043139415115e-17 2.152965149171645697e-19 +7.812499853032704028e-03 7.812500279798481259e-03 7.812350082258739774e-03 7.812350082365751396e-03 1.050061327306201373e-17 1.018748243646475980e-17 1.255526088916916614e-17 2.884255147975228781e-17 9.256801281552135578e-19 +7.812499853032684079e-03 7.812500279798443095e-03 7.812350082258605333e-03 7.812350082365557974e-03 1.110234188146072923e-16 5.476475696791553340e-17 9.458349117056311261e-17 7.886970031758802209e-17 3.443302604107927034e-17 +7.812499853032585199e-03 7.812500279797884514e-03 7.812350082257480365e-03 7.812350082363527480e-03 1.221025990081458542e-15 5.277097822561900040e-16 8.042486056611601589e-16 6.609800012573974879e-16 3.388298157432289595e-16 +7.812499853032228714e-03 7.812500279794808850e-03 7.812350082251317759e-03 7.812350082352021927e-03 7.688773607708341558e-15 3.222952618985768202e-15 4.719067260205915655e-15 4.031146146161859528e-15 1.884039370417977416e-15 +7.812499853031174869e-03 7.812500279782960688e-03 7.812350082226447029e-03 7.812350082305783740e-03 3.459153926335484060e-14 1.423009475135000606e-14 2.065106717651520955e-14 1.758670007424376872e-14 7.474971242608616118e-15 +7.812499853028622224e-03 7.812500279747522022e-03 7.812350082146477144e-03 7.812350082159213484e-03 1.228145204190944378e-13 4.981559865801570222e-14 7.232334033967236660e-14 6.002620078048621925e-14 2.330673017550618989e-14 +7.812499853023407645e-03 7.812500279660945443e-03 7.812350081934199032e-03 7.812350081777151914e-03 3.610941462883710220e-13 1.446487842594735793e-13 2.106461858849508682e-13 1.682485411779086762e-13 5.969979759489234567e-14 +7.812499853014897092e-03 7.812500279486930127e-03 7.812350081463906824e-03 7.812350080947388573e-03 8.986578228190934686e-13 3.554742578353971945e-13 5.197792228478134614e-13 3.957470702999447474e-13 1.276867248607976924e-13 +7.812499853005088098e-03 7.812500279205564918e-03 7.812350080604125828e-03 7.812350079464436790e-03 1.902129002541687645e-12 7.419716841836609477e-13 1.090168097358521198e-12 7.836573236885160296e-13 2.269353059419004219e-13 +7.812499853000657614e-03 7.812500278866488929e-03 7.812350079367172580e-03 7.812350077389442968e-03 3.385603051914610680e-12 1.299293649069382529e-12 1.919379016255142377e-12 1.289038721443987301e-12 3.261388284048605778e-13 +7.812499853009330364e-03 7.812500278626734532e-03 7.812350078155607877e-03 7.812350075432913411e-03 4.901700794298826520e-12 1.845807442333131019e-12 2.742383323432933970e-12 1.711872500631155452e-12 3.618101175167228489e-13 +7.812499853018082911e-03 7.812500278590924635e-03 7.812350077802290675e-03 7.812350074866239967e-03 5.396993520182899994e-12 2.001504125631436744e-12 2.981955563864776735e-12 1.839553005394764809e-12 3.385082846655620411e-13 +7.812499852932987786e-03 7.812500278033927478e-03 7.812350078412555986e-03 7.812350075183738599e-03 4.315407145162125193e-12 1.703056079344719690e-12 2.468677803485621447e-12 2.361762504659291149e-12 6.950218203357612152e-13 +7.812499852466974273e-03 7.812500273374220830e-03 7.812350074989517223e-03 7.812350066099102777e-03 6.283159864873798714e-12 3.169681657633534525e-12 4.281083262384277953e-12 7.474396685349264012e-12 3.134461378552293558e-12 +7.812499851005201730e-03 7.812500254476032260e-03 7.812350047197313789e-03 7.812350009764495659e-03 3.267183280083109047e-11 1.552890608038603436e-11 2.153012832021432507e-11 2.999039571018929183e-11 1.192963004046087639e-11 +7.812499847572922963e-03 7.812500200162266970e-03 7.812349942262116105e-03 7.812349812582107186e-03 1.418939026414260175e-10 6.257923727216895362e-11 8.890829388137152469e-11 9.827167982682776205e-11 3.508698292183345656e-11 +7.812499841149679949e-03 7.812500076640842978e-03 7.812349656646455642e-03 7.812349297842300852e-03 4.531185304792351007e-10 1.911716241251917738e-10 2.754704942626815632e-10 2.605143014572550335e-10 8.366148061447493069e-11 +7.812499831578885272e-03 7.812499846019973354e-03 7.812349034944595511e-03 7.812348211501761626e-03 1.153088037609147093e-09 4.718569550809047194e-10 6.864440626384909332e-10 5.765652531795112974e-10 1.666204089618884149e-10 +7.812499820987390577e-03 7.812499492320172136e-03 7.812347918113238948e-03 7.812346312754753913e-03 2.447702082586668115e-09 9.771504459394998477e-10 1.432182592776262639e-09 1.085202190312603517e-09 2.797335493584696527e-10 +7.812499814740346896e-03 7.812499062254251760e-03 7.812346269952624885e-03 7.812343587535403380e-03 4.418222801594663738e-09 1.724018381710924485e-09 2.543369039502271716e-09 1.745678194287174871e-09 3.925477856832722905e-10 +7.812499819669653858e-03 7.812498690802675665e-03 7.812344360995931644e-03 7.812340529108604235e-03 6.791658385448597663e-09 2.589635535318124385e-09 3.843587174577796148e-09 2.388121726329547615e-09 4.486778634736386646e-10 +7.812499836541287289e-03 7.812498540333734538e-03 7.812342867626963228e-03 7.812338223696329957e-03 8.770998199078791133e-09 3.264672608722082367e-09 4.871569121144878528e-09 2.769177408961638509e-09 4.069975426300912668e-10 +7.812499844218311236e-03 7.812498550624985029e-03 7.812342564980947340e-03 7.812337706375470196e-03 9.284480356680769592e-09 3.391579366265826169e-09 5.070184887145676427e-09 2.882656183351129511e-09 3.547336710690416432e-10 +7.812499781849658459e-03 7.812497938502010325e-03 7.812343184217111422e-03 7.812337931984741912e-03 8.187553284667456409e-09 3.083966817157662608e-09 4.539467182508874874e-09 3.660704609143170800e-09 6.855413362771258625e-10 +7.812499539571283146e-03 7.812494543140142793e-03 7.812341152959785887e-03 7.812332057382916951e-03 8.841744470361763275e-09 3.960847677671831129e-09 5.566699818414017084e-09 7.988727728025107941e-09 2.269703900840955374e-09 +7.812498977478036198e-03 7.812484406984244664e-03 7.812326615005588636e-03 7.812302905420510403e-03 2.180228070163895656e-08 1.051910237351932575e-08 1.469509777326951620e-08 2.154800783639236158e-08 6.441336062768101019e-09 +7.812497994380795431e-03 7.812462264526452878e-03 7.812281302555792832e-03 7.812220353796601319e-03 6.797441971956459514e-08 3.112683845546636387e-08 4.428691811001559565e-08 5.250018216563952165e-08 1.458559667171380079e-08 +7.812496642031469159e-03 7.812423582450244049e-03 7.812180052545585236e-03 7.812045025095691250e-03 1.780202938069342282e-07 7.735204086169203320e-08 1.116600602934448646e-07 1.089078623714063587e-07 2.722494382585283444e-08 +7.812495230981619278e-03 7.812368096507126165e-03 7.811998844602665269e-03 7.811742231074614295e-03 3.842368801176499279e-07 1.602847291236858473e-07 2.337376488854461481e-07 1.935971465318801878e-07 4.285591415854843683e-08 +7.812494328139583770e-03 7.812303379348786367e-03 7.811729874197701103e-03 7.811305756875472177e-03 7.032546837354541918e-07 2.835793382204843004e-07 4.166897389954705580e-07 2.982177140607078031e-07 5.728193039849254671e-08 +7.812494550142056599e-03 7.812245427258719503e-03 7.811398810282921268e-03 7.810782527030078054e-03 1.113727748184818239e-06 4.354043797212895802e-07 6.437087438942030785e-07 4.008686263785850362e-07 6.449845579325761372e-08 +7.812496138080336598e-03 7.812212893856464342e-03 7.811072727768756351e-03 7.810279691796943348e-03 1.541461156476913746e-06 5.846309847418375274e-07 8.688045986117029490e-07 4.729147334166597758e-07 5.986995545985544601e-08 +7.812498445556872832e-03 7.812213704232950744e-03 7.810843583203532815e-03 7.809932136645577130e-03 1.870616030668633253e-06 6.884156571567480939e-07 1.027329365299366220e-06 4.981846542090092702e-07 4.512119076652669270e-08 +7.812499643314411817e-03 7.812227465998996048e-03 7.810777050788949953e-03 7.809818584425421741e-03 1.996915864576686549e-06 7.162014155120878158e-07 1.070908963295831547e-06 5.007358000999807850e-07 3.290430957355282637e-08 +7.812497004583882597e-03 7.812192420099366673e-03 7.810833005781974391e-03 7.809841229764222931e-03 1.921887432159646985e-06 6.874135529587402941e-07 1.023172530687733249e-06 5.684268623121463193e-07 4.737660114594148372e-08 +7.812487977686922644e-03 7.812008194689230509e-03 7.810787695955377988e-03 7.809619485122610769e-03 1.857942469276308112e-06 7.085479518432960039e-07 1.035821288261976948e-06 8.540461262419201573e-07 1.176737671272773021e-07 +7.812471748767348123e-03 7.811562352071302860e-03 7.810207234515143850e-03 7.808473164261869534e-03 2.285569265615626913e-06 9.854058759137348325e-07 1.409932401056303498e-06 1.539858543220769961e-06 2.640648030851998174e-07 +7.812450529143469789e-03 7.810779042843053223e-03 7.808519956579640028e-03 7.805560882451594018e-03 3.896605580814575925e-06 1.787075451064486949e-06 2.548005225924580296e-06 2.765201026029978535e-06 4.813926593788763635e-07 +7.812429661862023596e-03 7.809674641149721812e-03 7.805202887404326904e-03 7.800181116207064586e-03 7.390363320579293810e-06 3.354519377221000757e-06 4.824207063860702588e-06 4.537698916556045439e-06 7.287005859073173523e-07 +7.812416165084923141e-03 7.808393536111879127e-03 7.800038510484820671e-03 7.792149825718211638e-03 1.316122584248707086e-05 5.776773434575371999e-06 8.402178779544433807e-06 6.667369014382867723e-06 9.343828152441929552e-07 +7.812415835781623234e-03 7.807194132714686402e-03 7.793337863448148058e-03 7.782082517240840498e-03 2.099925837947448981e-05 8.887746642244384300e-06 1.307323485563547160e-05 8.770203536976671789e-06 1.021168349833567159e-06 +7.812430158111208570e-03 7.806368467992530306e-03 7.786000020659196962e-03 7.771393248244110735e-03 2.996771098010651084e-05 1.224706928486793432e-05 1.820790009944723024e-05 1.037469218978934016e-05 9.437824387095230784e-07 +7.812454690656026220e-03 7.806110337177065567e-03 7.779316215103107730e-03 7.761914895057454335e-03 3.858110769296473004e-05 1.524525220567434296e-05 2.288872843530340110e-05 1.112352046586807781e-05 7.209921399975341084e-07 +7.812480201788416824e-03 7.806386805941349476e-03 7.774529785912486640e-03 7.755223553030285953e-03 4.528347453745602184e-05 1.731960264508936400e-05 2.622053730063316743e-05 1.100113352190226156e-05 4.399041900332164704e-07 +7.812496176044654919e-03 7.806891664948079936e-03 7.772291495159932770e-03 7.751926368829008263e-03 4.907275643454239819e-05 1.820754084061740197e-05 2.772288834078687984e-05 1.046061247568982606e-05 2.225225911981681611e-07 +7.812495292061822673e-03 7.807139215375609106e-03 7.772241751786874986e-03 7.751242393952807209e-03 5.001574978626547913e-05 1.812741955189118513e-05 2.764027203504243102e-05 1.032613486388670125e-05 1.665620513368287718e-07 +7.812476894523122731e-03 7.806683943209593787e-03 7.772945300038862533e-03 7.751111453457110168e-03 4.940863028517055046e-05 1.778892355151607562e-05 2.700354558676601411e-05 1.144278173216673945e-05 2.931356705096467600e-07 +7.812447633371830819e-03 7.805360622923213781e-03 7.772280325110742481e-03 7.748841300394401430e-03 4.946498788292683508e-05 1.819664607815776332e-05 2.735932394244346047e-05 1.421182877230432772e-05 5.348146728831700359e-07 +7.812418676200951796e-03 7.803399072295380545e-03 7.768182598560221565e-03 7.742056677893807692e-03 5.260502689341779259e-05 2.029938517503130136e-05 3.022889388385826916e-05 1.827918656212739249e-05 7.737969837445373764e-07 +7.812400713050573174e-03 7.801328899352429937e-03 7.759458933900293363e-03 7.729571012333778281e-03 6.059554765283085880e-05 2.461554399679295580e-05 3.650070756930909251e-05 2.260937471593158608e-05 9.062974796379607276e-07 +7.812399402924678250e-03 7.799725111593778897e-03 7.746317787884777345e-03 7.711834931169255294e-03 7.387281172230948569e-05 3.099207090489362784e-05 4.602122468061838116e-05 2.595267368927323958e-05 8.916091203328781368e-07 +7.812413332542555815e-03 7.798951317677097449e-03 7.730372562608386205e-03 7.690803617564479985e-03 9.132598392869010779e-05 3.860912329843406692e-05 5.757879489393928250e-05 2.744243129201358010e-05 7.582080085956336064e-07 +7.812435655750508100e-03 7.799045564899258556e-03 7.714106581128725958e-03 7.669307408003667517e-03 1.106354824953435383e-04 4.624173039586804786e-05 6.930319478072197116e-05 2.696493794476126531e-05 5.706638856372884918e-07 +7.812458049977899846e-03 7.799779002849843365e-03 7.700032119112999729e-03 7.650185626982551265e-03 1.290317728818038228e-04 5.267491242189746055e-05 7.931021912472004868e-05 2.510498190276937440e-05 3.874743003157170213e-07 +7.812474472833470102e-03 7.800806553791946735e-03 7.689895100482323394e-03 7.635495440478613609e-03 1.441671433054891155e-04 5.710082886942940348e-05 8.631673803264112315e-05 2.275885910941017286e-05 2.386244849668603841e-07 +7.812482976849034755e-03 7.801806678970187037e-03 7.684226346611384290e-03 7.626043122362352773e-03 1.547629942338338998e-04 5.933866733362661114e-05 8.998326647379967301e-05 2.069121747385026391e-05 1.297730912415325758e-07 +7.812485232220344605e-03 7.802559641047198541e-03 7.682363107231317788e-03 7.621351204389437833e-03 1.608167121281512204e-04 5.980453704693076267e-05 9.088196765691194143e-05 1.927999912557097661e-05 5.844008953976879205e-08 +7.812484687099224487e-03 7.802969819103481100e-03 7.682863284657014818e-03 7.620020195549746453e-03 1.633555907751381572e-04 5.927321903152686335e-05 9.015594799946130046e-05 1.851857110723650212e-05 2.355680679308437475e-08 +7.812484528579055273e-03 7.803053725096873068e-03 7.684099485053701856e-03 7.620313644105695082e-03 1.639054050789472161e-04 5.855667006084784424e-05 8.904796951092744850e-05 1.818147643885591132e-05 2.259562066722161082e-08 +7.812486347732097020e-03 7.802906138662985686e-03 7.684792010505495964e-03 7.620734657771241656e-03 1.639180799370792388e-04 5.823836154829621197e-05 8.849453651262909287e-05 1.801056113072297418e-05 4.482718225915012074e-08 +7.812489966877368686e-03 7.802652857458577430e-03 7.684311301855815610e-03 7.620397450278489949e-03 1.643642387066439835e-04 5.854960502899452695e-05 8.891359154098924097e-05 1.782919431049579911e-05 7.161912630444491773e-08 +7.812494127122805894e-03 7.802404580937485380e-03 7.682698807419341414e-03 7.619109876382451629e-03 1.655862811202974880e-04 5.939615713527549305e-05 9.021286715380141135e-05 1.757035112025118347e-05 8.559997302272443172e-08 +7.812497470211249989e-03 7.802228932425433333e-03 7.680464665858448801e-03 7.617210995022639063e-03 1.673906019698739671e-04 6.048444806446939652e-05 9.196185539774789648e-05 1.725117344749978250e-05 8.071052106673271989e-08 +7.812499262283496664e-03 7.802147068445501599e-03 7.678284905384741635e-03 7.615288498122666817e-03 1.692825327983098758e-04 6.147641588181483141e-05 9.362872093630432619e-05 1.693047970507380231e-05 6.424811185473353517e-08 +7.812499556017950091e-03 7.802145493693739449e-03 7.676725520415324244e-03 7.613906859695971675e-03 1.707300961208414974e-04 6.211532079841483437e-05 9.478777861569192588e-05 1.666872075534763098e-05 4.957518521111539337e-08 +7.812498898940323407e-03 7.802189426919653448e-03 7.676076529785660213e-03 7.613428103579155878e-03 1.713654284443885114e-04 6.229347725606795285e-05 9.523952736898054429e-05 1.649883460424523220e-05 4.584613527028352739e-08 +7.812497920560946760e-03 7.802232495060661827e-03 7.676319544958354509e-03 7.613946242661542678e-03 1.710785375910244487e-04 6.205778441104415428e-05 9.502791401655731585e-05 1.641215865889956077e-05 5.255976528493730751e-08 +7.812497066894792501e-03 7.802227167898124344e-03 7.677201581430874618e-03 7.615314113993682313e-03 1.700042512425950004e-04 6.156635540337338387e-05 9.437552276658168148e-05 1.636184653588275881e-05 6.184665501771761686e-08 +7.812496511241781051e-03 7.802139573436450704e-03 7.678360934842314196e-03 7.617224476854871258e-03 1.684368934514004535e-04 6.102002790153284524e-05 9.357839679933613655e-05 1.628189975863044079e-05 6.526686105702234742e-08 +7.812496219646037840e-03 7.801963573583982695e-03 7.679448409179731941e-03 7.619307392520942475e-03 1.667211245983212084e-04 6.059647760585791217e-05 9.290647870527361698e-05 1.611438596915572326e-05 5.944474959016087870e-08 +7.812496067262236082e-03 7.801724521784449314e-03 7.680207555690407410e-03 7.621215867234738643e-03 1.651611118942663268e-04 6.040796446319642645e-05 9.254061247558314075e-05 1.583289243326745281e-05 4.721294373152034348e-08 +7.812495939725520519e-03 7.801468805562560005e-03 7.680500815485480186e-03 7.622682332336906674e-03 1.639704408479166744e-04 6.049154736383084284e-05 9.255705934859457618e-05 1.545276710389118145e-05 3.486730501181152877e-08 +7.812495810392372161e-03 7.801245471614342251e-03 7.680293265591961113e-03 7.623542163437857511e-03 1.632627294083275303e-04 6.082500272239638590e-05 9.294827781949960212e-05 1.502481172788627132e-05 2.836530457701504368e-08 +7.812495774057383324e-03 7.801090398214164875e-03 7.679617741755038161e-03 7.623730980268567277e-03 1.630687270832232910e-04 6.135328767953494530e-05 9.365818359531991294e-05 1.461705702769232774e-05 3.062975683152378586e-08 +7.812496004572946559e-03 7.801019097885079565e-03 7.678544236128501121e-03 7.623267186730509938e-03 1.633636498553494383e-04 6.201144366886053398e-05 9.461157972898225999e-05 1.429342797726595519e-05 4.043850989161355651e-08 +7.812496631779798119e-03 7.801027496962795009e-03 7.677165776783217294e-03 7.622229199252808160e-03 1.640937838916600819e-04 6.273706605913448688e-05 9.572723457634188516e-05 1.409693806672889080e-05 5.277965583598395105e-08 +7.812497593986529945e-03 7.801096856079874943e-03 7.675599630972139084e-03 7.620731771399200105e-03 1.651974699868906436e-04 6.347246017827182240e-05 9.691547544110199126e-05 1.404137420550190033e-05 6.090756096056601143e-08 +7.812498566204971115e-03 7.801199754440974084e-03 7.673992897753495815e-03 7.618903661828040075e-03 1.666176502970805691e-04 6.416043472906765414e-05 9.806960623076769253e-05 1.411294308233202020e-05 5.993589060455973356e-08 +7.812499053771074925e-03 7.801305349386283491e-03 7.672518875246725489e-03 7.616869257773883906e-03 1.683046089823451085e-04 6.473936921646154048e-05 9.906343259329801248e-05 1.428210110113845229e-05 5.027682857905558417e-08 +7.812498632159666813e-03 7.801382900472925326e-03 7.671356652224933619e-03 7.614739595271466377e-03 1.702096434999436484e-04 6.514310541558802512e-05 9.976321818125709177e-05 1.452125443129783517e-05 3.829448713707502261e-08 +7.812497201837249015e-03 7.801403862531090978e-03 7.670657640407920266e-03 7.612615855838451850e-03 1.722743768132731137e-04 6.530927069172183942e-05 1.000534417096700466e-04 1.481781435146641011e-05 3.294263590754535029e-08 +7.812495078364333281e-03 7.801344666489945685e-03 7.670510553714322832e-03 7.610600036568103931e-03 1.744227893749939232e-04 6.519571551979745270e-05 9.986799788108100028e-05 1.517179567317124298e-05 4.016604303805187084e-08 +7.812492900103195845e-03 7.801192644470767747e-03 7.670919899304099940e-03 7.608803560422339532e-03 1.765599991482183864e-04 6.479804001506211746e-05 9.921318396850725772e-05 1.557572355818140049e-05 5.876129580872593247e-08 +7.812491399909044648e-03 7.800954310441960901e-03 7.671806713972414808e-03 7.607344211055998458e-03 1.785775612115598305e-04 6.415814227891146265e-05 9.817148076228197353e-05 1.599052210317778022e-05 8.069995376715356099e-08 +7.812491115931742038e-03 7.800660131530765505e-03 7.673033286305866278e-03 7.606329970254107307e-03 1.803626974654734159e-04 6.335517272175504935e-05 9.688053494765318523e-05 1.633939801180696436e-05 9.591747241806178274e-08 +7.812492133591250783e-03 7.800359190254140332e-03 7.674441600347642854e-03 7.605837575408820259e-03 1.818080321303487473e-04 6.248181849103899717e-05 9.549537823929271684e-05 1.653082719052810295e-05 9.833364655358530313e-08 +7.812494031046210430e-03 7.800102179172256622e-03 7.675896495846616999e-03 7.605897118576439818e-03 1.828226666389231193e-04 6.161441159967244615e-05 9.414446198404529656e-05 1.650237702724804381e-05 8.885369315965530215e-08 +7.812496052543584438e-03 7.799921303838168625e-03 7.677317282524499797e-03 7.606490090774489093e-03 1.833430573543588750e-04 6.079269373977964908e-05 9.289859503958730949e-05 1.625765820792788300e-05 7.334301113257308106e-08 +7.812497439077231015e-03 7.799819160821133690e-03 7.678687734277541560e-03 7.607558169686876905e-03 1.833426694457979708e-04 6.001769729579950902e-05 9.176364274852043203e-05 1.587269546633251967e-05 5.755832196158116801e-08 +7.812497729013648771e-03 7.799773549843452315e-03 7.680039522150496067e-03 7.609017003352169274e-03 1.828346147238102306e-04 5.926707271268964972e-05 9.069961910013031267e-05 1.546620639546001242e-05 4.367983950618309385e-08 +7.812496926672149108e-03 7.799752994451267067e-03 7.681416702438653189e-03 7.610766790791871801e-03 1.818667647155675722e-04 5.851800025715518221e-05 8.965562716129177984e-05 1.515316230951711319e-05 3.122579787001255668e-08 +7.812495468274187685e-03 7.799731951055652486e-03 7.682835526327059031e-03 7.612698745924777015e-03 1.805102346395485047e-04 5.776728284319049658e-05 8.860630501187015645e-05 1.500776599250491295e-05 2.081738234097757612e-08 +7.812494016638638072e-03 7.799697603207485230e-03 7.684256601122156811e-03 7.614700518728856164e-03 1.788464912402624996e-04 5.704162388654450915e-05 8.757577061659674008e-05 1.505214344464923625e-05 1.619689641452411641e-08 +7.812493190330011515e-03 7.799648584005202875e-03 7.685580722774925863e-03 7.616663927961365814e-03 1.769587121590053330e-04 5.639621921786125067e-05 8.664108488644773742e-05 1.526756760774609803e-05 2.164868747164934285e-08 +7.812493299653834079e-03 7.799590748379032698e-03 7.686670407032592141e-03 7.618494928507740273e-03 1.749302970073336380e-04 5.590279367022501475e-05 8.591411849626973997e-05 1.561254289370475563e-05 3.696860078954675002e-08 +7.812494265631523410e-03 7.799534011930964357e-03 7.687386700992878373e-03 7.620121303322026016e-03 1.728492941645273838e-04 5.563158007306383187e-05 8.550992286051971704e-05 1.603327927725472439e-05 5.520836506281878338e-08 +7.812495719581083985e-03 7.799488670675083432e-03 7.687630571093129368e-03 7.621494785823084046e-03 1.708138484432252554e-04 5.563085091837701400e-05 8.551007496670540967e-05 1.646635384646213534e-05 6.626114818767479494e-08 +7.812497205244232044e-03 7.799460270436679374e-03 7.687372984260292669e-03 7.622586576308315945e-03 1.689329458115936781e-04 5.591130652985255368e-05 8.593512815630114645e-05 1.684156091513745103e-05 6.387890909022737881e-08 diff --git a/tools/rt-tddft-tools/examples/ground-state-projection-Si/projection.py b/tools/rt-tddft-tools/examples/ground-state-projection-Si/projection.py index 10fa518c2ac..e8252190aa2 100644 --- a/tools/rt-tddft-tools/examples/ground-state-projection-Si/projection.py +++ b/tools/rt-tddft-tools/examples/ground-state-projection-Si/projection.py @@ -1,111 +1,116 @@ import numpy as np import matplotlib.pyplot as plt + + class Projection: - def __init__(self, stepref, klist, steps, fdir='./OUT.ABACUS', wfc_dir='', s_dir=''): + def __init__( + self, stepref, klist, steps, fdir="./OUT.ABACUS", wfc_dir="", s_dir="" + ): self.stepref = stepref self.klist = klist self.steps = steps self.wfc_dir = fdir + wfc_dir self.s_dir = fdir + s_dir - wfc_ref, Ocp_ref = self.read_wfc(klist[0]+1, stepref+1, dir=self.wfc_dir) + wfc_ref, Ocp_ref = self.read_wfc(klist[0] + 1, stepref + 1, dir=self.wfc_dir) self.nband = len(Ocp_ref) self.nlocal = len(wfc_ref[0]) - def read_wfc(self, kpoint, nstep, dir='.'): - file = dir+'/WFC_NAO_K'+str(kpoint)+'_ION'+str(nstep)+'.txt' - read_flag=0 - with open(file,'r') as f: + def read_wfc(self, kpoint, nstep, dir="."): + file = dir + "/WFC_NAO_K" + str(kpoint) + "_ION" + str(nstep) + ".txt" + read_flag = 0 + with open(file, "r") as f: for line in f: - if('bands' in line): - bands=int(line.split()[0]) - elif('orbitals' in line): - orbitals=int(line.split()[0]) - wavef0=np.zeros([bands,orbitals],dtype=complex) - Ocp=np.zeros(bands,dtype=float) - elif('(band)' in line): - read_flag=0 - i=int(line.split()[0])-1 - j=0 - elif('Occupations' in line): - Ocp[i]=float(line.split()[0]) - read_flag=1 + if "bands" in line: + bands = int(line.split()[0]) + elif "orbitals" in line: + orbitals = int(line.split()[0]) + wavef0 = np.zeros([bands, orbitals], dtype=complex) + Ocp = np.zeros(bands, dtype=float) + elif "(band)" in line: + read_flag = 0 + i = int(line.split()[0]) - 1 + j = 0 + elif "Occupations" in line: + Ocp[i] = float(line.split()[0]) + read_flag = 1 continue - elif(read_flag==1): - tmp=line.split() - for l in range(len(tmp)//2): - wavef0[i][j]=complex(float(tmp[2*l]),float(tmp[2*l+1])) - j+=1 - return wavef0,Ocp + elif read_flag == 1: + tmp = line.split() + for l in range(len(tmp) // 2): + wavef0[i][j] = complex(float(tmp[2 * l]), float(tmp[2 * l + 1])) + j += 1 + return wavef0, Ocp - def CSC(self, Cd,Sk,C): - Cdag=np.conjugate(Cd).transpose() - return np.matmul(Cdag,np.matmul(Sk,C)) - def CSC2(self, Cd,Sk,C): - CSC1=self.CSC(Cd,Sk,C) - return CSC1*CSC1.conjugate() + def CSC(self, Cd, Sk, C): + Cdag = np.conjugate(Cd).transpose() + return np.matmul(Cdag, np.matmul(Sk, C)) - def S_read(self, kpoint,nstep,dir='.'): - file = dir+'/'+str(nstep)+'_data-'+str(kpoint)+'-S' - count=0 - fir=1 - with open(file, 'r') as f1: + def CSC2(self, Cd, Sk, C): + CSC1 = self.CSC(Cd, Sk, C) + return CSC1 * CSC1.conjugate() + + def S_read(self, kpoint, nstep, dir="."): + file = dir + "/" + str(nstep) + "_data-" + str(kpoint) + "-S" + count = 0 + fir = 1 + with open(file, "r") as f1: for line in f1: - tmp=line.split() - if(fir==1): - dim=int(tmp[0]) - i=0 - Sk=np.zeros([dim,dim],dtype=complex) - fir=0 + tmp = line.split() + if fir == 1: + dim = int(tmp[0]) + i = 0 + Sk = np.zeros([dim, dim], dtype=complex) + fir = 0 for j in range(dim): - c_s=eval(tmp[j+1]) - Sk[i][j]=complex(c_s[0],c_s[1]) + c_s = eval(tmp[j + 1]) + Sk[i][j] = complex(c_s[0], c_s[1]) else: - for j in range(dim-i): - c_s=eval(tmp[j]) - Sk[i][i+j]=complex(c_s[0],c_s[1]) - i+=1 - if(i==0): - break + for j in range(dim - i): + c_s = eval(tmp[j]) + Sk[i][i + j] = complex(c_s[0], c_s[1]) + i += 1 + if i == 0: + break for i in range(dim): for j in range(i): - Sk[i][j]=Sk[j][i].conjugate() + Sk[i][j] = Sk[j][i].conjugate() return Sk def cal_Pnm(self, ik, nstep, wfc_ref): - wfc_t,Ocp_t=self.read_wfc(ik+1, nstep+1, dir=self.wfc_dir) - S_t=self.S_read(ik,nstep,dir=self.s_dir) - Pnm=np.zeros([self.nband,self.nband],dtype=float) + wfc_t, Ocp_t = self.read_wfc(ik + 1, nstep + 1, dir=self.wfc_dir) + S_t = self.S_read(ik, nstep, dir=self.s_dir) + Pnm = np.zeros([self.nband, self.nband], dtype=float) for a in range(self.nband): for b in range(self.nband): - Pnm[a][b] = self.CSC2(wfc_ref[a],S_t,wfc_t[b]).real + Pnm[a][b] = self.CSC2(wfc_ref[a], S_t, wfc_t[b]).real return Pnm, Ocp_t def cal_On_single(self, ik, nstep, wfc_ref): Pnm, Ocp_t = self.cal_Pnm(ik, nstep, wfc_ref) - On = np.zeros(self.nband,dtype=float) + On = np.zeros(self.nband, dtype=float) On = Ocp_t @ Pnm return On - + def save_On_all(self): for ik in self.klist: - wfc_ref,Ocp_ref=self.read_wfc(ik+1, self.stepref+1, dir=self.wfc_dir) - On_tot = np.zeros([len(steps),self.nband],dtype=float) + wfc_ref, Ocp_ref = self.read_wfc(ik + 1, self.stepref + 1, dir=self.wfc_dir) + On_tot = np.zeros([len(steps), self.nband], dtype=float) for n, nstep in enumerate(steps): On_tot[n] = self.cal_On_single(ik, nstep, wfc_ref) - np.savetxt('On_'+str(ik)+'.dat', On_tot) + np.savetxt("On_" + str(ik) + ".dat", On_tot) if __name__ == "__main__": - #the kpoints you need, check kpoints file to get the index, for this example, 0 means gamma point - klist=[0, 1] - #the steps you need, check STRU_MD file to get the index + # the kpoints you need, check kpoints file to get the index, for this example, 0 means gamma point + klist = [0, 1] + # the steps you need, check STRU_MD file to get the index start_step = 0 end_step = 10005 out_interval = 25 steps = range(start_step, end_step, out_interval) - #the ground state step - stepref=0 - #Ground state projection - pro=Projection(0, klist, steps) - #save the Occupation infos to file - pro.save_On_all() \ No newline at end of file + # the ground state step + stepref = 0 + # Ground state projection + pro = Projection(0, klist, steps) + # save the Occupation infos to file + pro.save_On_all() diff --git a/tools/rt-tddft-tools/overlap_generator.py b/tools/rt-tddft-tools/overlap_generator.py index d86f1af9405..bf6d3e09b49 100644 --- a/tools/rt-tddft-tools/overlap_generator.py +++ b/tools/rt-tddft-tools/overlap_generator.py @@ -6,28 +6,33 @@ import pyatb from pyatb.easy_use import stru_analyzer import re -Bohr=0.5291772105638411 + +Bohr = 0.5291772105638411 + + class overlap_R: def __init__(self, orb_file_dir, atoms0, atomst): # get orbital information from the structure - orb_file_list = list(atoms0.info['basis'].values()) + orb_file_list = list(atoms0.info["basis"].values()) orb_file_list = [orb_file_dir + orbfile for orbfile in orb_file_list] orb_file_num = len(orb_file_list) symbols = atoms0.get_chemical_symbols() element_counts = Counter(symbols) unique_elements = set(symbols) - assert orb_file_num == len(unique_elements), f"The number of orbitals{orb_file_num}does not match the number of unique elements{len(unique_elements)}!" + assert orb_file_num == len( + unique_elements + ), f"The number of orbitals{orb_file_num}does not match the number of unique elements{len(unique_elements)}!" # Build orbital collection self.orb = nao.RadialCollection() - self.orb.build(orb_file_num, orb_file_list, 'o') + self.orb.build(orb_file_num, orb_file_list, "o") # Standardize the orbital grid rmax = self.orb.rcut_max * 2.0 dr = 0.01 - nr = int(rmax/dr) + 1 - self.orb.set_uniform_grid(True, nr, rmax, 'i', True) + nr = int(rmax / dr) + 1 + self.orb.set_uniform_grid(True, nr, rmax, "i", True) # Print basic orbital information ntype = self.orb.ntype @@ -35,13 +40,13 @@ def __init__(self, orb_file_dir, atoms0, atomst): # Initialize the integrator self.S_intor = nao.TwoCenterIntegrator() - self.S_intor.tabulate(self.orb, self.orb, 'S', nr, rmax) + self.S_intor.tabulate(self.orb, self.orb, "S", nr, rmax) # Retrieve orbital index sorting from the structure # Determine the correspondence between the basis set indices and orbital information - self.lattice_vector = atoms0.get_cell()[:] / Bohr - self.atom_positions_c = atoms0.get_positions() / Bohr - self.atom_positions_ct = atomst.get_positions() / Bohr + self.lattice_vector = atoms0.get_cell()[:] / Bohr + self.atom_positions_c = atoms0.get_positions() / Bohr + self.atom_positions_ct = atomst.get_positions() / Bohr self.cal_R_direct_coor() self.iw2it = dict() @@ -54,56 +59,67 @@ def __init__(self, orb_file_dir, atoms0, atomst): count_atom = 0 for it, element in enumerate(unique_elements): for ia in range(element_counts[element]): - for iL in range(self.orb.lmax_(it)+1): + for iL in range(self.orb.lmax_(it) + 1): for iN in range(self.orb.nzeta(it, iL)): - for im in range(2*iL+1): + for im in range(2 * iL + 1): self.iw2it[count] = it - self.iw2positions_c[count] = self.atom_positions_c[count_atom] - self.iw2positions_ct[count] = self.atom_positions_ct[count_atom] + self.iw2positions_c[count] = self.atom_positions_c[ + count_atom + ] + self.iw2positions_ct[count] = self.atom_positions_ct[ + count_atom + ] self.iw2iL[count] = iL self.iw2iN[count] = iN - if im%2 == 0: - self.iw2im[count] = ((im+1) // 2) * -1 + if im % 2 == 0: + self.iw2im[count] = ((im + 1) // 2) * -1 else: - self.iw2im[count] = ((im+1) // 2) * 1 - + self.iw2im[count] = ((im + 1) // 2) * 1 + count = count + 1 count_atom = count_atom + 1 def cal_R_direct_coor(self): - rcut=self.orb.rcut_max*np.ones(len(self.atom_positions_c),dtype=float) + rcut = self.orb.rcut_max * np.ones(len(self.atom_positions_c), dtype=float) print(rcut) - Ncell = NeighbourCell(self.lattice_vector, self.atom_positions_c, self.atom_positions_ct, rcut) + Ncell = NeighbourCell( + self.lattice_vector, self.atom_positions_c, self.atom_positions_ct, rcut + ) self.R_direct_coor = np.array(Ncell.check_interaction_neighbours()) - + def cal_overlap(self): basis_num = len(self.iw2it) - self.SR = np.zeros((self.R_direct_coor.shape[0], basis_num, basis_num), dtype=float) + self.SR = np.zeros( + (self.R_direct_coor.shape[0], basis_num, basis_num), dtype=float + ) for iR, R_coor in enumerate(self.R_direct_coor): for row in range(basis_num): for col in range(basis_num): result = self.__cal_S(row, col, R_coor) self.SR[iR, row, col] = result[0] return self.SR - + def __cal_S(self, iw1, iw2, dR): dR = dR @ self.lattice_vector dtau = self.iw2positions_c[iw2] - self.iw2positions_ct[iw1] R = dR + dtau result = self.S_intor.calculate( - self.iw2it[iw1], + self.iw2it[iw1], self.iw2iL[iw1], self.iw2iN[iw1], self.iw2im[iw1], - self.iw2it[iw2], + self.iw2it[iw2], self.iw2iL[iw2], self.iw2iN[iw2], self.iw2im[iw2], - R, True) - + R, + True, + ) + return result - def cal_Sk(self,kpoint_direct_coor): + + def cal_Sk(self, kpoint_direct_coor): basis_num = len(self.iw2it) Sk = np.zeros([basis_num, basis_num], dtype=complex) for iR in range(self.R_direct_coor.shape[0]): @@ -111,25 +127,28 @@ def cal_Sk(self,kpoint_direct_coor): phase = complex(np.cos(arg), np.sin(arg)) Sk = Sk + phase * self.SR[iR] return Sk -def read_kpoints(file='.'): - file=file+'/kpoints' - with open(file,'r') as f: - read_flag=0 + + +def read_kpoints(file="."): + file = file + "/kpoints" + with open(file, "r") as f: + read_flag = 0 for line in f: - if('nkstot now' in line): - nks_tot=int(line.split()[3]) - kpoints=np.zeros([nks_tot,3],dtype=float) - if(read_flag==1): - tmp=line.split() - kpoints[ik]=np.array([float(tmp[1]),float(tmp[2]),float(tmp[3])]) - ik+=1 - if(ik==nks_tot): + if "nkstot now" in line: + nks_tot = int(line.split()[3]) + kpoints = np.zeros([nks_tot, 3], dtype=float) + if read_flag == 1: + tmp = line.split() + kpoints[ik] = np.array([float(tmp[1]), float(tmp[2]), float(tmp[3])]) + ik += 1 + if ik == nks_tot: break - if('WEIGHT' in line): - read_flag=1 - ik=0 + if "WEIGHT" in line: + read_flag = 1 + ik = 0 return kpoints + class NeighbourCell: def __init__(self, lattice_vectors, atom_positions0, atom_positionst, cutoff_radii): """ @@ -138,26 +157,40 @@ def __init__(self, lattice_vectors, atom_positions0, atom_positionst, cutoff_rad - atom_positions: Atom positions - cutoff_radii: Cutoff radii for each atom """ - if len(lattice_vectors) != 3 or len(atom_positions0) == 0 or len(cutoff_radii) != len(atom_positions0): + if ( + len(lattice_vectors) != 3 + or len(atom_positions0) == 0 + or len(cutoff_radii) != len(atom_positions0) + ): raise ValueError("Invalid lattice vectors, atom positions or cutoff radii") - + self.lattice_vectors = np.array(lattice_vectors) self.atom_positions0 = np.array(atom_positions0) self.atom_positionst = np.array(atom_positionst) self.cutoff_radii = np.array(cutoff_radii) self.natoms = len(atom_positions0) - def calculate_distance_to_neighbour(self, atom_index1, atom_index2, translation_vector): + def calculate_distance_to_neighbour( + self, atom_index1, atom_index2, translation_vector + ): """ Calculate the distance between any two atoms """ - if atom_index1 < 0 or atom_index1 >= self.natoms or \ - atom_index2 < 0 or atom_index2 >= self.natoms: + if ( + atom_index1 < 0 + or atom_index1 >= self.natoms + or atom_index2 < 0 + or atom_index2 >= self.natoms + ): raise IndexError("Atom index out of range") - - displacement = self.atom_positionst[atom_index2] - self.atom_positions0[atom_index1] + (self.lattice_vectors@np.array(translation_vector).T).T - - # Return the Euclidean distance + + displacement = ( + self.atom_positionst[atom_index2] + - self.atom_positions0[atom_index1] + + (self.lattice_vectors @ np.array(translation_vector).T).T + ) + + # Return the Euclidean distance return np.linalg.norm(displacement) def check_interaction_neighbours(self): @@ -167,39 +200,54 @@ def check_interaction_neighbours(self): translation_vector: The translation vector for the neighbouring unit cell Returns a list of translation vectors for all neighbouring cells with interactions. """ - interactions = [] # List to store translation vectors of neighbouring cells with interactions + interactions = ( + [] + ) # List to store translation vectors of neighbouring cells with interactions # Loop over translation vectors - for t in range(-5, 5): + for t in range(-5, 5): for u in range(-5, 5): for v in range(-5, 5): # Create a translation vector - neighbour_translation = np.array([t, u, v]) + neighbour_translation = np.array([t, u, v]) # Loop through each atom in the unit cell and check interactions with atoms in neighbouring cells if_find = False for i in range(self.natoms): for j in range(self.natoms): - distance = self.calculate_distance_to_neighbour(i, j, neighbour_translation) + distance = self.calculate_distance_to_neighbour( + i, j, neighbour_translation + ) # if overlap exists, add the translation vector to the list - if distance <= (self.cutoff_radii[i] + self.cutoff_radii[j]): + if distance <= ( + self.cutoff_radii[i] + self.cutoff_radii[j] + ): interactions.append(neighbour_translation) if_find = True - break + break if if_find: break return interactions + def save_upper_triangle_as_matrix(matrix, filename): # Open the file for writing - with open(filename, 'w') as f: - f.write(f'{matrix.shape[0]} ') + with open(filename, "w") as f: + f.write(f"{matrix.shape[0]} ") # Iterate over each row for i in range(matrix.shape[0]): # Extract the upper triangular part of the row - row = matrix[i, i:] - row_str = ' '.join(f'({x.real:.8e},{x.imag:.8e})' for x in row) - f.write(row_str + '\n') + row = matrix[i, i:] + row_str = " ".join(f"({x.real:.8e},{x.imag:.8e})" for x in row) + f.write(row_str + "\n") + -def overlap_gen(stepref: int, klist, steps, stru_dir='./OUT.ABACUS/STRU', orb_file_dir='',kpoits_dir='./OUT.ABACUS'): +def overlap_gen( + stepref: int, + klist, + steps, + stru_dir="./OUT.ABACUS/STRU", + orb_file_dir="", + kpoits_dir="./OUT.ABACUS", +): """Generate overlap files for moved atoms :params stepref: the ground state step :params klist: the list for needed kpoints @@ -208,34 +256,34 @@ def overlap_gen(stepref: int, klist, steps, stru_dir='./OUT.ABACUS/STRU', orb_fi :params orb_file_dir: the directory for orb files, same as 'orbital_dir' in the INPUT :params kpoits_dir: the directory for kpoints files """ - #read in ref STRU - with open(stru_dir+'/STRU_MD_'+str(stepref), 'r') as fd: + # read in ref STRU + with open(stru_dir + "/STRU_MD_" + str(stepref), "r") as fd: atoms0 = stru_analyzer.read_abacus_stru(fd, verbose=True) - #read in kpoints - kpt=read_kpoints(kpoits_dir) - #loop over steps + # read in kpoints + kpt = read_kpoints(kpoits_dir) + # loop over steps for n, nstep in enumerate(steps): - #read in time t STRU - with open(stru_dir+'/STRU_MD_'+str(nstep), 'r') as fd: + # read in time t STRU + with open(stru_dir + "/STRU_MD_" + str(nstep), "r") as fd: atomst = stru_analyzer.read_abacus_stru(fd, verbose=True) SR_tmp = overlap_R(orb_file_dir, atoms0, atomst) SR_tmp.cal_overlap() - #loop over kpoints needed + # loop over kpoints needed for ik in klist: Sk_ik = SR_tmp.cal_Sk(kpt[ik]) - save_upper_triangle_as_matrix(Sk_ik, f'{nstep}_data-{ik}-S') + save_upper_triangle_as_matrix(Sk_ik, f"{nstep}_data-{ik}-S") -#warning : pyatb and pyabacus are required, install them first +# warning : pyatb and pyabacus are required, install them first if __name__ == "__main__": - #the kpoints you need, check kpoints file to get the index - klist=[0] - #the steps you need, check STRU_MD file to get the index + # the kpoints you need, check kpoints file to get the index + klist = [0] + # the steps you need, check STRU_MD file to get the index start_step = 0 end_step = 20 out_interval = 5 steps = range(start_step, end_step, out_interval) - #the ground state step - stepref=0 - #generate overlap files for moved atoms + # the ground state step + stepref = 0 + # generate overlap files for moved atoms overlap_gen(stepref, klist, steps) diff --git a/tools/rt-tddft-tools/plot_absorption.py b/tools/rt-tddft-tools/plot_absorption.py index e46bd0a0eee..40e88db9d0a 100644 --- a/tools/rt-tddft-tools/plot_absorption.py +++ b/tools/rt-tddft-tools/plot_absorption.py @@ -20,32 +20,42 @@ import matplotlib.pyplot as plt # LaTeX rendering -plt.rcParams.update({ - "text.usetex": False, - "legend.fontsize": 16, - "axes.labelsize": 16, - "xtick.labelsize": 14, - "ytick.labelsize": 14, -}) +plt.rcParams.update( + { + "text.usetex": False, + "legend.fontsize": 16, + "axes.labelsize": 16, + "xtick.labelsize": 14, + "ytick.labelsize": 14, + } +) # Conversion: 1/fs → eV FREQ2EV = sc.h / sc.eV * 1e15 # Conversion: V/Å → a.u. of E-field, 1 a.u. = 51.422 V/Å -V_ANGSTROM_TO_AU_EFIELD = (sc.e / (4 * sc.pi * sc.epsilon_0 * sc.physical_constants['Bohr radius'][0]**2) * 1e-10) +V_ANGSTROM_TO_AU_EFIELD = ( + sc.e + / (4 * sc.pi * sc.epsilon_0 * sc.physical_constants["Bohr radius"][0] ** 2) + * 1e-10 +) # Conversion: fs → a.u. of time, 1 fs = 41.34137 a.u. -AU_TIME = sc.physical_constants['atomic unit of time'][0] +AU_TIME = sc.physical_constants["atomic unit of time"][0] FS_TO_AU_TIME = 1e-15 / AU_TIME # ====================== # Utility Functions # ====================== + def validate_inputs(direc: List[int], efield_path: List[str]) -> None: if len(direc) != len(efield_path): - raise ValueError(f"Number of --direc ({len(direc)}) != --efield_path ({len(efield_path)})") + raise ValueError( + f"Number of --direc ({len(direc)}) != --efield_path ({len(efield_path)})" + ) if not all(d in (0, 1, 2) for d in direc): raise ValueError("--direc values must be 0 (x), 1 (y), or 2 (z)") + def group_files_by_direction(direc: List[int], paths: List[str]) -> List[List[str]]: """Return [[x_files], [y_files], [z_files]]""" groups = [[], [], []] @@ -53,7 +63,10 @@ def group_files_by_direction(direc: List[int], paths: List[str]) -> List[List[st groups[d].append(p) return groups -def zero_pad_and_mask(signal: np.ndarray, dt: float, pad_factor: int = 10, decay_beta: float = 5.0) -> np.ndarray: + +def zero_pad_and_mask( + signal: np.ndarray, dt: float, pad_factor: int = 10, decay_beta: float = 5.0 +) -> np.ndarray: """Apply exponential decay mask and zero-padding for FFT.""" n = len(signal) t = np.arange(n) * dt @@ -62,16 +75,21 @@ def zero_pad_and_mask(signal: np.ndarray, dt: float, pad_factor: int = 10, decay padded[:n] = signal * mask return padded + def energy_from_fft(N: int, dt: float) -> np.ndarray: """Return positive-frequency energy array in eV.""" - freqs = np.fft.fftfreq(N, d=dt)[:N//2] # in 1/fs + freqs = np.fft.fftfreq(N, d=dt)[: N // 2] # in 1/fs return freqs * FREQ2EV + # ====================== # Data Loaders # ====================== -def load_dipole(filename: str, step_start: int, step_end: int, remove_dc: bool) -> np.ndarray: + +def load_dipole( + filename: str, step_start: int, step_end: int, remove_dc: bool +) -> np.ndarray: """Load current/dipole. Optionally remove DC component.""" data = np.loadtxt(filename) end = min(step_end or len(data), data.shape[0]) @@ -87,23 +105,30 @@ def load_dipole(filename: str, step_start: int, step_end: int, remove_dc: bool) sliced[i] -= sliced[i, 0] return sliced -def load_efield(file_groups: List[List[str]], step_start: int, step_end: int, remove_dc: bool) -> np.ndarray: + +def load_efield( + file_groups: List[List[str]], step_start: int, step_end: int, remove_dc: bool +) -> np.ndarray: """Load and sum E-field files per direction. Convert V/Å → a.u. Optionally remove DC component.""" n_steps = step_end - step_start efield = np.zeros((3, n_steps)) for i, files in enumerate(file_groups): for f in files: arr = np.loadtxt(f) - efield[i] += arr[step_start:step_end, 1] / V_ANGSTROM_TO_AU_EFIELD # V/Å → a.u. + efield[i] += ( + arr[step_start:step_end, 1] / V_ANGSTROM_TO_AU_EFIELD + ) # V/Å → a.u. # Remove DC (zero-frequency) component by subtracting mean if remove_dc and n_steps > 0: efield[i] -= np.mean(efield[i]) return efield + # ====================== # Core Calculator # ====================== + class AbsorptionSpectrum: def __init__( self, @@ -126,8 +151,12 @@ def __init__( def compute_alpha(self, direction: int) -> np.ndarray: """Compute alpha(ω) for a given direction (0,1,2). Returns full FFT array.""" - d_pad = zero_pad_and_mask(self.dipole[direction], self.dt_au, self.pad_factor, self.decay_beta) - e_pad = zero_pad_and_mask(self.efield[direction], self.dt_au, self.pad_factor, self.decay_beta) + d_pad = zero_pad_and_mask( + self.dipole[direction], self.dt_au, self.pad_factor, self.decay_beta + ) + e_pad = zero_pad_and_mask( + self.efield[direction], self.dt_au, self.pad_factor, self.decay_beta + ) d_fft = np.fft.fft(d_pad) e_fft = np.fft.fft(e_pad) @@ -139,39 +168,60 @@ def compute_alpha(self, direction: int) -> np.ndarray: elif self.system_type == "dipole_sigma": # Full frequency array (length = N_pad) freqs_full = np.fft.fftfreq(self.N_pad, d=self.dt_au) # f in a.u.^{-1} - omega = 2 * np.pi * freqs_full # ω in a.u.^{-1} + omega = 2 * np.pi * freqs_full # ω in a.u.^{-1} alpha = np.multiply(ratio.imag, omega) return np.abs(alpha) elif self.system_type == "current_epsilon": # Full frequency array (length = N_pad) freqs_full = np.fft.fftfreq(self.N_pad, d=self.dt_au) # f in a.u.^{-1} - omega = 2 * np.pi * freqs_full # ω in a.u.^{-1} - alpha = np.divide(ratio.real, omega, out=np.zeros_like(ratio.real), where=omega != 0) + omega = 2 * np.pi * freqs_full # ω in a.u.^{-1} + alpha = np.divide( + ratio.real, omega, out=np.zeros_like(ratio.real), where=omega != 0 + ) return np.abs(alpha) elif self.system_type == "current_sigma": return np.abs(ratio.real) else: - raise ValueError("system_type must be 'dipole_epsilon', 'dipole_sigma', 'current_epsilon', or 'current_sigma'") + raise ValueError( + "system_type must be 'dipole_epsilon', 'dipole_sigma', 'current_epsilon', or 'current_sigma'" + ) def get_positive_alpha(self, direction: int) -> np.ndarray: """Return alpha for positive frequencies only.""" - return self.compute_alpha(direction)[:self.N_pad // 2] + return self.compute_alpha(direction)[: self.N_pad // 2] def get_energy_axis(self) -> np.ndarray: return energy_from_fft(self.N_pad, self.dt) + # ====================== # Plotting Utilities # ====================== -def plot_time_series(ax, time: np.ndarray, data: np.ndarray, directions: List[int], labels: List[str], ylabel: str): + +def plot_time_series( + ax, + time: np.ndarray, + data: np.ndarray, + directions: List[int], + labels: List[str], + ylabel: str, +): for d in directions: ax.plot(time, data[d], label=labels[d]) ax.set_xlabel("Time (fs)") ax.set_ylabel(ylabel) ax.legend() -def plot_absorption(ax, x_vals: np.ndarray, alphas: List[np.ndarray], directions: List[int], xlabel: str, x_range: Optional[Tuple] = None): + +def plot_absorption( + ax, + x_vals: np.ndarray, + alphas: List[np.ndarray], + directions: List[int], + xlabel: str, + x_range: Optional[Tuple] = None, +): labels = {0: "$x$", 1: "$y$", 2: "$z$"} for d, alpha in zip(directions, alphas): ax.plot(x_vals, alpha, label=labels[d]) @@ -182,29 +232,51 @@ def plot_absorption(ax, x_vals: np.ndarray, alphas: List[np.ndarray], directions ax.set_xlim(x_range) mask = (x_vals >= min(x_range)) & (x_vals <= max(x_range)) if np.any(mask): - ax.set_ylim(0, 1.2 * max(max(a[mask]) for a in alphas if len(a) == len(x_vals))) - -def plot_fft(ax, energies: np.ndarray, signals: List[np.ndarray], directions: List[int], data_type: str): + ax.set_ylim( + 0, 1.2 * max(max(a[mask]) for a in alphas if len(a) == len(x_vals)) + ) + + +def plot_fft( + ax, + energies: np.ndarray, + signals: List[np.ndarray], + directions: List[int], + data_type: str, +): """Plot both real and imaginary parts of FFT for given signals.""" labels = {0: "$x$", 1: "$y$", 2: "$z$"} for d, sig in zip(directions, signals): - sig_pos = sig[:len(energies)] # positive frequency part - ax.plot(energies, sig_pos.real, '-', label=f'Re[{labels[d]}]') - ax.plot(energies, sig_pos.imag, '--', label=f'Im[{labels[d]}]') + sig_pos = sig[: len(energies)] # positive frequency part + ax.plot(energies, sig_pos.real, "-", label=f"Re[{labels[d]}]") + ax.plot(energies, sig_pos.imag, "--", label=f"Im[{labels[d]}]") ax.set_xlabel("Energy (eV)") ax.set_ylabel("FFT Amplitude") ax.set_xlim(0, 20) ax.legend() + # ====================== # Kramers-Kronig Relations # ====================== -def compute_response_function(dipole_fft: np.ndarray, efield_fft: np.ndarray) -> np.ndarray: + +def compute_response_function( + dipole_fft: np.ndarray, efield_fft: np.ndarray +) -> np.ndarray: """Compute complex response χ(ω) = D(ω) / E(ω)""" - return np.divide(dipole_fft, efield_fft, out=np.zeros_like(dipole_fft), where=efield_fft != 0) + return np.divide( + dipole_fft, efield_fft, out=np.zeros_like(dipole_fft), where=efield_fft != 0 + ) + -def auto_ylim(data: np.ndarray, x: np.ndarray, x_min: float = 0.5, x_max: float = 20.0, percentile: float = 99.5) -> Tuple[float, float]: +def auto_ylim( + data: np.ndarray, + x: np.ndarray, + x_min: float = 0.5, + x_max: float = 20.0, + percentile: float = 99.5, +) -> Tuple[float, float]: """ Automatically determine y-limits by: 1. Restricting to energy range [x_min, x_max] @@ -224,7 +296,10 @@ def auto_ylim(data: np.ndarray, x: np.ndarray, x_min: float = 0.5, x_max: float margin = 0.1 * (y_high - y_low) if y_high != y_low else 0.1 * max(abs(y_high), 1) return y_low - margin, y_high + margin -def kk_hilbert_transform(signal_pos: np.ndarray, omega: np.ndarray, is_odd: bool = True) -> np.ndarray: + +def kk_hilbert_transform( + signal_pos: np.ndarray, omega: np.ndarray, is_odd: bool = True +) -> np.ndarray: """ Compute the Hilbert transform of a function defined on positive frequencies. @@ -250,7 +325,9 @@ def kk_hilbert_transform(signal_pos: np.ndarray, omega: np.ndarray, is_odd: bool omega_full = np.linspace(-omega_max, omega_max, 2 * N - 1) # Interpolator for positive side - interp = interp1d(omega, signal_pos, kind='linear', bounds_error=False, fill_value=0.0) + interp = interp1d( + omega, signal_pos, kind="linear", bounds_error=False, fill_value=0.0 + ) # Extend to negative frequencies signal_full = np.zeros_like(omega_full) @@ -259,38 +336,66 @@ def kk_hilbert_transform(signal_pos: np.ndarray, omega: np.ndarray, is_odd: bool if is_odd: signal_full[~pos_mask] = -interp(-omega_full[~pos_mask]) # odd extension else: - signal_full[~pos_mask] = interp(-omega_full[~pos_mask]) # even extension + signal_full[~pos_mask] = interp(-omega_full[~pos_mask]) # even extension # Compute analytic signal → Hilbert transform is imaginary part analytic = hilbert_scipy(signal_full) ht_full = analytic.imag # this is H[signal_full] # Extract positive frequencies (center at index N-1) - ht_pos = ht_full[N - 1:] + ht_pos = ht_full[N - 1 :] return ht_pos + # ====================== # Main Entry Point # ====================== + def main(): - parser = argparse.ArgumentParser(description="Plot RT-TDDFT absorption spectrum from ABACUS output.") + parser = argparse.ArgumentParser( + description="Plot RT-TDDFT absorption spectrum from ABACUS output." + ) parser.add_argument("--td_dt", type=float, default=0.00484, help="Time step in fs") - parser.add_argument("--direc", type=int, nargs="+", required=True, help="Field directions: 0=x,1=y,2=z") - parser.add_argument("--efield_path", type=str, nargs="+", required=True, help="E-field file paths") + parser.add_argument( + "--direc", + type=int, + nargs="+", + required=True, + help="Field directions: 0=x,1=y,2=z", + ) + parser.add_argument( + "--efield_path", type=str, nargs="+", required=True, help="E-field file paths" + ) parser.add_argument("--dipolefile", type=str, default="./OUT.ABACUS/dipole_s1.txt") # parser.add_argument("--dipolefile", type=str, default="./OUT.ABACUS/dipole_s1.txt") - parser.add_argument("--material_name", type=str, - default=r"CH$_3$COOH", help="Name for plot title") + parser.add_argument( + "--material_name", type=str, default=r"CH$_3$COOH", help="Name for plot title" + ) parser.add_argument("--step_start", type=int, default=0) parser.add_argument("--step_end", type=int, default=8000) - parser.add_argument("--system_type", choices=["dipole_epsilon", "dipole_sigma", "current_epsilon", "current_sigma"], - default="dipole_sigma", help="Type of system and response for absorption calculation") - parser.add_argument("--pad_factor", type=int, default=10, help="Zero-padding factor for FFT") - parser.add_argument("--decay_beta", type=float, default=5, help="Exponential decay parameter for windowing") - parser.add_argument("--remove_dc", type=bool, default=False, - help="Whether to remove DC component from time signals") + parser.add_argument( + "--system_type", + choices=["dipole_epsilon", "dipole_sigma", "current_epsilon", "current_sigma"], + default="dipole_sigma", + help="Type of system and response for absorption calculation", + ) + parser.add_argument( + "--pad_factor", type=int, default=10, help="Zero-padding factor for FFT" + ) + parser.add_argument( + "--decay_beta", + type=float, + default=5, + help="Exponential decay parameter for windowing", + ) + parser.add_argument( + "--remove_dc", + type=bool, + default=False, + help="Whether to remove DC component from time signals", + ) args = parser.parse_args() @@ -298,8 +403,12 @@ def main(): Efile_groups = group_files_by_direction(args.direc, args.efield_path) # Load data - dipole_data = load_dipole(args.dipolefile, args.step_start, args.step_end, args.remove_dc) - efield_data = load_efield(Efile_groups, args.step_start, args.step_end, args.remove_dc) + dipole_data = load_dipole( + args.dipolefile, args.step_start, args.step_end, args.remove_dc + ) + efield_data = load_efield( + Efile_groups, args.step_start, args.step_end, args.remove_dc + ) # Compute absorption absorber = AbsorptionSpectrum( @@ -313,22 +422,30 @@ def main(): energies = absorber.get_energy_axis() - with np.errstate(divide='ignore'): - wavelengths = np.where(energies > 0, (sc.h * sc.c / sc.eV * 1e9) / energies, np.inf) + with np.errstate(divide="ignore"): + wavelengths = np.where( + energies > 0, (sc.h * sc.c / sc.eV * 1e9) / energies, np.inf + ) directions = sorted(set(args.direc)) # unique directions to plot # --- Save data --- alphas = [absorber.get_positive_alpha(d) for d in range(3)] data_out = np.column_stack([energies, wavelengths] + alphas) - np.savetxt("abs_dat.txt", data_out, header="Energy(eV) Wavelength(nm) alpha_X alpha_Y alpha_Z") + np.savetxt( + "abs_dat.txt", + data_out, + header="Energy(eV) Wavelength(nm) alpha_X alpha_Y alpha_Z", + ) # --- Plotting --- time = np.arange(args.step_end - args.step_start) * args.td_dt # 1. Dipole vs time fig, ax = plt.subplots(figsize=(10, 6)) - plot_time_series(ax, time, dipole_data, directions, ["$J_x$", "$J_y$", "$J_z$"], "Current (a.u.)") + plot_time_series( + ax, time, dipole_data, directions, ["$J_x$", "$J_y$", "$J_z$"], "Current (a.u.)" + ) ax.set_xlim(0, args.step_end * args.td_dt) fig.savefig("dipole.png", dpi=300, bbox_inches="tight") @@ -337,7 +454,9 @@ def main(): alphas_to_plot = [absorber.get_positive_alpha(d) for d in directions] xmax = 20 # plot_absorption(ax, energies, alphas_to_plot, directions, x_range=(5, xmax)) - plot_absorption(ax, energies, alphas_to_plot, directions, xlabel="Energy (eV)", x_range=(4, 20)) + plot_absorption( + ax, energies, alphas_to_plot, directions, xlabel="Energy (eV)", x_range=(4, 20) + ) # Automatically set y-limits all_alpha = np.concatenate([a for a in alphas_to_plot if len(a) == len(energies)]) if len(all_alpha) > 0: @@ -353,9 +472,18 @@ def main(): # Set wavelength range for plotting wl_min, wl_max = 80, 200 - plot_absorption(ax, wavelengths, alphas_to_plot, directions, xlabel="Wavelength (nm)", x_range=(wl_min, wl_max)) + plot_absorption( + ax, + wavelengths, + alphas_to_plot, + directions, + xlabel="Wavelength (nm)", + x_range=(wl_min, wl_max), + ) - all_alpha = np.concatenate([a for a in alphas_to_plot if len(a) == len(wavelengths)]) + all_alpha = np.concatenate( + [a for a in alphas_to_plot if len(a) == len(wavelengths)] + ) if len(all_alpha) > 0: ymin, ymax = auto_ylim(all_alpha, wavelengths, x_min=wl_min, x_max=wl_max) ax.set_ylim(0, ymax) @@ -366,19 +494,32 @@ def main(): # 3. E-field Fourier fig, ax = plt.subplots(figsize=(10, 6)) - efield_ffts = [np.fft.fft(zero_pad_and_mask(efield_data[d], args.td_dt, args.pad_factor)) for d in directions] + efield_ffts = [ + np.fft.fft(zero_pad_and_mask(efield_data[d], args.td_dt, args.pad_factor)) + for d in directions + ] plot_fft(ax, energies, efield_ffts, directions, "efield") fig.savefig("efield_fourier.png", dpi=300, bbox_inches="tight") # 4. Dipole Fourier fig, ax = plt.subplots(figsize=(10, 6)) - dipole_ffts = [np.fft.fft(zero_pad_and_mask(dipole_data[d], args.td_dt, args.pad_factor)) for d in directions] + dipole_ffts = [ + np.fft.fft(zero_pad_and_mask(dipole_data[d], args.td_dt, args.pad_factor)) + for d in directions + ] plot_fft(ax, energies, dipole_ffts, directions, "dipole") fig.savefig("dipole_fourier.png", dpi=300, bbox_inches="tight") # 5. E-field vs time fig, ax = plt.subplots(figsize=(10, 6)) - plot_time_series(ax, time, efield_data, directions, ["$E_x$", "$E_y$", "$E_z$"], "Electric Field (a.u.)") + plot_time_series( + ax, + time, + efield_data, + directions, + ["$E_x$", "$E_y$", "$E_z$"], + "Electric Field (a.u.)", + ) ax.set_xlim(0, 1) fig.savefig("efield_time.png", dpi=300, bbox_inches="tight") @@ -388,32 +529,46 @@ def main(): for idx, d in enumerate(directions): # --- Get complex response --- - d_pad = zero_pad_and_mask(dipole_data[d], args.td_dt, args.pad_factor, args.decay_beta) - e_pad = zero_pad_and_mask(efield_data[d], args.td_dt, args.pad_factor, args.decay_beta) + d_pad = zero_pad_and_mask( + dipole_data[d], args.td_dt, args.pad_factor, args.decay_beta + ) + e_pad = zero_pad_and_mask( + efield_data[d], args.td_dt, args.pad_factor, args.decay_beta + ) d_fft = np.fft.fft(d_pad) e_fft = np.fft.fft(e_pad) chi = compute_response_function(d_fft, e_fft) - chi_pos = chi[:len(energies)] + chi_pos = chi[: len(energies)] chi_real = chi_pos.real chi_imag = chi_pos.imag omega = energies # in eV # --- Reconstruct real part from imag --- - chi_real_KK = kk_hilbert_transform(chi_imag, omega, is_odd=True) # χ'' is odd → use odd extension + chi_real_KK = kk_hilbert_transform( + chi_imag, omega, is_odd=True + ) # χ'' is odd → use odd extension # --- Reconstruct imag part from real --- - chi_imag_KK = -kk_hilbert_transform(chi_real, omega, is_odd=False) # χ' is even → use even extension + chi_imag_KK = -kk_hilbert_transform( + chi_real, omega, is_odd=False + ) # χ' is even → use even extension # --- Plot: Real part comparison --- ax1 = axes_kk[idx, 0] - ax1.plot(omega, chi_real, 'b-', lw=1.5, label=r"$\chi'(\omega)$ (FFT)") - ax1.plot(omega, chi_real_KK, 'r--', lw=1.5, label=r"$\mathcal{H}[\chi''](\omega)$") + ax1.plot(omega, chi_real, "b-", lw=1.5, label=r"$\chi'(\omega)$ (FFT)") + ax1.plot( + omega, chi_real_KK, "r--", lw=1.5, label=r"$\mathcal{H}[\chi''](\omega)$" + ) ax1.set_xlabel("Energy (eV)") ax1.set_ylabel(r"$\chi'(\omega)$") - ax1.set_title(f"Direction {['$x$','$y$','$z$'][d]}: Real part KK check", fontsize=18, y=1.02) + ax1.set_title( + f"Direction {['$x$','$y$','$z$'][d]}: Real part KK check", + fontsize=18, + y=1.02, + ) ax1.legend() - ax1.grid(True, linestyle=':', alpha=0.6) + ax1.grid(True, linestyle=":", alpha=0.6) ax1.set_xlim(0, min(20, omega[-1])) # Automatically set y-limits ymin, ymax = auto_ylim(chi_real, omega, x_min=0.5, x_max=20.0) @@ -422,13 +577,19 @@ def main(): # --- Plot: Imaginary part comparison --- ax2 = axes_kk[idx, 1] - ax2.plot(omega, chi_imag, 'g-', lw=1.5, label=r"$\chi''(\omega)$ (FFT)") - ax2.plot(omega, chi_imag_KK, 'm--', lw=1.5, label=r"$-\mathcal{H}[\chi'](\omega)$") + ax2.plot(omega, chi_imag, "g-", lw=1.5, label=r"$\chi''(\omega)$ (FFT)") + ax2.plot( + omega, chi_imag_KK, "m--", lw=1.5, label=r"$-\mathcal{H}[\chi'](\omega)$" + ) ax2.set_xlabel("Energy (eV)") ax2.set_ylabel(r"$\chi''(\omega)$") - ax2.set_title(f"Direction {['$x$','$y$','$z$'][d]}: Imaginary part KK check", fontsize=18, y=1.02) + ax2.set_title( + f"Direction {['$x$','$y$','$z$'][d]}: Imaginary part KK check", + fontsize=18, + y=1.02, + ) ax2.legend() - ax2.grid(True, linestyle=':', alpha=0.6) + ax2.grid(True, linestyle=":", alpha=0.6) ax2.set_xlim(0, min(20, omega[-1])) # Automatically set y-limits ymin2, ymax2 = auto_ylim(chi_imag, omega, x_min=0.5, x_max=20.0) @@ -440,5 +601,6 @@ def main(): print("Plots and data saved successfully.") + if __name__ == "__main__": main() diff --git a/tools/rt-tddft-tools/projection.py b/tools/rt-tddft-tools/projection.py index 80d54504b1b..505fd40862c 100644 --- a/tools/rt-tddft-tools/projection.py +++ b/tools/rt-tddft-tools/projection.py @@ -1,111 +1,116 @@ import numpy as np import matplotlib.pyplot as plt + + class Projection: - def __init__(self, stepref, klist, steps, fdir='./OUT.ABACUS', wfc_dir='', s_dir=''): + def __init__( + self, stepref, klist, steps, fdir="./OUT.ABACUS", wfc_dir="", s_dir="" + ): self.stepref = stepref self.klist = klist self.steps = steps self.wfc_dir = fdir + wfc_dir - self.s_dir = fdir suffix + s_dir - wfc_ref, Ocp_ref = self.read_wfc(klist[0]+1, stepref+1, dir=self.wfc_dir) + self.s_dir = fdir + s_dir + wfc_ref, Ocp_ref = self.read_wfc(klist[0] + 1, stepref + 1, dir=self.wfc_dir) self.nband = len(Ocp_ref) self.nlocal = len(wfc_ref[0]) - def read_wfc(self, kpoint, nstep, dir='.'): - file = dir+'/WFC_NAO_K'+str(kpoint)+'_ION'+str(nstep)+'.txt' - read_flag=0 - with open(file,'r') as f: + def read_wfc(self, kpoint, nstep, dir="."): + file = dir + "/WFC_NAO_K" + str(kpoint) + "_ION" + str(nstep) + ".txt" + read_flag = 0 + with open(file, "r") as f: for line in f: - if('bands' in line): - bands=int(line.split()[0]) - elif('orbitals' in line): - orbitals=int(line.split()[0]) - wavef0=np.zeros([bands,orbitals],dtype=complex) - Ocp=np.zeros(bands,dtype=float) - elif('(band)' in line): - read_flag=0 - i=int(line.split()[0])-1 - j=0 - elif('Occupations' in line): - Ocp[i]=float(line.split()[0]) - read_flag=1 + if "bands" in line: + bands = int(line.split()[0]) + elif "orbitals" in line: + orbitals = int(line.split()[0]) + wavef0 = np.zeros([bands, orbitals], dtype=complex) + Ocp = np.zeros(bands, dtype=float) + elif "(band)" in line: + read_flag = 0 + i = int(line.split()[0]) - 1 + j = 0 + elif "Occupations" in line: + Ocp[i] = float(line.split()[0]) + read_flag = 1 continue - elif(read_flag==1): - tmp=line.split() - for l in range(len(tmp)//2): - wavef0[i][j]=complex(float(tmp[2*l]),float(tmp[2*l+1])) - j+=1 - return wavef0,Ocp + elif read_flag == 1: + tmp = line.split() + for l in range(len(tmp) // 2): + wavef0[i][j] = complex(float(tmp[2 * l]), float(tmp[2 * l + 1])) + j += 1 + return wavef0, Ocp - def CSC(self, Cd,Sk,C): - Cdag=np.conjugate(Cd).transpose() - return np.matmul(Cdag,np.matmul(Sk,C)) - def CSC2(self, Cd,Sk,C): - CSC1=self.CSC(Cd,Sk,C) - return CSC1*CSC1.conjugate() + def CSC(self, Cd, Sk, C): + Cdag = np.conjugate(Cd).transpose() + return np.matmul(Cdag, np.matmul(Sk, C)) - def S_read(self, kpoint,nstep,dir='.'): - file = dir+'/'+str(nstep)+'_data-'+str(kpoint)+'-S' - count=0 - fir=1 - with open(file, 'r') as f1: + def CSC2(self, Cd, Sk, C): + CSC1 = self.CSC(Cd, Sk, C) + return CSC1 * CSC1.conjugate() + + def S_read(self, kpoint, nstep, dir="."): + file = dir + "/" + str(nstep) + "_data-" + str(kpoint) + "-S" + count = 0 + fir = 1 + with open(file, "r") as f1: for line in f1: - tmp=line.split() - if(fir==1): - dim=int(tmp[0]) - i=0 - Sk=np.zeros([dim,dim],dtype=complex) - fir=0 + tmp = line.split() + if fir == 1: + dim = int(tmp[0]) + i = 0 + Sk = np.zeros([dim, dim], dtype=complex) + fir = 0 for j in range(dim): - c_s=eval(tmp[j+1]) - Sk[i][j]=complex(c_s[0],c_s[1]) + c_s = eval(tmp[j + 1]) + Sk[i][j] = complex(c_s[0], c_s[1]) else: - for j in range(dim-i): - c_s=eval(tmp[j]) - Sk[i][i+j]=complex(c_s[0],c_s[1]) - i+=1 - if(i==0): - break + for j in range(dim - i): + c_s = eval(tmp[j]) + Sk[i][i + j] = complex(c_s[0], c_s[1]) + i += 1 + if i == 0: + break for i in range(dim): for j in range(i): - Sk[i][j]=Sk[j][i].conjugate() + Sk[i][j] = Sk[j][i].conjugate() return Sk def cal_Pnm(self, ik, nstep, wfc_ref): - wfc_t,Ocp_t=self.read_wfc(ik+1, nstep+1, dir=self.wfc_dir) - S_t=self.S_read(ik,nstep,dir=self.s_dir) - Pnm=np.zeros([self.nband,self.nband],dtype=float) + wfc_t, Ocp_t = self.read_wfc(ik + 1, nstep + 1, dir=self.wfc_dir) + S_t = self.S_read(ik, nstep, dir=self.s_dir) + Pnm = np.zeros([self.nband, self.nband], dtype=float) for a in range(self.nband): for b in range(self.nband): - Pnm[a][b] = self.CSC2(wfc_ref[a],S_t,wfc_t[b]).real + Pnm[a][b] = self.CSC2(wfc_ref[a], S_t, wfc_t[b]).real return Pnm, Ocp_t def cal_On_single(self, ik, nstep, wfc_ref): Pnm, Ocp_t = self.cal_Pnm(ik, nstep, wfc_ref) - On = np.zeros(self.nband,dtype=float) + On = np.zeros(self.nband, dtype=float) On = Ocp_t @ Pnm return On - + def save_On_all(self): for ik in self.klist: - wfc_ref,Ocp_ref=self.read_wfc(ik+1, self.stepref+1, dir=self.wfc_dir) - On_tot = np.zeros([len(steps),self.nband],dtype=float) + wfc_ref, Ocp_ref = self.read_wfc(ik + 1, self.stepref + 1, dir=self.wfc_dir) + On_tot = np.zeros([len(steps), self.nband], dtype=float) for n, nstep in enumerate(steps): On_tot[n] = self.cal_On_single(ik, nstep, wfc_ref) - np.savetxt('On_'+str(ik)+'.dat', On_tot) + np.savetxt("On_" + str(ik) + ".dat", On_tot) if __name__ == "__main__": - #the kpoints you need, check kpoints file to get the index - klist=[0] - #the steps you need, check STRU_MD file to get the index + # the kpoints you need, check kpoints file to get the index + klist = [0] + # the steps you need, check STRU_MD file to get the index start_step = 0 end_step = 20 out_interval = 5 steps = range(start_step, end_step, out_interval) - #the ground state step - stepref=0 - #Ground state projection - pro=Projection(0, klist, steps) - #save the Occupation infos to file - pro.save_On_all() \ No newline at end of file + # the ground state step + stepref = 0 + # Ground state projection + pro = Projection(0, klist, steps) + # save the Occupation infos to file + pro.save_On_all() diff --git a/tools/selective_dynamics/README.md b/tools/selective_dynamics/README.md index eef94a6f857..a07a71093ab 100644 --- a/tools/selective_dynamics/README.md +++ b/tools/selective_dynamics/README.md @@ -10,6 +10,7 @@ ### Setting There is a setting file named `config.yaml`: + ```yaml origin_structure: 'STRU' # the original structure selected_indices: [18, 19] # the atom index that you concerned about, start from 0 @@ -91,15 +92,19 @@ job_script: | ### Submit jobs Use the following command + ```bash python3 path_to_selective_dynamics.py --submit ``` + to generate displaced structures and submit jobs. ### Postprocess Use the following command + ```bash python3 path_to_selective_dynamics.py --post ``` + to generate `FORCE_SETS` and results of phonon calculations. diff --git a/tools/selective_dynamics/selective_dynamics.py b/tools/selective_dynamics/selective_dynamics.py index 4e5c0e91fcc..c5174bfae88 100755 --- a/tools/selective_dynamics/selective_dynamics.py +++ b/tools/selective_dynamics/selective_dynamics.py @@ -18,18 +18,16 @@ def split_stru_with_index(input_file, selected_indices, output1, output2): basis = atoms.info["basis"] for i, atom in enumerate(atoms): - atom.tag = i + atom.tag = i atoms1 = atoms[selected_indices] - remaining_indices = [i for i in range(len(atoms)) if i not in selected_indices] atoms2 = atoms[remaining_indices] - - write(output1, atoms1, format='abacus', pp=pp, basis=basis) - write(output2, atoms2, format='abacus', pp=pp, basis=basis) - + write(output1, atoms1, format="abacus", pp=pp, basis=basis) + write(output2, atoms2, format="abacus", pp=pp, basis=basis) + print(f" Success! \n A.stru: {len(atoms1)} atoms\n B.stru: {len(atoms2)} atoms\n") return selected_indices, remaining_indices, pp, basis @@ -38,113 +36,114 @@ def merge_stru_by_index(file1, file2, indices1, indices2, pp, basis, output_file atoms1 = read(file1) atoms2 = read(file2) - total_atoms = len(atoms1) + len(atoms2) merged_atoms = [None] * total_atoms - + for i, idx in enumerate(indices1): merged_atoms[idx] = atoms1[i] - + for i, idx in enumerate(indices2): merged_atoms[idx] = atoms2[i] - cell = atoms2.get_cell() pbc = atoms2.get_pbc() positions = [atom.position for atom in merged_atoms] symbols = [atom.symbol for atom in merged_atoms] - + merged = Atoms(symbols=symbols, positions=positions, cell=cell, pbc=pbc) - write(output_file, merged, format='abacus', pp=pp, basis=basis) + write(output_file, merged, format="abacus", pp=pp, basis=basis) print(f"success! total {len(merged)} atoms") def parse_forces_from_file(indices, file_path="running_scf.log"): - with open(file_path, 'r', encoding='utf-8') as f: + with open(file_path, "r", encoding="utf-8") as f: contents = f.read() - lines = contents.split('\n') + lines = contents.split("\n") start_index = -1 for i, line in enumerate(lines): if "#TOTAL-FORCE (eV/Angstrom)#" in line: - start_index = i+4 + start_index = i + 4 break results = [] for i in indices: - results.append(lines[start_index+i]) + results.append(lines[start_index + i]) - result_text = '\n'.join(results) + result_text = "\n".join(results) return result_text def load_config(config_file="config.yaml"): - with open(config_file, 'r', encoding='utf-8') as f: + with open(config_file, "r", encoding="utf-8") as f: return yaml.safe_load(f) + def submit_jobs(): # loading settings config = load_config() - - # split structure into A and B - origin_structure = config['origin_structure'] - selected_indices = config['selected_indices'] - indices1, indices2, pp, basis = split_stru_with_index(origin_structure, selected_indices, - 'A.stru', 'B.stru') + # split structure into A and B + origin_structure = config["origin_structure"] + selected_indices = config["selected_indices"] + indices1, indices2, pp, basis = split_stru_with_index( + origin_structure, selected_indices, "A.stru", "B.stru" + ) # setting.conf for phonopy - setting_conf_content = config['setting.conf'] + setting_conf_content = config["setting.conf"] with open("setting.conf", "w", encoding="utf-8") as f: f.write(setting_conf_content) - # generate perturbed structures - result = subprocess.run("phonopy setting.conf --abacus -d -c A.stru", - shell=True, capture_output=True, text=True) + result = subprocess.run( + "phonopy setting.conf --abacus -d -c A.stru", + shell=True, + capture_output=True, + text=True, + ) print(result.stdout) - all_files = sorted(glob.glob("STRU-*")) TOTAL_TASKS = len(all_files) - TASKS_PER_BATCH = config['tasks_per_batch'] - WAIT_TIME = config['wait_time'] - TOTAL_BATCHES = (TOTAL_TASKS + TASKS_PER_BATCH - 1) // TASKS_PER_BATCH - print(f' TOTAL_TASKS = {TOTAL_TASKS}\n TASKS_PER_BATCH = {TASKS_PER_BATCH}\n TOTAL_BATCHES = {TOTAL_BATCHES}\n') - + TASKS_PER_BATCH = config["tasks_per_batch"] + WAIT_TIME = config["wait_time"] + TOTAL_BATCHES = (TOTAL_TASKS + TASKS_PER_BATCH - 1) // TASKS_PER_BATCH + print( + f" TOTAL_TASKS = {TOTAL_TASKS}\n TASKS_PER_BATCH = {TASKS_PER_BATCH}\n TOTAL_BATCHES = {TOTAL_BATCHES}\n" + ) # job script - job_script_content = config['job_script'] + job_script_content = config["job_script"] with open("job.sh", "w", encoding="utf-8") as f: f.write(job_script_content) os.chmod("job.sh", 0o755) # KPT - kpt_content = config['kpt'] + kpt_content = config["kpt"] with open("KPT", "w", encoding="utf-8") as f: f.write(kpt_content) - input_content = config['input'] + input_content = config["input"] num_digits = len(str(TOTAL_TASKS)) for batch in range(1, TOTAL_BATCHES + 1): print("-" * 30) print(f"Current batch: {batch}/{TOTAL_BATCHES}") print("-" * 30) - + for task in range(1, TASKS_PER_BATCH + 1): index = task - 1 + (batch - 1) * TASKS_PER_BATCH - + if index >= TOTAL_TASKS: break - new_index = f"{index+1:0{num_digits+1}d}" @@ -152,43 +151,44 @@ def submit_jobs(): os.makedirs(dir_name, exist_ok=True) os.chdir(dir_name) - # STRU perturbed_stru = f"../{all_files[index]}" - merge_stru_by_index(perturbed_stru, '../B.stru', indices1, indices2, - pp, basis, 'STRU') + merge_stru_by_index( + perturbed_stru, "../B.stru", indices1, indices2, pp, basis, "STRU" + ) # INPUT with open("INPUT", "w") as f: f.write(input_content) - # submit job try: - result = subprocess.run(["sbatch", "../job.sh"], - check=True, capture_output=True, text=True) + result = subprocess.run( + ["sbatch", "../job.sh"], check=True, capture_output=True, text=True + ) print(f"submit job: {new_index}") except subprocess.CalledProcessError as e: print(f"Failed - {e}") - + os.chdir("..") - + # sleep if not the last batch if batch < TOTAL_BATCHES: print(f"wait {WAIT_TIME} seconds...") time.sleep(WAIT_TIME) - + print("-" * 30) - + print("All job submitted!") print("-" * 30) + def postprocess(): - + # loading settings config = load_config() - selected_indices = config['selected_indices'] + selected_indices = config["selected_indices"] natom = len(selected_indices) all_files = sorted(glob.glob("STRU-*")) @@ -218,23 +218,27 @@ def postprocess(): with open("phonon.log", "w") as f: f.write(log) f.write(str(atom_forces)) - f.write("\n -------------------------------------------------------------------------") - + f.write( + "\n -------------------------------------------------------------------------" + ) os.chdir("../..") - result = subprocess.run("phonopy -f job_*/OUT*/phonon.log", - shell=True, check=True, capture_output=True, text=True) + result = subprocess.run( + "phonopy -f job_*/OUT*/phonon.log", + shell=True, + check=True, + capture_output=True, + text=True, + ) - - mesh_content = config['mesh.conf'] + mesh_content = config["mesh.conf"] with open("mesh.conf", "w") as f: - f.write(mesh_content) - - result = subprocess.run("phonopy -t mesh.conf", - shell=True, check=True, capture_output=True, text=True) - + f.write(mesh_content) + result = subprocess.run( + "phonopy -t mesh.conf", shell=True, check=True, capture_output=True, text=True + ) def main(): @@ -250,5 +254,6 @@ def main(): else: print(f"No such parameter: {sys.argv[1]}") + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/tools/stm/plot.py b/tools/stm/plot.py index edeaa948dd8..1f62b73bb7b 100644 --- a/tools/stm/plot.py +++ b/tools/stm/plot.py @@ -2,9 +2,7 @@ import matplotlib.pyplot as plt import numpy as np - - -dirname='OUT.autotest' +dirname = "OUT.autotest" bias = 2 z = 8.0 @@ -15,19 +13,19 @@ c = stm.get_averaged_current(bias, z) x, y, h = stm.scan(bias, c, repeat=(3, 5)) -plt.gca().axis('equal') +plt.gca().axis("equal") plt.contourf(x, y, h, 40) plt.colorbar() -plt.savefig('2d_current.png') +plt.savefig("2d_current.png") # 2. Constant height 2-d scan plt.figure() -plt.gca().axis('equal') +plt.gca().axis("equal") x, y, I = stm.scan2(bias, z, repeat=(3, 5)) plt.contourf(x, y, I, 40) plt.colorbar() -plt.savefig('2d_height.png') +plt.savefig("2d_height.png") # 3. Constant current line scan @@ -35,7 +33,7 @@ a = stm.atoms.cell[0, 0] x, y = stm.linescan(bias, c, [0, 0], [2 * a, 0]) plt.plot(x, y) -plt.savefig('line.png') +plt.savefig("line.png") # Scanning tunneling spectroscopy @@ -45,11 +43,11 @@ biasend = 3.0 biasstep = 0.1 bias, I, dIdV = stm.sts(0, 0, z, biasstart, biasend, biasstep) -plt.plot(bias, I, label='I') -plt.plot(bias, dIdV, label='dIdV') +plt.plot(bias, I, label="I") +plt.plot(bias, dIdV, label="dIdV") plt.xlim(biasstart, biasend) plt.legend() -plt.savefig('dIdV.png') +plt.savefig("dIdV.png") # 5. dI/dV map @@ -59,24 +57,26 @@ start_points = [0, 0, 8] end_points = [2, 0, 8] distance = np.linalg.norm(np.array(end_points) - np.array(start_points)) -biases, points, current, dIdV_map = stm.line_sts(biasstart, biasend, biasstep, start_points, end_points, 50) +biases, points, current, dIdV_map = stm.line_sts( + biasstart, biasend, biasstep, start_points, end_points, 50 +) plt.figure(figsize=(10, 6), dpi=150) # 2D Colormap -im = plt.pcolormesh(biases, points, dIdV_map, cmap='plasma', shading='auto') +im = plt.pcolormesh(biases, points, dIdV_map, cmap="plasma", shading="auto") # optional cmap: 'RdYlBu', 'plasma', 'inferno', 'viridis' # color bar -cbar = plt.colorbar(im, label='dI/dV', pad=0.02) +cbar = plt.colorbar(im, label="dI/dV", pad=0.02) # labels -plt.xlabel('Sample Bias (V)', fontsize=12) -plt.ylabel('distance to the start point (Angstrom)', fontsize=12) +plt.xlabel("Sample Bias (V)", fontsize=12) +plt.ylabel("distance to the start point (Angstrom)", fontsize=12) plt.xlim(biasstart, biasend) plt.ylim(0, distance) -plt.title('dI/dV (~density of states) map', fontsize=14) +plt.title("dI/dV (~density of states) map", fontsize=14) plt.tight_layout() -plt.savefig('dIdV_map.png', bbox_inches='tight', transparent=False) -plt.show() \ No newline at end of file +plt.savefig("dIdV_map.png", bbox_inches="tight", transparent=False) +plt.show() diff --git a/tools/stm/stm.py b/tools/stm/stm.py index 8bc3df71378..bcf3dc3d622 100644 --- a/tools/stm/stm.py +++ b/tools/stm/stm.py @@ -3,8 +3,9 @@ import matplotlib.pyplot as plt import numpy as np + class STM: - def __init__(self, dirname='.'): + def __init__(self, dirname="."): """Scanning tunneling microscope. dirname: string @@ -13,7 +14,6 @@ def __init__(self, dirname='.'): self.dirname = dirname - def read_ldos(self, bias): """Read local density of states from cube file. @@ -21,21 +21,19 @@ def read_ldos(self, bias): Bias voltage in Volts. """ - if(abs(bias) < 1e-5): + if abs(bias) < 1e-5: bias = 0.0 - filename = f'{self.dirname}/LDOS_{bias:.5g}eV.cube' - print('read in ' + filename) + filename = f"{self.dirname}/LDOS_{bias:.5g}eV.cube" + print("read in " + filename) self.ldos, self.atoms = read_cube_data(filename) self.cell = self.atoms.cell self.bias = bias - def write(self, filename): """Write local density of states to JSON file.""" write_json(filename, (self.ldos, self.bias, self.cell)) - def get_averaged_current(self, bias, z): """Calculate avarage current at height z (in Angstrom). @@ -51,9 +49,9 @@ def get_averaged_current(self, bias, z): n = int(n) % nz # Average and do linear interpolation: - return ((1 - dn) * self.ldos[:, :, n].mean() + - dn * self.ldos[:, :, (n + 1) % nz].mean()) - + return (1 - dn) * self.ldos[:, :, n].mean() + dn * self.ldos[ + :, :, (n + 1) % nz + ].mean() def scan(self, bias, current, z0=None, repeat=(1, 1)): """Constant current 2-d scan. @@ -88,7 +86,6 @@ def scan(self, bias, current, z0=None, repeat=(1, 1)): x, y = np.dot(ij / s0, self.cell[:2, :2]).T.reshape((2,) + s) return x, y, heights - def scan2(self, bias, z, repeat=(1, 1)): """Constant height 2-d scan. @@ -123,7 +120,6 @@ def scan2(self, bias, z, repeat=(1, 1)): # Returing scan with axes in Angstrom. return x, y, current - def linescan(self, bias, current, p1, p2, npoints=50, z0=None): """Constant current line scan. @@ -140,7 +136,7 @@ def linescan(self, bias, current, p1, p2, npoints=50, z0=None): p1 = np.asarray(p1, float) p2 = np.asarray(p2, float) d = p2 - p1 - s = np.dot(d, d)**0.5 + s = np.dot(d, d) ** 0.5 cell = self.cell[:2, :2] shape = np.array(heights.shape, float) @@ -151,7 +147,6 @@ def linescan(self, bias, current, p1, p2, npoints=50, z0=None): q = np.dot(p, M) * shape line[i] = interpolate(q, heights) return np.linspace(0, s, npoints), line - def pointcurrent(self, bias, x, y, z): """Current for a single x, y, z position for a given bias.""" @@ -174,13 +169,14 @@ def pointcurrent(self, bias, x, y, z): zp = int(zp) % nz # 3D interpolation of the LDOS at point (x,y,z) at given bias. - xyzldos = (((1 - dx) + (1 - dy) + (1 - dz)) * self.ldos[xp, yp, zp] + - dx * self.ldos[(xp + 1) % nx, yp, zp] + - dy * self.ldos[xp, (yp + 1) % ny, zp] + - dz * self.ldos[xp, yp, (zp + 1) % nz]) + xyzldos = ( + ((1 - dx) + (1 - dy) + (1 - dz)) * self.ldos[xp, yp, zp] + + dx * self.ldos[(xp + 1) % nx, yp, zp] + + dy * self.ldos[xp, (yp + 1) % ny, zp] + + dz * self.ldos[xp, yp, (zp + 1) % nz] + ) return dos2current(bias, xyzldos) - def sts(self, x, y, z, bias0, bias1, biasstep): """Returns the dI/dV curve for position x, y at height z (in Angstrom), @@ -198,7 +194,6 @@ def sts(self, x, y, z, bias0, bias1, biasstep): return biases, current, dIdV - def line_sts(self, bias0, bias1, biasstep, p1, p2, npoints=50): """Returns the dI/dV curve for line between p1 and p2, for bias from bias0 to bias1 with step biasstep.""" @@ -206,7 +201,7 @@ def line_sts(self, bias0, bias1, biasstep, p1, p2, npoints=50): p1 = np.asarray(p1, float) p2 = np.asarray(p2, float) d = p2 - p1 - s = np.dot(d, d)**0.5 + s = np.dot(d, d) ** 0.5 biases = np.arange(bias0, bias1 + biasstep, biasstep) current = np.zeros((npoints, len(biases))) @@ -224,7 +219,6 @@ def line_sts(self, bias0, bias1, biasstep, p1, p2, npoints=50): return biases, np.linspace(0, s, npoints), current, dIdV - def line_sts_ave(self, bias0, bias1, biasstep, npoints=50): biases = np.arange(bias0, bias1 + biasstep, biasstep) @@ -239,18 +233,18 @@ def line_sts_ave(self, bias0, bias1, biasstep, npoints=50): z = i / (npoints - 1) * nz dz = z - np.floor(z) z = int(z) % nz - current[i, b] = ((1 - dz) * self.ldos[:, :, z].mean() + - dz * self.ldos[:, :, (z + 1) % nz].mean()) - + current[i, b] = (1 - dz) * self.ldos[:, :, z].mean() + dz * self.ldos[ + :, :, (z + 1) % nz + ].mean() + dIdV = np.zeros((npoints, len(biases))) for i in range(npoints): dIdV[i, :] = np.gradient(current[i, :], biasstep) return biases, np.linspace(0, 1, npoints), current, dIdV - def find_current(self, ldos, z): - """ Finds current for given LDOS at height z.""" + """Finds current for given LDOS at height z.""" nz = self.ldos.shape[2] zp = z / self.cell[2, 2] * nz @@ -260,14 +254,14 @@ def find_current(self, ldos, z): ldosz = (1 - dz) * ldos[zp] + dz * ldos[(zp + 1) % nz] return dos2current(self.bias, ldosz) - + def dos2current(bias, dos): # Borrowed from gpaw/analyse/simple_stm.py: # The connection between density n and current I # n [e/Angstrom^3] = 0.0002 sqrt(I [nA]) # as given in Hofer et al., RevModPhys 75 (2003) 1287 - return 5000. * dos**2 * (1 if bias > 0 else -1) + return 5000.0 * dos**2 * (1 if bias > 0 else -1) def interpolate(q, heights): @@ -277,10 +271,12 @@ def interpolate(q, heights): qi %= heights.shape n0, m0 = qi n1, m1 = (qi + 1) % heights.shape - z = (g[0] * g[1] * heights[n0, m0] + - f[0] * g[1] * heights[n1, m0] + - g[0] * f[1] * heights[n0, m1] + - f[0] * f[1] * heights[n1, m1]) + z = ( + g[0] * g[1] * heights[n0, m0] + + f[0] * g[1] * heights[n1, m0] + + g[0] * f[1] * heights[n0, m1] + + f[0] * f[1] * heights[n1, m1] + ) return z @@ -296,11 +292,11 @@ def find_height(ldos, current, h, z0=None): else: return 0.0 - c2, c1 = ldos[n:n + 2] + c2, c1 = ldos[n : n + 2] return (n + 1 - (current - c1) / (c2 - c1)) * h def delta(biases, bias, width): """Return a delta-function centered at 'bias'""" - x = -((biases - bias) / width)**2 + x = -(((biases - bias) / width) ** 2) return np.exp(x) / (np.sqrt(np.pi) * width) diff --git a/tools/windows/README.md b/tools/windows/README.md index ef565821301..99a69f49032 100644 --- a/tools/windows/README.md +++ b/tools/windows/README.md @@ -1,78 +1,73 @@ # ABACUS Windows Installer -A lightweight one-click installer that brings ABACUS to Windows via WSL2 and -conda-forge. No C++ toolchain, no MPI build, no manual dependency juggling — -run `install-abacus.bat` once and type `abacus` from any Windows terminal. +A lightweight one-click installer that brings ABACUS to Windows via WSL2 and conda-forge. No C++ +toolchain, no MPI build, no manual dependency juggling — run `install-abacus.bat` once and type +`abacus` from any Windows terminal. ## How it works -ABACUS depends on a heavy Linux-native scientific stack (OpenMPI, ScaLAPACK, -ELPA, FFTW, libxc, OpenBLAS, …) that is painful to build natively on Windows. -Instead of porting, this installer provisions a standard Linux environment -inside WSL2 and exposes it through thin Windows launchers. +ABACUS depends on a heavy Linux-native scientific stack (OpenMPI, ScaLAPACK, ELPA, FFTW, libxc, +OpenBLAS, …) that is painful to build natively on Windows. Instead of porting, this installer +provisions a standard Linux environment inside WSL2 and exposes it through thin Windows launchers. The pipeline, end to end: 1. **`install-abacus.bat`** (runs on Windows, requires admin) - - Checks the Windows build (≥ 19041) and whether WSL is installed; if not, - runs `wsl --install --no-launch` and asks the user to reboot once. + + - Checks the Windows build (≥ 19041) and whether WSL is installed; if not, runs + `wsl --install --no-launch` and asks the user to reboot once. - Optionally enables TUNA (Tsinghua) mirrors for users in Mainland China. - - Prompts for an ABACUS version (blank = latest on conda-forge; an exact - version like `3.7.4` is pinned; a match-spec like `>=3.7,<3.8` is passed - through to conda). - - Detects the target distribution (`Ubuntu-22.04`) by querying the WSL - registry key `HKCU\Software\Microsoft\Windows\CurrentVersion\Lxss`. This - is immune to UTF-16 parsing pitfalls and to Store appx leftovers that - can make `wsl -d -- true` falsely report success. - - Calls `wsl --install -d Ubuntu-22.04 --no-launch` if the distro is - missing, then verifies the registry entry appeared. - - Invokes `provision.sh` inside the distribution, stripping any `\r` - bytes on the fly (`sed 's/\r$//' script | bash`) so Windows line - endings don't break shell parsing. - - Writes two small launcher `.cmd` files and adds them to the user PATH - via PowerShell (avoiding `setx`'s 1024-character truncation). - -2. **`provision.sh`** (runs as root inside the WSL distribution) + - Prompts for an ABACUS version (blank = latest on conda-forge; an exact version like `3.7.4` is + pinned; a match-spec like `>=3.7,<3.8` is passed through to conda). + - Detects the target distribution (`Ubuntu-22.04`) by querying the WSL registry key + `HKCU\Software\Microsoft\Windows\CurrentVersion\Lxss`. This is immune to UTF-16 parsing + pitfalls and to Store appx leftovers that can make `wsl -d -- true` falsely report + success. + - Calls `wsl --install -d Ubuntu-22.04 --no-launch` if the distro is missing, then verifies the + registry entry appeared. + - Invokes `provision.sh` inside the distribution, stripping any `\r` bytes on the fly + (`sed 's/\r$//' script | bash`) so Windows line endings don't break shell parsing. + - Writes two small launcher `.cmd` files and adds them to the user PATH via PowerShell (avoiding + `setx`'s 1024-character truncation). + +1. **`provision.sh`** (runs as root inside the WSL distribution) + - Optionally rewrites `/etc/apt/sources.list` to TUNA. - - `apt-get install`s a minimal set of prerequisites (curl, ca-certificates, - bzip2). - - Downloads the Miniforge installer (from GitHub or TUNA's GitHub-releases - mirror) and installs it to `/opt/abacus-miniforge`. - - `conda create -n abacus_env -c conda-forge abacus` (or the TUNA - conda-forge channel) — a single package pulls in the entire scientific - runtime. conda-forge ships `abacus` for `linux-64` and `linux-aarch64`, - which is exactly what WSL2 provides. - - Writes two system-wide launchers, `/usr/local/bin/abacus` and - `/usr/local/bin/abacus-mpi`, that activate the env and exec the real - binary. Both set `OMP_NUM_THREADS=1` by default to avoid thread - oversubscription. `abacus-mpi` additionally sets OpenMPI 4/5 + PRRTE - "allow run as root" environment variables and passes - `--allow-run-as-root` to `mpirun`, so the default WSL root user can - launch parallel jobs without creating a non-root user. - -3. **Windows launchers** (`abacus.cmd`, `abacus-mpi.cmd`) + - `apt-get install`s a minimal set of prerequisites (curl, ca-certificates, bzip2). + - Downloads the Miniforge installer (from GitHub or TUNA's GitHub-releases mirror) and installs + it to `/opt/abacus-miniforge`. + - `conda create -n abacus_env -c conda-forge abacus` (or the TUNA conda-forge channel) — a single + package pulls in the entire scientific runtime. conda-forge ships `abacus` for `linux-64` and + `linux-aarch64`, which is exactly what WSL2 provides. + - Writes two system-wide launchers, `/usr/local/bin/abacus` and `/usr/local/bin/abacus-mpi`, that + activate the env and exec the real binary. Both set `OMP_NUM_THREADS=1` by default to avoid + thread oversubscription. `abacus-mpi` additionally sets OpenMPI 4/5 + PRRTE "allow run as root" + environment variables and passes `--allow-run-as-root` to `mpirun`, so the default WSL root + user can launch parallel jobs without creating a non-root user. + +1. **Windows launchers** (`abacus.cmd`, `abacus-mpi.cmd`) + - Added to `%LOCALAPPDATA%\ABACUS\bin` and the user PATH. - - Each launcher sets `WSLENV=OMP_NUM_THREADS:MKL_NUM_THREADS:OPENBLAS_NUM_THREADS:...` - so thread-count overrides set on the Windows side are visible inside WSL. + - Each launcher sets `WSLENV=OMP_NUM_THREADS:MKL_NUM_THREADS:OPENBLAS_NUM_THREADS:...` so + thread-count overrides set on the Windows side are visible inside WSL. - Body is just: ``` wsl -d Ubuntu-22.04 --cd "%CD%" -- abacus %* ``` - `--cd "%CD%"` maps the current Windows directory (`C:\…\case`) to its - WSL path (`/mnt/c/…/case`), so users can `cd` into a case directory in - `cmd`/PowerShell/Terminal and just type `abacus`. - -4. **`uninstall-abacus.bat`** - - Reads `install-state.txt` (written by the installer) to learn whether - the Ubuntu-22.04 distribution was pre-existing or added by us. - - If it was added by us, prompts whether to `wsl --unregister` the entire - distribution, or to only wipe `/opt/abacus-miniforge` and the launchers. + `--cd "%CD%"` maps the current Windows directory (`C:\…\case`) to its WSL path + (`/mnt/c/…/case`), so users can `cd` into a case directory in `cmd`/PowerShell/Terminal and + just type `abacus`. + +1. **`uninstall-abacus.bat`** + + - Reads `install-state.txt` (written by the installer) to learn whether the Ubuntu-22.04 + distribution was pre-existing or added by us. + - If it was added by us, prompts whether to `wsl --unregister` the entire distribution, or to + only wipe `/opt/abacus-miniforge` and the launchers. - If it was pre-existing, only the ABACUS files inside are removed. - - Cleans Windows-side launchers and removes the bin directory from the - user PATH. - - Does **not** touch WSL itself (runtime, Windows optional features, or - other distributions). See *Uninstallation* below for how to fully - remove WSL if you want to. + - Cleans Windows-side launchers and removes the bin directory from the user PATH. + - Does **not** touch WSL itself (runtime, Windows optional features, or other distributions). See + *Uninstallation* below for how to fully remove WSL if you want to. ## Requirements @@ -80,22 +75,21 @@ The pipeline, end to end: - Administrator privileges for the first run (to enable WSL features). - Virtualization enabled in BIOS/UEFI. - ~2 GB free disk space (Ubuntu + conda env). -- Network access to GitHub and conda-forge, or to TUNA if you choose the - China mirror option. +- Network access to GitHub and conda-forge, or to TUNA if you choose the China mirror option. ## Installation 1. Clone or download this repository. -2. Right-click `install-abacus.bat` → **Run as administrator**. -3. Answer the China-mirror prompt (`y` recommended inside Mainland China). - Then pick an ABACUS version when prompted (leave blank for the latest on - conda-forge; for a pinned install, type an exact version such as `3.7.4`). -4. If this is the first time WSL is installed on the machine, the script - will ask you to reboot and run it again. -5. Wait for `[*] Provisioning ABACUS …` to finish (5–15 minutes on first - run; most of it is the conda-forge download). -6. When you see `Installation complete!`, **open a new terminal window** - (so the updated PATH takes effect) and verify: +1. Right-click `install-abacus.bat` → **Run as administrator**. +1. Answer the China-mirror prompt (`y` recommended inside Mainland China). Then pick an ABACUS + version when prompted (leave blank for the latest on conda-forge; for a pinned install, type an + exact version such as `3.7.4`). +1. If this is the first time WSL is installed on the machine, the script will ask you to reboot and + run it again. +1. Wait for `[*] Provisioning ABACUS …` to finish (5–15 minutes on first run; most of it is the + conda-forge download). +1. When you see `Installation complete!`, **open a new terminal window** (so the updated PATH takes + effect) and verify: ``` abacus --version ``` @@ -122,19 +116,18 @@ set OMP_NUM_THREADS=2 abacus-mpi -n 4 ``` -Set `OMP_NUM_THREADS` (and/or `MKL_NUM_THREADS`, `OPENBLAS_NUM_THREADS`) in -your Windows shell and the launcher will forward the value into WSL through -`WSLENV`. Unset, it defaults to 1 — a safe choice when running pure MPI. +Set `OMP_NUM_THREADS` (and/or `MKL_NUM_THREADS`, `OPENBLAS_NUM_THREADS`) in your Windows shell and +the launcher will forward the value into WSL through `WSLENV`. Unset, it defaults to 1 — a safe +choice when running pure MPI. -Interactive Linux shell (for advanced debugging, manually running -`mpirun`, inspecting logs, etc.): +Interactive Linux shell (for advanced debugging, manually running `mpirun`, inspecting logs, etc.): ``` wsl -d Ubuntu-22.04 ``` -Inside the shell you can `conda activate abacus_env` to get access to -`mpirun`, `mpiexec`, and other tools from the conda environment. +Inside the shell you can `conda activate abacus_env` to get access to `mpirun`, `mpiexec`, and other +tools from the conda environment. ## Uninstallation @@ -142,24 +135,21 @@ Inside the shell you can `conda activate abacus_env` to get access to Run `uninstall-abacus.bat`. This handles the common case: -- Removes `/opt/abacus-miniforge` and the `abacus` / `abacus-mpi` launchers - inside WSL. -- If the installer added the `Ubuntu-22.04` distribution, asks whether you - also want to `wsl --unregister` it (pick `y` to reclaim the disk space, - `n` to keep the Linux environment for other uses). -- Deletes `%LOCALAPPDATA%\ABACUS\` and removes its `bin\` directory from - your user PATH. +- Removes `/opt/abacus-miniforge` and the `abacus` / `abacus-mpi` launchers inside WSL. +- If the installer added the `Ubuntu-22.04` distribution, asks whether you also want to + `wsl --unregister` it (pick `y` to reclaim the disk space, `n` to keep the Linux environment for + other uses). +- Deletes `%LOCALAPPDATA%\ABACUS\` and removes its `bin\` directory from your user PATH. -This is enough for almost every user. WSL itself and any *other* WSL -distributions you have stay untouched — important because WSL is commonly -shared with Docker Desktop, VS Code Remote, and other toolchains. +This is enough for almost every user. WSL itself and any *other* WSL distributions you have stay +untouched — important because WSL is commonly shared with Docker Desktop, VS Code Remote, and other +toolchains. ### Nuclear: remove WSL itself -Only do this if you truly have no other use for WSL on this machine. -Removing WSL will break Docker Desktop, VS Code Remote-WSL, any other -Linux distros you have, and so on. Run the following in an elevated -PowerShell: +Only do this if you truly have no other use for WSL on this machine. Removing WSL will break Docker +Desktop, VS Code Remote-WSL, any other Linux distros you have, and so on. Run the following in an +elevated PowerShell: ```powershell # 1. Unregister every WSL distribution (this wipes all their files). @@ -188,19 +178,17 @@ Remove-Item "$env:UserProfile\.wslconfig" -ErrorAction SilentlyContinue Restart-Computer ``` -After the reboot `wsl.exe` no longer exists. If you also ran step 4, the -Hyper-V virtualization layer used by WSL2 is disabled. +After the reboot `wsl.exe` no longer exists. If you also ran step 4, the Hyper-V virtualization +layer used by WSL2 is disabled. -> On older Windows builds where `wsl --uninstall` is not available (WSL -> shipped via the in-box `wsl.exe` rather than the Store package), use -> `Get-AppxPackage *WindowsSubsystemForLinux* | Remove-AppxPackage` as a -> fallback for step 2. +> On older Windows builds where `wsl --uninstall` is not available (WSL shipped via the in-box +> `wsl.exe` rather than the Store package), use +> `Get-AppxPackage *WindowsSubsystemForLinux* | Remove-AppxPackage` as a fallback for step 2. ## Performance notes -- Files under `/mnt/c/...` are served through the 9P protocol and are - noticeably slower than native ext4. For heavy I/O (large SCF, MD - trajectories), run the case from inside the WSL filesystem: +- Files under `/mnt/c/...` are served through the 9P protocol and are noticeably slower than native + ext4. For heavy I/O (large SCF, MD trajectories), run the case from inside the WSL filesystem: ``` wsl -d Ubuntu-22.04 cp -r /mnt/c/path/to/case ~/case @@ -208,8 +196,8 @@ Hyper-V virtualization layer used by WSL2 is disabled. abacus ``` - The first `wsl` invocation after a boot triggers a 10–30 s VM cold start. -- OpenMPI runs all ranks inside a single WSL2 VM, so there is no network - overhead between ranks — you get near-native parallel performance. +- OpenMPI runs all ranks inside a single WSL2 VM, so there is no network overhead between ranks — + you get near-native parallel performance. ## File layout @@ -239,20 +227,16 @@ Inside WSL (Ubuntu-22.04): ## Design choices and trade-offs -- **Why WSL2 + conda-forge instead of a native Windows build?** ABACUS's - MPI + ScaLAPACK + ELPA stack has no reliable native Windows build. Going - through WSL2 lets us reuse the Linux binaries conda-forge already ships, - turning a multi-week porting problem into a 200-line shell script. -- **Why a dedicated `Ubuntu-22.04` distribution?** conda-forge ABACUS is - built against glibc from 22.04-era Ubuntu. Using `Ubuntu` (rolling) risks - mismatches; pinning the version keeps the install reproducible. -- **Why put conda under `/opt/abacus-miniforge` rather than `/root`?** - Clean uninstall path, clear ownership, and doesn't interfere with a - user's personal conda install if they later add one inside the same - distribution. -- **Why not ship a pre-built WSL rootfs?** Would cut first-run time from - ~10 min to ~1 min, but balloons the installer from a few KB of scripts - to 300–500 MB, requires CI infrastructure, and needs code signing to - avoid SmartScreen warnings. A scripted online installer is the - lowest-maintenance starting point; the pre-built rootfs path remains - open for a future v1. +- **Why WSL2 + conda-forge instead of a native Windows build?** ABACUS's MPI + ScaLAPACK + ELPA + stack has no reliable native Windows build. Going through WSL2 lets us reuse the Linux binaries + conda-forge already ships, turning a multi-week porting problem into a 200-line shell script. +- **Why a dedicated `Ubuntu-22.04` distribution?** conda-forge ABACUS is built against glibc from + 22.04-era Ubuntu. Using `Ubuntu` (rolling) risks mismatches; pinning the version keeps the install + reproducible. +- **Why put conda under `/opt/abacus-miniforge` rather than `/root`?** Clean uninstall path, clear + ownership, and doesn't interfere with a user's personal conda install if they later add one inside + the same distribution. +- **Why not ship a pre-built WSL rootfs?** Would cut first-run time from ~10 min to ~1 min, but + balloons the installer from a few KB of scripts to 300–500 MB, requires CI infrastructure, and + needs code signing to avoid SmartScreen warnings. A scripted online installer is the + lowest-maintenance starting point; the pre-built rootfs path remains open for a future v1. From 03cbb10a5d449a998c73a88507c2bb9d6f1e1c67 Mon Sep 17 00:00:00 2001 From: Growl Date: Wed, 13 May 2026 22:25:12 +0800 Subject: [PATCH 7/7] Remove messed header notes of CMake files --- cmake/FindCereal.cmake | 8 +++----- cmake/FindDeePMD.cmake | 10 +++------- cmake/FindELPA.cmake | 9 +++------ cmake/FindFFTW3.cmake | 8 +++----- cmake/FindLibComm.cmake | 8 +++----- cmake/FindLibRI.cmake | 7 +++---- cmake/FindMKL.cmake | 6 +++--- cmake/FindNEP.cmake | 19 +++---------------- cmake/FindPEXSI.cmake | 11 +++-------- cmake/FindScaLAPACK.cmake | 9 +++------ cmake/FindTensorFlow.cmake | 8 +++----- 11 files changed, 33 insertions(+), 70 deletions(-) diff --git a/cmake/FindCereal.cmake b/cmake/FindCereal.cmake index fafaa6cd909..739921c800d 100644 --- a/cmake/FindCereal.cmake +++ b/cmake/FindCereal.cmake @@ -1,8 +1,6 @@ -# ############################################################################## -# * Find cereal Find the native cereal headers. -# -# CEREAL_FOUND - True if cereal is found. CEREAL_INCLUDE_DIR - Where to find -# cereal headers. +# =============================================== +# Find Cereal headers. +# =============================================== find_path( CEREAL_INCLUDE_DIR cereal/cereal.hpp diff --git a/cmake/FindDeePMD.cmake b/cmake/FindDeePMD.cmake index bb987f4ca4b..b61925a8cbe 100644 --- a/cmake/FindDeePMD.cmake +++ b/cmake/FindDeePMD.cmake @@ -1,10 +1,6 @@ -# ############################################################################## -# * Find DeePMD Find the native DeePMD headers and libraries. -# -# DeePMD_FOUND - True if lib is found. DeePMDC_FOUND - True if C -# API is found. DeePMD_LIBRARIES - List of libraries DeePMD_INCLUDE_DIR - -# Where to find DeePMD headers. -# +# =============================================== +# Find DeePMD headers and libraries. +# =============================================== # C API find_path( diff --git a/cmake/FindELPA.cmake b/cmake/FindELPA.cmake index 6414a966f86..a42dc2e6d6e 100644 --- a/cmake/FindELPA.cmake +++ b/cmake/FindELPA.cmake @@ -1,9 +1,6 @@ -# ############################################################################## -# * Find ELPA Find the native ELPA headers and libraries. -# -# ELPA_FOUND - True if libelpa is found. ELPA_LIBRARIES - List of -# libraries when using libyaml ELPA_INCLUDE_DIR - Where to find ELPA headers. -# +# =============================================== +# Find ELPA headers and libraries. +# =============================================== find_package(PkgConfig) diff --git a/cmake/FindFFTW3.cmake b/cmake/FindFFTW3.cmake index e6da3deceaa..bdc928f3a03 100644 --- a/cmake/FindFFTW3.cmake +++ b/cmake/FindFFTW3.cmake @@ -1,8 +1,6 @@ -# * Find FFTW3 Find the native double precision FFTW3 headers and libraries. -# -# FFTW3_INCLUDE_DIRS - Where to find FFTW3 headers. FFTW3_LIBRARIES - List -# of libraries when using FFTW3. FFTW3_FOUND - True if FFTW3 is found. -# +# =============================================== +# Find FFTW3 headers and libraries. +# =============================================== find_path( FFTW3_INCLUDE_DIR diff --git a/cmake/FindLibComm.cmake b/cmake/FindLibComm.cmake index 98de2b48da3..7b90106924a 100644 --- a/cmake/FindLibComm.cmake +++ b/cmake/FindLibComm.cmake @@ -1,8 +1,6 @@ -# ############################################################################## -# * Find LibComm Find the native LibComm files. -# -# LIBCOMM_FOUND - True if LibComm is found. LIBCOMM_DIR - Where to find LibComm -# files. +# =============================================== +# Find LibComm headers. +# =============================================== find_path( LIBCOMM_DIR include/Comm/Comm_Tools.h diff --git a/cmake/FindLibRI.cmake b/cmake/FindLibRI.cmake index 3722abef9cb..f4752f6080f 100644 --- a/cmake/FindLibRI.cmake +++ b/cmake/FindLibRI.cmake @@ -1,7 +1,6 @@ -# ############################################################################## -# * Find LibRI Find the native LibRI files. -# -# LIBRI_FOUND - True if LibRI is found. LIBRI_DIR - Where to find LibRI files. +# =============================================== +# Find LibRI headers. +# =============================================== find_path( LIBRI_DIR include/RI/version.h diff --git a/cmake/FindMKL.cmake b/cmake/FindMKL.cmake index 8da18a9433c..48ed23ef299 100644 --- a/cmake/FindMKL.cmake +++ b/cmake/FindMKL.cmake @@ -1,6 +1,6 @@ -# * Find mkl Find the native MKL headers and libraries. -# -# MKL_INCLUDE - where to find mkl.h, etc. MKL_FOUND - True if mkl found. +# =============================================== +# Find MKL headers and libraries. +# =============================================== # find_package(MKL NO_MODULE) # try using official module first if(NOT TARGET MKL::MKL) diff --git a/cmake/FindNEP.cmake b/cmake/FindNEP.cmake index 99441915e42..9b534264751 100644 --- a/cmake/FindNEP.cmake +++ b/cmake/FindNEP.cmake @@ -1,23 +1,10 @@ -# ############################################################################## -# * Find NEP Finds the NEP header and library. +# ============================================================================== +# Find NEP header and library. # -# This module will search for the NEP library, looking for a hint from the -# NEP_DIR environment variable or CMake variable. -# -# This module defines the following variables: -# -# NEP_FOUND - True if the NEP library and headers were found. -# NEP_INCLUDE_DIR - The directory where nep.h is located. NEP_LIBRARY - -# The full path to the NEP library. -# -# It also defines the following imported target: -# -# NEP::nep - The NEP library target. -# -# ############################################################################## # Note: Currently only CPU version is supported, Since the NEP interface with # GPU support is not available yet. In feature, if available, we can use # USE_CUDA to switch between CPU and GPU version. +# ============================================================================== find_path( NEP_INCLUDE_DIR nep.h diff --git a/cmake/FindPEXSI.cmake b/cmake/FindPEXSI.cmake index f6cbfa0e5d6..89964ce3449 100644 --- a/cmake/FindPEXSI.cmake +++ b/cmake/FindPEXSI.cmake @@ -1,11 +1,6 @@ -# ############################################################################## -# * Find PEXSI Find PEXSI and its dependencies. -# -# PEXSI_FOUND - True if pexsi is found. PEXSI_INCLUDE_DIR - Where to -# find pexsi headers. PEXSI_LIBRARY - pexsi library. ParMETIS_INCLUDE_DIR -# - Where to find pexsi headers. ParMETIS_LIBRARY - parmetis library. -# METIS_LIBRARY - metis library. SuperLU_DIST_LIBRARY - superlu_dist -# library. +# =============================================== +# Find PEXSI and its dependencies. +# =============================================== find_path( PEXSI_INCLUDE_DIR diff --git a/cmake/FindScaLAPACK.cmake b/cmake/FindScaLAPACK.cmake index 8d5e154a538..7337b06d318 100644 --- a/cmake/FindScaLAPACK.cmake +++ b/cmake/FindScaLAPACK.cmake @@ -1,9 +1,6 @@ -# * Find ScaLAPACK Find the native double precision ScaLAPACK headers and -# libraries. -# -# ScaLAPACK_LIBRARIES - List of libraries when using ScaLAPACK. -# ScaLAPACK_FOUND - True if ScaLAPACK is found. -# +# =============================================== +# Find ScaLAPACK headers and libraries. +# =============================================== # Accept common root hints from cache vars and environment. set(_scalapack_hints ${SCALAPACK_DIR} ${SCALAPACK_ROOT} $ENV{SCALAPACK_DIR} diff --git a/cmake/FindTensorFlow.cmake b/cmake/FindTensorFlow.cmake index bf51c651122..801211faef5 100644 --- a/cmake/FindTensorFlow.cmake +++ b/cmake/FindTensorFlow.cmake @@ -1,8 +1,6 @@ -# ############################################################################## -# * Find TensorFlow Find the native TensorFlow libraries. -# -# TensorFlow_FOUND - True if lib is found. TensorFlow_LIBRARIES - List -# of libraries +# =============================================== +# Find TensorFlow libraries. +# =============================================== find_library( tensorflow_cc