diff --git a/.conda/README.md b/.conda/README.md index aa43c9f3..6e113c8b 100644 --- a/.conda/README.md +++ b/.conda/README.md @@ -1,4 +1,9 @@ # Build conda recipe for sparc + +**Note** the official conda-forge package for SPARC can be found at +[`sparc-x`](https://github.com/conda-forge/sparc-x-feedstock). This +recipe is maintained for CI purpose only. + 1. Install `conda-build` and (optionally) `boa` ```bash conda install -c conda-forge "conda-build>=3.20" colorama pip ruamel ruamel.yaml rich mamba jsonschema @@ -22,16 +27,9 @@ anaconda login anaconda upload $CONDA_PREFIX/conda-bld/linux-64/sparc-..
-.bz2 ``` -If the SPARC package is finally in production, we need to merge it to `conda-forge` channel (perhaps using a different name `sparc-dft`?) - 4. Using the package ```bash conda install -c sparc ``` This will automatically install `sparc` with `openmpi` + `scalapack` + `openblas` support. No compilation requires afterwards. - -5. TODOs -- [ ] Configure the mpi-aware fftw package -- [ ] Include mkl-variant? -- [ ] Complete conda-forge merge once in upstream main \ No newline at end of file diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index d0fa7031..cd298c95 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -10,13 +10,41 @@ on: workflow_dispatch: jobs: + # Check if initialization.c is up-to-date with Changelog + package-date-check: + runs-on: ubuntu-latest + defaults: + run: + shell: bash -l {0} + steps: + - uses: actions/checkout@v4 + - uses: conda-incubator/setup-miniconda@v3 + with: + python-version: "3.11" + activate-environment: sparc-test + conda-build-version: "24.9.0" + miniforge-version: latest # Fix according to https://github.com/conda-incubator/setup-miniconda?tab=readme-ov-file#example-10-miniforge + channels: conda-forge,defaults + channel-priority: true + - name: Install SPARC-X-API stable version for docparser + run: | + mamba install -c conda-forge pip setuptools + pip install git+https://github.com/SPARC-X/SPARC-X-API.git@v1.0.5 + - name: Convert parameters.json + run: | + python -m sparc.docparser --include-subdirs doc/.LaTeX + - name: Check package version and ChangeLog date + run: | + # Usage: + # python test-outdated-package.py + python .github/workflows/test-outdated-package.py \ + ./parameters.json ChangeLog build-linux: runs-on: ubuntu-latest defaults: run: shell: bash -l {0} - strategy: - max-parallel: 5 + needs: package-date-check steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/test-missing-parameters.py b/.github/workflows/test-missing-parameters.py new file mode 100644 index 00000000..5b7faa62 --- /dev/null +++ b/.github/workflows/test-missing-parameters.py @@ -0,0 +1,87 @@ +"""Test script to check parameters coverage in examples +""" +import json +import os +from pathlib import Path +from sparc.io import _read_inpt + +def load_parameters_json(json_path): + """ + Load the parameters from the parameters.json file. + """ + with open(json_path, 'r') as f: + parameters = json.load(f) + if "parameters" not in parameters: + raise KeyError("The 'parameters' field is missing in parameters.json") + return parameters["parameters"] + +def check_missing_parameters(test_dir, parameters_json_path): + """ + Check for missing parameters in the documentation. + test_dir must be structured in /standard/.inpt + """ + test_dir = Path(test_dir) + documented_parameters = load_parameters_json(parameters_json_path) + + # Iterate through the .inpt files and check for missing parameters + report = {} + for match_file in test_dir.glob("*/standard/*.inpt"): + test_name = match_file.stem + try: + inpt_data = _read_inpt(match_file) + params_in_file = inpt_data["inpt"]["params"] + except Exception: + # Something could be buggy with SPARC-X-API? + pass + + # Check missing or typo parameters + missing_params = [ + param for param in params_in_file + if (param.upper() not in documented_parameters) + # TODO: Obsolete BOUNDARY_CONDITION keyword + and (param.upper() != "BOUNDARY_CONDITION") + ] + if missing_params: + report[test_name] = missing_params + + # Generate report and return error if missing parameters are found + if report: + print("Missing / Incorrect Parameters Report:") + print("-" * 60) + for file_path, missing_params in report.items(): + print(f"Test name: {file_path}") + print(f"Missing Parameters: {', '.join(missing_params)}") + print("-" * 60) + return False + else: + print("All parameters are documented correctly.") + return True + + +def main(): + import argparse + parser = argparse.ArgumentParser( + description="Check for missing / incorrect parameters in SPARC examples." + ) + parser.add_argument( + "test_directory", + type=str, + help="Path to the directory containing test .inpt files." + ) + parser.add_argument( + "parameters_json", + type=str, + help="Path to the parameters.json file." + ) + + args = parser.parse_args() + + # Run the check + success = check_missing_parameters(args.test_directory, + args.parameters_json) + if not success: + exit(1) + else: + exit(0) +if __name__ == "__main__": + main() diff --git a/.github/workflows/test-outdated-package.py b/.github/workflows/test-outdated-package.py new file mode 100644 index 00000000..1ea3c138 --- /dev/null +++ b/.github/workflows/test-outdated-package.py @@ -0,0 +1,108 @@ +"""Test script to check if SPARC package version is older than +the latest Changelog entry + +We generally do not check the other way around since sometimes a trivial bump of SPARC version may be necessary +""" +import re +import json +from datetime import datetime +from pathlib import Path + + +def load_parameters_json(json_path): + """ + Load the parameters from the parameters.json file. + """ + with open(json_path, 'r') as f: + parameters = json.load(f) + if "sparc_version" not in parameters: + raise KeyError("The 'sparc_version' field is missing in parameters.json") + return parameters["sparc_version"] + + +def extract_latest_date_from_changelog(changelog_path): + """ + Extracts the latest date from the changelog file. + """ + date_patterns = [ + r"(?P\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{1,2}, \d{4})", + r"(?P\b(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}, \d{4})", + ] + + latest_date = None + changelog_path = Path(changelog_path) + + with changelog_path.open("r") as f: + content = f.read() + + for pattern in date_patterns: + matches = re.findall(pattern, content) + for match in matches: + try: + # Convert matched date to datetime object + parsed_date = datetime.strptime(match, "%b %d, %Y") if "," in match else datetime.strptime(match, "%B %d, %Y") + if latest_date is None or parsed_date > latest_date: + latest_date = parsed_date + except ValueError: + continue # Skip invalid date formats + + if latest_date is None: + raise ValueError("No valid date found in the changelog.") + return latest_date + + +def check_version_against_changelog(parameters_json_path, changelog_path): + """ + Check if the package version in parameters.json is older than the latest changelog date. + """ + # Load sparc_version from parameters.json + sparc_version = load_parameters_json(parameters_json_path) + version_date = datetime.strptime(sparc_version, "%Y.%m.%d") + + # Extract the latest date from the changelog + latest_changelog_date = extract_latest_date_from_changelog(changelog_path) + + if version_date < latest_changelog_date: + print("Version Check Report:") + print("-" * 60) + print(f"ERROR: SPARC version ({version_date.strftime('%Y.%m.%d')}) " + f"is older than the latest changelog date ({latest_changelog_date.strftime('%Y.%m.%d')}).") + print("Please update initialization.c!") + print("-" * 60) + return False + else: + print("Version Check Report:") + print("-" * 60) + print("SUCCESS:") + print("-" * 60) + return True + + +def main(): + import argparse + parser = argparse.ArgumentParser( + description="Check if package version is up-to-date with the changelog." + ) + parser.add_argument( + "parameters_json", + type=str, + help="Path to the parameters.json file." + ) + parser.add_argument( + "changelog", + type=str, + help="Path to the changelog file." + ) + + args = parser.parse_args() + + # Run the version check + success = check_version_against_changelog(args.parameters_json, args.changelog) + if not success: + exit(1) + else: + exit(0) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/update-doc-pdf.yml b/.github/workflows/update-doc-pdf.yml new file mode 100644 index 00000000..cc319ee1 --- /dev/null +++ b/.github/workflows/update-doc-pdf.yml @@ -0,0 +1,90 @@ +name: Check and render LaTeX doc into pdf + +on: + push: + branches: + - master + paths: + - doc/** + - .github/workflows/update-doc-pdf.yml + pull_request: + branches: + - master + paths: + - doc/** + - .github/workflows/update-doc-pdf.yml + workflow_dispatch: + +jobs: + check-parameters: + runs-on: ubuntu-latest + defaults: + run: + shell: bash -l {0} + steps: + - uses: actions/checkout@v4 + - uses: conda-incubator/setup-miniconda@v3 + with: + python-version: "3.11" + activate-environment: sparc-test + conda-build-version: "24.9.0" + miniforge-version: latest # Fix according to https://github.com/conda-incubator/setup-miniconda?tab=readme-ov-file#example-10-miniforge + channels: conda-forge,defaults + channel-priority: true + - name: Install SPARC-X-API stable version for docparser + run: | + mamba install -c conda-forge pip setuptools + pip install git+https://github.com/SPARC-X/SPARC-X-API.git@v1.0.5 + - name: Convert parameters.json + run: | + python -m sparc.docparser --include-subdirs doc/.LaTeX + - name: Check missing parameters in test examples + run: | + # Usage: + # python test-missing-parameters.py + # If test fails, a list of missing / typo params will + # be written in output + python .github/workflows/test-missing-parameters.py \ + tests/ ./parameters.json + + render-pdf-linux: + runs-on: ubuntu-latest + defaults: + run: + shell: bash -l {0} + needs: check-parameters + steps: + - uses: actions/checkout@v4 + - uses: conda-incubator/setup-miniconda@v3 + with: + python-version: "3.11" + activate-environment: sparc-test + conda-build-version: "24.9.0" + miniforge-version: latest # Fix according to https://github.com/conda-incubator/setup-miniconda?tab=readme-ov-file#example-10-miniforge + channels: conda-forge,defaults + channel-priority: true + - name: Install tectonic as latex rendering engine + run: | + mamba install -c conda-forge tectonic + - name: Make temp build dir + run: | + mkdir -p doc/_build + - name: Render main manual + run: | + tectonic -X compile doc/.LaTeX/Manual.tex \ + --outdir doc/_build + ls -al doc/_build + - name: Render subdir manuals + run: | + for dir in doc/.LaTeX/*; do + if [ -d "$dir" ]; then + manual=$(find "$dir" -maxdepth 1 -name "*Manual.tex" | head -n 1) + if [ -n "$manual" ]; then + tectonic -X compile "$manual" \ + --outdir doc/_build + echo "Rendered: $manual" + fi + fi + done + ls -al doc/_build + diff --git a/ChangeLog b/ChangeLog index 8899d221..992f5edf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,15 @@ -Date -Name -changes +-------------- +Nov 23, 2024 +Name: Tian Tian +Changes: (doc, CI workflow) +1. Fix typo in SQ LaTeX doc +2. Add CI workflow to check missing parameters +3. Add CI workflow to validate and render LaTeX doc +4. Add CI workflow to check outdated initialization.c (SPARC version) if older than current Changelog + -------------- Nov 18, 2024 Name: Tian Tian, Lucas Timmerman diff --git a/doc/.LaTeX/Introduction.tex b/doc/.LaTeX/Introduction.tex index 7e0ec355..15990a7d 100644 --- a/doc/.LaTeX/Introduction.tex +++ b/doc/.LaTeX/Introduction.tex @@ -46,6 +46,8 @@ \begin{itemize} \item \textbf{Benjamin Comer}: Code testing, Initial testing framework \item \textbf{Sushree Jagriti Sahoo}: Code testing + \item \textbf{Tian Tian}: Socket communication layer, code testing, Python API + \item \textbf{Lucas R Timmerman}: Socket communication layer, code testing, Python API \end{itemize} \end{itemize} @@ -416,6 +418,14 @@ \begin{block}{Orbital Free DFT} \hyperlink{OFDFT_FLAG}{\texttt{OFDFT\_FLAG}} $\vert$ \hyperlink{TOL_OFDFT}{\texttt{TOL\_OFDFT}} $\vert$ \hyperlink{OFDFT_LAMBDA}{\texttt{OFDFT\_LAMBDA}} \end{block} + + \begin{block}{Socket communication} + \hyperlink{SOCKET_FLAG}{\texttt{SOCKET\_FLAG}} $\vert$ + \hyperlink{SOCKET_HOST}{\texttt{SOCKET\_HOST}} $\vert$ + \hyperlink{SOCKET_PORT}{\texttt{SOCKET\_PORT}} $\vert$ + \hyperlink{SOCKET_INET}{\texttt{SOCKET\_INET}} $\vert$ + \hyperlink{SOCKET_MAX_NITER}{\texttt{SOCKET\_MAX\_NITER}} $\vert$ + \end{block} \end{frame} diff --git a/doc/.LaTeX/Manual.tex b/doc/.LaTeX/Manual.tex index df1b77ab..28639662 100644 --- a/doc/.LaTeX/Manual.tex +++ b/doc/.LaTeX/Manual.tex @@ -101,5 +101,6 @@ \include{Print} \include{Paral} \include{OFDFT} +\include{Socket} \end{document} diff --git a/doc/.LaTeX/highT/Introduction.tex b/doc/.LaTeX/highT/Introduction.tex index 693844a9..3fa3a29c 100644 --- a/doc/.LaTeX/highT/Introduction.tex +++ b/doc/.LaTeX/highT/Introduction.tex @@ -66,7 +66,7 @@ \hyperlink{SQ_HIGHT_FLAG}{\texttt{SQ\_HIGHT\_FLAG}} $\vert$ \hyperlink{SQ_RCUT}{\texttt{SQ\_RCUT}} $\vert$ \hyperlink{SQ_NPL_G}{\texttt{SQ\_NPL\_G}} $\vert$ -\hyperlink{SQ_GAUSS_HYBRID_MEM}{\texttt{SQ\_HIGHT\_GAUSS\_HYBRID\_MEM}} $\vert$ +\hyperlink{SQ_HIGHT_GAUSS_HYBRID_MEM}{\texttt{SQ\_HIGHT\_GAUSS\_HYBRID\_MEM}} $\vert$ \hyperlink{SQ_TOL_OCC}{\texttt{SQ\_TOL\_OCC}} $\vert$ \hyperlink{NP_DOMAIN_SQ_PARAL}{\texttt{NP\_DOMAIN\_SQ\_PARAL}} \end{block} diff --git a/doc/.LaTeX/mlff/Manual_mlff.tex b/doc/.LaTeX/mlff/Manual_mlff.tex deleted file mode 100644 index ed0a40e7..00000000 --- a/doc/.LaTeX/mlff/Manual_mlff.tex +++ /dev/null @@ -1,73 +0,0 @@ -\documentclass[xcolor=dvipsnames,t]{beamer} -%\usepackage[utf8]{inputenc} -\usepackage{verbatim} % for comment -\usetheme{Madrid} -\usecolortheme{seahorse} -\usepackage{beamerouterthemesplit} -\usepackage[T1]{fontenc} - -\setbeamerfont{institute}{size=\normalsize} - -\title[] {SPARC - MLFF \\ {\normalsize Machine-learned force fields} \\ {\small User guide}} -%\author{} -%\author{Qimen Xu, Abhiraj Sharma, Phanish Suryanarayana, } - -\institute[] -{ -Material Physics \& Mechanics Group \\ -PI: Phanish Suryanarayana \\ -%Main Developers: Shashikant Kumar, Abhiraj Sharma\\ -%Collaborators: J.E. Pask (LLNL)\\ -Georgia Institute of Technology \\ -\hyperlink{Contributors}{Contributors}\\ -\hyperlink{Citation}{Citation} \\ -\hyperlink{Acknowledgements}{Acknowledgements} -} - -\date{} -\setbeamertemplate{frametitle continuation}{} -\setbeamertemplate{navigation symbols}{} -\setbeamercolor{block title}{bg=Apricot!50,fg=black} -%\addtobeamertemplate{block begin}{\vskip -\smallskipamount}{} -%\addtobeamertemplate{block end}{}{\vskip -\smallskipamount} -\addtobeamertemplate{block begin}{\vspace*{-0.6pt}}{} -\addtobeamertemplate{block end}{}{\vspace*{-0.6pt}} -\hypersetup{colorlinks, -citecolor=violet, -linkcolor=blue, -menucolor=white, -anchorcolor=yellow -filecolor=pink, -} - - -\setbeamertemplate{footline}{ - \hbox{% - \begin{beamercolorbox}[wd=\paperwidth,ht=1ex,dp=1.5ex,leftskip=2ex,rightskip=2ex]{page footer}% - \usebeamerfont{title in head/foot}% - \insertshorttitle \hfill - \insertsection \hfill - \insertframenumber{} / \inserttotalframenumber - \end{beamercolorbox}}% -} - -\let\otp\titlepage -\renewcommand{\titlepage}{\otp\addtocounter{framenumber}{-1}} - - -%\includeonly{Introduction,Stress,MD,Optimization,Print} -%\includeonly{Introduction} - -\begin{document} - -%\frame{\titlepage} - -\begin{frame}[plain] - \titlepage -\end{frame} - -\include{Introduction} -\include{mlff} - - -\end{document} diff --git a/src/initialization.c b/src/initialization.c index 82aad807..30f551a9 100644 --- a/src/initialization.c +++ b/src/initialization.c @@ -3649,7 +3649,7 @@ void write_output_init(SPARC_OBJ *pSPARC) { } fprintf(output_fp,"***************************************************************************\n"); - fprintf(output_fp,"* SPARC (version Nov 18, 2024) *\n"); + fprintf(output_fp,"* SPARC (version Nov 23, 2024) *\n"); fprintf(output_fp,"* Copyright (c) 2020 Material Physics & Mechanics Group, Georgia Tech *\n"); fprintf(output_fp,"* Distributed under GNU General Public License 3 (GPL) *\n"); fprintf(output_fp,"* Start time: %s *\n",c_time_str);