[{"content":"👋 你好！ 欢迎来到我的个人博客。这个站点是我在科研之余，利用 Hugo 和 Stack 主题搭建的“数字花园”。\n🔍 这里主要聊什么？ 根据目前的规划，我会在这里分享以下内容：\n科研与随笔 (/posts)：记录研究进展、论文笔记以及一些零碎的想法。 科研课题 (/projects)：展示我正在参与或已经完成的学术项目和研究课题。 建站与折腾 (/tricks)：记录我在技术探索、工具优化过程中的实践经验（比如这个博客的搭建过程）。 🚀 关于我 一名热衷于深度学习与分子动力学交叉领域的探索者。如果你对我的研究感兴趣，或者只是想打个招呼，欢迎通过侧边栏的社交媒体联系我。\n“Stay hungry, stay foolish.” 希望你在这里能有所收获！\n","date":"2026-03-05T00:00:00+08:00","image":"/posts/welcome-to-my-blog/cover.jpg","permalink":"/posts/welcome-to-my-blog/","title":"欢迎来到我的数字空间"},{"content":"记一次 QE 编译排障：从 FHC 收敛坑到 oneAPI/MKL 与 AOCL 优化 作为一个刚开始认真折腾第一性原理计算的新人，我原本以为编译 Quantum ESPRESSO 只是“把依赖装好，然后 cmake \u0026amp;\u0026amp; make”这么简单。结果这一轮下来，我对 HPC 环境、数值库、编译器、运行时链接，以及“同样的版本号不代表同样的行为”这句话，有了非常痛的体会。\n这篇文章记录一次完整的踩坑过程：我为什么重新在 CPU 集群上编译 QE，为什么一度被“同一个构型、同样版本的 QE，却在不同环境下一个能收敛一个不收敛”这件事气到，以及最后是如何把问题逐渐收束到 Libxc 的 FHC 选项、oneAPI + MKL 的优化路径，以及 AOCC 并不等于 AOCL 这几个关键点上的。\n一、起因：2×9654 也不是万能的 我最开始的想法其实很朴素：手里明明有 AMD EPYC 9654 这样的 CPU 节点，跑一些 QE 单点构型重标注，应该不会太慢吧？\n但实际测试下来，我发现我的 case 跑得并不理想。尤其是批量构型一多，单个 case 的耗时就很刺眼。于是我开始想：\n既然 CPU 集群上已经装好了 Intel oneAPI 和 MKL； 而我这批计算本质上又是 CPU 密集型； 那么是否应该在 Intel CPU 集群上重新编译一版 QE，走 oneAPI + MKL 路线，看看能不能把性能和稳定性一起拉起来？ 这个想法后来证明完全正确。只是我没想到，真正先把我绊倒的，不是性能，而是收敛性。\n二、最让我气愤的一幕：同一个构型、同版本 QE，居然一个收敛一个不收敛 最开始我遇到的问题不是“算得慢”，而是“算不下来”。\n症状很典型：某些构型在一个环境里可以继续往下跑，而在另一个环境里却报类似下面的错误：\n1 2 Error in routine c_bands (1): too many bands are not converged 或者更直接一点，在第一步、前几步就崩掉。\n最让我难受的是：QE 版本号明明一样。\n我一度非常恼火。因为在一个 DFT 新手的直觉里，版本一样、输入一样、赝势一样，结果至少不应该差这么离谱。后来我才真正认识到，在 HPC 科学计算里，所谓“环境”从来都不只是一个版本号。它背后至少还包括：\n编译器； MPI 实现； BLAS/LAPACK/FFT 后端； 外部库的版本与编译选项； 动态库还是静态库； 运行时究竟加载了哪一份库。 也正是在这一轮排查中，我第一次真正理解了：“软件版本相同”根本不等于“数值路径相同”。\n三、第一轮排查：怀疑 MPI、怀疑脚本、怀疑链接，最后聚焦到 Libxc 起初我的排查路线比较朴素，主要看这些：\nsrun 和 mpirun 的差异； pw.x 究竟链接的是哪一套 MPI； LD_LIBRARY_PATH 是否正确； libxc 是否真的被启用； MKL 是否被正确加载； 运行时到底吃的是哪份 libxc。 其中一个重要发现是：不同节点上的 pw.x 二进制其实根本不是同一个构建结果。 虽然源码版本一致，但哈希值不同，依赖链也不同。换句话说，我之前以为自己在比较“同一程序在不同机器上的表现”，实际上是在比较“两套不同构建结果的 QE”。\n进一步查下去，我开始逐渐把怀疑集中到 Libxc 上，尤其是对 SCAN 这类泛函的支持。\n四、关键转折：FHC 才是那个真正影响“能不能算”的元凶之一 后来最关键的线索出现了： 我发现自己之前的 libxc 编译里，FHC 是开启的。\n而在后续排查中，我注意到一个非常重要的事实：对于 SCAN 这类 meta-GGA 泛函，libxc 的 Fermi hole curvature（FHC） 选项可能直接影响数值稳定性。更具体地说，它不是“算得快不快”的问题，而是“同一个构型到底能不能稳定收敛”的问题。\n这就解释了为什么我会遇到那么诡异的现象：\n输入文件一样； 赝势一样； QE 版本号一样； 但某个构型在一套环境里会在前几步就报 too many bands are not converged，而在另一套环境里却能正常收敛。\n后来当我重新编译一套 关闭 FHC 的 libxc 后，原本不稳定的构型居然就能继续稳稳往下跑，并最终完成收敛。这一刻我真的有点震撼： 一个编译选项，足以决定“同一个构型到底是算得下来，还是算不下来”。\n也正因为这个经历，我现在对 libxc 的态度已经完全变了。以前总觉得它只是“QE 的一个依赖”，现在我会把它视为：\n对某些泛函来说，libxc 的版本与编译方式，本身就是数值模型的一部分。\n五、第二个坑：CMake 升太新，也会出问题 解决完 libxc/FHC 这条主线后，我又踩到了另一个很典型、但一开始并不显眼的坑：CMake 版本太新。\n因为系统自带的 CMake 太旧，所以我当时一口气把 CMake 升到了 4.3.1。按直觉看，这似乎是“升级工具链、拥抱新版本”的标准操作。但实际情况是，新版 CMake 对一些旧模块、旧写法更严格，结果导致 QE 构建中的某些模块开始报兼容性问题。\n最直接的影响包括：\n内置 LAPACK 相关模块报错； MBD 相关模块出现兼容性问题； 某些旧语法需要额外策略兼容。 最后的处理思路不是回退一切，而是：\n放弃 QE 内置数学库路线； 直接切到 oneAPI + MKL； FFT 路线指定为 Intel_DFTI； 再通过追加 1 -DCMAKE_POLICY_VERSION_MINIMUM=3.5 让新版 CMake 对旧模块“网开一面”。\n这一段很有代表性。它说明一件事： “新”不一定直接等于“更适合生产环境”。 在科学计算软件生态里，一个过新的构建工具，反而可能把原本就不够现代化的上层项目折腾出额外兼容性问题。\n六、我最后采用的生产路线：oneAPI + MKL + no-FHC libxc 在 Intel CPU 集群上，我最终确定下来的主线是：\n编译器：mpiicx / mpiifx MPI：Intel MPI BLAS/LAPACK：MKL FFT：Intel_DFTI Libxc：单独编译，关闭 FHC QE：CMake 构建 我的环境变量大致是：\n1 2 3 4 5 6 7 8 9 # Libxc 相关路径 export LIBXC_SRC=\u0026#34;/opt/libxc_src\u0026#34; export LIBXC_BUILD=\u0026#34;/opt/libxc_src/build\u0026#34; export LIBXC_PREFIX=\u0026#34;/opt/libxc/6.2.2-nofhc-ifx\u0026#34; # Quantum ESPRESSO (QE) 相关路径 export QE_SRC=\u0026#34;/opt/q-e-qe-7.3.1\u0026#34; export QE_BUILD=\u0026#34;/opt/q-e-qe-7.3.1/build\u0026#34; export QE_PREFIX=\u0026#34;/opt/qe-7.3.1-ifx-cmake-nofhc\u0026#34; 最终使用的 QE 配置命令核心部分是：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 cmake \u0026#34;$QE_SRC\u0026#34; \\ -DCMAKE_C_COMPILER=mpiicx \\ -DCMAKE_Fortran_COMPILER=mpiifx \\ -DCMAKE_BUILD_TYPE=Release \\ -DCMAKE_C_FLAGS=\u0026#34;-O2\u0026#34; \\ -DCMAKE_Fortran_FLAGS=\u0026#34;-O2\u0026#34; \\ -DQE_ENABLE_MPI=ON \\ -DQE_ENABLE_OPENMP=ON \\ -DQE_ENABLE_LIBXC=ON \\ -DQE_BLAS_INTERNAL=OFF \\ -DQE_LAPACK_INTERNAL=OFF \\ -DQE_FFTW_VENDOR=Intel_DFTI \\ -DCMAKE_PREFIX_PATH=\u0026#34;$LIBXC_PREFIX\u0026#34; \\ -DLibxc_ROOT=\u0026#34;$LIBXC_PREFIX\u0026#34; \\ -DCMAKE_INSTALL_PREFIX=\u0026#34;$QE_PREFIX\u0026#34; \\ -DCMAKE_INSTALL_RPATH=\u0026#34;$LIBXC_PREFIX/lib;/opt/intel/oneapi/mpi/2021.11/lib;/opt/intel/oneapi/compiler/2024.0/lib\u0026#34; \\ -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \\ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 而 libxc 这边，最关键的一条就是：\n1 -DDISABLE_FHC=ON 这条看似不起眼，但在我的这批 SCAN 构型上，几乎就是决定生死的选项。\n七、一个很容易误判的点：没报缺库，不代表你真的理解了链接方式 中间我还遇到一个非常容易让人误判的问题： 有时候 ldd pw.x 里看不到 libxc.so，但程序并不报缺库，而且照样能跑。\n这让我一开始很困惑，以为是不是 libxc 根本没连上。后来才意识到，这里还要区分：\n动态链接：ldd 能直接看到 libxc.so 静态链接：ldd 看不到，但构建和符号里实际上已经吃进去了 对于我这种刚开始折腾 DFT 环境的人来说，这又是一个很有教育意义的坑： “程序能跑”和“你知道它为什么能跑”是两件事。\n科学计算环境里，真正麻烦的从来不是出错，而是那种“看起来能跑，但你并没有完全搞清楚依赖链”的状态。因为那会让后续复现和迁移都变得非常危险。\n八、另一个重要认知：我其实只是用了 AOCC 编译器，并没有真正用到 AOCL 当 Intel 这套新环境跑顺之后，我又回头看了一眼自己之前在 AMD 9654 节点上的构建，结果发现了一个相当扎心的事实：\n我之前只是用了 AOCC 编译 QE，但根本没有真正用 AOCL。\n也就是说，我当时走的是：\nAOCC 编译器； 但 BLAS/LAPACK 用的是 internal； FFT 用的也是 internal。 难怪性能那么一般。\n这一点后来让我印象特别深。因为在很多人（包括之前的我）的直觉里，会下意识地把：\n“用了 AMD 编译器” 和“用了 AMD 优化数学库” 这两件事混为一谈。\n但实际上完全不是一回事。\nAOCC 是编译器 AOCL 才是数学库加速栈 如果你只是用了 AOCC，却仍然把：\nQE_BLAS_INTERNAL=ON QE_LAPACK_INTERNAL=ON QE_FFTW_VENDOR=Internal 写进 CMake 里，那本质上你并没有把 9654 这颗大 CPU 真正榨出来。\n这也是我后来特别想写下来的原因之一。因为它真的很容易让人产生一种错觉：\n“我明明已经在高端节点上编译了，为什么还是不快？”\n答案可能并不是 CPU 不够强，而是你根本没有把正确的后端接上去。\n九、结果：生产效率一下子进入了另一个量级 当 oneAPI + MKL + no-FHC 的 Intel 版本跑通后，我再回头看自己的批量任务，心态已经完全不一样了。\n以前看着几千个构型，会本能地觉得：\n这是不是又要跑很多天？ 哪个节点上挂了怎么办？ 收敛不稳会不会拖垮整批任务？ 但当单个 24 原子构型在 4 核下不到两分钟就能算完时，量级立刻变了。 一旦批量并发开起来，原来觉得非常沉重的 DFT 重标注任务，突然就变成了一个可以认真规划、快速交付的工作流。\n这一刻我真正体会到：\nHPC 科学计算里的“调优”，从来不是锦上添花，而是决定你能不能把一件事从“理论可行”变成“工程上可执行”。\n十、这次最大的收获，不是把 QE 编译成功，而是学会了如何看待“环境” 如果只是把结论写成一句话，那就是：\n科学计算里，版本号只是入口，环境才是本体。\n这次折腾之后，我对下面几件事的理解都比以前深得多：\n1. libxc 不是无脑依赖 它的版本、编译方式，尤其是像 FHC 这样的选项，可能直接改变收敛行为。\n2. 编译器不等于数学库 AOCC 不等于 AOCL；oneAPI 也不只是编译器，还包含了一整套数值后端生态。\n3. “能跑”不够 真正的生产环境应该满足三件事：\n能跑； 稳定； 快。 少任何一项，后面都要付出代价。\n4. HPC 调优是科研生产力的一部分 有时候，手握 9654 这样的硬件“利器”，但没有把库链、FFT、BLAS、LAPACK、MPI、外部依赖配对好，那你其实并没有真正拥有它的性能。\n结语：新手也能折腾，但最好别只靠运气 回头看，这整个过程其实非常像我刚接触第一性原理计算时的状态：\n对软件栈的认识是碎片化的； 遇到错误时容易把问题归结为“玄学不收敛”； 对 HPC 环境里“编译方式”和“运行结果”之间的关系缺乏真正的直觉。 但也正是因为这一轮完整踩坑，我第一次认真意识到：\n编译不是安装，部署不是复制，调优也不是可有可无的附加项。\n尤其是在科学计算里，很多时候“为什么同样的 case 这个环境能算、那个环境不能算”，背后未必是什么高深的理论问题，而可能就是一个你之前根本不会在意的库选项。\n所以如果你也在新环境里折腾 QE、CP2K、LAMMPS 这类软件，我想说的一点经验是：\n不要只记“命令怎么敲”； 一定要顺手把构建参数、依赖版本、路径和踩过的坑写下来。 因为等你真的踩过一次之后就会发现， 最可怕的不是报错，而是你明明修好了，却不知道自己到底修好了什么。\n而这，恐怕才是从“会运行程序”到“能掌控计算环境”之间，最重要的一步。\n","date":"2026-04-14T00:00:00+08:00","permalink":"/tricks/build_qe_with_oneapi/","title":"记一次 QE 编译排障：从 FHC 收敛坑到 oneAPI/MKL 与 AOCL 优化"},{"content":"你是否也曾经历过这样的循环：在本地写完一篇精彩的博客，然后手动运行 hugo 生成静态文件，接着打开 FTP 客户端或敲下一串 scp 命令，把 public 文件夹传到服务器，最后还要解压、覆盖……一次两次还能忍受，但每次都要重复这套“搬砖”流程，不仅消磨写作热情，还容易出错。\n今天，我们来彻底终结这种低效的手动部署。借助 GitHub Actions，我们可以打造一条完全自动化的部署流水线：只需在本地执行 git push，几十秒后，你的云服务器上的博客就会自动更新到最新版本。 全程无需手动连接服务器，一切都由 GitHub 免费提供的云虚拟机完成。\n自动化部署的核心原理 整个流水线的逻辑非常清晰，像一个高效的工厂流水线：\n触发：当你将代码推送到 GitHub 仓库的 main 分支（或其他指定分支）时，流水线自动启动。 构建环境：GitHub 分配一台临时的 Ubuntu 容器，里面预装了最新的软件包。 准备代码：自动拉取你的博客源码，包括所有子模块（比如 Hugo 主题 Stack）。 生成静态网站：安装指定版本的 Hugo（extended 版），运行 hugo --minify 命令，生成压缩后的静态网页文件。 同步到服务器：通过 SSH 协议，利用 rsync 工具将生成的 public 目录内容增量同步到你云服务器的 Nginx 网站根目录。 整个过程自动化、可重复、可追溯，而且完全免费。\n打通服务器的“免密通道” 要让 GitHub 的机器人能够登录你的云服务器并写入文件，必须配置 SSH 密钥认证。这是整个配置中最容易让人混淆的一步，核心原则是：私钥留给 GitHub，公钥锁在服务器上。\n打开本地终端，执行以下命令生成一对专用的部署密钥（这里使用 ed25519 算法，安全性更高，且不需要输入密码）：\nbash\n1 ssh-keygen -t ed25519 -f ~/.ssh/github_deploy_key -N \u0026#34;\u0026#34; 执行后会生成两个文件：\n~/.ssh/github_deploy_key —— 私钥（钥匙）：绝对不能泄露，需要交给 GitHub。 ~/.ssh/github_deploy_key.pub —— 公钥（锁）：需要安装在云服务器上。 将私钥交给 GitHub 在浏览器中打开你的 GitHub 仓库，依次进入 Settings -\u0026gt; Secrets and variables -\u0026gt; Actions。 点击 New repository secret。 Name 填写 SSH_PRIVATE_KEY（注意大小写，后面会用到）。 Secret 中粘贴 私钥文件 github_deploy_key 的完整内容，包括 -----BEGIN OPENSSH PRIVATE KEY----- 和 -----END OPENSSH PRIVATE KEY----- 这两行。 点击 Add secret 保存。 将公钥锁到服务器上 登录你的云服务器（假设你使用普通用户 cong 进行部署），执行以下命令：\nbash\n1 2 3 4 5 6 7 8 9 10 11 # 确保 ~/.ssh 目录存在且权限正确 mkdir -p ~/.ssh chmod 700 ~/.ssh # 将公钥内容追加到 authorized_keys 文件中 cat \u0026gt;\u0026gt; ~/.ssh/authorized_keys \u0026lt;\u0026lt; \u0026#39;EOF\u0026#39; （这里粘贴 github_deploy_key.pub 的完整内容） EOF # 设置正确的权限 chmod 600 ~/.ssh/authorized_keys ⚠️ 注意：如果你的云服务器 SSH 端口不是默认的 22（例如改成了 2222），请在后续的 GitHub Secrets 中正确配置端口，并在本地先测试免密登录是否成功：\nbash\n1 ssh -i ~/.ssh/github_deploy_key -p \u0026lt;你的端口\u0026gt; \u0026lt;用户名\u0026gt;@\u0026lt;服务器IP\u0026gt; 如果能够直接登录而不需要密码，说明密钥配置成功。\n编写 GitHub Actions 工作流 在本地博客仓库的根目录下，创建文件夹 .github/workflows/，并在其中新建一个文件，例如 deploy.yml。这个 YAML 文件就是告诉 GitHub Actions 如何执行部署的“剧本”。\n以下是一个完整且经过测试的配置示例，关键部分已添加注释：\nyaml\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 name: Deploy Hugo Blog to Cloud Server on: push: branches: - main # 当推送到 main 分支时触发 jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: submodules: recursive # 如果使用了 git submodule（如主题），拉取完整代码 fetch-depth: 0 - name: Setup Hugo uses: peaceiris/actions-hugo@v3 with: hugo-version: \u0026#39;latest\u0026#39; extended: true # 如果主题使用 SCSS 等特性，必须启用 extended 版本 - name: Build site run: hugo --minify # 生成静态文件，输出到 public 目录 - name: Deploy to server via rsync uses: easingthemes/ssh-deploy@main env: SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} REMOTE_HOST: ${{ secrets.REMOTE_HOST }} # 你的服务器 IP REMOTE_USER: ${{ secrets.REMOTE_USER }} # 登录用户名，如 cong REMOTE_PORT: ${{ secrets.REMOTE_PORT }} # SSH 端口，默认为 22 TARGET: /var/www/html # 服务器上的网站根目录 SOURCE: public/ # 本地要同步的目录（注意末尾的斜杠） ARGS: -avzr --delete # rsync 参数：归档、压缩、递归、删除多余文件 注意：REMOTE_HOST、REMOTE_USER、REMOTE_PORT 这些敏感信息也建议保存在 GitHub Secrets 中，避免直接写在文件里。你可以在仓库 Secrets 中分别添加 REMOTE_HOST、REMOTE_USER、REMOTE_PORT，然后在上述文件中通过 ${{ secrets.REMOTE_HOST }} 引用。\n最后一步：确保服务器目录权限正确 GitHub Actions 将使用你在 REMOTE_USER 中指定的用户身份登录服务器。如果该用户对目标目录（如 /var/www/html）没有写入权限，rsync 会失败并报 Permission denied 错误。\n假设你的部署用户是 cong，网站目录为 /var/www/html，请登录服务器执行：\nbash\n1 sudo chown -R cong:cong /var/www/html 这条命令将目录的所有者改为 cong 用户，确保部署用户有完全的读写权限。\n享受一键部署的畅快 所有配置完成后，将你的 Hugo 博客源码推送到 GitHub 仓库的 main 分支：\nbash\n1 2 3 git add . git commit -m \u0026#34;Add GitHub Actions auto deploy\u0026#34; git push origin main 然后打开 GitHub 仓库的 Actions 标签页，你会看到一个新的工作流正在运行，黄色的圆圈表示进行中。等待几十秒，当它变成绿色的 ✓ 时，访问你的博客网址，内容已经是最新的了！\n从此以后，你可以心无旁骛地专注于写作，每次写完文章，只需执行常规的 git add、git commit、git push，剩下的就交给 GitHub Actions 和 rsync 去完成。技术，本该如此优雅。\n延伸思考：如果你有多个分支需要部署，或者想要在部署前运行测试，都可以通过修改 on.push.branches 或增加新的 job 来实现。GitHub Actions 的灵活性远不止于此，等待你去发掘。\n","date":"2026-03-10T00:00:00+08:00","permalink":"/tricks/github%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2/","title":"Github自动部署"},{"content":"1. 研究背景与问题引入 超临界水在诸多化工和能源领域具有重要的应用价值，而精确描述其微观热力学特性的核心在于构建可靠的分子间相互作用势。\n此前，发表在 JCPL 上的原版超临界水模型虽然在宏观性质的预测上取得了一定成果，但在深入分析其底层物理图像时，我们发现了一个关键缺陷：该模型在 O-H 拉伸势能面（Potential Energy Surface）上存在明显的受力描述伪影（Artifacts）。 这种物理上的不平滑和非物理震荡，会直接影响长时间分子动力学（MD）模拟的稳定性和动力学性质的计算精度。\n2. 模型重构：消除 O-H 拉伸受力伪影 为了解决这一痛点，本工作基于 Deep Potential (DP) 方法重新进行了数据集采样与模型训练。\n数据清洗与增强：针对 O-H 拉伸的关键构型区域进行了高精度第一性原理（DFT）数据的补充。 物理规律对齐：通过调整神经网络的训练策略与损失函数权重，重点优化了对极端构型下受力的拟合表现。 结果表明： 新训练的 DP 模型彻底消除了原有的受力描述伪影，O-H 拉伸势能面恢复了物理上应有的平滑过渡，显著提升了模型在极端条件下的鲁棒性。\n(👇 提示：在这里可以用 Typora 截图粘贴你的势能面对比图，比如命名为 pes-compare.png) 3. 工程优化：dpmdkit2 助力 5.5 倍加速 在保证物理精度的前提下，超临界水的相态和团簇演化往往需要大尺度、长时间的 MD 模拟，这对模型的推理速度提出了极高要求。\n在本工作中，我们引入了最新的 dpmdkit2 工具链。通过其内置的新一代模型压缩（Model Compression）工具，对训练好的 DP 冗余参数进行了深度精简与计算图优化。\n精度损失：压缩前后，能量与受力的 RMSE 保持在极小的阈值内，精度几乎无损。 速度提升：在相同的硬件测试节点上，压缩后的模型单步计算效率达到了原版的 5.5 倍！ (👇 提示：在这里可以插入一张柱状图，直观展示压缩前后的耗时对比) 4. 总结与展望 这套全新的超临界水 DP 模型，兼顾了底层物理的准确性（无伪影）与极致的计算效率（大倍率加速）。这不仅为后续的大尺度超临界水热力学/动力学性质研究铺平了道路，也验证了 dpmdkit2 在复杂体系势函数优化中的巨大潜力。\n接下来，我们将利用该模型进一步探索超临界水在不同温压条件下的氢键网络拓扑演化规律。敬请期待！\n","date":"2026-03-09T00:00:00+08:00","permalink":"/projects/dp-paper/","title":"基于深度势能(DP)的超临界水模型：修复受力伪影与 5.5 倍推理加速"},{"content":"缘起：为什么选择自己折腾？ 为了更好地沉淀个人的项目经验与学习心得，我决定搭建一个纯粹、极简、完全属于自己的学术展示主页。没有选择臃肿的动态博客框架（如 WordPress），而是走向了“静态生成 + 容器化部署 + 自动化脚本”的硬核极客路线。\n这套方案不仅对服务器资源消耗极低，而且将内容的绝对控制权掌握在了自己本地的电脑里。\n🛠️ 我的建站工具流 (Toolchain) 整个网站的运转就像一条精密的流水线，涉及的工具可以分为“云端基础设施”和“本地内容生产”两部分。\n1. 云端基础设施 (Server-Side) 宿主机：某云厂商的入门级轻量应用服务器（内存不足 2GB，所以对资源分配要求极高）。 管理面板：CasaOS。一个基于 Docker 的极简轻量级面板，作为整个服务器的“可视化物业管理”。 反向代理网关：Nginx Proxy Manager (NPM)。负责霸占服务器的 80 和 443 端口，未来等域名备案通过后，统一负责域名的流量转发和 SSL 证书（HTTPS 小绿锁）的自动续签。 前端展示：基础版 Nginx 容器。只分配了 128MB 的内存限制，占用内部的 8080 端口，纯粹用来挂载和展示静态的 HTML 网页文件。 2. 本地内容生产 (Local-Side) 静态网站生成器：Hugo。极其强大的 Go 语言静态博客框架，配合极简的 PaperMod 主题，瞬间将 Markdown 转化为漂亮的网页。 编辑器：Typora。配合 Hugo 的 Page Bundle（页面打包）机制，开启“复制图片到当前文件夹”功能，彻底告别图床失效和路径错乱的烦恼。 自动化部署：自定义 PowerShell 双子星脚本。 new_post.ps1：一键选择板块（项目/随笔）并生成标准化 Markdown 模板。 deploy.ps1：一键执行 Hugo 编译、打包 ZIP，并通过 SSH/SCP 自动推送到服务器并解压覆盖。实现了“本地敲完字，回车即上线”的极致体验。 🕳️ 踩坑实录与避坑指南 折腾的过程并非一帆风顺，期间遇到了几个非常经典的工程问题：\n坑 1：80 端口的“假性占用” 一开始准备部署 NPM 时，命令行提示 80 端口被占用。用 lsof -i :80 查阅后，发现是云厂商自带的监控插件和元数据代理。 破案： 仔细观察网络状态发现是 ESTABLISHED（主动向外请求）而不是 LISTEN（本地监听）。所以本地 80 端口其实是空闲的，直接绕过报错强行启动 Docker 即可。\n坑 2：内存告急与 Docker 的“紧箍咒” 云服务器内存不到 2G，如果不对 Docker 容器设限，极端情况下可能会导致宿主机死机。 解决： 放弃纯 UI 操作，改用 docker-compose.yml 结合 sudo tee 强力写入，在配置中加入 deploy.resources.limits.memory。给 NPM 限制 512M，给静态 Nginx 限制 128M，把每一兆内存都用在刀刃上。\n坑 3：Let\u0026rsquo;s Encrypt 证书申请报 \u0026ldquo;Internal Error\u0026rdquo; 在 NPM 里配置好域名后，死活申请不下来 SSL 证书，一直报内部错误。 破案： 域名还在 ICP 备案审核期！云厂商的骨干网在流量到达服务器前就直接拦截了所有通过 80 端口查水表的 Let\u0026rsquo;s Encrypt 验证请求。目前只能用“IP+端口”的模式曲线救国，静候管局佳音。\n坑 4：自动化脚本乱码与页面“神秘失踪” 在编写 PowerShell 脚本时遇到了字符吞噬的报错，在终于把文件传到服务器后，网页列表却空空如也。 解决： 1. 脚本报错是因为 PowerShell 默认编码问题，将 .ps1 文件另存为带 BOM 的 UTF-8 即可解决。 2. 页面不显示是因为 Hugo 默认过滤草稿。将 .md 文件头的 draft: true 改为 false，并在 hugo.toml 中明确配置 mainSections = [\u0026quot;posts\u0026quot;, \u0026quot;projects\u0026quot;]，文章瞬间完美呈现。\n结语 从底层的防火墙放行、Docker 容器编排，到前端的主题配置、本地的自动化脚本编写，这次建站犹如一次全栈工程的微缩演练。把重复的操作交给脚本，把精力的焦点还给内容，这大概就是折腾技术最大的乐趣所在。\n接下来，就是不断往这个“基站”里填充有价值的思想了。\n","date":"2026-03-09T00:00:00+08:00","permalink":"/tricks/build-website/","title":"记一次硬核又优雅的个人学术主页建站之旅"}]