<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ionizing Radiation</title>
    <link>http://ionizing.page/</link>
    <description>Recent content on Ionizing Radiation</description>
    <generator>Hugo -- gohugo.io</generator>
    <lastBuildDate>Tue, 03 Feb 2026 16:59:00 +0800</lastBuildDate>
    
        <atom:link href="http://ionizing.page/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>About</title>
      <link>http://ionizing.page/about/</link>
      <pubDate>Tue, 13 Apr 2021 00:00:00 +0800</pubDate>
      
      <guid>http://ionizing.page/about/</guid>
      
        <description>&lt;p&gt;A Ph.D candidate who majors in physical chemistry.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Abilities&lt;/th&gt;
&lt;th&gt;Level&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C/C++&lt;/td&gt;
&lt;td&gt;Beginner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;Beginner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LaTeX&lt;/td&gt;
&lt;td&gt;Newbie&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VASP&lt;/td&gt;
&lt;td&gt;Beginner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;Beginner&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://english.stackexchange.com/questions/83832/list-of-expertise-levels-from-beginner-to-expert&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://english.stackexchange.com/questions/83832/list-of-expertise-levels-from-beginner-to-expert&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      
    </item>
    
    <item>
      <title>External-link</title>
      <link>http://ionizing.page/external-link/</link>
      <pubDate>Fri, 16 Apr 2021 21:26:00 +0800</pubDate>
      
      <guid>http://ionizing.page/external-link/</guid>
      
        <description>&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Person&lt;/th&gt;
&lt;th&gt;Link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Liam0205&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://liam.page/about/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://liam.page/about/&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mr. Joker&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://mrjokersince1997.gitee.io&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://mrjokersince1997.gitee.io&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</description>
      
    </item>
    
    <item>
      <title>单层 TMD 材料的三能带紧束缚模型构建</title>
      <link>http://ionizing.page/post/tmd-tightbinding/</link>
      <pubDate>Tue, 03 Feb 2026 16:59:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/tmd-tightbinding/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%bc%95%e8%a8%80&#34;&gt;引言&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#tmd-%e7%9a%84%e6%99%b6%e4%bd%93%e7%bb%93%e6%9e%84%e4%b8%8e%e5%af%b9%e7%a7%b0%e6%80%a7%e5%88%86%e6%9e%90&#34;&gt;TMD 的晶体结构与对称性分析&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#tmd-%e7%9a%84%e5%ae%9e%e7%a9%ba%e9%97%b4%e7%bb%93%e6%9e%84%e4%b8%8e%e5%b8%83%e9%87%8c%e6%b8%8a%e5%8c%ba&#34;&gt;TMD 的实空间结构与布里渊区&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#tmd-%e7%9a%84%e5%af%b9%e7%a7%b0%e6%80%a7&#34;&gt;TMD 的对称性&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%9f%ba%e7%bb%84%e7%9a%84%e7%a1%ae%e5%ae%9a%e5%8f%8a%e5%af%b9%e7%a7%b0%e6%80%a7%e7%ae%97%e7%ac%a6&#34;&gt;基组的确定及对称性算符&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%b4%a7%e6%9d%9f%e7%bc%9a-hamiltonian-%e7%9a%84%e6%9e%84%e5%bb%ba&#34;&gt;紧束缚 Hamiltonian 的构建&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%9d%90%e6%a0%87%e7%b3%bb%e4%b8%8e%e8%bf%91%e9%82%bb%e5%8e%9f%e5%ad%90&#34;&gt;坐标系与近邻原子&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%b4%a7%e6%9d%9f%e7%bc%9a%e6%a8%a1%e5%9e%8b-hamiltonian&#34;&gt;紧束缚模型 Hamiltonian&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%9c%80%e8%bf%91%e9%82%bb%e6%a8%a1%e5%9e%8b&#34;&gt;最近邻模型&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%89%e8%bf%91%e9%82%bb%e6%a8%a1%e5%9e%8b&#34;&gt;第三近邻模型&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%87%aa%e6%97%8b-%e8%bd%a8%e9%81%93%e8%80%a6%e5%90%88%e7%9a%84%e5%bc%95%e5%85%a5&#34;&gt;自旋-轨道耦合的引入&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8e%9f%e5%ad%90%e5%86%85-soc-%e7%9a%84%e5%9f%ba%e6%9c%ac%e5%bd%a2%e5%bc%8f&#34;&gt;原子内 SOC 的基本形式&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%b8%89%e8%83%bd%e5%b8%a6%e6%a8%a1%e5%9e%8b%e4%b8%ad%e7%9a%84-soc-%e4%bd%9c%e7%94%a8&#34;&gt;三能带模型中的 SOC 作用&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#l-z-%e7%ae%97%e7%ac%a6&#34;&gt;\(L_z\) 算符&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#s-z-%e7%ae%97%e7%ac%a6&#34;&gt;\(S_z\) 算符&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%80%83%e8%99%91%e8%87%aa%e6%97%8b%e8%bd%a8%e9%81%93%e8%80%a6%e5%90%88%e5%90%8e%e7%9a%84%e8%83%bd%e5%b8%a6&#34;&gt;考虑自旋轨道耦合后的能带&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8f%82%e6%95%b0%e7%9a%84%e6%8b%9f%e5%90%88&#34;&gt;参数的拟合&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%9b%ae%e6%a0%87%e8%83%bd%e5%b8%a6&#34;&gt;目标能带&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%9e%84%e9%80%a0%e6%8d%9f%e5%a4%b1%e5%87%bd%e6%95%b0&#34;&gt;构造损失函数&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e5%92%8c%e8%ae%a1%e7%ae%97%e7%bb%93%e6%9e%9c&#34;&gt;程序设计和计算结果&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%a8%a1%e5%9e%8b%e7%9a%84%e5%b1%80%e9%99%90%e6%80%a7&#34;&gt;模型的局限性&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34;&gt;总结&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%be%85%e7%bb%ad&#34;&gt;待续&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%bb%a3%e7%a0%81%e4%b8%8b%e8%bd%bd&#34;&gt;代码下载&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%87%b4%e8%b0%a2&#34;&gt;致谢&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;本文将从对称性与轨道选择出发，逐步构建单层 TMD 的三能带紧束缚模型，并说明它为何足以描述 K/K′
点附近的带边性质。&lt;/p&gt;
&lt;h2 id=&#34;引言&#34;&gt;引言&lt;/h2&gt;
&lt;p&gt;单层过渡金属二硫化物（TMD，如 MoS&lt;sub&gt;2&lt;/sub&gt;、WS&lt;sub&gt;2&lt;/sub&gt;、MoSe&lt;sub&gt;2&lt;/sub&gt; 等）是近年来非常受关注的一类二维半导体材料。
它们在单层极限下表现为直接带隙体系，并且具有明显的自旋-轨道耦合效应和能谷（valley）自由度，
这使得许多新奇的物理都集中在 K/K&#39; 点附近。在这个能量区间内，价带顶与导带底几乎完全由过渡金属原子的
\(d\) 轨道组成，它们分别是 \(d_{z^2}\) 、 \(d_{xy}\) 与 \(d_{x^2-y^2}\) 。基于这一事实，我们可以构建一个仅包含这三个轨道的紧束缚模型，也就是常常提到的三能带模型。尽管这个模型的基组很小，但已经足够描述 K/K&#39; 点附近的带边性质。&lt;/p&gt;
&lt;p&gt;不妨在这里简要介绍一下紧束缚模型。所谓紧束缚模型，是指利用局域的原子轨道来描述晶体电子结构的办法：
它假设电子主要局域在各个原子附近，即波函数由一组正交的原子轨道线性组合而成，并允许电子通过有限距离的跳跃
(hopping) 在晶格中传播。它的 Hamiltonian 通常由原位 (on-site)
能级和近邻/远近邻跳跃项组成，它的参数可以由对称性约束得到简化，并通过拟合 DFT 能带得到。
紧束缚模型因其形式直观、计算高效，特别适合分析带边、能谷以及自旋-轨道耦合等物理性质。&lt;/p&gt;
&lt;p&gt;本文将从对称性出发，依次介绍三能带紧束缚模型基组的选择与 Hamiltonian 的构建，并利用该模型复现 DFT 能带的结果。&lt;/p&gt;
&lt;h2 id=&#34;tmd-的晶体结构与对称性分析&#34;&gt;TMD 的晶体结构与对称性分析&lt;/h2&gt;
&lt;p&gt;在构建紧束缚模型之前，我们首先要弄明白研究对象的晶体结构，这包含了材料的晶胞形状以及对称性信息。
而紧束缚模型中跳跃矩阵的各项参数并非完全独立，受材料对称性的约束，这些参数之间有存在相应的关联，
这些关联操作可以大大减少跳跃矩阵中独立参数的数量，使问题简单化。因此，我们有必要弄明白 TMD
材料的对称性信息。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;注：为了避免误会，接下来我们所提到的 TMD 材料均为单层材料。而 TMD 的单层材料中有两个常见的相，
分别是 1T 相和 2H 相，其中 1T 相为金属， 2H 相为半导体（或绝缘体）。我们下面所讨论的相均为 2H 相。&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;tmd-的实空间结构与布里渊区&#34;&gt;TMD 的实空间结构与布里渊区&lt;/h3&gt;
&lt;p&gt;单层 TMD 材料的化学式为 MX&lt;sub&gt;2&lt;/sub&gt; ，其中 M 为过渡金属元素（如Mo、W和V等），X为硫族元素（如S、Se以及Te等）。
其结构如图&lt;a href=&#34;#figure--fig:TMD-StructureBZ&#34;&gt;1&lt;/a&gt;
所示（图片引自文献&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;），图中灰色原子为过渡金属原子，黄色原子为硫族原子，它们组成了一种类似
“三明治”的结构，金属原子形成了二维的六角晶格，硫族原子分别位于金属原子的上下两侧，形成了三棱柱形的配位环境，形状如图&lt;a href=&#34;#figure--fig:TMD-StructureBZ&#34;&gt;1&lt;/a&gt;
(b)所示。&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:TMD-StructureBZ&#34;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;link rel=&#34;stylesheet&#34; href=&#34;http://ionizing.page/css/hugo-easy-gallery.css&#34; /&gt;
&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;TMD-Structure.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 1: &amp;lt;/span&amp;gt;TMD 材料的晶体结构以及布里渊区示意图，灰色球为 M 原子，黄色球为 X 原子，(c) 为布里渊区示意图，图片引自文献。&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;TMD-Structure.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 1: &lt;/span&gt;TMD 材料的晶体结构以及布里渊区示意图，灰色球为 M 原子，黄色球为 X 原子，(c) 为布里渊区示意图，图片引自文献。&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;而由于 MX&lt;sub&gt;2&lt;/sub&gt; 的原胞为六角晶型，它的布里渊区同样为六角形，如图&lt;a href=&#34;#figure--fig:TMD-StructureBZ&#34;&gt;1&lt;/a&gt;
(c)所示。
在这个布里渊区中，除了原点 \(\Gamma\) 和边中心 \(M\) 以外，我们对位于六边形顶点的 \(+K\) 与 \(-K\) 点比较感兴趣，
它们决定着能谷（valley）中存在许多有趣的物理性质。&lt;/p&gt;
&lt;h3 id=&#34;tmd-的对称性&#34;&gt;TMD 的对称性&lt;/h3&gt;
&lt;p&gt;单层 TMD 的点群为 \(D_{3h}\) ，它主要包括以下几种对称性：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;三重旋转对称性：绕 \(z\) 轴旋转 120° 后系统保持不变，即&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:symmetry-C3-xy}
C_3: \begin{bmatrix} x \\ y \end{bmatrix} \to
\begin{bmatrix}
\cos(\theta) &amp;amp; -\sin(\theta) \\&lt;br&gt;
\sin(\theta) &amp;amp;  \cos(\theta)
\end{bmatrix}
\begin{bmatrix} x \\ y \end{bmatrix}, \;\; \theta = \frac{2\pi}{3}
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;水平镜面反射：关于 \(xy\) 平面反射后系统不变，即&lt;/p&gt;
&lt;p&gt;\begin{equation}
\sigma_h: (x, y, z) \to (x, y, -z)
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;竖直的镜面对称：分别沿 M‒X 键做反映（以&lt;a href=&#34;#figure--fig:TMD-StructureBZ&#34;&gt;1&lt;/a&gt;
中沿\(yz\)反映面为例）&lt;/p&gt;
&lt;p&gt;\begin{equation}
\sigma_v: (x, y, z) \to (-x, y, z)
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以上三种对称操作可以相互组合，并形成更多的对称操作，下面将部分操作总结在表&lt;a href=&#34;#table--tab:TMD-symmetry-ops&#34;&gt;1&lt;/a&gt;
中&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;table--tab:TMD-symmetry-ops&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;table-caption&#34;&gt;
  &lt;span class=&#34;table-number&#34;&gt;&lt;a href=&#34;#table--tab:TMD-symmetry-ops&#34;&gt;Table 1&lt;/a&gt;:&lt;/span&gt;
  TMD 材料的部分对称性操作
&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;对称操作&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;符号&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;表达式&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;旋转 \(\frac{2\pi}{3}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(C_3\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(C_3\)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;旋转 \(\frac{4\pi}{3}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(C_3^2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(C_3 \cdot C_3\)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;沿 \(yz\) 面反映&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\sigma_v\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\sigma_v\)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;沿 \(yz\) 面反映后旋转 \(\frac{2\pi}{3}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\sigma_v&#39;\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(C_3 \cdot \sigma_v\)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;沿 \(yz\) 面反映后旋转 \(\frac{4\pi}{3}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\sigma_v&#39;&#39;\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(C_3 \cdot C_3 \cdot \sigma_v \)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;基组的确定及对称性算符&#34;&gt;基组的确定及对称性算符&lt;/h2&gt;
&lt;p&gt;在构建紧束缚 Hamiltonian 之前，我们需要明确系统的基组。
众所周知，“紧束缚模型”也称为“原子轨道线性组合法”（LCAO, linear combination of atomic
orbitals），它使用原子轨道作为基组表示系统的波函数，因此我们需要明确具体使用哪些原子轨道。&lt;/p&gt;
&lt;p&gt;以 MoS&lt;sub&gt;2&lt;/sub&gt; 为例，G. B. Liu&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;等使用 DFT 软件计算得到它的原子轨道投影能带，如图&lt;a href=&#34;#figure--fig:TMD-DFT-bandstructure&#34;&gt;2&lt;/a&gt;
所示（图片引自文献&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;）。不难看出 MoS&lt;sub&gt;2&lt;/sub&gt; 的价带最高（VBM）与导带最低（CBM）均主要由原子的
\(d\) 轨道贡献，而 \(p\) 轨道占比相比之下就小很多，\(s\) 轨道则更是几乎没有。
由于我们通常只关心 VBM 与 CBM 的带隙与色散，因此只使用 M 原子的这三个 \(d\)
轨道来构成紧束缚模型的基组是可行的。为此我们认为 X 原子的所有轨道以及 M 原子的 \(sp\) 轨道都可以忽略不计，
它们不参与紧束缚模型的构建。&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:TMD-DFT-bandstructure&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;TMD-DFT-bandstructure.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 2: &amp;lt;/span&amp;gt;使用 VASP 计算得到的 MoS&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; 能带及原子轨道投影，图片引自文献。&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;TMD-DFT-bandstructure.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 2: &lt;/span&gt;使用 VASP 计算得到的 MoS&lt;sub&gt;2&lt;/sub&gt; 能带及原子轨道投影，图片引自文献。&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;在此，我们的紧束缚模型基组确定为 M 原子的三条 \(d\) 轨道：&lt;/p&gt;
&lt;p&gt;\begin{equation}
\qty{ \ket{d_{z^2}}, \ket{d_{xy}}, \ket{d_{x^2-y^2}} }
\end{equation}&lt;/p&gt;
&lt;p&gt;从轨道的基函数表达式不难判断，它们对应了几种对称性：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;\(\ket{d_{z^2}}\) 的基函数为 \(z^2\) ，与 xy 无关，因此它对于 \(xy\) 平面内的操作不变，即 \(C_3\)
操作与 \(\sigma_v\) 操作对它不起作用：&lt;/p&gt;
&lt;p&gt;\begin{equation}
C_3: \ket{d_{z^2}} \to \ket{d_{z^2}}; \;\; \sigma_v: \ket{d_{z^2}} \to \ket{d_{z^2}}
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;\(\ket{d_{xy}}\) 的基函数为 \(xy\) ，它对于沿 \(yz\) 平面的反映产生符号改变：&lt;/p&gt;
&lt;p&gt;\begin{equation}
\sigma_v: \ket{d_{xy}} \to - \ket{d_{xy}}
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;\(\ket{d_{xy}}\) 与 \(\ket{d_{x^2-y^2}}\) 组合起来时，它对三重旋转操作有以下关系&lt;/p&gt;
&lt;p&gt;\begin{equation}
C_3:
\begin{bmatrix} \ket{d_{xy}} \\ \ket{d_{x^2-y^2}} \end{bmatrix} \to
\begin{bmatrix}
\cos(2\frac{2\pi}{3}) &amp;amp; -\sin(2\frac{2\pi}{3}) \\&lt;br&gt;
\sin(2\frac{2\pi}{3}) &amp;amp; \cos(2\frac{2\pi}{3})
\end{bmatrix}
\begin{bmatrix} \ket{d_{xy}} \\ \ket{d_{x^2-y^2}} \end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;p&gt;这个式子的意思是，当一个波函数可以用 \(\ket{d_{xy}}\) 与 \(\ket{d_{x^2-y^2}}\) 这两种轨道的线性组合表示时，
它经过三重旋转后的结果仍可以使用这两个轨道表示，旋转操作只改变了两种轨道的组合系数&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;。
需要指出的是，尽管这个式子看起来与公式\eqref{eq:symmetry-C3-xy}
很像，但它们是完全不同的概念。当前对称操作作用的基底是原子轨道&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;，而
\eqref{eq:symmetry-C3-xy} 作用的基底则是位置坐标 \(xy\) 。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;那么，在 \(\qty{ \ket{d_{z^2}}, \ket{d_{xy}}, \ket{d_{x^2-y^2}} }\) 基组中，上面两种对称操作可以用下面的算符表示：&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:Dnmatrix}
D(C_3) =
\begin{bmatrix}
1 &amp;amp; 0 &amp;amp; 0 \\&lt;br&gt;
0 &amp;amp; \cos(2\frac{2\pi}{3}) &amp;amp; -\sin(2\frac{2\pi}{3}) \\&lt;br&gt;
0 &amp;amp; \sin(2\frac{2\pi}{3}) &amp;amp; \cos(2\frac{2\pi}{3})
\end{bmatrix}; \;\;
D(\sigma_v) =
\begin{bmatrix}
1 &amp;amp; 0 &amp;amp; 0 \\&lt;br&gt;
0 &amp;amp; -1 &amp;amp; 0 \\&lt;br&gt;
0 &amp;amp; 0 &amp;amp; 1
\end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;p&gt;有了以上两种对称操作后，表&lt;a href=&#34;#table--tab:TMD-symmetry-ops&#34;&gt;1&lt;/a&gt;
中对称操作对应的矩阵形式就都可以得到了。&lt;/p&gt;
&lt;p&gt;由于 X 原子不参与到模型中，系统只由 M 原子组成，并且所有 M 原子都在同一平面内，\(z\) 方向上的对称操作对这个系统的基函数也不起作用，因此
\(D_{3h}\) 点群中其它与 \(z\) 方向相关的操作，如 \(xy\) 平面反映 \(\sigma_h\) 与绕 \(x\) 轴的二次旋转 \(C_2\) 等均不需要考虑&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;h2 id=&#34;紧束缚-hamiltonian-的构建&#34;&gt;紧束缚 Hamiltonian 的构建&lt;/h2&gt;
&lt;h3 id=&#34;坐标系与近邻原子&#34;&gt;坐标系与近邻原子&lt;/h3&gt;
&lt;p&gt;在此我们不妨明确一下系统的坐标系，如图&lt;a href=&#34;#figure--fig:TMD-coordinate-system&#34;&gt;3&lt;/a&gt;
所示。&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:TMD-coordinate-system&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;coordinate-system.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 3: &amp;lt;/span&amp;gt;本文所使用的坐标系，以及 M 原子的最近邻（nearest neighbor, NN）、次近邻（next-nearest neighbor, NNN）和第三近邻（third-nearest neighbor, TNN） M 原子位置示意图&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;coordinate-system.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 3: &lt;/span&gt;本文所使用的坐标系，以及 M 原子的最近邻（nearest neighbor, NN）、次近邻（next-nearest neighbor, NNN）和第三近邻（third-nearest neighbor, TNN） M 原子位置示意图&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;图中 \(ab\) 表示两个晶格矢量，它们分别是&lt;/p&gt;
&lt;p&gt;\begin{equation}
\vec{a} = (l, 0);\;\; \vec{b} = (\frac{l}{2}, \frac{\sqrt{3}}{2}l)
\end{equation}&lt;/p&gt;
&lt;p&gt;\(l\) 是相邻两个 M 原子的距离，在本文中它也表示晶格常数。最近邻原子、次近邻原子与第三近邻原子的位置分别用
\(R_n\) 、 \(\tilde{R}_n\) 以及 \(2R_n\) (\(n = 1, 2, &amp;hellip;, 6\)) 表示，它们对应的分数坐标为&lt;/p&gt;
&lt;p&gt;\begin{gathered}
R_1 = (1, 0);\; R_2 = (0, 1);\; R_3 = (-1, 1);\\&lt;br&gt;
R_4 = (-1, 0);\; R_5 = (0, -1);\; R_6 = (1, -1) \\&lt;br&gt;
\\&lt;br&gt;
\tilde{R}_1 = (1, 1);\; \tilde{R}_2 = (-1, 2);\; \tilde{R}_3 = (-2, 1);\\&lt;br&gt;
\tilde{R}_4 = (-1, -1);\; \tilde{R}_5 = (1, -2);\; \tilde{R}_6 = (2, -1) \\&lt;br&gt;
\\&lt;br&gt;
2R_1 = (2, 0);\; 2R_2 = (0, 2);\; 2R_3 = (-2, 2);\\&lt;br&gt;
2R_4 = (-2, 0);\; 2R_5 = (0, -2);\; 2R_6 = (2, -2) \\&lt;br&gt;
\end{gathered}&lt;/p&gt;
&lt;h3 id=&#34;紧束缚模型-hamiltonian&#34;&gt;紧束缚模型 Hamiltonian&lt;/h3&gt;
&lt;p&gt;由于我们研究的晶胞内只包含一个 M 原子，每个原子有三个 \(d\) 轨道，因此三能带模型的紧束缚 Hamiltonian
在动量空间中表示为一个 3x3 的矩阵&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:tb-hamiltonian}
H(\vb{k}) =
\begin{bmatrix}
H_{11}(\vb{k}) &amp;amp; H_{12}(\vb{k}) &amp;amp; H_{13}(\vb{k}) \\&lt;br&gt;
H_{21}(\vb{k}) &amp;amp; H_{22}(\vb{k}) &amp;amp; H_{23}(\vb{k}) \\&lt;br&gt;
H_{31}(\vb{k}) &amp;amp; H_{32}(\vb{k}) &amp;amp; H_{33}(\vb{k})
\end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;p&gt;为了方便起见，我们不妨定义以下记号&lt;/p&gt;
&lt;p&gt;\begin{equation}
\ket{\phi_1} = d_{z^2}\, , \;
\ket{\phi_2} = d_{xy}\, , \;
\ket{\phi_3} = d_{x^2-y^2}
\end{equation}&lt;/p&gt;
&lt;p&gt;公式 \eqref{eq:tb-hamiltonian} 中每一项对应的表达式为&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:tb-hamiltonian-Hijk}
H_{ij}(\vb{k}) = \sum_{\vb{R}} e^{i\vb{k}\vdot\vb{R}} E_{ij}(\vb{R})
\end{equation}&lt;/p&gt;
&lt;p&gt;其中 \(E_{ij}(\vb{R})\) 即为轨道间的跳跃项，&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:on-site}
E_{ij}(\vb{R}) = \mel{\phi_i(\vb{r})}{\hat{H}}{\phi_j(\vb{r} - \vb{R})}
\end{equation}&lt;/p&gt;
&lt;p&gt;它表示位于原点的 \(i\) 轨道跳跃到位于 \(\vb{R}\) 的 \(j\) 轨道的能量积分，
这里 \(\vb{R}\) 表示近邻的原子。这个积分有一个十分重要的性质 \(E_{ij}( R) = E_{ji}(-R)^*\) ，
证明如下&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:tb-hopping-transpose}
\begin{aligned}
E_{ij}(\vb{R}) &amp;amp;={} \mel{\phi_i(\vb{r})}{\hat{H}}{\phi_j(\vb{r} - \vb{R})} \\&lt;br&gt;
&amp;amp;={} \mel{\phi_j(\vb{r} - R)}{\hat{H}}{\phi_i(\vb{r})}^* \\&lt;br&gt;
&amp;amp;={} \mel{\phi_j(\vb{r})}{\hat{H}}{\phi_i(\vb{r} + \vb{R})}^*
\quad (\text{变量替换} \vb{r} \to \vb{r} + \vb{R}) \\&lt;br&gt;
&amp;amp;={} E_{ji}(-\vb{R})^* \\&lt;br&gt;
\end{aligned}
\end{equation}&lt;/p&gt;
&lt;p&gt;此外，当有了其中一个近邻原子轨道的 \(E_{ij}(\vb{R})\) 后，我们可以通过对称性操作推导出其它近邻原子轨道对应的跳跃积分 \(E_{ij}(\vb{R&#39;})\)，它们可以通过下面的式子推得&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:tb-hopping-symmetry}
E(\hat{g}_n \vb{R}) =
D(\hat{g}_n) E(\vb{R}) \bqty{D(\hat{g}_n)}^{\dagger}
\end{equation}&lt;/p&gt;
&lt;p&gt;\(E( R)\) 表示由 \(E_{ij}(\vb{R})\) 组成的矩阵， \(\hat{g}_n\) 是具体的对称操作，
\(D(\hat{g}_n)\) 是 \(\hat{g}_n\) 对应的矩阵形式，它们已在公式\eqref{eq:Dnmatrix} 中给出&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;在 TMD 中，根据考虑近邻原子的多少不同，跳跃项分最近邻项、次近邻项和第三近邻项，
下面将以最近邻模型和第三近邻模型为例分别阐述它们的具体形式。&lt;/p&gt;
&lt;h4 id=&#34;最近邻模型&#34;&gt;最近邻模型&lt;/h4&gt;
&lt;p&gt;现在我们考虑最简单的一种情况，即只考虑最近邻原子的跳跃，如图&lt;a href=&#34;#figure--fig:TMD-hopping-NN&#34;&gt;4&lt;/a&gt;
所示&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:TMD-hopping-NN&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:270px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;TMD-hopping-NN.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 4: &amp;lt;/span&amp;gt;最近邻模型中涉及的原子&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;TMD-hopping-NN.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 4: &lt;/span&gt;最近邻模型中涉及的原子&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;那么 Hamiltonian 包含以下两项&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:hamiltonian-nn-model}
H^{\text{NN-Model}} = H^{\text{on-site}} + H^{\text{NN}}
\end{equation}&lt;/p&gt;
&lt;p&gt;其中 \(H^{\text{on-site}}\) 是原位项，\(H^{\text{NN}}\) 则是最近邻跳跃项，
它们的形式如下。&lt;/p&gt;
&lt;h5 id=&#34;原位项&#34;&gt;原位项&lt;/h5&gt;
&lt;p&gt;原位项是紧束缚模型里最简单的一项，我们把 \(R=R_0=0\) 代入公式\eqref{eq:on-site}后，可得&lt;/p&gt;
&lt;p&gt;\begin{equation}
H_{ij}^{\text{on-site}}
= E_{ij}^{\text{on-site}} = \mel{\phi_i(\vb{r})}{\hat{H}}{\phi_j(\vb{r})}
= \epsilon_j \cdot \delta_{ij}
= \begin{bmatrix}
\epsilon_1 &amp;amp; &amp;amp; \\&lt;br&gt;
&amp;amp; \epsilon_2 &amp;amp; \\&lt;br&gt;
&amp;amp; &amp;amp; \epsilon_2 \\&lt;br&gt;
\end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;p&gt;即各个原子轨道的本征值，它其实是比最近邻原子“更加近邻”的那一项。需要指出的是，在 \(\Gamma\) 点，
导带存在简并现象，因此原位项里 \(\phi_2\) 与 \(\phi_3\) 的本征值都是 \(\epsilon_2\) 。&lt;/p&gt;
&lt;h5 id=&#34;最近邻项&#34;&gt;最近邻项&lt;/h5&gt;
&lt;p&gt;最近邻项包括 \(R_1, R_2, \cdots R_6\) 共 6 个位点，我们不妨设 \(R_0\) 到 \(R_1\) 的跳跃积分都为实数&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:NN-hopping}
E(R_1) = \begin{bmatrix}
t_{11} &amp;amp; t_{12} &amp;amp; t_{13} \\&lt;br&gt;
t_{21} &amp;amp; t_{22} &amp;amp; t_{23} \\&lt;br&gt;
t_{31} &amp;amp; t_{32} &amp;amp; t_{33}
\end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;p&gt;其一共包含 9 个参数，但它们不完全是相互独立的，受对称性约束，有些参数之间存在关联，下面我们来寻找一下。&lt;/p&gt;
&lt;p&gt;不难发现， \(R_1\) 与 \(R_4\) 刚好互为镜像，即 \(R_1 = -R_4\) ，可以应用公式\eqref{eq:tb-hopping-symmetry}
以及公式\eqref{eq:tb-hopping-transpose} 得到下面的关系&lt;/p&gt;
&lt;p&gt;\begin{equation}
\begin{aligned}
E(\sigma_v \vb{R}_1) &amp;amp;={} E(\vb{R}_4) = E(-\vb{R}_1) \\&lt;br&gt;
D(\sigma_v) E(\vb{R}_1) [D(\sigma_v)]^{\dagger} &amp;amp;={} E(\vb{R}_1)^\dagger
\end{aligned}
\end{equation}&lt;/p&gt;
&lt;p&gt;使用下面的 SymPy 脚本，可以解出部分参数之间的关系&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;ch&#34;&gt;#!/usr/bin/env python3&lt;/span&gt;

&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sympy&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sym&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sympy&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;S&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;t11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t13&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;symbols&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;t11, t12, t13&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;real&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;t21&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t22&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t23&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;symbols&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;t21, t22, t23&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;real&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;t31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t33&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;symbols&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;t31, t32, t33&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;real&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;DSigmaV&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                      &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                      &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]])&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t13&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t21&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t22&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t33&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]])&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;equation_matrix&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DSigmaV&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DSigmaV&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;equations&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;equation_matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;solutions&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;solve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;equations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t13&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t21&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t22&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t33&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;solutions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Output:&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# {t12: -t21, t13: t31, t23: -t32}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;将 \(t_{12} = -t_{21}\) 、 \(t_{13} = t_{31}\) 和 \(t_{23} = -t_{32}\) 代入\eqref{eq:NN-hopping}
中，可得简化后的跳跃矩阵：&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(R_1) = \begin{bmatrix}
t_{11} &amp;amp;  t_{12} &amp;amp; t_{13} \\&lt;br&gt;
-t_{12} &amp;amp;  t_{22} &amp;amp; t_{23} \\&lt;br&gt;
t_{13} &amp;amp; -t_{23} &amp;amp; t_{33}
\end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;p&gt;现在我们只需要 \(t_{11}\) 、 \(t_{12}\) 、 \(t_{13}\) 、 \(t_{22}\) 、 \(t_{23}\) 和 \(t_{33}\)
这六个参数即可描述最近邻的跳跃了。&lt;/p&gt;
&lt;p&gt;在确定了 \(E(R_1)\) 后，我们可以通过公式\eqref{eq:tb-hopping-symmetry} 得到 \(R_2\) 到 \(R_6\) 对应的跳跃项&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;\(R_2\) 可以通过 \(R_1\) 先转动 \(\frac{2\pi}{3}\) ，再沿 \(yz\) 面反映得到：&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(R_2) = D(\sigma_v \cdot C_3) E(R_1) D(\sigma_v \cdot C_3)^\dagger
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;\(R_3\) 可以通过 \(R_1\) 直接转动 \(\frac{2\pi}{3}\) 得到：&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(R_3) = D(C_3) E(R_1) D(C_3)^\dagger
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;\(R_4\) 刚好是 \(-R_1\)：&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(R_4) = E(R_1)^\dagger
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;\(R_5\) 是 \(R_1\) 转动 \(\frac{4\pi}{3}\) 得到：&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(R_5) = D(C_3 \cdot C_3) E(R_1) D(C_3 \cdot C_3)^\dagger
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;\(R_6\) 是 \(R_1\) 转动 \(\frac{4\pi}{3}\) 再沿 \(yz\) 面反映得到：&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(R_6) = D(\sigma_v \cdot C_3 \cdot C_3) E(R_1) D(\sigma_v \cdot C_3 \cdot C_3)^\dagger
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;将以上式子代入公式\eqref{eq:tb-hamiltonian-Hijk} 可得到 \(\vb{k}\) 点处完整的最近邻跳跃贡献&lt;/p&gt;
&lt;p&gt;\begin{aligned}
H^{\text{NN}} &amp;amp;={} e^{i\vb{k}\cdot \vb{R_1}} E(R_1) +
e^{i\vb{k}\cdot \vb{R_2}} E(R_2) +
e^{i\vb{k}\cdot \vb{R_3}} E(R_3) \\&lt;br&gt;
&amp;amp;\phantom{{}={}} + e^{i\vb{k}\cdot \vb{R_4}} E(R_4) +
e^{i\vb{k}\cdot \vb{R_5}} E(R_5) +
e^{i\vb{k}\cdot \vb{R_6}} E(R_6)
\end{aligned}&lt;/p&gt;
&lt;p&gt;将参数 \(\epsilon_1 \cdots \epsilon_3, t_{11} \cdots t_{33}\)
代入公式\eqref{eq:hamiltonian-nn-model} 并对角化它，即可得到能带。&lt;/p&gt;
&lt;h5 id=&#34;能带求解&#34;&gt;能带求解&lt;/h5&gt;
&lt;p&gt;以 MoS&lt;sub&gt;2&lt;/sub&gt; 为例，这里借用刘贵斌教授 &lt;em&gt;Phys Rev B&lt;/em&gt; 给出的数值&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;参数&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;文献符号&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;数值 (eV)&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;参数&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;文献符号&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;数值 (eV)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1.046&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{13}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.507&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;2.104&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.218&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_0\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-0.184&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{23}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.338&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.401&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{33}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.057&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可得能带图如下：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;code/pbe-NN.png&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;code/pbe-NN.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;不难看出，最近邻模型对带边的描述效果不错，比如对于 K/K&#39; 点的 VBM 和 CBM ，以及 Γ 点的
VBM ，最近邻模型都给出的十分接近于 DFT 的能带。如果我们只关心 K/K&#39;
点的能带性质，那么最近邻模型已经是一个相当可用的工具。但如果我们想让它最束缚模型的能带与
DFT 符合地更好，仅使用最近邻跳跃就不够了，我们需要考虑更多的跳跃项。&lt;/p&gt;
&lt;h4 id=&#34;第三近邻模型&#34;&gt;第三近邻模型&lt;/h4&gt;
&lt;p&gt;第三近邻模型在最近邻模型的基础上增加了 &lt;strong&gt;次近邻&lt;/strong&gt; 以及 &lt;strong&gt;第三近邻&lt;/strong&gt; 跳跃，这样可以得到更符合 DFT
的结果。它的 Hamiltonian 包括&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:hamiltonian-tnn-model}
H^{\text{TNN-Model}} = H^{\text{on-site}} + H^{\text{NN}} + H^{\text{NNN}} + H^{\text{TNN}}
\end{equation}&lt;/p&gt;
&lt;p&gt;其中 \(H^{\text{NNN}}\) 是次近邻跳跃贡献， \(H^{\text{TNN}}\) 是第三近邻跳跃贡献。&lt;/p&gt;
&lt;h5 id=&#34;第三近邻项&#34;&gt;第三近邻项&lt;/h5&gt;
&lt;p&gt;我们不妨从第三近邻跳跃开始，如图所示。&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:TMD-hopping-TNN&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:350px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;TMD-hopping-TNN.png&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;TMD-hopping-TNN.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;第三近邻跳跃的矢量对应于 \(2R_n\) ，它刚好是最近邻跳跃 \(R_n\)
矢量的倍数，因此这种跳跃也符合最近邻跳跃的对称性约束，我们直接复用最近邻跳跃矩阵
\(E(R_1)\) 的形式即可。为方便区分， \(E(2R_1)\) 的矩阵元用 \(u_{ij}\) 表示，即&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:TNN-hopping}
E(2R_1) = \begin{bmatrix}
u_{11} &amp;amp;  u_{12} &amp;amp; u_{13} \\&lt;br&gt;
-u_{12} &amp;amp;  u_{22} &amp;amp; u_{23} \\&lt;br&gt;
u_{13} &amp;amp; -u_{23} &amp;amp; u_{33}
\end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;p&gt;因此第三近邻跳跃的 Hamiltonian 形式如下&lt;/p&gt;
&lt;p&gt;\begin{aligned}
H^{\text{TNN}} &amp;amp;={} e^{i\vb{k}\cdot \vb{2R_1}} E(2R_1) +
e^{i\vb{k}\cdot \vb{2R_2}} E(2R_2) +
e^{i\vb{k}\cdot \vb{2R_3}} E(2R_3) \\&lt;br&gt;
&amp;amp;\phantom{{}={}} + e^{i\vb{k}\cdot \vb{2R_4}} E(2R_4) +
e^{i\vb{k}\cdot \vb{2R_5}} E(2R_5) +
e^{i\vb{k}\cdot \vb{2R_6}} E(2R_6)
\end{aligned}&lt;/p&gt;
&lt;h5 id=&#34;次近邻项&#34;&gt;次近邻项&lt;/h5&gt;
&lt;p&gt;不妨令次近邻跳跃 \(\tilde{R}_1\) 对应积分为 \(E(\tilde{R}_1)\) ，有&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(\tilde{R}_1) = \begin{bmatrix}
r_{11} &amp;amp; r_{12} &amp;amp; r_{13} \\&lt;br&gt;
r_{21} &amp;amp; r_{22} &amp;amp; r_{23} \\&lt;br&gt;
r_{31} &amp;amp; r_{32} &amp;amp; r_{33}
\end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;p&gt;次近邻跳跃如图所示，此时跳跃矢量不再是 \(R_n\)
的倍数，它的方向有所改变，因此我们需要寻找其它的对称性来减少参数数量。&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:TMD-hopping-NNN&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:270px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;TMD-hopping-NNN.png&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;TMD-hopping-NNN.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;仔细观察，不难看出，对于 \(\tilde{R}_1\) ，我们可以先做 \(C_3\)
转动变换为 \(\tilde{R}_3\) ，再经过 \(yz\) 面反映变换回 \(\tilde{R}_1\) 。即&lt;/p&gt;
&lt;p&gt;\begin{gathered}
\tilde{R}_1 \xrightarrow{C_3} \tilde{R}_3 \xrightarrow{\sigma_v} \tilde{R}_1 \\&lt;br&gt;
\Downarrow \\&lt;br&gt;
E(\tilde{R}_1) = D(\sigma_v \cdot C_3) E(\tilde{R}_1) D(\sigma_v \cdot C_3)^{\dagger}
\end{gathered}&lt;/p&gt;
&lt;p&gt;同样，使用下面的 SymPy 脚本，可以解出 \(E(\tilde{R}_1)\) 中部分参数之间的关系&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;n&#34;&gt;r11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r13&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;symbols&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;r11, r12, r13&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;real&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;r21&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r22&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r23&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;symbols&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;r21, r22, r23&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;real&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;r31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r33&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;symbols&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;r31, r32, r33&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;real&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;DC3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;          &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;         &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                  &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;S&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                  &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;S&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]])&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;DSigmaV&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                      &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                      &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]])&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r13&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r21&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r22&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r33&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]])&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;equation_matrix&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DSigmaV&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DC3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DSigmaV&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DC3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;equations&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;equation_matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;solutions&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;solve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;equations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r13&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r21&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r22&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r33&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;solutions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Output:&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# {r12: -sqrt(3)*r13, r21: -sqrt(3)*r31, r22: -2*sqrt(3)*r32/3 + r33, r23: r32}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;因此可得简化后的跳跃矩阵&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(\tilde{R}_1) = \begin{bmatrix}
r_{11} &amp;amp; r_{12} &amp;amp; -\frac{1}{\sqrt{3}} r_{12}\\&lt;br&gt;
r_{21} &amp;amp; r_{22} &amp;amp; r_{23} \\&lt;br&gt;
-\frac{1}{\sqrt{3}} r_{21} &amp;amp; r_{23} &amp;amp; r_{22} + \frac{2}{\sqrt{3}} r_{23}
\end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;p&gt;有了 \(\tilde{R}_1\) 后，我们可以通过对称性陆续得到其它的次近邻跳跃项
\(\tilde{R}_2 \cdots \tilde{R}_6\)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;为方便理解，我们先从 \(\tilde{R}_4\) 开始，刚好有 \(\tilde{R}_4  = -\tilde{R}_1\) ，因此有&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(\tilde{R}_4) = E(\tilde{R}_1)^{\dagger}
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;\(\tilde{R}_2\) 可以使用 \(\tilde{R}_4\) 经过两次 \(C_3\) 转动得到&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(\tilde{R}_2) = D(C_3 \cdot C_3) E(\tilde{R}_1)^{\dagger} D(C_3 \cdot C_3)^{\dagger}
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;\(\tilde{R}_3\) 可以使用 \(\tilde{R}_1\) 经过一次 \(C_3\) 转动得到&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(\tilde{R}_3) = D(C_3) E(\tilde{R}_1) D(C_3)^{\dagger}
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;\(\tilde{R}_5\) 可以使用 \(\tilde{R}_1\) 经过两次 \(C_3\) 转动得到&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(\tilde{R}_5) = D(C_3 \cdot C_3) E(\tilde{R}_1) D(C_3 \cdot C_3)^{\dagger}
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;\(\tilde{R}_6\) 可以使用 \(\tilde{R}_4\) 经过一次 \(C_3\) 转动得到&lt;/p&gt;
&lt;p&gt;\begin{equation}
E(\tilde{R}_6) = D(C_3) E(\tilde{R}_1)^{\dagger} D(C_3)^{\dagger}
\end{equation}&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;此时次近邻跳跃的 Hamiltonian 形式如下：&lt;/p&gt;
&lt;p&gt;\begin{aligned}
H^{\text{NNN}} &amp;amp;={} e^{i\vb{k}\cdot \vb{\tilde{R}_1}} E(\tilde{R}_1) +
e^{i\vb{k}\cdot \vb{\tilde{R}_2}} E(\tilde{R}_2) +
e^{i\vb{k}\cdot \vb{\tilde{R}_3}} E(\tilde{R}_3) \\&lt;br&gt;
&amp;amp;\phantom{{}={}} + e^{i\vb{k}\cdot \vb{\tilde{R}_4}} E(\tilde{R}_4) +
e^{i\vb{k}\cdot \vb{\tilde{R}_5}} E(\tilde{R}_5) +
e^{i\vb{k}\cdot \vb{\tilde{R}_6}} E(\tilde{R}_6)
\end{aligned}&lt;/p&gt;
&lt;p&gt;将参数代入 \(H^{\text{NNN}}\) 和 \(H^{\text{TNN}}\) 中，即可得到第三近邻模型下的能带结构。
需要注意的是，在使用第三近邻模型时，
\(H^{\text{on-site}}\) 与 \(H^{\text{NN}}\) 的参数也需要更新。&lt;/p&gt;
&lt;h5 id=&#34;能带求解&#34;&gt;能带求解&lt;/h5&gt;
&lt;p&gt;这里同样使用刘贵斌教授给出的数值：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;参数&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;文献符号&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;数值 (eV)&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;参数&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;文献符号&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;数值 (eV)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.683&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{13}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.506&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1.707&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.085&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_0\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-0.146&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{23}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.162&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.114&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{33}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.073&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_0\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.060&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.016&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-0.236&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{23}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.087&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{21}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.067&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_0\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-0.038&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.266&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.046&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{23}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-0.176&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{13}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.001&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{33}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-0.150&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可得能带图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;code/pbe-TNN.png&#34; alt=&#34;&#34;&gt;
显然，这次模型所得能带与 DFT 符合的很好，
这说明考虑次近邻跳跃与第三近邻跳跃后的三能带模型已经可以很好地满足带边的描述需求。&lt;/p&gt;
&lt;h2 id=&#34;自旋-轨道耦合的引入&#34;&gt;自旋-轨道耦合的引入&lt;/h2&gt;
&lt;p&gt;在前面的讨论中，我们构建了一个仅包含轨道自由度的紧束缚模型。然而，对于单层 TMD
材料而言，自旋轨道耦合 (spin-orbit coupling, SOC)
不仅仅是一种微小的能量修正，它是决定能带精细结构以及谷激子性质的关键因素，因此我们有必要研究如何将
SOC 引入紧束缚模型。&lt;/p&gt;
&lt;h3 id=&#34;原子内-soc-的基本形式&#34;&gt;原子内 SOC 的基本形式&lt;/h3&gt;
&lt;p&gt;所谓自旋轨道耦合，就是电子的自旋角动量与轨道角动量相互作用的一种狭义相对论效应。
当电子在原子核产生的电场中高速运动时，相对论效应会使其感应出有效磁场，这种磁场与电子自身的自旋磁矩产生相互作用，从而导致能级分裂和谱线精细结构的产生。&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;SOC 的通用形式为&lt;/p&gt;
&lt;p&gt;\begin{equation}
H^{\text{SOC}} = \frac{\hbar}{4mc^2} \sigma \vdot \vb{p} \cp \grad{v}(\vb{r})
\end{equation}&lt;/p&gt;
&lt;p&gt;其中:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\(\sigma\) 是泡利矩阵；&lt;/li&gt;
&lt;li&gt;\(\vb{p}\) 是电子的动量；&lt;/li&gt;
&lt;li&gt;\(v(\vb{r})\) 是电子感受到的静电势；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在真实体系中，这个表达中的 \(\grad{v(\vb{r})}\) 并不容易得到，因此我们将它与前面的系数合并为
\(\lambda\) 作为一个经验参数给出此时 SOC 可以写成&lt;/p&gt;
&lt;p&gt;\begin{equation}
H_{\text{atom}}^{\text{SOC}} = \lambda \vb{L} \vdot \vb{S}
\end{equation}&lt;/p&gt;
&lt;p&gt;其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\(\lambda = \frac{\grad{v(\vb{r})}}{2mc^2}\) 表示 SOC 作用的强度，它决定了 SOC 对能级劈裂的贡献；&lt;/li&gt;
&lt;li&gt;\(\vb{L}\) 是电子的轨道角动量；&lt;/li&gt;
&lt;li&gt;\(\vb{S} = \frac{\hbar}{2} \sigma\) 是电子的自旋角动量。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们将用这个式子对紧束缚模型中的 SOC 作用进行建模。需要指出的是，一般认为 SOC 仅作用于 on-site
项，即它只作用于同一个原胞内的同一个原子，不涉及跳跃项。&lt;/p&gt;
&lt;h3 id=&#34;三能带模型中的-soc-作用&#34;&gt;三能带模型中的 SOC 作用&lt;/h3&gt;
&lt;p&gt;在三能带模型中，我们选取的轨道基组为&lt;/p&gt;
&lt;p&gt;\begin{equation}
\qty{ \ket{d_{z^2}},\; \ket{d_{xy}},\; \ket{d_{x^2-y^2}} }
\end{equation}&lt;/p&gt;
&lt;p&gt;当 \(\vb{L}\) 算符作用到它们时， \(L_x\) 与 \(L_y\) 分量所得结果可能会得到
\(\ket{d_{yz}}\) 、 \(\ket{d_{xz}}\) 分量，而这些分量并不在三能带模型的基组内；
相反，当使用 \(\ket{L_z}\) 算符作用时，所得结果仍可用现有的基组表达。
因此在三能带近似下，可以将 \(m_z\) 视为一个好量子数， SOC 被简化为&lt;sup id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;\begin{equation}
H^{\text{SOC}} = \lambda L_z S_z
\end{equation}&lt;/p&gt;
&lt;p&gt;下面我们来讨论三能带基组下 SOC 的矩阵元。&lt;/p&gt;
&lt;h4 id=&#34;l-z-算符&#34;&gt;\(L_z\) 算符&lt;/h4&gt;
&lt;p&gt;对于各个实轨道，它们都可以写成复球谐函数的线性组合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\(\ket{d_{z^2}} = Y_{2,0}\)&lt;/li&gt;
&lt;li&gt;\(\ket{d_{xy}} = \frac{i}{\sqrt{2}} (Y_{2,-2} - Y_{2,2})\)&lt;/li&gt;
&lt;li&gt;\(\ket{d_{x^2-y^2}} = \frac{1}{\sqrt{2}} (Y_{2,-2} + Y_{2,2})\)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对每个球谐函数，有&lt;sup id=&#34;fnref:8&#34;&gt;&lt;a href=&#34;#fn:8&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;\begin{equation}
L_z Y_{lm} = m Y_{lm}
\end{equation}&lt;/p&gt;
&lt;p&gt;将 \(L_z\) 作用于实轨道时，有&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\(\hat{L}_z \ket{d_{z^2}} = 0\)&lt;/li&gt;
&lt;li&gt;\(\hat{L}_z \ket{d_{xy}} = \frac{i}{\sqrt{2}} (-2 Y_{2,-2} - 2 Y_{2,2})
= -2i \frac{1}{\sqrt{2}} (Y_{2,-2} + Y_{2,2}) = -2i \ket{d_{x^2-y^2}}\)&lt;/li&gt;
&lt;li&gt;\(\hat{L}_z \ket{d_{x^2-y^2}} = \frac{1}{\sqrt{2}} (-2 Y_{2,-2} + 2 Y_{2,2})
= 2i \frac{-i}{\sqrt{2}} (-Y_{2,-2} + Y_{2,2}) = 2i \ket{d_{xy}}\)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此， \(\hat{L}_z\) 的矩阵元 \(\mel{i}{\hat{L}_z}{j}\) 中有以下关系&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\(\mel{d_{z^2}}{\hat{L}_z}{j} = 0\)&lt;/li&gt;
&lt;li&gt;\(\mel{d_{xy}}{\hat{L}_z}{d_{x^2-y^2}} = \mel{d_{x^2-y^2}}{\hat{L}_z}{d_{xy}}^* = 2i\)&lt;/li&gt;
&lt;li&gt;\(\mel{d_{xy}}{\hat{L}_z}{d_{xy}} = \mel{d_{x^2-y^2}}{\hat{L}_z}{d_{x^2-y^2}} = 0\)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;把上面的关系写成矩阵形式有&lt;/p&gt;
&lt;p&gt;\begin{equation}
L_z = \begin{bmatrix}
0 &amp;amp; 0 &amp;amp; 0 \\&lt;br&gt;
0 &amp;amp; 0 &amp;amp; 2i \\&lt;br&gt;
0 &amp;amp; -2i &amp;amp; 0
\end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;h4 id=&#34;s-z-算符&#34;&gt;\(S_z\) 算符&lt;/h4&gt;
&lt;p&gt;由于我们忽略了 \(L_x\) 与 \(L_y\) 的贡献，因此电子自旋也只需考虑 \(S_z\) 的贡献&lt;/p&gt;
&lt;p&gt;\begin{equation}
S_z = \frac{1}{2} \sigma_z = \begin{bmatrix}
\frac{1}{2} &amp;amp; 0 \\&lt;br&gt;
0 &amp;amp; -\frac{1}{2}
\end{bmatrix}
\end{equation}&lt;/p&gt;
&lt;p&gt;此时我们可以得到完整的 SOC 矩阵&lt;/p&gt;
&lt;p&gt;\begin{aligned}
H^{\text{SOC}} &amp;amp;={} \lambda S_z \otimes L_z \\&lt;br&gt;
&amp;amp;={} \begin{bmatrix}
\frac{\lambda}{2} L_z &amp;amp; 0 \\&lt;br&gt;
0 &amp;amp; -\frac{\lambda}{2} L_z
\end{bmatrix}
\end{aligned}&lt;/p&gt;
&lt;p&gt;这里我们相当于引入了新的自由度，即自旋，因此需要使用克罗内克积(Kronecker Product, 也称“直积”)
符号 \(\otimes\) &lt;sup id=&#34;fnref:9&#34;&gt;&lt;a href=&#34;#fn:9&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;9&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;h3 id=&#34;考虑自旋轨道耦合后的能带&#34;&gt;考虑自旋轨道耦合后的能带&lt;/h3&gt;
&lt;p&gt;前面我们已经得到了紧束缚模型的 Hamiltonian \(H^0\) 和完整的 SOC 矩阵
\(H^{\text{SOC}}\) ，现在可以将它们组合起来&lt;/p&gt;
&lt;p&gt;\begin{aligned}
H^{\text{TB+SOC}}(\vb{k}) &amp;amp;={} I_2 \otimes H^0(\vb{k}) + H^{\text{SOC}} \\&lt;br&gt;
&amp;amp;={} \begin{bmatrix}
H_0 + \frac{\lambda}{2} L_z &amp;amp; 0 \\&lt;br&gt;
0 &amp;amp; H_0 - \frac{\lambda}{2} L_z
\end{bmatrix}
\end{aligned}&lt;/p&gt;
&lt;p&gt;这里 \(I_2 = \bmqty{1 &amp;amp; 0 \\ 0 &amp;amp; 1}\) 表示单位矩阵。&lt;/p&gt;
&lt;p&gt;借用刘贵斌教授 &lt;em&gt;Phys. Rev. B&lt;/em&gt; 给出的数值， MoS&lt;sub&gt;2&lt;/sub&gt; 中 \(\lambda = 0.073\) ，代入
\(H^{\text{TB+SOC}}\) 中，可得能带如图&lt;a href=&#34;#figure--fig:TNNvsDFT-soc&#34;&gt;5&lt;/a&gt;
所示&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:TNNvsDFT-soc&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;code/pbe-TNN-soc.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 5: &amp;lt;/span&amp;gt;包含 SOC 后 DFT 能带图与第三邻模型的对比。&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;code/pbe-TNN-soc.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 5: &lt;/span&gt;包含 SOC 后 DFT 能带图与第三邻模型的对比。&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;不难看出，在包含 SOC 后，三能带模型与 DFT 计算结果仍然符合地不错。比如
K 谷里 VBM 较大的劈裂和 CBM 微小的劈裂都被良好地复现出来，而 \(\Gamma\)
谷 VBM 存在简并的特性也一样得到保留。这说明在只取 \(L_z\) 近似下的 SOC
就可以描述出较为合理的自旋轨道劈裂。&lt;/p&gt;
&lt;h2 id=&#34;参数的拟合&#34;&gt;参数的拟合&lt;/h2&gt;
&lt;p&gt;到目前为止，我们的模型在建立好之后一直依赖查文献来获取模型的参数，这对于 MoS&lt;sub&gt;2&lt;/sub&gt;
这样已经十分熟悉的体系而言是没什么问题的，但对于一个文献鲜有报道的体系，我们就不得不自己来拟合这些参数。&lt;/p&gt;
&lt;p&gt;我们来简化一下这个问题，它等同于：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;有一个函数 \(f\) ，它接受一个参数集 \(\{p\}\) 并输出结果 \(E\)
，现在求一个 \(\{p\}\) 使得 \(E\) 尽可能接近目标值 \(E^0\) ，即&lt;/p&gt;
&lt;p&gt;\begin{equation}
\min_{p} \sum_{\vb{k}} \bqty{ f_{\vb{k}}(\{p\}) - E_{\vb{k}}^0 }^2
\end{equation}&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;其中 \(f\) 即为紧束缚模型；&lt;/li&gt;
&lt;li&gt;\(\qty{p} = \qty{\epsilon_1, \epsilon_2, t_{11}, &amp;hellip;}\) ；&lt;/li&gt;
&lt;li&gt;\(E^0\) 为目标能带的具体数值。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;这是一个典型的最优化问题，直接交给程序去完成即可。&lt;/p&gt;
&lt;h3 id=&#34;目标能带&#34;&gt;目标能带&lt;/h3&gt;
&lt;p&gt;这里我们以 MoS&lt;sub&gt;2&lt;/sub&gt; 为例演示如何通过拟合 HSE 能带（不带 SOC）得到三能带紧束缚模型的参数值。图
&lt;a href=&#34;#figure--fig:MoS2-HSE-target&#34;&gt;6&lt;/a&gt;
中突出显示的即为目标能带。&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:MoS2-HSE-target&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;code/hse-target.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 6: &amp;lt;/span&amp;gt;使用 DFT &amp;#43; HSE06 计算得到的 MoS&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; 能带及选取的目标能带&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;code/hse-target.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 6: &lt;/span&gt;使用 DFT + HSE06 计算得到的 MoS&lt;sub&gt;2&lt;/sub&gt; 能带及选取的目标能带&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;h3 id=&#34;构造损失函数&#34;&gt;构造损失函数&lt;/h3&gt;
&lt;p&gt;损失函数的构造其实相当简单，只需&lt;/p&gt;
&lt;p&gt;\begin{equation}
f_{\text{loss}}\bqty{p} = \sum_{n,\vb{k}} \abs{ E\bqty{p}(n, \vb{k}) - E_0(n, \vb{k}) }^2
\end{equation}&lt;/p&gt;
&lt;p&gt;其中 \(E\bqty{p}(n, \vb{k})\) 是在当前参数空间 \(p\)
中计算所得能带值。这个损失函数其实就表示当前能带“距离目标能带有多远”，式中 \(||^2\)
就表示求两个量的欧氏距离。&lt;/p&gt;
&lt;h3 id=&#34;程序设计和计算结果&#34;&gt;程序设计和计算结果&lt;/h3&gt;
&lt;p&gt;这里我们使用 Julia 的 &lt;a href=&#34;https://julianlsolvers.github.io/Optim.jl/stable&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Optim.jl&lt;/a&gt;
 包，大概流程如下&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Evaluate bands, pvec is the vector of TB params&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;forward_bands&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pvec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kpath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;c&#34;&gt;# Const and diagonalize the Hamiltonian&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;Hk&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;E&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eigvals!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Hk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;E&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Loss function&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make_loss&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Etarget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kpath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;loss&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pvec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;Etb&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;forward_bands&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pvec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kpath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;
        &lt;span class=&#34;nd&#34;&gt;@inbounds&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Etb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Etb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Etarget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;w&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;loss&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# main function&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;loss&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make_loss&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Etarget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kpath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mask&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mask&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reg&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nsegs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nsegs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# 1) Coarse: Nelder-Mead (robust, no gradients)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;res1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;optimize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;loss&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NelderMead&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;p1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Optim&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minimizer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@info&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;After NelderMead: loss = &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Optim&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minimum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# 2) Refine: BFGS (fast local)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;res2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;optimize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;loss&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BFGS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Optim&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Options&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;show_trace&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;p_opt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Optim&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minimizer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@info&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;After BFGS: loss = &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Optim&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minimum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;在上面的代码中，我们先用 &lt;a href=&#34;https://julianlsolvers.github.io/Optim.jl/stable/algo/nelder_mead/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;NelderMead&lt;/a&gt;
 方法进行快速地粗优化，然后在此基础上使用 &lt;a href=&#34;https://julianlsolvers.github.io/Optim.jl/stable/algo/lbfgs/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;BFGS&lt;/a&gt;

算法进行更精细地优化，拟合所得参数如下&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;参数&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;文献符号&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;数值 (eV)&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;参数&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;文献符号&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;数值 (eV)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1.126&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{13}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.653&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(\epsilon_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;2.211&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.205&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_0\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-0.208&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{23}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.231&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-0.203&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{33}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(t_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.065&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_0\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.055&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.023&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-0.271&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{23}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.107&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_{21}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(r_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.040&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_0\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-0.015&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{11}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.267&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_1\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.064&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{23}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{12}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.184&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{13}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_2\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.026&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{33}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;\(u_{22}\)&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0.179&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;其对应的能带结果如下&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:MoS2-HSE-TNN&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;code/pbe-TNN-hse.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 7: &amp;lt;/span&amp;gt;MoS&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; 中 HSE06 能带与 TNN 模型能带对比&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;code/pbe-TNN-hse.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 7: &lt;/span&gt;MoS&lt;sub&gt;2&lt;/sub&gt; 中 HSE06 能带与 TNN 模型能带对比&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;不难看出，用拟合参数计算得到的能带与 HSE 能带在 Γ 谷和 K 谷符合地非常好，但在 M 与 M&#39;
谷及附近还存在 ~15meV 左右的差距，尽管如此，笔者依然认为这是一个相当好的结果，至少证明了我们的程序是可用的。&lt;/p&gt;
&lt;h2 id=&#34;模型的局限性&#34;&gt;模型的局限性&lt;/h2&gt;
&lt;p&gt;至此，我们已经给出了单层 TMD 体系中三能带紧束缚模型的完整构建过程，并证明该模型能够较好地再现 K/K&#39;
谷附近的低能电子结构。然而，在模型构建过程中我们不可避免地引入了一系列假设与近似，
这也意味着该模型的适用性存在明确的边界。本节将系统总结三能带模型的适用范围，并讨论其主要局限性。&lt;/p&gt;
&lt;p&gt;三能带模型仅保留了过渡金属（M）原子的 \(\ket{d_{z^2}},\; \ket{d_{xy}},\; 和 \ket{d_{x^2-y2}}\)
三个轨道。在这一近似下，该模型能够较为准确地描述 K/K&#39; 谷附近、费米能级上下若干电子伏特范围内的能带性质，
包括带隙大小、有效质量以及价带的自旋-轨道耦合劈裂等关键物理量。&lt;/p&gt;
&lt;p&gt;然而，在以下情形中，三能带模型的局限性会逐渐显现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 Γ 点附近，导带底（CBM）往往不再由所选取的三条金属 d 轨道主导。若希望正确描述 Γ 谷附近的能带结构，必须在基组中引入更多轨道自由度，例如硫（或硒）原子的 p 轨道或金属原子的其它 d 轨道；&lt;/li&gt;
&lt;li&gt;当 \(\vb{k}\) 远离 K/K′ 点（例如靠近 M/M&#39; 谷）时，三能带模型对能带色散关系的描述精度明显下降；&lt;/li&gt;
&lt;li&gt;对于远离费米能级的高能能带，该模型本身并不具备描述能力，此时应考虑采用多能带模型，甚至使用 Wannier 轨道基；&lt;/li&gt;
&lt;li&gt;在当前模型中，自旋–轨道耦合仅以 on-site 项的形式引入，并忽略了 \(L_x\) 和 \(L_y\) 分量以及可能存在的
inter-site SOC，这一近似在研究精细自旋结构或强外场效应时可能不再充分；&lt;/li&gt;
&lt;li&gt;模型的结构高度依赖于单层 TMD 材料所具有的 \(D_{3h}\)
点群对称性。一旦体系的对称性被破坏，例如施加垂直电场或磁场、引入单轴应变、构造异质结或莫尔超结构，
原有的对称性约束将不再成立，此时整个模型需要重新审视甚至重新构建。换言之，该模型在不同体系之间的泛用性是有限的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上讨论总结了三能带紧束缚模型的主要局限性。在实际研究中，只要所关注的物理问题处于其适用范围之内，
这一模型依然是一个结构简洁、物理清晰且行之有效的理论工具。&lt;/p&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;本文以单层 TMD 材料的三能带紧束缚模型为核心，系统介绍了该模型的构建思路与实现过程。
我们从晶体结构与对称性分析出发，依次讨论了轨道基组的选择、紧束缚哈密顿量的构建方法以及自旋-轨道耦合的引入方式，
展示了如何在最小基组的框架下刻画 TMD 体系中最受关注的带边电子结构。&lt;/p&gt;
&lt;p&gt;三能带模型之所以具有代表性，主要体现在以下几个方面：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;单层 TMD 的导带底与价带顶主要由金属原子的三条 \(d\)
轨道贡献，其它原子及轨道的影响可以在低能近似下被有效吸收，从而保留了带隙起源及带边态的本征轨道性质；&lt;/li&gt;
&lt;li&gt;尽管模型中未显式包含硫（或硒）原子的轨道自由度，但金属原子之间的有效跃迁参数已经隐式地包含了
M–X–M 路径的贡献；&lt;/li&gt;
&lt;li&gt;在模型构建的全过程中，对称性始终作为首要约束条件，这显著减少了自由参数数量，并保证了模型结构与物理结果的一致性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;凭借其简洁而不失物理内涵的特点，三能带紧束缚模型不仅是研究单层 TMD 能谷物理的重要工具，也非常适合作为紧束缚建模方法的入门示例。通过这一模型，人们可以清晰地看到如何在复杂材料体系中提炼出最关键的自由度，并在可控近似下建立具有明确物理解释力的有效理论。&lt;/p&gt;
&lt;h2 id=&#34;待续&#34;&gt;待续&lt;/h2&gt;
&lt;p&gt;既然已经提到了紧束缚模型，那只用它算个能带未免有点太浪费了，后面可能会考虑做以下几个实验（也可能没时间做）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; 贝里联络、贝里曲率的计算；&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; 引入二体相互作用（主要是电子电子、电子空穴的库仑直接项与交换项）；&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; 实现一个半导体布洛赫方程；&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; 对 TMD 中的高次谐波等非线性光学性质进行模拟；&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;代码下载&#34;&gt;代码下载&lt;/h2&gt;
&lt;p&gt;文中所有代码已经打包到 &lt;a href=&#34;code.zip&#34;&gt;code.zip&lt;/a&gt;
 其中包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;计算能带脚本： &lt;a href=&#34;code/tmd-tb-main.jl&#34;&gt;tmd-tb-main.jl&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;画图脚本： &lt;a href=&#34;code/tmd-plot.py&#34;&gt;tmd-plot.py&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;TMD 紧束缚模型的参数: &lt;a href=&#34;code/tmd-params.toml&#34;&gt;tmd-params.toml&lt;/a&gt;
 &lt;sup id=&#34;fnref:10&#34;&gt;&lt;a href=&#34;#fn:10&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;10&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;拟合 HSE 能带的脚本： &lt;a href=&#34;code/tmd-tb-fit-params.jl&#34;&gt;tmd-fit-params.jl&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;MoS&lt;sub&gt;2&lt;/sub&gt; 使用 DFT 计算得到的能带信息，这里不一一列举。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其中大部分代码是在我已经写好的基础上使用 ChatGPT 优化所得，因此需要给到
ChatGPT 部分 credit ，在此表示感谢。&lt;/p&gt;
&lt;h2 id=&#34;致谢&#34;&gt;致谢&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;刘贵斌教授：本文基本属于他那篇 &lt;em&gt;Phys. Rev. B&lt;/em&gt; 的复现；&lt;/li&gt;
&lt;li&gt;nguyn21012003：他是正在越南一所高校就读的研一大佬， &lt;a href=&#34;https://github.com/nguyn21012003/Semiconductor-Bloch-Equation-for-TMD&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;他的仓库&lt;/a&gt;
对本文帮助很大；&lt;/li&gt;
&lt;li&gt;长岛冰茶109：茶佬帮助解决了困扰我很久的跳跃矩阵对称性约束问题；&lt;/li&gt;
&lt;/ul&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Liu, G.-B.; Shan, W.-Y.; Yao, Y.; Yao, W.; Xiao, D. Three-Band Tight-Binding Model for Monolayers of Group-VIB Transition Metal Dichalcogenides. &lt;em&gt;Phys. Rev. B&lt;/em&gt; 2013, 88 (8), 085433. &lt;a href=&#34;https://doi.org/10.1103/PhysRevB.88.085433&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://doi.org/10.1103/PhysRevB.88.085433&lt;/a&gt;
.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;这是因为 \(\ket{d_{xy}}\) 与 \(\ket{d_{x^2-y^2}}\) 构成了 \(C_3\) 群中 \(E\) 不可约表象的完备基函数。原谅我因为不会群论，不得不这样绕一下来讲 \(C_3\) 转动群的不可约表示。&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;这个对称操作矩阵其实可以从 Wigner D 矩阵得到。 &lt;a href=&#34;https://en.wikipedia.org/wiki/Wigner_D-matrix&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Wigner_D-matrix&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;确切地说，受 LCAO 的三条原则（对称性匹配原则、最大重叠原则和能量相近原则）中对称性匹配原则的约束， \(\ket{d_{z^2}}\) 与 \(\ket{d_{xy}}\) 以及 \(\ket{d_{x^2-y^2}}\) 对于 \(xy\) 平面的反映 \(\sigma_h\) 都是偶对称性，而其它的 \(d\) 轨道，即 \(\ket{d_{xz}}\) 和 \(\ket{d_{yz}}\) 轨道对于 \(\sigma_h\) 则是奇对称性，两者对称性不匹配，所以文中选取的 \(d\) 轨道与其它 \(d\) 轨道的耦合严格为 0 ；因此在选择该基组后已经约束了所有轨道都是 \(\sigma_h\) 偶对称，也就是不需要考虑 \(\sigma_h\) 操作。其它与 \(z\) 相关的对称操作也是如此。&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;这里如果将不同不可约表示的对称算符分开写会更符合群论&amp;quot;原理&amp;quot;，但考虑到本人不熟悉群论，以及这个系统本身轨道数不多，就不那样处理了。&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;这段话来自 Wiki &lt;a href=&#34;https://en.wikipedia.org/wiki/Spin%E2%80%93orbit_interaction&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Spin%E2%80%93orbit_interaction&lt;/a&gt;
 。&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:7&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;等价于我们限制了自旋的取向为 \(\pm z\) ，因此这其实可以看成一种伊辛模型 (Ising model) 近似。&amp;#160;&lt;a href=&#34;#fnref:7&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:8&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;这里取 \(\hbar = 1\) ，因此量纲没表现出来。&amp;#160;&lt;a href=&#34;#fnref:8&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:9&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Kronecker_product&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Kronecker_product&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:9&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:10&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;这份参数表源自刘贵斌老师的 &lt;em&gt;Phys. Rev. B&lt;/em&gt; ，由于 GitHub 用户 &lt;a href=&#34;https://github.com/nguyn21012003&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;@nguyn21012003&lt;/a&gt;
 整理，详见&lt;a href=&#34;https://github.com/nguyn21012003/Semiconductor-Bloch-Equation-for-TMD&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;这个仓库&lt;/a&gt;
。&amp;#160;&lt;a href=&#34;#fnref:10&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
    <item>
      <title>一起动手算原子弹的临界质量</title>
      <link>http://ionizing.page/post/calculate_critical_mass_of_atomic_bomb/</link>
      <pubDate>Thu, 18 Sep 2025 21:27:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/calculate_critical_mass_of_atomic_bomb/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%97%ae%e9%a2%98%e5%81%87%e8%ae%be%e5%8f%8a%e7%9b%ae%e6%a0%87&#34;&gt;问题假设及目标&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%b8%ad%e5%ad%90%e6%89%a9%e6%95%a3%e6%96%b9%e7%a8%8b%e7%9a%84%e5%af%bc%e5%87%ba&#34;&gt;中子扩散方程的导出&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%b8%ad%e5%ad%90%e6%89%a9%e6%95%a3%e6%96%b9%e7%a8%8b%e7%9a%84%e6%b1%82%e8%a7%a3&#34;&gt;中子扩散方程的求解&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%97%b6%e9%97%b4%e6%bc%94%e5%8c%96%e6%96%b9%e7%a8%8b&#34;&gt;时间演化方程&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%a9%ba%e9%97%b4%e5%88%86%e5%b8%83%e6%96%b9%e7%a8%8b&#34;&gt;空间分布方程&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%be%b9%e7%95%8c%e6%9d%a1%e4%bb%b6&#34;&gt;边界条件&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%b8%b4%e7%95%8c%e8%b4%a8%e9%87%8f%e7%9a%84%e5%af%bc%e5%87%ba&#34;&gt;临界质量的导出&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%b0%8f%e7%bb%93%e4%b8%8e%e8%83%a1%e6%89%af&#34;&gt;小结与胡扯&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;偶然看到了 Dr. Jorge S. Diaz 关于&lt;a href=&#34;https://www.youtube.com/watch?v=DIuoFAW9H3E&amp;amp;ab_channel=Dr.JorgeS.Diaz&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;如何计算原子弹临界质量的视频&lt;/a&gt;
，觉得挺有意思，于是稍微记录一下推导过程。
下面这个公式就是整篇文章的核心。
\[
\frac{\partial N}{\partial t} =
\frac{(\nu - 1)}{\tau} N + \frac{\lambda_t \lambda_f}{3\tau} \nabla^2 N
\]&lt;/p&gt;
&lt;h2 id=&#34;问题假设及目标&#34;&gt;问题假设及目标&lt;/h2&gt;
&lt;p&gt;既然是要算原子弹的临界质量，我们要先明确问题的条件（假设）以及问题的目标。我们先看原子弹的定义：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;所谓原子弹，又称裂变弹，是利用铀、钚等可裂变物质的核裂变反应释放巨大能量而制成的爆炸装置。
&amp;mdash; Wikipedia&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;从定义可知，原子弹主要利用到了核裂变(fission)。所谓核裂变，以 U-235 为例，就是一个 U-235 原子在吸收一个中子(neutron)后，变成不稳定的 U-236 ，最后迅速分解为一个 Kr-92 原子、一个 Ba-141 原子，
以及释放出三个中子；而这三个中子随后会继续轰击其它 U-235 原子，继续得到更多的中子，
从而在短时间内使系统内发生裂变的原子数量呈指数极增加，在这个过程释放出巨大的能量，这个过程表现在宏观上就是“爆炸”。&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:U-235-fission-reaction&#34;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;link rel=&#34;stylesheet&#34; href=&#34;http://ionizing.page/css/hugo-easy-gallery.css&#34; /&gt;
&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;calculate-critical-mass-of-atomic-bomb/Nuclear_fission_reaction.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 1: &amp;lt;/span&amp;gt;U-235 的裂变反应示意图&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;calculate-critical-mass-of-atomic-bomb/Nuclear_fission_reaction.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 1: &lt;/span&gt;U-235 的裂变反应示意图&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;在上面的分析中，我们不难看出，问题的关键在于中子的数量，准确地讲是弹体中的中子分布密度。
如果中子分布密度可以随时间指数级地递增，那么链式反应就能发生，原子弹就可以爆炸；
反之，如果中子分布密度随时间递减，则原子弹不会爆炸。因此我们将问题简化为求解关于弹体内中子分布密度函数的微分方程。&lt;/p&gt;
&lt;p&gt;为此我们不妨做出下面假设：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;弹体由均匀的 U-235 组成；&lt;/li&gt;
&lt;li&gt;弹体为球形；&lt;/li&gt;
&lt;li&gt;弹体中的中子分布密度用含时函数 \(N(\vb{r}, t)\) 表示；&lt;/li&gt;
&lt;li&gt;弹体边界处的中子分布密度为0；&lt;/li&gt;
&lt;li&gt;中子在遇到 U-235 原子时可能会被吸收引发裂变，也可能发生弹性散射被弹开；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;求解目标为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;求解关于 \(N(\vb{r}, t)\) 的微分方程，给出维持链式反应最小质量（临界质量）。
至于这个方程长什么样，我们还不得而知。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;中子扩散方程的导出&#34;&gt;中子扩散方程的导出&lt;/h2&gt;
&lt;p&gt;取弹体中的任意一点 \(\vb{r}\)，它经中子密度为 \(N(\vb{r}, t)\) ，如果此时没有中子被原子吸收，
也没有其它的原子产生中子，则中子数守恒， \(\vb{r}\) 处的中子密度满足 &lt;strong&gt;流体连续性方程&lt;/strong&gt; ：&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:continuity-eq}
\pdv{N}{t} + \divergence \vb{J} = 0
\end{equation}&lt;/p&gt;
&lt;p&gt;公式\eqref{eq:continuity-eq} 中 \(\vb{J}\) 是中子流密度，它代表了单位时间内中子流过某个点的数量，
而 \(\divergence N = \pdv{N_x}{x} + \pdv{N_y}{y} + \pdv{N_z}{z}\) 则表示求它的&lt;a href=&#34;https://betterexplained.com/articles/divergence/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;散度&lt;/a&gt;
。
这个公式的含义是在任意一点增加的中子数量等于其流出的中子数量，也即中子数守恒&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;公式\eqref{eq:continuity-eq} 中的 \(\vb{J}\) 可以从菲克扩散定律(Fick&amp;rsquo;s law of diffusion)推出：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;粒子从高浓度区向低浓度区的流动速率正比于浓度梯度。 &amp;mdash; 菲克定律&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;将菲克定律应用于中子分布密度，可以得到&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:fick-law}
\vb{J} = - D \grad N
\end{equation}&lt;/p&gt;
&lt;p&gt;公式\eqref{eq:fick-law} 中 \(\grad N\) 表示求中子的浓度梯度； \(D\) 为扩散常数，它的量纲是
\(\frac{\text{长度}^2}{时间}\) &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;，代表了中子扩散的强弱。
一般中子的扩散常数可以使用下面的式子计算&lt;/p&gt;
&lt;p&gt;\begin{equation}
D = \frac{1}{3} \lambda_t \expval{v}
\end{equation}&lt;/p&gt;
&lt;p&gt;其中 \(\lambda_t\) 表示中子输运的平均自由程（即发生两次裂变之间中子经过路程的平均值，
\(t\) 表示 transport）； \(\expval{v}\) 表示中子的平均运动速率，它可以使用下面的式子近似计算&lt;/p&gt;
&lt;p&gt;\begin{equation}
\expval{v} = \frac{\lambda_f}{\tau}
\end{equation}&lt;/p&gt;
&lt;p&gt;其中 \(\lambda_f\) 表示裂变时中子的平均自由程。自由程可以使用宏观的散射截面来计算&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;：&lt;/p&gt;
&lt;p&gt;\begin{equation}
\begin{aligned}
\lambda
= \frac{1}{\Sigma}
= \frac{1}{N \sigma}
= \frac{1}{(\rho N_A/M) \sigma}
= \frac{M}{\rho N_A \sigma}
\end{aligned}
\end{equation}&lt;/p&gt;
&lt;p&gt;其中 \(\Sigma\) 是宏观散射截面，\(N\) 是单位体积内的原子核数量， \(\sigma\) 是微观散射截面，
\(\rho\) 是宏观密度， \(N_A\) 是阿伏加德罗常数， \(M\) 是原子相对质量。对于裂变自由程 \(\lambda_f\) ，
其微观散射截面就是裂变散射截面 \(\sigma_f\) ；而对于输运自由程 \(\lambda_t\) ，
其微观散射截面就是裂变散射截面由裂变散射截面和弹性散射截面共同组成
(\(\sigma_t = \sigma_f + \sigma_e\)) 。&lt;/p&gt;
&lt;p&gt;但在原子弹中，中子可以被 U-235 吸收，也可以通过裂变产生，那么中子数量并不守恒，
因此这个方程的右手边需要加入中子产生项和中子吸收项：&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:continuity-eq-with-source}
\pdv{N}{t} + \divergence \vb{J} = S_+ - S_-
\end{equation}&lt;/p&gt;
&lt;p&gt;公式\eqref{eq:continuity-eq-with-source} 的右手边 \(S_+\) 表示产生的中子数， \(S_-\) 表示吸收的中子数，
它们分别可以写为&lt;/p&gt;
&lt;p&gt;\begin{align} \label{eq:neutron-source-sink-term}
S_+ &amp;amp;={} \nu \frac{N}{\tau} \quad \text{裂变产生的中子} \\&lt;br&gt;
S_- &amp;amp;={} \frac{N}{\tau} \quad \text{裂变消耗的中子}
\end{align}&lt;/p&gt;
&lt;p&gt;式\eqref{eq:neutron-source-sink-term} 中 \(\nu\) 表示每次裂变反应生成的中子数，而 \(\tau\) 表示平均发生两次裂变反应的间隔时间。&lt;/p&gt;
&lt;p&gt;现在我们把公式\eqref{eq:continuity-eq-with-source} 各项都展开，有
\[
\pdv{N}{t} + \divergence (-D \grad N) = \frac{(\nu - 1)}{\tau} N
\]
使用矢量运算关系式 \(\divergence (\grad N) = \laplacian N
= \pdv[2]{N}{x} + \pdv[2]{N}{y} + \pdv[2]{N}{z}\) ，以及代入扩散常数 \(D\) 的表达式，
对中子扩散方程进行整理，可以得到文章开头的那个公式&lt;/p&gt;
&lt;p&gt;\begin{equation}  \label{eq:neutron-diffusion-equation}
\pdv{N}{t} = \frac{(\nu - 1)}{\tau} N - \frac{\lambda_t \lambda_f}{3\tau} \laplacian N
\end{equation}&lt;/p&gt;
&lt;p&gt;这便是中子扩散方程，也是我们计算原子弹临界质量的理论基础。下面我们来解这个方程，并推导出临界质量。&lt;/p&gt;
&lt;h2 id=&#34;中子扩散方程的求解&#34;&gt;中子扩散方程的求解&lt;/h2&gt;
&lt;p&gt;不妨仔细观察这个方程，我们把需要求的变量用红色标出
\[
\pdv{\color{red}N}{t} =
\frac{(\nu - 1)}{\tau} {\color{red}N} - \frac{\lambda_t \lambda_f}{3\tau} \laplacian {\color{red}N}
\]
不难看出这是一个关于 \(N\) 的偏微分方程，议程左边只依赖于时间 \(t\) ，右边只依赖于空间坐标 \(x,y,z\) ，
因此可以使用分离变量法来求解。我们可以将 \(N(\vb{r}, t)\) 写成两个函数的积，其中 \(f(\vb{r})\)
只与位置 \(\vb{r}\) 有关， \(g(t)\) 只与时间 \(t\) 相关：&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:variable-separation}
N(\vb{r}, t) = f(\vb{r}) g(t)
\end{equation}&lt;/p&gt;
&lt;p&gt;此时将公式\eqref{eq:variable-separation} 代入方程\eqref{eq:neutron-diffusion-equation} ，可得&lt;/p&gt;
&lt;p&gt;\begin{aligned}
&amp;amp; f \pdv{g}{t} = \frac{\nu - 1}{\tau} fg + \frac{\lambda_t \lambda_f}{3\tau} (\laplacian f)g \\&lt;br&gt;
\implies &amp;amp;  \frac{1}{g} \pdv{g}{t} = \frac{\nu - 1}{\tau}
+ \frac{\lambda_t \lambda_f}{3\tau} \frac{\laplacian f}{f} \equiv K = \frac{\nu&#39;}{\tau}
\end{aligned}&lt;/p&gt;
&lt;p&gt;我们得到两个关系式&lt;/p&gt;
&lt;p&gt;\begin{gather}
\frac{1}{g} \pdv{g}{t} = \frac{\nu&#39;}{\tau}
\label{eq:g-pde} \\&lt;br&gt;
\frac{\nu&#39;}{\tau} = \frac{(\nu - 1)}{\tau} + \frac{\lambda_t \lambda_f}{3\tau} \frac{\laplacian f}{f}
\label{eq:nu-prime-definition}
\end{gather}&lt;/p&gt;
&lt;p&gt;其中方程\eqref{eq:g-pde} 是只关于 \(g\) 的微分方程，且方程右边与 \(g\) 无关，故我们将等式右边重新定义为 \(\frac{\nu&#39;}{\tau}\) ，其具体形式如公式\eqref{eq:nu-prime-definition} 所示。&lt;/p&gt;
&lt;h3 id=&#34;时间演化方程&#34;&gt;时间演化方程&lt;/h3&gt;
&lt;p&gt;\(g\) 只与时间相关，所以式\eqref{eq:g-pde} 是中子分布密度的时间演化方程，它也是 一个典型的常微分方程，
我们可以轻松写出它的通解&lt;/p&gt;
&lt;p&gt;\begin{align}
\frac{1}{g} \dv{g}{t} &amp;amp;={} \frac{\nu&#39;}{\tau} \notag \\&lt;br&gt;
\implies \dv{\ln{g}}{t} &amp;amp;={} \frac{\nu&#39;}{\tau} \notag \\&lt;br&gt;
\implies g(t) &amp;amp;={} A e^{\nu&amp;rsquo;t/\tau} \label{eq:g-solution}
\end{align}&lt;/p&gt;
&lt;p&gt;公式\eqref{eq:g-solution} 显示 \(g\) 是一个指数函数，虽然其指前因子 \(A\) 与指数部分 \(\nu&#39;\)
待定，但现在我们至少可以得出一个结论，即要想中子的数量短时间大量扩增， \(g\) 必须为增函数，
即指数 \(\nu&#39;\) 必须为正，否则 \(g\) 是减函数，中子数量会逐渐衰减。
Alex Wellerstein 制作了一个网站用于&lt;a href=&#34;https://blog.nuclearsecrecy.com/misc/criticality/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;演示裂变反应的具体过程&lt;/a&gt;
，它可以生动地反映当 \(\nu&#39;\) 大于零以及小于零时系统中裂变反应的剧烈程度，读者有兴趣可以尝试&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;h3 id=&#34;空间分布方程&#34;&gt;空间分布方程&lt;/h3&gt;
&lt;p&gt;下面我们来求解 \(f\) ，其只与 \(x,y,z\) 有关，因此它描述的是中子的空间分布。
对公式\eqref{eq:nu-prime-definition} 进行化简，我们可以得到关于 \(f\) 的微分方程：&lt;/p&gt;
&lt;p&gt;\begin{align}
&amp;amp;\frac{\nu&#39;}{\tau} = \frac{(\nu - 1)}{\tau} + \frac{\lambda_t \lambda_f}{3\tau} \frac{\laplacian f}{f}
\notag \\&lt;br&gt;
\implies &amp;amp; \frac{\lambda_t \lambda_f}{3\tau} \frac{\laplacian f}{f} + \frac{\nu - 1 - \nu&#39;}{\tau} = 0
\notag \\&lt;br&gt;
\implies &amp;amp; \laplacian f + \pqty{\frac{3(\nu - \nu&#39; - 1)}{\lambda_t \lambda_f}} f = 0
\notag \\&lt;br&gt;
\implies &amp;amp; \laplacian f + \kappa^2 f = 0 \label{eq:f-equation}
\end{align}&lt;/p&gt;
&lt;p&gt;方程\eqref{eq:f-equation} 类似振子振动的方程，其中 \(f\) 前面的系数我们用
\(\kappa^2 = \pqty{\frac{3(\nu - \nu&#39; - 1)}{\lambda_t \lambda_f}}\) 表示。&lt;/p&gt;
&lt;p&gt;由于弹体是球形，系统具有球对称性，我们在球坐标系下求解这个方程会更容易：&lt;/p&gt;
&lt;p&gt;\begin{equation}
f(\vb{r}) = f(r, \theta, \phi) \equiv f( r)
\end{equation}&lt;/p&gt;
&lt;p&gt;这里我们舍去角向的 \(\theta, \phi\) 部分，只考虑径向 \(r\) 的分布。拉普拉斯算符在球坐标系下可以转化为&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:spherical-laplacian}
\laplacian f = \frac{1}{r^2} \dv{}{r} \pqty{ r^2 \dv{f}{r} }
\end{equation}&lt;/p&gt;
&lt;p&gt;如果直接将公式\eqref{eq:spherical-laplacian} 代入方程\eqref{eq:f-equation} ，
则很难求解这个微分方程，因此这里使用一个辅助函数 \(u( r) = r f( r)\) 使得 \(f( r) = u( r) / r\) ，此时&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:laplacian-auxiliary}
\laplacian f = \frac{1}{r} \dv[2]{u}{r}
\end{equation}&lt;/p&gt;
&lt;p&gt;将式\eqref{eq:laplacian-auxiliary} 代入公式\eqref{eq:f-equation} ，可得&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:u-function}
\dv[2]{u}{r} + \kappa^2 u = 0
\end{equation}&lt;/p&gt;
&lt;p&gt;不难解得&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:u-solution}
u( r) = B \cos(\kappa r) + C \sin(\kappa r)
\end{equation}&lt;/p&gt;
&lt;p&gt;将 \(u\) 代回 \(f( r) = u( r) / r\) ，可得&lt;/p&gt;
&lt;p&gt;\begin{equation} \label{eq:f-solution}
f( r) = B \frac{\cos(\kappa r)}{r} + C \frac{\sin(\kappa r)}{r}
\end{equation}&lt;/p&gt;
&lt;p&gt;此时关于 \(N\) 的两个分量都有了表达式，将式\eqref{eq:g-solution} 与式\eqref{eq:f-solution}
合并，可得 \(N\) 关于半径和时间的函数关系式&lt;/p&gt;
&lt;p&gt;\begin{gather}
N(r, t) = A e^{\nu&#39; t/\tau} \pqty{B \frac{\cos(\kappa r)}{r} + C \frac{\sin(\kappa r)}{r}} \\&lt;br&gt;
\kappa^2 = \frac{3(\nu - \nu&#39; - 1)}{\lambda_t \lambda_f} \label{eq:kappa-squared}
\end{gather}&lt;/p&gt;
&lt;p&gt;这个式子还是有些复杂，并且还包含更多待定的因子，如 \(A, B, C\) 等，我们需要利用边界条件对它进行化简。&lt;/p&gt;
&lt;h4 id=&#34;边界条件&#34;&gt;边界条件&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;弹体中心处的中子密度是有限的；&lt;/p&gt;
&lt;p&gt;这要求 \(N(r=0,t) \ne \infty\) ，
考虑到 \(\displaystyle \lim_{r\to 0} B \frac{\cos(\kappa r)}{r} \to \infty\) ，因此 \(B\) 必须为零；
而 \(\displaystyle \lim_{r\to 0} C \frac{\sin(\kappa r)}{r} \to C \kappa\) ，因此 \(C \ne 0\) 。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;弹体中心处的初始中子密度为 \(N_0\) ；&lt;/p&gt;
&lt;p&gt;即 \(N(r=0, t=0) = N_0\) ，对应于 \(\displaystyle \lim_{\substack{r\to 0 \\ t \to 0}} N(r,t)
= AC\kappa\) ，由此可以推出 \(AC = \frac{N_0}{\kappa}\) 。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;弹体足够大，以至边界处的中子数为零。&lt;/p&gt;
&lt;p&gt;即 \(N(r=R, t) = N_0 e^{\nu&amp;rsquo;t/\tau} \pqty{\frac{\sin(\kappa R)}{\kappa R}} = 0\) ，
上面的式子要求满足 \(\sin(\kappa R) = 0\) ，因此可以取 \(\kappa = \frac{\pi}{R}\) 。
结合前面我们得到的 \(\kappa^2\) 关系式，我们可以求出待定参数 \(\nu&#39;\)&lt;/p&gt;
&lt;p&gt;\begin{gather}
\kappa^2 = \frac{3(\nu - \nu&#39; - 1)}{\lambda_t \lambda_f} = \frac{\pi^2}{R^2} \notag \\&lt;br&gt;
\implies \nu&#39; = (\nu - 1) - \frac{\pi^2 \lambda_t \lambda_f}{3R^2} \notag
\end{gather}&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;临界质量的导出&#34;&gt;临界质量的导出&lt;/h3&gt;
&lt;p&gt;在上一节，我们得到了关于 \(\nu&#39;\) 的表达式，而我们在时间演化方程那一节曾讨论过，原子弹爆炸的一个必要条件是 \(\nu&#39; &amp;gt; 0\) ，因此我们可以得到弹体的临界半径&lt;/p&gt;
&lt;p&gt;\begin{gather}
\nu&#39; = (\nu - 1) - \frac{\pi^2 \lambda_t \lambda_f}{3R^2} = 0 \label{eq:nu-prime-condition} \\&lt;br&gt;
\implies R_c = \pi \sqrt{\frac{\lambda_t \lambda_f}{3(\nu - 1)}}
% = \frac{\pi M}{\rho N_A} \pqty{\frac{1}{3\sigma_t \sigma_f (\nu-1)}}^{1/2}\\&lt;br&gt;
\end{gather}&lt;/p&gt;
&lt;p&gt;进而根据半径算出体积，以及临界质量的表达式&lt;/p&gt;
&lt;p&gt;\begin{equation}
\implies M_c = \frac{4}{3} \pi \rho R_c^3
% = \frac{4\pi^4 M^3}{3\rho^2 N_A^3}
% \pqty{\frac{1}{3\sigma_t \sigma_f (\nu - 1)}}^{3/2}
\end{equation}&lt;/p&gt;
&lt;p&gt;代入实验上测得的微观数据&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;数据名称&lt;/th&gt;
&lt;th&gt;符号&lt;/th&gt;
&lt;th&gt;数值&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;中子寿命（平均两次裂变反应间隔时间）&lt;/td&gt;
&lt;td&gt;\(\tau\)&lt;/td&gt;
&lt;td&gt;16.5 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;平均每次裂变产生的中子数&lt;/td&gt;
&lt;td&gt;\(\nu\)&lt;/td&gt;
&lt;td&gt;2.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;中子输运自由程&lt;/td&gt;
&lt;td&gt;\(\lambda_t\)&lt;/td&gt;
&lt;td&gt;3.596 cm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;中子裂变自由程&lt;/td&gt;
&lt;td&gt;\(\lambda_f\)&lt;/td&gt;
&lt;td&gt;16.89 cm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;铀-235 的密度&lt;/td&gt;
&lt;td&gt;\(\rho\)&lt;/td&gt;
&lt;td&gt;19.050 g/cm³&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以计算得到临界半径和临界质量分别为&lt;/p&gt;
&lt;p&gt;\begin{gathered}
R_c \approx 11 \, \text{cm} \\&lt;br&gt;
M_c \approx 106 \, \text{kg}
\end{gathered}&lt;/p&gt;
&lt;p&gt;以上是一种“基础解”，它简单地要求边界处的中子数为零，这个条件过于严格。
如果我们放宽边界条件的限制，其临界质量也会有所变化。
另一种常用的边界条件是在边界处允许一半的中子流逃逸到弹体外面，即&lt;/p&gt;
&lt;p&gt;\begin{gather}
J( R) = -D \pdv{\phi}{r}\bigg|_R \ge \frac{1}{2} \phi( R), \quad \phi( r) = N( r) \expval{v}  \notag \\&lt;br&gt;
\implies N(r=R, t) \le - \frac{2}{3} \lambda_t \pdv{N}{r}\bigg|_{r=R} \label{eq:marshak-bc}
\end{gather}&lt;/p&gt;
&lt;p&gt;式\eqref{eq:marshak-bc} 也被称为 Marshak 边界条件&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;，此时可以得到&lt;/p&gt;
&lt;p&gt;\begin{equation}
\frac{3R}{2\lambda_t} \le 1 - \frac{\kappa R}{\tan (\kappa R)} \label{eq:marshak-critical-radius}
\end{equation}&lt;/p&gt;
&lt;p&gt;联系到我们使用公式\eqref{eq:nu-prime-condition} 求临界质量时要求 \(\nu&#39; = 0\) ，
这里我们也使用这个条件，并将它与其它参数代入式\eqref{eq:kappa-squared} ，可以得到 \(\kappa\)
的具体值，然后我们可以使用计算机求解方程\eqref{eq:marshak-critical-radius} ，便可以得到一个新的临界半径 \(R_c\)，及其对应的临界质量 \(M_c\)：
\[
R_c \approx 8.37\;\text{cm}; \quad M_c \approx 46\;\text{kg}
\]
至此，我们得到了 Marshak 边界条件下的 U-235 原子弹临界质量，相比于实际临界质量(52 kg)&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;，
这个值又偏小，说明 Marshak 边界条件又过于宽松。&lt;/p&gt;
&lt;h2 id=&#34;小结与胡扯&#34;&gt;小结与胡扯&lt;/h2&gt;
&lt;p&gt;以上便是从中子扩散理论出发得到的两种原子弹临界质量，分别为 106 kg 和 46 kg ，尽管它们与实际值有着不小的差别，但其推导过程仍具有启发意义。在此再次感谢 Dr. Jorge S. Diaz 博主的影片，
其在视频最后还留了几道家庭作业，分别是计算钸-239的临界质量以及正方体和圆柱体弹体的临界质量。
鉴于本人对做 Homework 并不感兴趣，这几道题还是留给读者吧。
如果读者对其它推导方法感兴趣，可以参考&lt;a href=&#34;https://doi.org/10.1021/ed073p162&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;这篇文献&lt;/a&gt;
&lt;sup id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;7&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;稍微讲一些胡说八道吧，本文抓住了中子分布密度这一核心变量来建模整个原子弹，
通过求解它的含时方程与空间分布方程，我们可以得到整个原子弹的临界半径与临界质量，
这一步看似简单，但其实并不容易，需要建模人员有敏锐的直觉和丰富的经验。
另外一个点是，文中推导的中子扩散方程实际是以菲克扩散定律为基础，而后者可以从微观粒子的随机行走理论推导得到，这实际上忽略了中子与中子的相互作用而只考虑了中子与铀原子核的相互作用，
如果考虑中子与中子的相互作用，那么得到的临界质量又会是另外一个值。
最后要说的是，推导的最后，我们仅仅改变了中子扩散方程的边界条件，所得到的临界质量就大相径庭，
这说明我们在建模时不仅需要简化模型，也需要适当考虑更多的因素，这实际上相当考验建模人员的数学功底和物理直觉，至少本人自己做不到^_^。&lt;/p&gt;
&lt;p&gt;文章结尾再送读者一篇文献&lt;sup id=&#34;fnref:8&#34;&gt;&lt;a href=&#34;#fn:8&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;8&lt;/a&gt;&lt;/sup&gt;，如果你对海森堡算错临界质量这件事比较感兴趣可以看这篇文献，
文章系统描述了二战后海森堡在和平环境下用一周的时间内算出的结果，
他甚至还考虑了带中子反射层的边界条件，得到的临界质量与实验值“惊人地一致”，
这也侧面说明研究环境对于研究人员状态的影响有多大。&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;如果把\(N\)换成质量，它也就是流体力学中的质量守恒定律；&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;如果单独搜索“扩散系数”，会有资料显示它的量纲是长度 (\(D = \frac{\lambda}{3}\)， \(\lambda\)
是平均自由程)，此时 \(D\) 中的速度项被 \(\vb{J} = -D \grad \vb{\phi}\) 中的 \(\vb{\phi}\) 所吸收，
详见&lt;a href=&#34;https://www.nuclear-power.com/nuclear-power/reactor-physics/neutron-diffusion-theory/diffusion-coefficient/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;这个链接&lt;/a&gt;
。&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;详见 &lt;a href=&#34;https://clive.semmens.org.uk/Energy/FreePath.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://clive.semmens.org.uk/Energy/FreePath.html&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;裂变反应模拟网站 &lt;a href=&#34;https://blog.nuclearsecrecy.com/misc/criticality/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://blog.nuclearsecrecy.com/misc/criticality/&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Noh, Taewan. “A Study on Diffusion Approximations to Neutron Transport Boundary Conditions.” Journal of the Nuclear Fuel Cycle and Waste Technology(JNFCWT) 16, no. 2 (2018): 203–9. &lt;a href=&#34;https://doi.org/10.7733/jnfcwt.2018.16.2.203&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://doi.org/10.7733/jnfcwt.2018.16.2.203&lt;/a&gt;
.&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Critical_mass&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Critical_mass&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:7&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Reed, B. Cameron. “Estimating the Critical Mass of a Fissionable Isotope.” Journal of Chemical Education 73, no. 2 (1996): 162. &lt;a href=&#34;https://doi.org/10.1021/ed073p162&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://doi.org/10.1021/ed073p162&lt;/a&gt;
.&amp;#160;&lt;a href=&#34;#fnref:7&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:8&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;El Naschie, M.S. “Heisenberg’s Critical Mass Calculations for an Explosive Nuclear Reaction.” Chaos, Solitons &amp;amp; Fractals 11, no. 6 (2000): 987–97. &lt;a href=&#34;https://doi.org/10.1016/S0960-0779%2899%2900110-1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://doi.org/10.1016/S0960-0779(99)00110-1&lt;/a&gt;
.&amp;#160;&lt;a href=&#34;#fnref:8&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
    <item>
      <title>如何将文件打包进 C/C&#43;&#43;/Fortran 程序内</title>
      <link>http://ionizing.page/post/embed_binary_to_c_fortran/</link>
      <pubDate>Tue, 04 Apr 2023 00:10:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/embed_binary_to_c_fortran/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%97%ae%e9%a2%98%e6%8f%8f%e8%bf%b0&#34;&gt;问题描述&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%b3%95&#34;&gt;解决方法&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%9b%b4%e6%8e%a5%e5%86%99-const-char&#34;&gt;直接写 &lt;code&gt;const char*&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%80%9a%e8%bf%87-inline-assembly&#34;&gt;通过 inline assembly&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%ae%8f-plus-%e5%86%85%e8%81%94%e6%b1%87%e7%bc%96&#34;&gt;宏+内联汇编&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#fortran-%e7%9a%84%e5%a4%84%e7%90%86&#34;&gt;Fortran 的处理&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%b0%8f%e7%bb%93&#34;&gt;小结&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;最近在写 Fortran 程序时有一个需求：把另一个文件打包进二进制里面，以便可以随时 &lt;code&gt;print&lt;/code&gt; 出来，经过一番网上冲浪，
摸索出来几个 workaround ，在此记录一下。&lt;/p&gt;
&lt;h2 id=&#34;问题描述&#34;&gt;问题描述&lt;/h2&gt;
&lt;p&gt;现在有一个不可变的文件名为 &lt;code&gt;foo.txt&lt;/code&gt; ，编写一个 C/C++/Fortran 程序，使得它能在任意地方打印出 &lt;code&gt;foo.txt&lt;/code&gt; 的内容。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt; ： &lt;em&gt;任意地方&lt;/em&gt; 也包括其它人的机器。&lt;/p&gt;
&lt;h2 id=&#34;解决方法&#34;&gt;解决方法&lt;/h2&gt;
&lt;h3 id=&#34;直接写-const-char&#34;&gt;直接写 &lt;code&gt;const char*&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file_content&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Hello world&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;with a new line here.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;puts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;file_content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;缺点：麻烦，遇到换行时需要额外加 &lt;code&gt;\n\&lt;/code&gt; ，可以用 python 脚本生成 &lt;code&gt;.c&lt;/code&gt; 文件来解决；如果文件为二进制，则需要手写十六进制数据。&lt;/p&gt;
&lt;h3 id=&#34;通过-inline-assembly&#34;&gt;通过 inline assembly&lt;/h3&gt;
&lt;p&gt;C 语言中每个全局变量对应一个 label ，并且这个 label 可以直接当作变量名来访问，比如&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Hello world.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Linux 上对应的汇编代码就是&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;    &lt;span class=&#34;na&#34;&gt;.globl&lt;/span&gt;  &lt;span class=&#34;no&#34;&gt;str&lt;/span&gt;
    &lt;span class=&#34;na&#34;&gt;.type&lt;/span&gt;   &lt;span class=&#34;no&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;@object&lt;/span&gt;
    &lt;span class=&#34;na&#34;&gt;.size&lt;/span&gt;   &lt;span class=&#34;no&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;13&lt;/span&gt;
&lt;span class=&#34;nl&#34;&gt;str:&lt;/span&gt;
    &lt;span class=&#34;na&#34;&gt;.string&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Hello world.&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;可见，除了一些内存对齐、类型标注等，主要起作用的还是 &lt;code&gt;.section .rodata&lt;/code&gt; 和 &lt;code&gt;number: .string &amp;quot;Hello world.&amp;quot;&lt;/code&gt; 了，前者对应了 &lt;code&gt;const&lt;/code&gt;
，后者对应了 &lt;code&gt;char str[] = &amp;quot;Hello world.&amp;quot;&lt;/code&gt; 。那么借用这个方法，我们可以手动定义一个 &lt;code&gt;const char[]&lt;/code&gt; 的变量，然后在 C 代码中调用这个变量，
即可达到访问被包含文件的目的。&lt;/p&gt;
&lt;p&gt;GCC 支持用 &lt;code&gt;__asm__()&lt;/code&gt; 来内联汇编代码，那么我们可以这样写&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;__asm__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;#34;.section .rodata &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;#34;.globl foo_str &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;#34;foo_str:&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;#34;.string &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;Hello world&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;#34;.byte 0&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;extern&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;foo_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[];&lt;/span&gt;

&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;puts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foo_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样这个程序可以正常输出 &amp;ldquo;Hello world&amp;rdquo; ，那把 &lt;code&gt;.string ...&lt;/code&gt; 换成 &lt;code&gt;.incbin&lt;/code&gt; 就完成了：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;n&#34;&gt;__asm__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;#34;.section .rodata &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;#34;.globl foo_str &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;#34;foo_str:&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;#34;.incbin &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;#34;.byte 0&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此时运行程序会输出&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ ./a.out
Hello world from &lt;span class=&#34;s2&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此时我们的目的就达到了，应该可以收工了？&lt;/p&gt;
&lt;p&gt;如果这个代码只在 Linux 平台编译，那应该是可以收工了，但如果这个代码要在 macOS 或者 Windows 平台编译，
编译器会报错，因为不同系统上的汇编代码并不完全兼容，我们还需要对它进行一点点修改：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows 平台上 &lt;code&gt;.rodata&lt;/code&gt; 对应 &lt;code&gt;.rdata &amp;quot;dr&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;macOS 平台上 &lt;code&gt;.rodata&lt;/code&gt; 对应 &lt;code&gt;__TEXT,__const&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;此外， macOS 上的编译器生成的汇编代码里符号前面会多一个下划线：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;hello world&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对应的汇编代码是&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;    &lt;span class=&#34;na&#34;&gt;.section&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;__TEXT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;__const&lt;/span&gt;
    &lt;span class=&#34;na&#34;&gt;.globl&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;_str&lt;/span&gt;                    &lt;span class=&#34;c&#34;&gt;## @str
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;na&#34;&gt;.asciz&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;hello world&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;那么对应的 &lt;code&gt;__asm__()&lt;/code&gt; 内也要把这个下划线加上，否则编译器会报错。&lt;/p&gt;
&lt;h3 id=&#34;宏-plus-内联汇编&#34;&gt;宏+内联汇编&lt;/h3&gt;
&lt;p&gt;如果代码里只有一处需要打包文件，那么直接手写内联汇编没什么问题；但需要打包的东西多了后再这么做就很麻烦了，
于是&lt;a href=&#34;https://gist.github.com/mmozeiko/ed9655cf50341553d282&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;有人&lt;/a&gt;
写了一个宏来解决：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define STR2(x) #x
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define STR(x) STR2(x)
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;cp&#34;&gt;#ifdef _WIN32
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define INCBIN_SECTION &amp;#34;.rdata, \&amp;#34;dr\&amp;#34;&amp;#34;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#else
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define INCBIN_SECTION &amp;#34;.rodata&amp;#34;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#endif
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;// this aligns start address to 16 and terminates byte array with explict 0
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// which is not really needed, feel free to change it to whatever you want/need
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define INCBIN(name, file) \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;    __asm__(&amp;#34;.section &amp;#34; INCBIN_SECTION &amp;#34;\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.global incbin_&amp;#34; STR(name) &amp;#34;_start\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.balign 16\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;incbin_&amp;#34; STR(name) &amp;#34;_start:\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.incbin \&amp;#34;&amp;#34; file &amp;#34;\&amp;#34;\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.global incbin_&amp;#34; STR(name) &amp;#34;_end\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.balign 1\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;incbin_&amp;#34; STR(name) &amp;#34;_end:\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.byte 0\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;    ); \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;    extern __attribute__((aligned(16))) const char incbin_ ## name ## _start[]; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;    extern                              const char incbin_ ## name ## _end[]
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;INCBIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foobar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;binary.bin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;但这个宏只能在 Linux 和 Windows 上运行，本人对其做了一点修改，使之能在 macOS 上跑，并且多定义一个表示大小的 &lt;code&gt;_size&lt;/code&gt; 变量：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define STR2(x) #x
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define STR(x) STR2(x)
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;cp&#34;&gt;#ifdef __APPLE__
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define USTR(x) &amp;#34;_&amp;#34; STR(x)
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#else
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define USTR(x) STR(x)
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#endif
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;cp&#34;&gt;#ifdef _WIN32
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define INCBIN_SECTION &amp;#34;.rdata, \&amp;#34;dr\&amp;#34;&amp;#34;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#elif defined __APPLE__
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define INCBIN_SECTION &amp;#34;__TEXT,__const&amp;#34;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#else
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define INCBIN_SECTION &amp;#34;.rodata&amp;#34;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#endif
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;// this aligns start address to 16 and terminates byte array with explict 0
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// which is not really needed, feel free to change it to whatever you want/need
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#define INCBIN(prefix, name, file) \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;    __asm__(&amp;#34;.section &amp;#34; INCBIN_SECTION &amp;#34;\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.global &amp;#34; USTR(prefix) &amp;#34;_&amp;#34; STR(name) &amp;#34;_start\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.balign 16\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            USTR(prefix) &amp;#34;_&amp;#34; STR(name) &amp;#34;_start:\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.incbin \&amp;#34;&amp;#34; file &amp;#34;\&amp;#34;\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.global &amp;#34; STR(prefix) &amp;#34;_&amp;#34; STR(name) &amp;#34;_end\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.balign 1\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            USTR(prefix) &amp;#34;_&amp;#34; STR(name) &amp;#34;_end:\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.byte 0\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.balign 16\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.global &amp;#34; STR(prefix) &amp;#34;_&amp;#34; STR(name) &amp;#34;_size\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            USTR(prefix) &amp;#34;_&amp;#34; STR(name) &amp;#34;_size:\n&amp;#34; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;            &amp;#34;.long &amp;#34; USTR(prefix) &amp;#34;_&amp;#34; STR(name) &amp;#34;_end&amp;#34; &amp;#34; - &amp;#34;  USTR(prefix) &amp;#34;_&amp;#34; STR(name) &amp;#34;_start \n&amp;#34;\
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;    ); \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;    extern __attribute__((aligned(16))) const char prefix ## _ ## name ## _start[]; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;    extern                              const char prefix ## _ ## name ## _end[]; \
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;    extern __attribute__((aligned(16))) const long prefix ## _ ## name ## _size
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;INCBIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;incbin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;foobar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;// printf(&amp;#34;%s\n&amp;#34;, incbin_foobar_start);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对于 C++ 而言，上面的代码几乎可以照抄，唯一需要注意的是 C++ 对符号有 mangling 操作，变量名和 label 不一样，
所以需要把 &lt;code&gt;extern const ...&lt;/code&gt; 改成 &lt;code&gt;extern &amp;quot;C&amp;quot; const ...&lt;/code&gt; 让编译器知道这个变量对应的 label 不需要 mangling ，
从而正确找到目标文件里对应的 label 。&lt;/p&gt;
&lt;h3 id=&#34;fortran-的处理&#34;&gt;Fortran 的处理&lt;/h3&gt;
&lt;p&gt;Fortran 不能内联汇编，所以上面的代码放到 &lt;code&gt;.F&lt;/code&gt; 里是不能用的，我们可以通过 FFI 让 Fortran 间接实现这些操作。&lt;/p&gt;
&lt;p&gt;需要注意的是， Fortran 的字符串带长度信息，而 C 字符串则是以 &lt;code&gt;&#39;\0&#39;&lt;/code&gt; 来表示结尾，并没有直接标注长度信息，
这个不同给 Fortran 和 C 的互操作带来的不小的麻烦……&lt;/p&gt;
&lt;p&gt;准备一个 &lt;code&gt;incbin.c&lt;/code&gt; 文件，里面用上一节的方法包含想要的文件，并暴露出 &lt;code&gt;file_start&lt;/code&gt; 和 &lt;code&gt;file_size&lt;/code&gt; 两个变量，
准备一个 &lt;code&gt;main.f90&lt;/code&gt; 文件，用 &lt;code&gt;iso_c_binding&lt;/code&gt; 提供的 &lt;code&gt;bind&lt;/code&gt; 来对接刚刚暴露的变量：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fortran&#34; data-lang=&#34;fortran&#34;&gt;&lt;span class=&#34;k&#34;&gt;module &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;use &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;iso_c_binding
&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit none
&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;c_int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;C&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;incbin_foobar_size&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;slen&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;c_char&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;C&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;incbin_foobar_start&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cstr&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:),&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;allocatable&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fstr&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;slen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fstr&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cstr&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;contains
&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;    subroutine &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;initialize&lt;/span&gt;
        &lt;span class=&#34;kt&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;allocated&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fstr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return
&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;        allocate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fstr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;forall&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fstr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cstr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;end subroutine &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;initialize&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end module &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;program &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;use &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;implicit none
&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;    call &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;initialize&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;(A)&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fstr&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end program &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它通过 &lt;code&gt;initialize&lt;/code&gt; 函数来把 C 代码中定义的 &lt;code&gt;incbin_foobar_size&lt;/code&gt; 转换成 Fortran 里带长度信息的字符串，这个操作产生了一次内存复制，
如果你没有内存复制洁癖，这也是可以接受的。&lt;/p&gt;
&lt;p&gt;但如果你不想要这多余的内存复制操作，可以把 &lt;code&gt;cstr&lt;/code&gt; 里的 &lt;code&gt;len=1024*1024&lt;/code&gt; 直接改成 &lt;code&gt;len=&amp;lt;length of file&amp;gt;&lt;/code&gt; ，然后可以直接
&lt;code&gt;print &#39;(A)&#39;, cstr&lt;/code&gt; 也能访问。手动输入文件长度也很麻烦，那不如在 &lt;code&gt;Makefile&lt;/code&gt; 里定义一个宏，把文件长度填进去即可：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;nv&#34;&gt;FILELEN&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;shell &lt;span class=&#34;se&#34;&gt;\l&lt;/span&gt;s -l incbin.c &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;{print $$5}&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;FFLAGS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; -DFILELEN&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;FILELEN&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fortran&#34; data-lang=&#34;fortran&#34;&gt;&lt;span class=&#34;kt&#34;&gt;character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;c_char&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FILELEN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;C&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;incbin_foobar_start&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cstr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后 &lt;code&gt;print &#39;(A)&#39;, cstr&lt;/code&gt; 就能直接得到对应文件的信息了。&lt;/p&gt;
&lt;p&gt;顺便多说一句，这各写法已经是我能想到最简洁的方法了，本人曾试过其它更优雅的写法，但都无法成功，只能作罢。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结&lt;/h2&gt;
&lt;p&gt;以上只是一些把文件打包里程序里的奇技淫巧，本身不值一提，只是被 Fortran 与 C 字符串的互操作恶心到了，不吐不快。其实关于打包文件，
有人已经写了比较成熟的库，就叫 &lt;a href=&#34;https://github.com/graphitemaster/incbin&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;incbin&lt;/a&gt;
 ，我大概浏览了一下，里面对多个平台、多个编译器做了适配，甚至对 SIMD 的内存对齐也有考虑，
可以说是相当完善，有需要可以直接用。&lt;/p&gt;</description>
      
    </item>
    
    <item>
      <title>在 CentOS 7 上使用 Clangd 作为 C/C&#43;&#43; 的 LSP</title>
      <link>http://ionizing.page/post/use_clangd_as_lsp_on_centos7/</link>
      <pubDate>Sat, 25 Mar 2023 19:22:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/use_clangd_as_lsp_on_centos7/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%9f%ba%e6%9c%ac%e7%8e%af%e5%a2%83%e8%a6%81%e6%b1%82&#34;&gt;基本环境要求&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%ae%89%e8%a3%85-clangd&#34;&gt;安装 &lt;code&gt;clangd&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%85%8d%e7%bd%ae-coc-dot-nvim&#34;&gt;配置 &lt;code&gt;coc.nvim&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;最近在 CentOS 7 服务器上写程序时没有 LSP 的帮助，感觉写起来很费劲，于是折腾了一下 &lt;code&gt;clangd&lt;/code&gt; 使之能为 &lt;code&gt;coc.nvim&lt;/code&gt; 所用。&lt;/p&gt;
&lt;h2 id=&#34;基本环境要求&#34;&gt;基本环境要求&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Anaconda/Miniconda
可以去各大镜像站下载安装包，然后直接 &lt;code&gt;sh Anaconda_xxx.sh&lt;/code&gt; 进行安装。这里推荐使用 miniconda ，因为 Anaconda
内置的包太多，每次 &lt;code&gt;conda install&lt;/code&gt; 解析依赖冲突都会耗时 114514 年，而 miniconda 因为内置的包更少，依赖解析起来反倒更快。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vim 及其插件
使用 &lt;code&gt;conda&lt;/code&gt; 命令安装 Vim 8.0 或更高的版本&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;      conda install -c conda-forge vim
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后查看 vim 的版本号：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;      $ vim --version
      VIM - Vi IMproved 9.0 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2022&lt;/span&gt; Jun 28, compiled Aug &lt;span class=&#34;m&#34;&gt;31&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2022&lt;/span&gt; 01:19:52&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
      Included patches: 1-335
      Compiled by conda@065326dfb3d2
      Huge version without GUI.  Features included &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;+&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; or not &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;-&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:
      +acl               +file_in_path      +mouse_urxvt       -tag_any_white
      ...
      ...
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;是 9.0 ，说明安装成功。&lt;/p&gt;
&lt;p&gt;然后安装 &lt;code&gt;vim-plug&lt;/code&gt; 和 &lt;code&gt;coc.nvim&lt;/code&gt; ，直接 Follow 官网上的安装教程即可&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/junegunn/vim-plug&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;vim-plug&lt;/code&gt; 的官网&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/junegunn/vim-plug&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;coc.nvim&lt;/code&gt; 的官网&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;安装-clangd&#34;&gt;安装 &lt;code&gt;clangd&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;CentOS 7 的 yum 源里也有 &lt;code&gt;llvm&lt;/code&gt; 和 &lt;code&gt;clang&lt;/code&gt; 的包，但它们都没有提供 &lt;code&gt;clangd&lt;/code&gt; ，那我们只能去自己安装了。&lt;/p&gt;
&lt;p&gt;其实如果你使用 &lt;code&gt;coc-clangd&lt;/code&gt; 的话，它会帮你下载 &lt;code&gt;clangd&lt;/code&gt; 的可执行文件，但网上预编译的 &lt;code&gt;clangd&lt;/code&gt; 没有对
CentOS 7 这种老平台适配，运行时会报这个经典错误&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;/lib64/libc.so.6: version `GLIBC_2.18&amp;#39; not found (required by clangd)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这是因为 CentOS 7 默认的 &lt;code&gt;glibc&lt;/code&gt; 只有 2.17 ，而贸然升级 &lt;code&gt;glibc&lt;/code&gt; 又是管理 Linux 服务器的大忌（各种程序会炸），
那就只能寻求别的办法了。&lt;/p&gt;
&lt;p&gt;所幸 Anaconda 提供了 &lt;code&gt;clangd&lt;/code&gt; ，我们只需要执行下面的命令即可&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;conda install -c conda-forge clang clangxx clang-tools
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后检查一下各个程序的版本&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ clang --version
clang version 14.0.6
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /public/home/xxx/.miniconda/bin

$ clang++ --version
clang version 14.0.6
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /public/home/xxx/.miniconda/bin

$ clangd --version
clangd version 14.0.6
Features: linux
Platform: x86_64-unknown-linux-gnu
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;写一个 C 的 Hello world ：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[])&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;puts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Hello world.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;看能不能用 Clang 编译&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ clang main.c &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./a.out
Hello world.
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;看来是没问题的；那么 C++ 的 Hello world 呢？&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cout&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Hello world.&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;使用 &lt;code&gt;clang++&lt;/code&gt; 编译：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ clang++ main.cpp
main.cpp:1:10: fatal error: &lt;span class=&#34;s1&#34;&gt;&amp;#39;iostream&amp;#39;&lt;/span&gt; file not found
&lt;span class=&#34;c1&#34;&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;
         ^~~~~~~~~~
&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; error generated.
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这又是一个很经典的错误，它表示 &lt;code&gt;clang++&lt;/code&gt; 找不到头文件 &lt;code&gt;iostream&lt;/code&gt; ，解决它的办不是添加 &lt;code&gt;-I/usr/include/...&lt;/code&gt; 等参数，而是告诉 &lt;code&gt;clang++&lt;/code&gt; 借用 &lt;code&gt;gcc&lt;/code&gt; 工具链内的一些头文件和链接库，具体办法就是使用 &lt;code&gt;--gcc-toolchain&lt;/code&gt; 这个参数，
官网&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
上对这个参数的说明中表示&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;--gcc-toolchain=&amp;lt;arg&amp;gt;
Specify a directory where Clang can find ‘include’ and ‘lib{,32,64}/gcc{,-cross}/$triple/$version’. Clang will use the GCC installation with the largest version
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;那就很好办了，直接指定 &lt;code&gt;--gcc-toolchain=/usr&lt;/code&gt; 即可：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ clang++ --gcc-toolchain&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/usr main.cpp &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./a.out
Hello world.
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;编译运行成功。&lt;/p&gt;
&lt;p&gt;此时关于 Clang 的安装就完成了。&lt;/p&gt;
&lt;h2 id=&#34;配置-coc-dot-nvim&#34;&gt;配置 &lt;code&gt;coc.nvim&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;coc.nvim&lt;/code&gt; 的官网提供了 &lt;code&gt;clangd&lt;/code&gt; 的配置模板，直接复制到 &lt;code&gt;~/.vim/coc-settings.json&lt;/code&gt; 里即可&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;languageserver&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;s2&#34;&gt;&amp;#34;clangd&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;s2&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;clangd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;s2&#34;&gt;&amp;#34;rootPatterns&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;compile_flags.txt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;compile_commands.json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.git/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.hg/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
    &lt;span class=&#34;s2&#34;&gt;&amp;#34;filetypes&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;c&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cpp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;c++&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;objc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;objcpp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此时，用 Vim 打开刚才写的 C Hello world &lt;code&gt;main.c&lt;/code&gt; 应该已经可以提供补全了，如图所示
&lt;img src=&#34;vim-clangd-C.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;接下来配置 C++ 源文件的补全。如果不添加别的参数，那么打开刚刚的 C++ Hello world &lt;code&gt;main.cpp&lt;/code&gt; ，应该会出现以下错误
&lt;img src=&#34;vim-clangd-cxx-1.png&#34; alt=&#34;&#34;&gt;
这和之前直接用 &lt;code&gt;clang++&lt;/code&gt; 编译时的错误一模一样，之前是通过给 &lt;code&gt;clang++&lt;/code&gt; 加一个参数 &lt;code&gt;--gcc-toolchain=/usr&lt;/code&gt; 来解决的，
那么一定有方法可以把编译参数传给 &lt;code&gt;clang++&lt;/code&gt; 来让 &lt;code&gt;clangd&lt;/code&gt; 正常工作。 &lt;code&gt;clangd&lt;/code&gt; 官网上给出的解决方案是在 &lt;code&gt;main.cpp&lt;/code&gt; 同目录下写一个配置文件让 &lt;code&gt;clangd&lt;/code&gt; 来正确调用相关的程序，有三种格式可供选择：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;compile_commands.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这个就是用 json 的格式把编译时需要的命令和参数记录下来传给 &lt;code&gt;clangd&lt;/code&gt; ，它需要把每个文件的编译命令都显式写出来，
我想没人会喜欢手写 json ，并且是如此啰嗦的 json ，
下面是一个示例&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;      &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
          &lt;span class=&#34;s2&#34;&gt;&amp;#34;directory&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/public/home/xxx/tests/cxx&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;s2&#34;&gt;&amp;#34;arguments&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/public/home/xxx/.miniconda/bin/clang++&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;--gcc-toolchain=/usr&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;main.cpp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
          &lt;span class=&#34;s2&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;file.cc&amp;#34;&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;compile_flags.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这个文件的格式非常简单，把参数逐行写到这个文件里即可&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;      --gcc-toolchain=/usr
      --std=c++11
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后 &lt;code&gt;clangd&lt;/code&gt; 就能正常工作了。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;!--listend--&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.clangd&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这个文件格式会稍微复杂一些，官网&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;上有详细的解释，这里给出一个可用的示例&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;      CompileFlags:
        Add: [--gcc-toolchain=/usr]
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;将上述三个文件中的任意一个放到 &lt;code&gt;main.cpp&lt;/code&gt; 的同目录下，用 Vim 打开 &lt;code&gt;main.cpp&lt;/code&gt; ， LSP 应该能正常补全了
&lt;img src=&#34;vim-clangd-cxx-2.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;看起来效果不错，但总要写这些配置文件总让人不爽，倒不是说参数太长，而是连建个 Hello world 都要写个配置文件难免过于麻烦了，而且编译参数在 &lt;code&gt;Makefile&lt;/code&gt; 里已经写过一遍，再写一遍岂不很累。有没有办法不用写这些配置，就把参数传给 &lt;code&gt;clang++&lt;/code&gt; ？经过上网冲浪，在 &lt;code&gt;vscode&lt;/code&gt; 和 &lt;a href=&#34;https://github.com/clangd/coc-clangd&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;coc-clangd&lt;/code&gt;&lt;/a&gt;
 的配置里有个参数叫 &lt;code&gt;--fallbackFlags&lt;/code&gt; ，它表示当
&lt;code&gt;clangd&lt;/code&gt; 找不到上面 &lt;code&gt;compile.json&lt;/code&gt; 、 &lt;code&gt;compile_flags.txt&lt;/code&gt; 和 &lt;code&gt;.clangd&lt;/code&gt; 中任意一个时所使用的参数。从 &lt;code&gt;coc-clangd&lt;/code&gt;
的源码&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;里得知，
这个参数应该被放在 &lt;code&gt;initializationOptions&lt;/code&gt; 下面。打开 &lt;code&gt;~/.vim/coc-settings.json&lt;/code&gt; ，加上这个参数：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;languageserver&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;s2&#34;&gt;&amp;#34;clangd&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;s2&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;clangd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;s2&#34;&gt;&amp;#34;rootPatterns&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;compile_flags.txt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;compile_commands.json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.git/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.hg/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
        &lt;span class=&#34;s2&#34;&gt;&amp;#34;filetypes&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;c&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cpp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;c++&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;objc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;objcpp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
        &lt;span class=&#34;s2&#34;&gt;&amp;#34;initializationOptions&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;s2&#34;&gt;&amp;#34;fallbackFlags&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--gcc-toolchain=/usr&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;删掉 &lt;code&gt;compile.json&lt;/code&gt; 、 &lt;code&gt;compile_flags.txt&lt;/code&gt; 和 &lt;code&gt;.clangd&lt;/code&gt; ，然后打开 &lt;code&gt;main.cpp&lt;/code&gt; ，补全依然正常工作，大功告成。&lt;/p&gt;
&lt;p&gt;当然如果你需要为某个工程写特定的编译参数，那还是老老实实用那三个配置文件吧， &lt;code&gt;initializationOptions&lt;/code&gt; 仅限简单场景使用。&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-gcc-toolchain&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-gcc-toolchain&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://clang.llvm.org/docs/JSONCompilationDatabase.html#format&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://clang.llvm.org/docs/JSONCompilationDatabase.html#format&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://clangd.llvm.org/config&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://clangd.llvm.org/config&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/clangd/coc-clangd/blob/ff784ff7e9bcbcad2bbac556e6849be08c3f048c/src/ctx.ts#L73&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://github.com/clangd/coc-clangd/blob/ff784ff7e9bcbcad2bbac556e6849be08c3f048c/src/ctx.ts#L73&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
    <item>
      <title>利用 Const Generics 实现编译期量纲分析</title>
      <link>http://ionizing.page/post/dimensional-analysis-using-const-generics/</link>
      <pubDate>Sun, 05 Mar 2023 11:59:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/dimensional-analysis-using-const-generics/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%bb%80%e4%b9%88%e6%98%af%e9%87%8f%e7%ba%b2%e5%88%86%e6%9e%90&#34;&gt;什么是量纲分析&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%bb%80%e4%b9%88%e6%98%af-const-generics&#34;&gt;什么是 Const Generics&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8-const-generics-%e5%ae%9e%e7%8e%b0%e9%87%8f%e7%ba%b2%e5%88%86%e6%9e%90&#34;&gt;如何使用 Const Generics 实现量纲分析&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%bf%90%e8%a1%8c%e6%9c%9f%e9%87%8f%e7%ba%b2%e5%88%86%e6%9e%90&#34;&gt;运行期量纲分析&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%88%a9%e7%94%a8-const-generics-%e5%ae%9e%e7%8e%b0%e7%bc%96%e8%af%91%e6%9c%9f%e7%9a%84%e9%87%8f%e7%ba%b2%e5%88%86%e6%9e%90&#34;&gt;利用 const generics 实现编译期的量纲分析&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#siunit-%e7%9a%84%e7%bc%96%e8%af%91%e6%9c%9f%e8%bf%90%e7%ae%97&#34;&gt;&lt;code&gt;SiUnit&lt;/code&gt; 的编译期运算&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#physicalquantity-%e7%9a%84%e5%8a%a0%e5%87%8f%e6%b3%95%e8%bf%90%e7%ae%97&#34;&gt;&lt;code&gt;PhysicalQuantity&lt;/code&gt; 的加减法运算&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#physicalquantity-%e7%9a%84%e4%b9%98%e9%99%a4%e6%b3%95%e8%bf%90%e7%ae%97&#34;&gt;&lt;code&gt;PhysicalQuantity&lt;/code&gt; 的乘除法运算&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#physicalquantity-%e7%9a%84%e4%b9%98%e6%96%b9%e5%bc%80%e6%96%b9%e8%bf%90%e7%ae%97&#34;&gt;&lt;code&gt;PhysicalQuantity&lt;/code&gt; 的乘方开方运算&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%97%a0%e9%87%8f%e7%ba%b2%e6%95%b0%e5%8f%8a%e5%b8%b8%e7%b3%bb%e6%95%b0%e7%9a%84%e7%89%b9%e6%ae%8a%e5%a4%84%e7%90%86&#34;&gt;无量纲数及常系数的特殊处理&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%85%b6%e5%ae%83%e5%ae%9e%e7%8e%b0&#34;&gt;其它实现&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34;&gt;总结&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;开学前折腾了一段时间的 Rust const generics ，也读了一些前人的代码，并自己写出了自己的编译期量纲分析代码，
因此吸收总结这一过程所得知识，产生了这篇博文。本文的实现全部代码在&lt;a href=&#34;https://play.rust-lang.org/?version=nightly&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=4807be24f1e6493bcc5c7cb86457439c&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;这里&lt;/a&gt;
。&lt;/p&gt;
&lt;h2 id=&#34;什么是量纲分析&#34;&gt;什么是量纲分析&lt;/h2&gt;
&lt;p&gt;这里浅薄地介绍一下什么是量纲分析。贴一下 Wiki&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; 上关于量纲和量纲分析的定义：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;量纲是表示一个物理量由基本量组成的情况。确定若干个基本量后，每个派生量都可以表示为基本量的幂的乘积的形式，
引入量纲分析可以进行量纲分析，这既是物理学的基础，又有很多重要的应用。通常一个物理量的量纲是由像质量、
长度、时间、电荷量、温度一类的基础量纲结合而成；&lt;/li&gt;
&lt;li&gt;量纲分析是指对数学或者物理学中物理量的量纲可以用来分析或检验几个物理量之间的关系。
在判断一个由推导获得的方程式或计算结果是否合理时，可以对等号两边的量纲进行化简，从而确认是否一致，这个过程
即用到了量纲分析。对于较为复杂的情况，量纲分析也可以用来建立合理的假设，然后用严格的实验加以验证，或用已
发展成功的理论来仔细推敲。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;由于目前的基本物理量有七个，故在量纲中分别用七个字母表示它们的量纲，分别为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;长度（L）&lt;/li&gt;
&lt;li&gt;质量（M）&lt;/li&gt;
&lt;li&gt;温度（Θ）&lt;/li&gt;
&lt;li&gt;电流（I）&lt;/li&gt;
&lt;li&gt;时间（T）&lt;/li&gt;
&lt;li&gt;物质的量（N）&lt;/li&gt;
&lt;li&gt;发光强度（J）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;任何一个物理量 \(A\) 都可以写出下列量纲式：
\[
\text{dim} A = L^{\alpha} M^{\beta} \Theta^{\gamma} I^{\delta} T^{\epsilon} N^{\zeta} J^{\eta}
\]
如果一个物理量的量纲中所有的指数为 0 ，那么称它为无量纲量，常见的无量纲量有精细结构常数 \(\alpha \approx 1/137\) 、
雷诺数 \(\text{Re} = \frac{\rho VL}{\mu} = \frac{VL}{\nu}\) 以及各种比值、概率等。
两个物理量量纲一致是它们能够相加减的必要条件，而不是充要条件，比如力矩和能量的量纲都是 \(F \cdot L\) ，但这两个量显然无法相加减。物理量的乘除乘方开方则没有这个限制，直接按照相应的代数运算法则对各个基本量纲处理再化简即可。&lt;/p&gt;
&lt;p&gt;值得注意的是，能放在指数和真数位置上的物理量一定是无量纲量。回想一下统计力学中几乎无处不在的
\( \frac{E}{k_{\mathrm{B}} T}\) ，其中分母 \(k_B T\) 的量纲是能量，刚好与分子上 \(E\) 相抵消，导致指数整体是一个无量纲量，进而使得 \( \frac{E}{k_{\mathrm{B}} T}\) 这个整体也是一个无量纲量；又比如在化学反应中常见的公式
\(\Delta G = \Delta G^{\ominus} + RT \ln K\) ，其中化学平衡常数 \(K\) 处于真数的位置，它一定是一个无量纲量。&lt;/p&gt;
&lt;p&gt;此时，我们可以大致总结一下量纲分析运算的规则：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;物理量的量纲由 7 个基本量纲构成；&lt;/li&gt;
&lt;li&gt;具有相同量纲的物理量才能相加减；&lt;/li&gt;
&lt;li&gt;物理量在乘除、乘方和开方时基本量纲的指数遵循代数运算法则；&lt;/li&gt;
&lt;li&gt;处于指数、真数位置的物理量是无量纲量。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这些规则是我们程序实现量纲分析的参考。&lt;/p&gt;
&lt;h2 id=&#34;什么是-const-generics&#34;&gt;什么是 Const Generics&lt;/h2&gt;
&lt;p&gt;Const generics 翻译过来即为常量泛型。在涉及 Rust 泛型代码时，如果泛型参数是一个常量值，而不是类型或生命周期参数等，那么这个泛型参数就称为常量泛型参数&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;。
例如下面一段代码就用到了泛型参数&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Position&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;usize&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// N 即为常量泛型参数
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pos&lt;/span&gt;: &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面代码中 &lt;code&gt;const N: usize&lt;/code&gt; 中的 &lt;code&gt;const&lt;/code&gt; 前缀很贴心地告诉你后面的 &lt;code&gt;N&lt;/code&gt; 是一个泛型参数，而 &lt;code&gt;: usize&lt;/code&gt; 则表明
&lt;code&gt;N&lt;/code&gt; 的类型是 &lt;code&gt;usize&lt;/code&gt; 。这段代码定义了一个泛型的 &lt;code&gt;struct&lt;/code&gt; ，其中包含一个名为 &lt;code&gt;pos&lt;/code&gt; 的数组成员，这个数组元素的类型由 &lt;code&gt;T&lt;/code&gt; 决定，而长度由常量泛型参数 &lt;code&gt;N&lt;/code&gt; 决定。注意，这里面的 &lt;code&gt;T&lt;/code&gt; 和 &lt;code&gt;N&lt;/code&gt; 都是编译期参数，也就是说它们在编译期就已经确定，由于 Rust 是一门静态语言，所有变量的类型在编译成机器码时都是可以被推导出来的，
我们不能用一个程序运行期的变量（比如一个用户输入的值）作为 &lt;code&gt;T&lt;/code&gt; 或 &lt;code&gt;N&lt;/code&gt; ，这是不被允许，并且编译器也无法做到的。&lt;/p&gt;
&lt;p&gt;那么 Rust 为什么要添加 &lt;code&gt;const generics&lt;/code&gt; 这个特性呢？其中的原因在 &lt;a href=&#34;https://rust-lang.github.io/rfcs/2000-const-generics.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;RFC#2000&lt;/a&gt;
 已经写得很清楚了，简单来说就是
Rust 将 &lt;code&gt;[T; 1]&lt;/code&gt; 、 &lt;code&gt;[T; 2]&lt;/code&gt; 、 &lt;code&gt;[T;3]&lt;/code&gt; ……这样不同长度的数组看做不同的类型，那么在实现一些操作时就会显得很脏，比如&lt;a href=&#34;https://doc.rust-lang.org/1.37.0/std/primitive.array.html#impl-Eq&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;早期版本的 Rust 标准库&lt;/a&gt;
在实现比较两个定长数组是否相等的特质 &lt;code&gt;Eq&lt;/code&gt; 时就分别对 &lt;code&gt;[T; 0]&lt;/code&gt; 、 &lt;code&gt;[T; 1]&lt;/code&gt; 、
&lt;code&gt;[T; 2]&lt;/code&gt; 等等的定长数组各自实现，一直到 &lt;code&gt;[T; 32]&lt;/code&gt; 。那么如果你有一个长度大于 32 的定长数组需要比较时怎么办？
比如这样的代码&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// https://godbolt.org/z/zn1TYfaev
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;compare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lhs&lt;/span&gt;: &lt;span class=&#34;kp&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;i32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;33&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;: &lt;span class=&#34;kp&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;i32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;33&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lhs&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// error[E0369]: binary operation `==` cannot be applied to type `&amp;amp;[i32; 33]`
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//  --&amp;gt; &amp;lt;source&amp;gt;:2:9
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   |
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 2 |     lhs == rhs
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   |     --- ^^ --- &amp;amp;[i32; 33]
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   |     |
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   |     &amp;amp;[i32; 33]
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   |
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   = note: an implementation of `std::cmp::PartialEq` might be missing for `&amp;amp;[i32; 33]`
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;编译器会直接报错罢工，而如果把两个 &lt;code&gt;33&lt;/code&gt; 全部换成 &lt;code&gt;32&lt;/code&gt; 则可以正常编译，是不是感觉非常不可思议？当然这个问题在 2021
年 3 月份 &lt;a href=&#34;https://blog.rust-lang.org/2021/02/26/const-generics-mvp-beta.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;const generics 稳定后&lt;/a&gt;
就已经被解决了。在 Rustc 1.51 以后，你可以对任意长度的 &lt;code&gt;[T; LEN]&lt;/code&gt; 运行比较，以及其它相关的操作，再也不用担心编译器摆烂。&lt;/p&gt;
&lt;p&gt;除了解决定长数组的相关问题， const generics 还有其它很多有用的地方，比如可以实现编译期的计算（写 C++
的同学可能已经开始狂喜了，别高兴太早，用 &lt;del&gt;Ruast&lt;/del&gt; 的 const generics 来写类似 C++ 的模板元编译期计算会非常地痛苦，
建议不要尝试）等。有一个相对关键的点在于，泛型参数只存在于编译期，也就是说在运行期这个参数不存在。这也意味着常量泛型参数自己并不占内存，比如&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;usize&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个结构体的大小用 &lt;code&gt;std::mem::size_of::&amp;lt;Foo&amp;lt;1&amp;gt;&amp;gt;()&lt;/code&gt; 求出来是 &lt;code&gt;8&lt;/code&gt; ，正好等于 &lt;code&gt;i64&lt;/code&gt; 本身的大小；事实上，不管
&lt;code&gt;N&lt;/code&gt; 取多少，甚至 &lt;code&gt;std::mem::size_of::&amp;lt;Foo&amp;lt;114514&amp;gt;&amp;gt;()&lt;/code&gt; ，得到的仍然是 &lt;code&gt;8&lt;/code&gt; ，这为编译器的优化提供了可能。&lt;/p&gt;
&lt;p&gt;除此之外，当 &lt;code&gt;N&lt;/code&gt; 不同时， &lt;code&gt;Foo&amp;lt;N&amp;gt;&lt;/code&gt; 被认为是不同的类型。即使你分别为 &lt;code&gt;Foo&amp;lt;N1&amp;gt;&lt;/code&gt; 和 &lt;code&gt;Foo&amp;lt;N2&amp;gt;&lt;/code&gt; 分别实现了相同的特质（这里以 &lt;code&gt;Eq&lt;/code&gt; 为例），那么当你写下 &lt;code&gt;Foo::&amp;lt;N1&amp;gt;::default() == Foo::&amp;lt;N2&amp;gt;::default()&lt;/code&gt; 这样的代码时，除非 &lt;code&gt;N1 == N2&lt;/code&gt;
否则编译器会报错提醒你：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#[derive(Default, PartialEq, Eq)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;usize&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Foo&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Foo&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;());&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// error[E0308]: mismatched types
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//  --&amp;gt; src/main.rs:7:43
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   |
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 7 |     println!(&amp;#34;{}&amp;#34;, Foo::&amp;lt;0&amp;gt;::default() == Foo::&amp;lt;1&amp;gt;::default());
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   |                                           ^^^^^^^^^^^^^^^^^^^ expected `0`, found `1`
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   |
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   = note: expected struct `Foo&amp;lt;0&amp;gt;`
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//              found struct `Foo&amp;lt;1&amp;gt;`
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个特性对于实现编译期量纲分析是至关重要的，可以说如果没有这个特性，编译期的量纲分析就无法实现。&lt;/p&gt;
&lt;p&gt;当然，现在稳定版的 const generics 所支持的功能还十分有限，如果想了解关于它的更多信息，可以戳&lt;a href=&#34;https://rustmagazine.github.io/rust_magazine_2021/chapter_2/lang.html?highlight=const%20generics#%E5%85%B3%E4%BA%8E-const-generics-mvp-%E4%BD%A0%E9%9C%80%E8%A6%81%E7%9F%A5%E9%81%93%E7%9A%84&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;这个链接&lt;/a&gt;
。&lt;/p&gt;
&lt;h2 id=&#34;如何使用-const-generics-实现量纲分析&#34;&gt;如何使用 Const Generics 实现量纲分析&lt;/h2&gt;
&lt;p&gt;在阐述如何使用 const generics 实现编译期量纲分析之前，我们先来了解一下运行期量纲分析有啥缺点。&lt;/p&gt;
&lt;h3 id=&#34;运行期量纲分析&#34;&gt;运行期量纲分析&lt;/h3&gt;
&lt;p&gt;为了描述量纲，我们需要定义一个结构体来储存七个基本量纲的指数，为了方便实现，这里直接取国际单位制：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#[derive(Default, PartialEq, Eq, Clone, Copy)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// make SiUnit::default() and SiUnit == SiUnit possible
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// meter
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// second
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kg&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// kilogram
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// coulomb
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cd&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// candela
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mol&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// mole
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// kelvin
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后这个结构体需要实现加减运算特质，以满足两个物理量乘除时对量纲的运算：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;ops&lt;/span&gt;::&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Mul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// required trait for overload of `+` and `-`.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// required associate type
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;             &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kg&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;             &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cd&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mol&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mol&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mol&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// required associate type
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样我们就可以直接执行 &lt;code&gt;SiUnit + SiUnit&lt;/code&gt; 、 &lt;code&gt;SiUnit - SiUnit&lt;/code&gt; 这样的操作了。&lt;/p&gt;
&lt;p&gt;为了实现物理量的乘方开方运算，它还需要实现 &lt;code&gt;Mul&lt;/code&gt; 和 &lt;code&gt;Div&lt;/code&gt; 特质，与实现 &lt;code&gt;Add&lt;/code&gt;
和 &lt;code&gt;Sub&lt;/code&gt; 特质不同的是， &lt;code&gt;Mul&lt;/code&gt; 和 &lt;code&gt;Div&lt;/code&gt; 特质里的右操作数 &lt;code&gt;Rhs&lt;/code&gt; 都是 &lt;code&gt;i8&lt;/code&gt;
类型，而不是 &lt;code&gt;SiUnit&lt;/code&gt; 本身，因为乘方开方的指数都是没有量纲的。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;ops&lt;/span&gt;::&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Mul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Mul&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;mul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;             &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kg&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;             &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cd&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mol&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mol&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此时， &lt;code&gt;SiUnit&lt;/code&gt; 可以进行 &lt;code&gt;SiUnit * 2&lt;/code&gt; 、 &lt;code&gt;SiUnit / 2&lt;/code&gt; 这样的运算了。那么把和一个值打包在一起就组成一个物理量了：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unit&lt;/span&gt;:  &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后我们再为它实现各种运算操作，就可以用它代入各种公式求值了。那么这其中有什么问题呢？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;它占用的内存太多。用 &lt;code&gt;std::mem::size_of::&amp;lt;PhysicalQuantity&amp;lt;f64&amp;gt;&amp;gt;()&lt;/code&gt; 查看一下这个结构体占用的内存，
为 16 字节，这说明不参与值运算的 &lt;code&gt;unit&lt;/code&gt; 成员就占用了一半的空间；如果对一个 &lt;code&gt;[PhysicalQuantity; len]&lt;/code&gt;
这样的数组运算，那么所有元素的 &lt;code&gt;unit&lt;/code&gt; 成员就交错分布在真正需要运算的 &lt;code&gt;value&lt;/code&gt; 成员中间，这对 CPU
的缓存命中和 SIMD 优化是非常不利的，进而造成可观的性能损失；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PhysicalQuantity&lt;/code&gt; 之间没有区分，也就是说 &lt;code&gt;unit&lt;/code&gt; 不同的 &lt;code&gt;PhysicalQuantity&lt;/code&gt; 被认为是同一个类型，
当它们被放在同一个数组等线性表里时，编译器不会报错，而且人工检查也只能在运行时进行；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PhysicalQuantity&lt;/code&gt; 在执行加减运算时需要手动检查 &lt;code&gt;unit&lt;/code&gt; 是否一致；在执行乘除法时，需要对 &lt;code&gt;unit&lt;/code&gt; 运行相应
的运算，这些均在运行时进行，并且每个元素操作时都要做，这也会严重降低运行效率。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如此这些缺陷在 const generics 的加持下都可以解决。&lt;/p&gt;
&lt;h3 id=&#34;利用-const-generics-实现编译期的量纲分析&#34;&gt;利用 const generics 实现编译期的量纲分析&lt;/h3&gt;
&lt;p&gt;为了让编译器在编译期帮助我们推导量纲，我们可以利用 const generics ，把量纲信息放在泛型参数里，如下所示：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#![feature(adt_const_params)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[derive(PartialEq)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;需要注意的是，在现在 Rustc 最新稳定版(1.67)里，只能支持整数、 &lt;code&gt;bool&lt;/code&gt; 以及 &lt;code&gt;char&lt;/code&gt; 作为 const generic params ，
想要放结构体进去需要切换到 nightly 频道，并在代码开头加上 &lt;code&gt;#![feature(adt_const_params)]&lt;/code&gt; 来开启 &lt;code&gt;adt_const_params&lt;/code&gt;
这个 feature ，从而支持把 &lt;code&gt;SiUnit&lt;/code&gt; 放到泛型参数里。此时，运行 &lt;code&gt;std::mem::size_of&amp;lt;PhysicalQuantity&amp;lt;f64, SiUnit::default()&amp;gt;&amp;gt;()&lt;/code&gt; ，
输出为 8 ，说明没有多余的空间占用，第一个问题得以解决。&lt;/p&gt;
&lt;p&gt;为了方便起见，我们定义一些类型别名&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;METER&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kg&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cd&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mol&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Meter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;METER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;METER_PER_SEC&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;:  &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;: &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kg&lt;/span&gt;:  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;:  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cd&lt;/span&gt;:  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mol&lt;/span&gt;:  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;:  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Mps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;METER_PER_SEC&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后比较一个两个量纲不同的量，看会有什么反应&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Meter&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;f64&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Mps&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;f64&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assert_ne&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// cannot compile
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// error[E0308]: mismatched types
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   --&amp;gt; src/main.rs:54:5
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//    |
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 54 |     assert_ne!(a, b);   // cannot compile
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//    |     ^^^^^^^^^^^^^^^^ expected `SiUnit { m: 1, s: 0, kg: 0, c: 0, cd: 0, mol: 0, k: 0 }`, found `SiUnit { m: 1, s: -1, kg: 0, c: 0, cd: 0, mol: 0, k: 0 }`
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//    |
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//    = note: expected struct `PhysicalQuantity&amp;lt;_, SiUnit { m: 1, s: 0, kg: 0, c: 0, cd: 0, mol: 0, k: 0 }&amp;gt;`
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//               found struct `PhysicalQuantity&amp;lt;_, SiUnit { m: 1, s: -1, kg: 0, c: 0, cd: 0, mol: 0, k: 0 }&amp;gt;`
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//    = note: this error originates in the macro `assert_ne` (in Nightly builds, run with -Z macro-backtrace for more info)
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// For more information about this error, try `rustc --explain E0308`.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此时，编译器拒绝编译，并给出了错误信息，其中明确说明参数 &lt;code&gt;b&lt;/code&gt; 存在类型错误，从而避免用户强行将两者放在一起比较。
这也表明只要量纲一致，那么类型肯定一致；反之如果量纲不一致，类型也一定不同，这可以将用户的编码错误提前到编译期暴露出来，
第二个问题得以解决。&lt;/p&gt;
&lt;p&gt;以上只是一个示例，下面我们来为 &lt;code&gt;PhysicalQuantity&lt;/code&gt; 实现更多功能。&lt;/p&gt;
&lt;h4 id=&#34;siunit-的编译期运算&#34;&gt;&lt;code&gt;SiUnit&lt;/code&gt; 的编译期运算&lt;/h4&gt;
&lt;p&gt;首先，我们需要在编译期对 &lt;code&gt;SiUnit&lt;/code&gt; 进行运算，之前的 &lt;code&gt;impl Add for SiUnit { ... }&lt;/code&gt; 是为 &lt;code&gt;SiUnit&lt;/code&gt; 实现一个函数，
然而这个函数只能在运行期跑，如何解决？这里就要用到 nightly 的另一个不稳定特性 &lt;code&gt;const_trait_impl&lt;/code&gt; ，然后
&lt;code&gt;impl const Add for SiUnit&lt;/code&gt; 就可以了：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#![feature(const_trait_impl)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Mul&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id=&#34;physicalquantity-的加减法运算&#34;&gt;&lt;code&gt;PhysicalQuantity&lt;/code&gt; 的加减法运算&lt;/h4&gt;
&lt;p&gt;然后我们来考虑为 &lt;code&gt;PhysicalQuantity&lt;/code&gt; 实现各种运算。我们先为它实现最为简单的加减运算，由于加减运算的两个操作数量纲一致，
类型肯定相同，那么实现加减法就不需要对 &lt;code&gt;SiUnit&lt;/code&gt; 进行运算：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id=&#34;physicalquantity-的乘除法运算&#34;&gt;&lt;code&gt;PhysicalQuantity&lt;/code&gt; 的乘除法运算&lt;/h4&gt;
&lt;p&gt;而 &lt;code&gt;PhysicalQuantity&lt;/code&gt; 的乘除法不要求左右操作数量纲一致，并且产生的结果可能有着第三种量纲，因此在实现乘除法的特质时会稍微麻烦一点，也会用到本文提到的第三个不稳定特性 &lt;code&gt;generic_const_exprs&lt;/code&gt; ，它支持在 const generic params 里写表达式，
而这个表达式则需要用花括号包起来，比如像 &lt;code&gt;PhysicalQuantity&amp;lt;T, {U+V}&amp;gt;&lt;/code&gt; 这样：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#![feature(generic_const_exprs)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Mul&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// generic_const_exprs used
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;mul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// generic_const_exprs used
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rhs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面的代码的每个特质的实现中，除了 &lt;code&gt;T&lt;/code&gt; 之外，一共有三个泛型，分别是 &lt;code&gt;U&lt;/code&gt; 、 &lt;code&gt;V&lt;/code&gt; 和 &lt;code&gt;U±V&lt;/code&gt; ，而在 &lt;code&gt;impl&amp;lt;&amp;gt;&lt;/code&gt; 只能写 &lt;code&gt;U&lt;/code&gt; 和 &lt;code&gt;V&lt;/code&gt;
这两个参数（ &lt;code&gt;U&lt;/code&gt; 属于 &lt;code&gt;PhysicalQuantity&lt;/code&gt; ， &lt;code&gt;V&lt;/code&gt; 存在于 &lt;code&gt;Mul&amp;lt;Rhs&amp;gt;&lt;/code&gt; 中的 &lt;code&gt;Rhs&lt;/code&gt; 内），那么 &lt;code&gt;U±V&lt;/code&gt; 就只能放在 &lt;code&gt;where&lt;/code&gt; 里进行约束了。&lt;/p&gt;
&lt;p&gt;那么，为什么不直接 &lt;code&gt;where {U±V}:,&lt;/code&gt; 这样来约束呢，那是因为现在编译器还不够强，不支持这样写，如果 &lt;code&gt;U&lt;/code&gt; 和 &lt;code&gt;V&lt;/code&gt; 是 &lt;code&gt;usize&lt;/code&gt; 类型，
官方支持 &lt;code&gt;where [(); {U±V}]:,&lt;/code&gt; 这样来进行约束。但不幸的是，这里的 &lt;code&gt;U&lt;/code&gt; 和 &lt;code&gt;V&lt;/code&gt; 是 &lt;code&gt;SiUnit&lt;/code&gt; 类型，除非你为它实现了转换到 &lt;code&gt;usize&lt;/code&gt;
的特质，然后写 &lt;code&gt;where [(); {U±V}.into::&amp;lt;usize&amp;gt;()]:,&lt;/code&gt; 这样的约束条件。除了这个选择，我们可以直接约束 &lt;code&gt;PhysicalQuantity&amp;lt;T, {U±V}&amp;gt;&lt;/code&gt;
这个类型本身，幸运的是， rustc 确实接受这样的写法，谢天谢地。&lt;/p&gt;
&lt;p&gt;顺便吐槽一下， &lt;code&gt;generic_const_exprs&lt;/code&gt; 所支持的表达式十分有限，甚至当 &lt;code&gt;U&lt;/code&gt; 和 &lt;code&gt;V&lt;/code&gt; 为 &lt;code&gt;usize&lt;/code&gt; 时， &lt;code&gt;{U+V}&lt;/code&gt; 和 &lt;code&gt;{V+U}&lt;/code&gt; 被认为是不等价的，
这也意味着我们在写表达式时需要十分小心表达式的顺序，如果写错的话，编译器吐出来的东西可能会非常难看……&lt;/p&gt;
&lt;p&gt;言归正传，经过上面的实现后，我们可以对不同量纲的物理量进行乘除运算了，比如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Meter&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;f64&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Mps&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;f64&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;type: {}, value: {}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;any&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;type_name_of_val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// type: playground::PhysicalQuantity&amp;lt;f64, playground::SiUnit { m: 0, s: 1, kg: 0, c: 0, cd: 0, mol: 0, k: 0 }&amp;gt;, value: 0.5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;在打印出 &lt;code&gt;c&lt;/code&gt; 的类型后，它的量纲确实是时间，说明我们的实现是正确的。&lt;/p&gt;
&lt;h4 id=&#34;physicalquantity-的乘方开方运算&#34;&gt;&lt;code&gt;PhysicalQuantity&lt;/code&gt; 的乘方开方运算&lt;/h4&gt;
&lt;p&gt;到现在为止，我们已经为 &lt;code&gt;PhysicalQuantity&amp;lt;T, U&amp;gt;&lt;/code&gt; 实现了四则运算。相比于前面的实现，乘方、开方的运算要更麻烦一些，因为返回值的量纲取决于指数，等于说返回的类型取决于指数，这要求我们必须把指数放在 &lt;code&gt;const generics param&lt;/code&gt; 的位置上，否则存在于运行期的指数无论如何也无法让编译器在编译期推导出返回类型。特质 &lt;code&gt;num::pow::Pow&lt;/code&gt; 定义了 &lt;code&gt;.pow()&lt;/code&gt; 函数，但这个函数的签名中指数存在于第二个函数参数的位置上，而不是常量泛型参数的位置上，因此不能使用；尽管如此，我们仍可以照猫画虎，仿照 &lt;code&gt;num::pow::Pow&lt;/code&gt;
来自己定义一个特质 &lt;code&gt;Power&lt;/code&gt; ：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PowerI&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 关联类型
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;powi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后为 &lt;code&gt;PhysicalQuantity&lt;/code&gt; 实现它&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PowerI&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Pow&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;powi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;最后，我们应该怎样调用它呢？经过与 rustc 的搏斗，我发现主要有以下两种写法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;let f2 = &amp;lt;Meter&amp;lt;f64&amp;gt; as PowerI&amp;lt;2&amp;gt;&amp;gt;::powi(f);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;let f2 = PowerI::&amp;lt;2&amp;gt;::powi(f);&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;第 1 种写法看着就令人头疼，第 2 种写法稍微好一些，但也只是五十步笑百步。造成写法如此难看的原因是指数 &lt;code&gt;power&lt;/code&gt;
被放在了 &lt;code&gt;trait&lt;/code&gt; 的泛型参数里，而不是 &lt;code&gt;fn powi&amp;lt;power&amp;gt;(self) ...&lt;/code&gt;  这个函数的泛型参数里。但是，如果将 &lt;code&gt;power&lt;/code&gt;
写在 &lt;code&gt;fn powi()&lt;/code&gt; 里，那么当你在实现时不得不面对 &lt;a href=&#34;https://doc.rust-lang.org/error_codes/E0207.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;E0207 错误&lt;/a&gt;
 ：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PowerI&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;powi&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PowerI&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Pow&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;powi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//     |
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 182 | impl&amp;lt;T, const U: SiUnit, const power: i8&amp;gt; PowerI for PhysicalQuantity&amp;lt;T, U&amp;gt;
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//     |                          ^^^^^^^^^^^^^^^ unconstrained const parameter
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//     |
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//     = note: expressions using a const parameter must map each value to a distinct output value
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//     = note: proving the result of expressions other than the parameter are unique is not supported
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个报错告诉我们常量泛型参数 &lt;code&gt;power&lt;/code&gt; 必须出现在 &lt;code&gt;impl&amp;lt;...&amp;gt; Trait&amp;lt;...&amp;gt; for Object&amp;lt;...&amp;gt;&lt;/code&gt; 的后两个尖括号内，
或者直接出现 &lt;code&gt;where&lt;/code&gt; 约束的从句里，以表达式的形式出现则不被接受。上面代码里就是因为
&lt;code&gt;where PhysicalQuantity&amp;lt;T, {U*power}&amp;gt;&lt;/code&gt; 中 &lt;code&gt;power&lt;/code&gt; 是以表达式的形式出现而被拒绝编译，以笔者水平，看来这条路是走不通了。&lt;/p&gt;
&lt;p&gt;那有没有简单、直接点的实现，让我们可以 &lt;code&gt;f.powi::&amp;lt;power&amp;gt;()&lt;/code&gt; 呢？当然有的，直接 &lt;code&gt;impl&lt;/code&gt; ，给 &lt;code&gt;PhysicalQuantity&lt;/code&gt;
添加方法即可：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Pow&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;powi&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;power&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样就能使用 &lt;code&gt;let f2 = f.powi::&amp;lt;2&amp;gt;()&lt;/code&gt; 来求得 &lt;code&gt;f&lt;/code&gt; 的平方了，看起来这样的实现既简单，效果也好 &lt;del&gt;所谓大道至简，也即是如此吧2333&lt;/del&gt; 。
至于开方，它和乘方的实现几乎一致，这里限制 &lt;code&gt;T&lt;/code&gt; 为浮点数类型，为了使返回类型 &lt;code&gt;T&lt;/code&gt; 与输入类型 &lt;code&gt;T&lt;/code&gt; 一致：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Float&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;From&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;f64&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;nth_root&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;root&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;root&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;root&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;powf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;f64&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;root&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;f64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;into&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后就可以 &lt;code&gt;f.nth_root::&amp;lt;3&amp;gt;()&lt;/code&gt; 来求 &lt;code&gt;f&lt;/code&gt; 的立方根了。&lt;/p&gt;
&lt;h4 id=&#34;无量纲数及常系数的特殊处理&#34;&gt;无量纲数及常系数的特殊处理&lt;/h4&gt;
&lt;p&gt;有时公式中还会出现无量纲系数直接相乘的情况，比如 \(\frac{1}{4\pi \epsilon}\) ，
这时如果把 \(4\pi\) 手动写成 &lt;code&gt;PhysicalQuantity::&amp;lt;T, U&amp;gt;::new(4.0 * pi)&lt;/code&gt; 的形式，未免过于冗长。这种情况下，我们需要为直接数
&lt;code&gt;T&lt;/code&gt; 实现到无量纲 &lt;code&gt;PhysicalQuantity&lt;/code&gt; 类型的转换特质：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DIMENSIONLESS&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SiUnit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kg&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cd&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mol&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Dimensionless&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PhysicalQuantity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DIMENSIONLESS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;From&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Dimensionless&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Dimensionless&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Dimensionless&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后就可以这样写了：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;4.0.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;into&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;type: {}, value: {}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;any&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;type_name_of_val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// type: playground::PhysicalQuantity&amp;lt;f64, playground::SiUnit { m: 0, s: 1, kg: 0, c: 0, cd: 0, mol: 0, k: 0 }&amp;gt;, value: 2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;注意，这里还有一个坑， &lt;code&gt;let d = 4.0.into() * c&lt;/code&gt; 是无法编译的，因为 &lt;code&gt;a * b&lt;/code&gt; 运算具体调用哪个函数首先取决于 &lt;code&gt;a&lt;/code&gt; 的类型，编译器会查找左操作数类型与 &lt;code&gt;a&lt;/code&gt;
一致的函数，然后在其中查找右操作数类型与 &lt;code&gt;b&lt;/code&gt; 一致的函数 &lt;code&gt;mul(type_a, type_b)&lt;/code&gt; ，最后调用 &lt;code&gt;mul()&lt;/code&gt; 。如果 &lt;code&gt;4.0.into()&lt;/code&gt; 写在 &lt;code&gt;*&lt;/code&gt; 的左边，由于 &lt;code&gt;4.0.into()&lt;/code&gt;
得到并不是一个固定的类型，这个类型取决于上下文，那么查找相应 &lt;code&gt;mul&lt;/code&gt; 函数的第一步就无法完成，编译器自然会报错。如何解决呢？我们可以指定 &lt;code&gt;.into()&lt;/code&gt;
得到的类型： &lt;code&gt;&amp;lt;f64 as Into&amp;lt;Dimensionless&amp;lt;f64&amp;gt;&amp;gt;&amp;gt;::into(4.0)&lt;/code&gt; 或者 &lt;code&gt;Dimensionless::&amp;lt;f64&amp;gt;::from(4.0)&lt;/code&gt; ，但这两种写法都太麻烦了，不如直接把 &lt;code&gt;4.0.into()&lt;/code&gt;
写在右面，一样可以编译通过。&lt;/p&gt;
&lt;p&gt;尽管如此， &lt;code&gt;4.0.into()&lt;/code&gt; 这种写法依然看起来很糟糕，为什么不能直接实现 &lt;code&gt;4.0 * c&lt;/code&gt; 这样的写法呢？因为要支持这样的写法意味着我们需要对四则运算分别再实现一遍，
像 &lt;code&gt;impl&amp;lt;T&amp;gt; Op&amp;lt;T&amp;gt; for Dimensionless&amp;lt;T&amp;gt; where T: Num&lt;/code&gt; 这样；而且由于孤儿规则的存在，编译器也不允许我们
&lt;code&gt;impl&amp;lt;T&amp;gt; Op&amp;lt;Dimensionless&amp;lt;T&amp;gt;&amp;gt; for T where T: Num&lt;/code&gt; ，所以只能作罢。出于复用 &lt;code&gt;PhysicalQuantity&lt;/code&gt; 之间已经实现的运算的目的，不如把无量纲系数转换为
&lt;code&gt;Dimensionless&amp;lt;T&amp;gt;&lt;/code&gt; ，再利用已有的函数去实现各种运算，何乐而不为呢（）。至于 &lt;code&gt;4.0.into()&lt;/code&gt; 这种看起来很丑的写法，这是 Ruast 的一大特色，不得不品尝，
连标准库的文档里都充斥着 &lt;code&gt;1.0_f64.sqrt()&lt;/code&gt; 这种一样“很丑”的写法，习惯就好啦，你多看几眼就不觉得丑啦 &lt;del&gt;（这就是 Ruast 带给我们的自信）&lt;/del&gt; 。&lt;/p&gt;
&lt;p&gt;对于一般的数，乘法运算是对易的，但除法却不是。当除数是无量纲数时，我们可以使用 &lt;code&gt;c / 4.0.into()&lt;/code&gt; ；但当被除数是无量纲数时，我们只能
&lt;code&gt;Dimensionless::from(4.0f64) / c&lt;/code&gt; 这样来处理了。&lt;/p&gt;
&lt;p&gt;对于 \(e^{c}\) 和 \(\ln{c}\) 等限制输入为无量纲数的函数，我们可以通过只为 &lt;code&gt;Dimensionless&lt;/code&gt; 类型实现相关函数来实现：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Dimensionless&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ln&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Self&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ln&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样，即使用户传入了一个非无量纲数，编译器也会在编译期把这种代码拒之门外。&lt;/p&gt;
&lt;p&gt;至此，我们已经为 &lt;code&gt;PhysicalQuantity&lt;/code&gt; 实现了基础的运算操作，现在已经可以用它去做一些简单的推导了，并且推导的过程完全是编译期完成的，
并且只要能编译成功，就能保证结果的量纲和单位正确。&lt;/p&gt;
&lt;h4 id=&#34;其它实现&#34;&gt;其它实现&lt;/h4&gt;
&lt;p&gt;其实很早就有编译期量纲分析的实现了，它们没有用到 &lt;code&gt;const generics&lt;/code&gt; 这个特性，而是直接使用 &lt;a href=&#34;https://docs.rs/typenum/latest/typenum/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;typenum&lt;/a&gt;
 这个库提供的 &lt;code&gt;Integer&lt;/code&gt; 特质，其定义如下&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Integer&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Sealed&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Copy&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Default&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;&amp;#39;static&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I8&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I16&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I32&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I64&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;i64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ISIZE&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;isize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;kt&#34;&gt;i8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_i16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;kt&#34;&gt;i16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_i32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;kt&#34;&gt;i32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_i64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;kt&#34;&gt;i64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_isize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;kt&#34;&gt;isize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个特质作为泛型约束出现，那么它所约束的泛型参数就相当于本文实现中 &lt;code&gt;const unit: SiUnit&lt;/code&gt; 内的的成员，然后分别定义了一系列 &lt;code&gt;P1&lt;/code&gt; 、 &lt;code&gt;P2&lt;/code&gt; 、 &lt;code&gt;N1&lt;/code&gt; ……
等等 &lt;strong&gt;类型&lt;/strong&gt; ，对这些类型实现 &lt;code&gt;Integer&lt;/code&gt; 特质，使用时调用 &lt;code&gt;.to_i8()&lt;/code&gt; 等函数则返回 &lt;code&gt;1&lt;/code&gt; 、 &lt;code&gt;2&lt;/code&gt; 、 &lt;code&gt;-1&lt;/code&gt; 等等整数，从而模拟 &lt;code&gt;const generics&lt;/code&gt;
内的整数，由于 &lt;code&gt;P1&lt;/code&gt; 等本质还是类型，所以它不受 &lt;code&gt;const generics&lt;/code&gt; 里弱鸡表达式的限制，当然作者为了实现类型之间的运算也是花了很大的功夫，
这里就不谈了（其实是没读懂）。比较完善的量纲分析库，我找到的有两个，分别是 &lt;a href=&#34;https://docs.rs/dimensioned/latest/dimensioned/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;dimensioned&lt;/a&gt;
 和 &lt;a href=&#34;https://docs.rs/uom/latest/uom/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;uom&lt;/a&gt;
 ，其中 dimensioned 的作者也是
&lt;code&gt;typenum&lt;/code&gt; 的作者， crates.io 上统计 &lt;code&gt;typenum&lt;/code&gt; 的下载量将近八千万，而 &lt;code&gt;dimensioned&lt;/code&gt; 也就三万不到，对于作者来说
&lt;code&gt;dimensioned&lt;/code&gt; 只是顺手一写的小项目了，即便如此，它的提供了丰富的内置单位和转换操作，足够一般使用。&lt;/p&gt;
&lt;p&gt;除了使用 &lt;code&gt;typenum&lt;/code&gt; 库的实现，还有用 &lt;code&gt;const generics&lt;/code&gt; 实现的库 &lt;a href=&#34;https://docs.rs/const_unit_poc/latest/const_unit_poc/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;const_unit_poc&lt;/a&gt;
 ，这是利用 const generics 实现量纲分析的一个
proof of concept ，足够简短，代码也好读，本文就是参考了它的实现。&lt;/p&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;本文分别实现了运行期的量纲分析和借助 const genreics 实现的编译期量纲分析，着重后者了后者的优势，以及实现上的细节。在使用 const generics
时，依次用到了三个不稳定特性： &lt;code&gt;adt_const_params&lt;/code&gt; （让 const generics 支持自定义的 &lt;code&gt;SiUnit&lt;/code&gt; 结构体）， &lt;code&gt;const_trait_impl&lt;/code&gt; （为 &lt;code&gt;SiUnit&lt;/code&gt;
实现编译期的四则运算）和 &lt;code&gt;generic_const_exprs&lt;/code&gt; （允许在 const generic params 内写表达式）。这些不稳定特性现在只能临时使用，将来可能会有语法、
行为上的变化，因此本文的实现不保证在未来依然可用。在实现的同时，我们也发现了一些 Rust 不那么优雅的地方，比如冗长的
&lt;code&gt;&amp;lt;f64 as Into&amp;lt;Dimensionless&amp;lt;f64&amp;gt;&amp;gt;&amp;gt;::into(4.0)&lt;/code&gt; 表达式、对孤儿规则的妥协、 &lt;code&gt;generic_const_exprs&lt;/code&gt; 对表达式极为有限的支持等等。
不过相比起 C++ 标准的更新速度， Rust 的标准库更新速度还是可以期待的。&lt;/p&gt;
&lt;p&gt;本文实现的全部代码在&lt;a href=&#34;https://play.rust-lang.org/?version=nightly&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=4807be24f1e6493bcc5c7cb86457439c&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;这里&lt;/a&gt;
&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;还有几篇博文对本人帮助很大：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;zqp-cn 大佬的&lt;a href=&#34;https://zjp-cn.github.io/rust-note/forum/impl-const-param.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;针对常量泛型参数的分类实现&lt;/a&gt;
；&lt;/li&gt;
&lt;li&gt;Rust 官方的 &lt;a href=&#34;https://blog.rust-lang.org/2021/02/26/const-generics-mvp-beta.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Const generics MVP hits beta!&lt;/a&gt;
；&lt;/li&gt;
&lt;li&gt;Rust 官方的 &lt;a href=&#34;https://blog.rust-lang.org/inside-rust/2021/09/06/Splitting-const-generics.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Splitting the const generics features&lt;/a&gt;
；&lt;/li&gt;
&lt;li&gt;Rust 中文社区 2021 年的&lt;a href=&#34;https://rustmagazine.github.io/rust_magazine_2021/chapter_11/bench-and-const.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Rust AEAD benchmark 与 Const generics&lt;/a&gt;
。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;说来编译期的量纲分析其实在 1995 年就被 John J. Barton 和
Lee R. Nackman&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;
使用 C++ 的模板元编程所实现，
C++ 大师 Scott Meyers 也曾专门写了一篇文章阐述如何使用 C++ template 实现量纲分析&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt; 。
本人其实也是受这个实现所启发，进而产生了用 Rust 的泛型系统重新实现一下这个功能的想法，进而稍微读了些前人的实现，之后便有了这篇文章。
不得不感叹，读别人的代码和自己写完全是两种感觉，有些坑只有自己踩了才会知道，也才能明白有些代码写得拐弯抹角是为了解决啥问题，有啥优势等等。&lt;/p&gt;
&lt;p&gt;超长假期学到的一点点东西总算记录了下来，希望不会那么快地忘掉。现在已经开学一两周了，接下来的一两年可能才是艰难险阻的开始，祈祷好运吧……&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Dimensional_analysis&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Dimensional_analysis&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.rust-lang.org/2021/02/26/const-generics-mvp-beta.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://blog.rust-lang.org/2021/02/26/const-generics-mvp-beta.html&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://play.rust-lang.org/?version=nightly&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=4807be24f1e6493bcc5c7cb86457439c&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://play.rust-lang.org/?version=nightly&amp;mode=debug&amp;edition=2021&amp;gist=4807be24f1e6493bcc5c7cb86457439c&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;John J. Barton 与 Lee R. Nackman 的书 &lt;a href=&#34;https://www.amazon.com/Scientific-Engineering-Introduction-Advanced-Techniques/dp/0201533936&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://www.amazon.com/Scientific-Engineering-Introduction-Advanced-Techniques/dp/0201533936&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Scott Meyers 的文章
&lt;a href=&#34;https://se.inf.ethz.ch/~meyer/publications/OTHERS/scott_meyers/dimensions.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://se.inf.ethz.ch/~meyer/publications/OTHERS/scott_meyers/dimensions.pdf&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
    <item>
      <title>简易 DFT 玩具</title>
      <link>http://ionizing.page/post/simple-dft-toy/</link>
      <pubDate>Sun, 14 Aug 2022 22:13:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/simple-dft-toy/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%90%86%e8%ae%ba%e5%9f%ba%e7%a1%80&#34;&gt;理论基础&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%a8%8b%e5%ba%8f%e5%ae%9e%e7%8e%b0&#34;&gt;程序实现&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#nabla-2-%e7%9a%84%e7%9f%a9%e9%98%b5%e8%a1%a8%e7%a4%ba&#34;&gt;\(\nabla^2\) 的矩阵表示&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8a%bf%e8%83%bd%e7%9a%84%e8%a1%a8%e7%a4%ba&#34;&gt;势能的表示&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%a4%96%e5%9c%ba%e5%8a%bf%e8%83%bd-v-text-ext--mathbf-r&#34;&gt;外场势能 \(v_\text{ext}(\mathbf r)\)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%94%b5%e5%ad%90%e5%af%86%e5%ba%a6-rho--mathbf-r&#34;&gt;电子密度 \(\rho(\mathbf r)\)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%ba%93%e4%bb%91%e5%8a%bf-v-text-ha--mathbf-r&#34;&gt;库仑势 \(v_\text{Ha}(\mathbf r)\)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%ba%a4%e6%8d%a2%e5%85%b3%e8%81%94%e5%8a%bf&#34;&gt;交换关联势&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#hamiltonian-%e7%9a%84%e6%9e%84%e9%80%a0&#34;&gt;Hamiltonian 的构造&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#ks-%e6%96%b9%e7%a8%8b%e7%9a%84%e8%bf%ad%e4%bb%a3%e6%b1%82%e8%a7%a3&#34;&gt;KS 方程的迭代求解&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93%e4%b8%8e%e6%8b%93%e5%b1%95&#34;&gt;总结与拓展&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;一直在用别人写好的 DFT 软件，对软件的运行过程略有兴趣，查阅资料弄懂了一些运行原理并参考了前人的程序后，这次我们来自己写一个 DFT 的玩具～&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;首先感谢一个 GitHub 上的仓库，为本文的代码提供了参考&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;理论基础&#34;&gt;理论基础&lt;/h2&gt;
&lt;p&gt;我们的目标是求解 Kohn-Sham 方程。&lt;/p&gt;
&lt;p&gt;对于 Kohn-Sham 方程，系统的能量包含下面几个部分&lt;/p&gt;
&lt;p&gt;\[
E[\rho] = T_s[\rho] + \int d\mathbf r v_\text{ext}(\mathbf r) \rho(\mathbf r) + E_\text{Ha} [\rho] + E_\text{xc}[\rho]
\]&lt;/p&gt;
&lt;p&gt;其中 \(T_s\) 是 Kohm-Sham 动能项，它的表达形式为&lt;/p&gt;
&lt;p&gt;\[
T_s[\rho] = \sum_{i=1}^{N} \int d\mathbf r \varphi^*(\mathbf r) \left( -\frac{\hbar^2}{2m}
\nabla^2 \right) \varphi_i( r)
\]&lt;/p&gt;
&lt;p&gt;\(v_\text{ext}(\mathbf r)\) 是外场作用在系统所有电子上的势能，这里“外”是指除所研究电子以外，
电子与原子核的相互作用也算在这一项内；&lt;/p&gt;
&lt;p&gt;\(E_\text{H}[\rho]\) 为 Hartree 能，也就是电子-电子的库仑相互作用项&lt;/p&gt;
&lt;p&gt;\[
E_\text{H}[\rho] = \frac{e^2}{8\pi\epsilon} \int d\mathbf r \int d\mathbf{r&#39;} \frac{\rho(\mathbf r)
\rho(\mathbf {r&#39;})}{|\mathbf r - \mathbf{r&#39;}|}
\]&lt;/p&gt;
&lt;p&gt;\(E_\text{xc}[\rho]\) 是交换关联能，这里为了简便处理，只使用 LDA 近似处理交换项，忽略关联项。
在 LDA 近似下&lt;/p&gt;
&lt;p&gt;\[
E_\text{x}^\text{LDA}[\rho] = -\frac 34 (\frac 3\pi)^{1/3} \int \rho^{4/3} d \mathbf r
\]&lt;/p&gt;
&lt;p&gt;上面式子中 \(\rho\) 代表系统的电子密度，它是通过下面方式计算得到：
令一系列正交归一的占据态电子轨道为 \(\varphi_i\)，则体系的电子密度为
\[
\rho(\mathbf r) = \sum_i^N |\varphi_i(\mathbf r)|^2
\]&lt;/p&gt;
&lt;p&gt;上面的式子表示的都是能量，现在将它们对应到 Kohn-Sham 方程的 Hamiltonian 中&lt;/p&gt;
&lt;p&gt;\[
\hat{H}_\text{KS} \Psi = E_\text{KS} \Psi
\]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;显然动能算符是 \(-\frac{\hbar^2}{2m}\nabla^2\)&lt;/li&gt;
&lt;li&gt;外场作用算符为 \(v_\text{ext}(\mathbf r) = \frac{\delta \int d\mathbf r v_\text{ext}(\mathbf r) \rho(\mathbf r)}{\delta \rho}\)&lt;/li&gt;
&lt;li&gt;Hartree 作用算符为 \(v_\text{Ha}(\mathbf r) = \frac{\delta E_\text{Ha}[\rho]}{\delta \rho}
= \frac{e^2 \Delta V}{4\pi \epsilon} \int\frac{\rho(\mathbf r&#39;)}{\sqrt{(\mathbf r - \mathbf r&#39;)^2}} d\mathbf r&#39;\)&lt;/li&gt;
&lt;li&gt;交换项算符为 \(v_\text{x}(\mathbf r) = \frac{\delta E_\text{x}[\rho]}{\delta \rho} = -(\frac 3\pi)^{1/3} \rho^{1/3}\)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;此时 KS 方程和 Hamiltonian 可以展开为&lt;/p&gt;
&lt;p&gt;\[\begin{aligned}
\hat{H}_\text{KS} &amp;amp;={} -\frac{\hbar^2}{2m}\nabla^2 + v(\mathbf r) \\&lt;br&gt;
&amp;amp;={} -\frac{\hbar^2}{2m}\nabla^2 + v_\text{ext}(\mathbf r) +
v_\text{Ha}(\mathbf r) + v_\text{x}(\mathbf r) \\&lt;br&gt;
&amp;amp;={} -\frac{\hbar^2}{2m}\nabla^2 + v_\text{ext}(\mathbf r) +
\frac{e^2}{4\pi \epsilon} \int\frac{\rho(\mathbf r&#39;)}{\sqrt{(\mathbf r - \mathbf r&#39;)^2}} d\mathbf r&#39;
-(\frac 3\pi)^{1/3} \rho^{1/3}
\end{aligned}\]&lt;/p&gt;
&lt;p&gt;将 KS 方程的 Hamiltonian 写成矩阵形式，并对角化，即可得到 KS 轨道 \(\varphi_i\) 和它们对应的能量 \(E_i\) 。&lt;/p&gt;
&lt;h2 id=&#34;程序实现&#34;&gt;程序实现&lt;/h2&gt;
&lt;p&gt;为方便起见，这里依然使用 Julia 来实现，请确保机器上的 Julia 已经装上了 Arpack 和 Plots 库。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LinearAlgebra&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Arpack&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Printf&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PlotlyJS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;同时既然是玩具，这里就在一维的空间里计算电子的波函数。这里用到的大部分基础知识在上篇文章
《使用数值方法求解单电子 Schrodinger 方程》 里都能找到（尤其是一维势箱模型系统的求解部分），
因此下面的介绍会有所简化。&lt;/p&gt;
&lt;p&gt;这里在 \([-5, 5]\) 之间均匀取 200 个格点来表示整个系统所在的空间。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;LinRange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;nabla-2-的矩阵表示&#34;&gt;\(\nabla^2\) 的矩阵表示&lt;/h3&gt;
&lt;p&gt;这个算符的矩阵表示在上一篇博客里已经讲过了，这里不再赘述:&lt;/p&gt;
&lt;p&gt;\[
\frac{d^2}{dx^2} = \frac{1}{\Delta x^2} \begin{bmatrix}
-2 &amp;amp; 1 &amp;amp;   &amp;amp;  &amp;amp;   \newline
1 &amp;amp; -2 &amp;amp; 1 &amp;amp;  &amp;amp;   \newline
&amp;amp; 1 &amp;amp; -2 &amp;amp; \ddots &amp;amp;   \newline
&amp;amp;   &amp;amp; \ddots &amp;amp; \ddots  &amp;amp; 1 \newline
&amp;amp;   &amp;amp;   &amp;amp; 1 &amp;amp; -2
\end{bmatrix}
\]&lt;/p&gt;
&lt;p&gt;写成代码的形式即为&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;∇²&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Tridiagonal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;势能的表示&#34;&gt;势能的表示&lt;/h3&gt;
&lt;p&gt;一般情况下， Hamiltonian 里势能部分的贡献直接体现在对角线上，这里只给出一维形式的势能函数，然后会在所有势能计算好后一并加到 Hamiltonian 里。除此之外，由于取了模型势，电子质量和一些物理常数就直接取为 1 ，比如
\(\frac{e^2}{8\pi\epsilon}\) 和 \(\frac{\hbar^2}{2m_e}\) 等。&lt;/p&gt;
&lt;h4 id=&#34;外场势能-v-text-ext--mathbf-r&#34;&gt;外场势能 \(v_\text{ext}(\mathbf r)\)&lt;/h4&gt;
&lt;p&gt;这里我们选择三个外场模型：无相互作用系统、无限深势阱系统和谐振子系统。&lt;/p&gt;
&lt;!--list-separator--&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一维势箱系统&lt;/p&gt;
&lt;p&gt;在没有周期性边界条件的情况下， \(v_\text{ext}(x) = 0\)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;!--list-separator--&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;无限深势阱系统&lt;/p&gt;
&lt;p&gt;这里的“无限深”也等价于周围的墙壁无限高，即
\[
v_\text{ext}(x) = \begin{cases}
\infty &amp;amp; x &amp;lt; -d \\&lt;br&gt;
0 &amp;amp; -d \le x \le d \\&lt;br&gt;
\infty &amp;amp; x &amp;gt; d
\end{cases}
\]
其中 \(d\) 就是中间势阱宽度，程序中取为 2 。 由于程序中无法直接表示值 \(\infty\) ，因此使用一个非常大的正实数来代替，
这里取 \(1.0\times 10^10\) 这个值。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;n&#34;&gt;V_well&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1e10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;V_well&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!--list-separator--&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;谐振子系统&lt;/p&gt;
&lt;p&gt;谐振子系统的势能是一条抛物线
\[
v_\text{ext}(x) = kx^2
\]&lt;/p&gt;
&lt;p&gt;出于简化的目的，这里 \(k\) 直接取为 1 。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;n&#34;&gt;V_harm&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;以上三种势能函数画出来如下图所示：&lt;/p&gt;

&lt;link rel=&#34;stylesheet&#34; href=&#34;http://ionizing.page/css/hugo-easy-gallery.css&#34; /&gt;
&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;simple-dft-potentials.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;simple-dft-potentials.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;电子密度-rho--mathbf-r&#34;&gt;电子密度 \(\rho(\mathbf r)\)&lt;/h4&gt;
&lt;p&gt;Kohn-Sham 方程中包含电子之间库仑相互作用项（也称作 Hartree 项），和交换关联项，
而这两者都是电子密度的泛函，因此需要计算电子密度函数 \(\rho(\mathbf r)\) ：&lt;/p&gt;
&lt;p&gt;首先应保证每个电子的波函数是正交归一的&lt;/p&gt;
&lt;p&gt;\[
\langle \phi_i | \phi_i \rangle = 1
\]&lt;/p&gt;
&lt;p&gt;然后电子密度函数为&lt;/p&gt;
&lt;p&gt;\[
\rho(x) = \sum_n f_n |\phi(x)|^2
\]&lt;/p&gt;
&lt;p&gt;其中 \(f_n\) 表示第 \(n\) 个能级上的电子占据数，本文的体系目前暂不考虑电子的自旋，故
\(f_n\) 的最大值可达到 2 。&lt;/p&gt;
&lt;p&gt;根据上面公式，可以写出下面的代码&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_density&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;c&#34;&gt;# fn 是长度为 nlevel 的向量，表示电子的占据数函数&lt;/span&gt;
    &lt;span class=&#34;c&#34;&gt;# ψ 是一个 ngrid x nlevel 的矩阵&lt;/span&gt;

    &lt;span class=&#34;c&#34;&gt;# 首先来归一化波函数&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;norms&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dims&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;norms&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;c&#34;&gt;# 求电子密度函数&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dims&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dropdims&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dims&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;我们求解不包含库仑势和交换关联势的 Schrodinger 方程后，求得波函数和电子密度如下图所示&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;simple-dft-psi_rho.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;simple-dft-psi_rho.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;h4 id=&#34;库仑势-v-text-ha--mathbf-r&#34;&gt;库仑势 \(v_\text{Ha}(\mathbf r)\)&lt;/h4&gt;
&lt;p&gt;库仑势的公式为：&lt;/p&gt;
&lt;p&gt;\[
v_\text{Ha}(x) = \frac{e^2 \Delta x}{4\pi \epsilon} \int\frac{\rho(x&#39;)}{\sqrt{(x - x&#39;)^2}} dx&#39;
\]&lt;/p&gt;
&lt;p&gt;在程序实现时，限于积分精度和除零的问题，分母中的 \(\sqrt{(x - x&#39;)^2}\) 需要加上一个小量 \(\varepsilon\)
避免除零的出现&lt;/p&gt;
&lt;p&gt;\[
v_\text{Ha} = \int \frac{n_j \Delta x}{\sqrt{(x - x&#39;)^2 + \varepsilon}} dx&#39;
\]&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_hartree&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1e-1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}}&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;energy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;collect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Iterators&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;flatten&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dims&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;energy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;potential&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id=&#34;交换关联势&#34;&gt;交换关联势&lt;/h4&gt;
&lt;p&gt;首先忽略关联势，使用 LDA 近似，得到交换势为&lt;/p&gt;
&lt;p&gt;\[
v_\text{x}^\text{LDA}[\rho] = -\sqrt[3]{3\rho / \pi}
\]&lt;/p&gt;
&lt;p&gt;那么使用代码表示出来就很简单了：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_exchange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}}&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;energy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;4.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cbrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;π&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;4.0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cbrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;π&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cbrt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;energy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;potential&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;hamiltonian-的构造&#34;&gt;Hamiltonian 的构造&lt;/h3&gt;
&lt;p&gt;上面说到 Hamiltonian 里势能的部分体现在对角线上&lt;/p&gt;
&lt;p&gt;\[\hat{H} = \frac{1}{(\Delta x)^2}
\begin{bmatrix}
-2 &amp;amp; 1 &amp;amp;   &amp;amp;  &amp;amp;   \newline
1 &amp;amp; -2 &amp;amp; 1 &amp;amp;  &amp;amp;   \newline
&amp;amp; 1 &amp;amp; -2 &amp;amp; \ddots &amp;amp;   \newline
&amp;amp;   &amp;amp; \ddots &amp;amp; \ddots  &amp;amp; 1 \newline
&amp;amp;   &amp;amp;   &amp;amp; 1 &amp;amp; -2
\end{bmatrix} +
\begin{bmatrix}
V_1 &amp;amp; &amp;amp; &amp;amp; \newline
&amp;amp; V_2 &amp;amp; &amp;amp; \newline
&amp;amp; &amp;amp; \ddots &amp;amp; \newline
&amp;amp; &amp;amp; &amp;amp; V_n
\end{bmatrix} \]&lt;/p&gt;
&lt;p&gt;用代码写出来&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_hamiltonian&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
                         &lt;span class=&#34;n&#34;&gt;v_ext&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ex_energy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ex_potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_exchange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ha_energy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ha_potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_hartree&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;∇²&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Tridiagonal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;c&#34;&gt;# Hamiltonian&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;H&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;∇²&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;./&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Diagonal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ex_potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ha_potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;v_ext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对这个 Hamiltonian 对角化，可以得到一系列波函数 \(\phi_i(x)\) 。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;n&#34;&gt;E&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eigs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nlevel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;which&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;:LM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sigma&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;# 这个函数需要 using Arpack&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;ks-方程的迭代求解&#34;&gt;KS 方程的迭代求解&lt;/h3&gt;
&lt;p&gt;电子密度 \(\rho(x)\) 依赖于波函数 \(\phi_i(x)\) ，而求解 \(\phi_i(x)\) 所用的 Hamiltonian 又反过来依赖于 \(\rho(x)\) ，
这意味着我们不能一次性求得正确的波函数 \(\phi_i(x)\) ， 因此我们需要用迭代的方法来求解：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先猜一个初始电荷密度 \(\rho(x)\) ；&lt;/li&gt;
&lt;li&gt;用 \(\rho(x)\) 构造 Hartree 势和交换关联势，然后构造 Hamiltonian ；&lt;/li&gt;
&lt;li&gt;对角化 Hamiltonian 求得本征值 \(E_i\) 和波函数 \(\phi_i(x)\) ；&lt;/li&gt;
&lt;li&gt;判断此次求得本征值 \(E_i\) 与上一次结果相差是否足够小，如果是，则停止计算，否则进入第 5 步；&lt;/li&gt;
&lt;li&gt;使用波函数 \(\phi_i(x)\) 构造电子密度 \(\rho(x)\) ，并返回第 2 步。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;上面的过程也叫做自洽迭代(self-consistency loop)。&lt;/p&gt;
&lt;p&gt;到这一步，我们把所有代码整合起来运行一下，便能得到一个简易的 DFT 玩具&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;  1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 89
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 90
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 91
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 92
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 93
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 94
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 95
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 96
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 97
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 98
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 99
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;100
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;101
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;102
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;103
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;104
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;c&#34;&gt;#!/usr/bin/env julia&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LinearAlgebra&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Arpack&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Formatting&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Plots&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Some functions&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_density&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;c&#34;&gt;# fn 是长度为 nlevel 的向量，表示电子的占据数函数&lt;/span&gt;
    &lt;span class=&#34;c&#34;&gt;# ψ 是一个 ngrid x nlevel 的矩阵&lt;/span&gt;

    &lt;span class=&#34;c&#34;&gt;# 首先来归一化波函数&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;norms&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dims&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;norms&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;c&#34;&gt;# 求电子密度函数&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dims&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dropdims&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dims&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_hartree&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1e-1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}}&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;energy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;collect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Iterators&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;flatten&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dims&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;energy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;potential&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_exchange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}}&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;energy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;4.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cbrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;π&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;4.0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cbrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;π&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cbrt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;energy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;potential&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_hamiltonian&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
                         &lt;span class=&#34;n&#34;&gt;v_ext&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;Float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ex_energy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ex_potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_exchange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ha_energy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ha_potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_hartree&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;∇²&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Tridiagonal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;c&#34;&gt;# Hamiltonian&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;H&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;∇²&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;./&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Diagonal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ex_potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ha_potential&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;v_ext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;abspath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;PROGRAM_FILE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;nd&#34;&gt;@__FILE__&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;nlevel&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;nelect&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;17&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;collect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;LinRange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;∇²&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Tridiagonal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ones&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;c&#34;&gt;# V_ext&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;V_empty&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;zeros&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;V_well&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1e10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ngrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;nd&#34;&gt;@.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;V_well&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;V_harm&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;

    &lt;span class=&#34;c&#34;&gt;# construct fn&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;zeros&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nlevel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nelect÷2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nelect&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nelect÷2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;max_iter&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;E_threshold&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1E-5&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;log0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;E&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;ΔE&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;# Use `log0` instead of `log` to avoid confict&lt;/span&gt;

    &lt;span class=&#34;c&#34;&gt;# 使用自由电子的波函数做为初始猜测的电子波函数，可以加速收敛&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;E&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eigs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;∇²&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;./&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nlevel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;which&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;:LM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sigma&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_density&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_iter&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;H&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_hamiltonian&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;V_harm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

        &lt;span class=&#34;n&#34;&gt;E0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eigs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nlevel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;which&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;:LM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sigma&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;E&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;E0&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ0&lt;/span&gt;

        &lt;span class=&#34;n&#34;&gt;E_tot&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;E&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;# 求占据态电子能量之和&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;ΔE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;E_tot&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;log0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;E&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;push!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;log0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;E&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;E_tot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;push!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;log0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;ΔE&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ΔE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;printfmtln&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;step: {:5d} E: {:10.4f} ΔE {:14.10f}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;log0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;E&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;log0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;ΔE&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;

        &lt;span class=&#34;c&#34;&gt;# 判断基能量是否收敛&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;abs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ΔE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;E_threshold&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;converged!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

        &lt;span class=&#34;c&#34;&gt;# 更新电子密度&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;ρ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_density&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Δx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sprintf1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%.3f&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;E&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;ψ&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它运行时会出现下面的日志输出（以 \(V_\text{ext} = V_\text{empty}\) 为例）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;step:     1 E:   191.3250 ΔE           -Inf
step:     2 E:   188.6149 ΔE  -2.7101725428
step:     3 E:   189.9835 ΔE   1.3686497726
step:     4 E:   189.2422 ΔE  -0.7413493772
step:     5 E:   189.7313 ΔE   0.4891692181
step:     6 E:   189.4190 ΔE  -0.3123247101
step:     7 E:   189.6381 ΔE   0.2191170430
step:     8 E:   189.4893 ΔE  -0.1488193569
step:     9 E:   189.5950 ΔE   0.1057145189
step:    10 E:   189.5214 ΔE  -0.0735956265
step:    11 E:   189.5738 ΔE   0.0523625987
step:    12 E:   189.5369 ΔE  -0.0368426628
step:    13 E:   189.5631 ΔE   0.0262003363
step:    14 E:   189.5446 ΔE  -0.0185224236
step:    15 E:   189.5578 ΔE   0.0131633325
step:    16 E:   189.5484 ΔE  -0.0093260810
step:    17 E:   189.5551 ΔE   0.0066245797
step:    18 E:   189.5504 ΔE  -0.0046981797
step:    19 E:   189.5537 ΔE   0.0033362576
step:    20 E:   189.5513 ΔE  -0.0023672119
step:    21 E:   189.5530 ΔE   0.0016807098
step:    22 E:   189.5518 ΔE  -0.0011928024
step:    23 E:   189.5527 ΔE   0.0008468043
step:    24 E:   189.5521 ΔE  -0.0006010437
step:    25 E:   189.5525 ΔE   0.0004266762
step:    26 E:   189.5522 ΔE  -0.0003028617
step:    27 E:   189.5524 ΔE   0.0002149933
step:    28 E:   189.5523 ΔE  -0.0001526097
step:    29 E:   189.5524 ΔE   0.0001083320
step:    30 E:   189.5523 ΔE  -0.0000768987
step:    31 E:   189.5523 ΔE   0.0000545872
step:    32 E:   189.5523 ΔE  -0.0000387486
step:    33 E:   189.5523 ΔE   0.0000275059
step:    34 E:   189.5523 ΔE  -0.0000195251
step:    35 E:   189.5523 ΔE   0.0000138599
step:    36 E:   189.5523 ΔE  -0.0000098385
converged!
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;和前面一样，把波函数和电子密度函数画出来，如下图所示：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;simple-dft-psi_rho_dft.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;simple-dft-psi_rho_dft.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;下面以 \(V_\text{empty}\) 为例，对比一下原来的波函数与 DFT 方法算出的 KS 波函数的变化：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;simple-dft-psi_org_dft.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;simple-dft-psi_org_dft.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;可以看到， KS 波函数的空间分布与原来无相互作用波函数空间分布差别很大， KS 波函数的波包的顶点都发生了偏移，说明库仑相互作用和交换相互作用影响较大。例如 \(\psi_1\) ，无相互作用体系里波函数分布最大的地方在 \(x=0\) 处，但 KS 波函数里空间分布最大的地方在 \(x=\pm 4.2\) 处左右，表明其它能级更高的电子对它的分布也产生了显著的影响。除此之外，波函数的本征值也变化巨大。实际上这里的对比不太严谨：原来无相互作用体系的波函数是一个电子在不同能级的波函数，而 KS 波函数则被当成是一个含有 N 个电子的体系里每个电子的波函数，这两者概念上的差异不能忽略。&lt;/p&gt;
&lt;p&gt;需要注意的是，尽管我们习惯用 KS 轨道表示真实体系里每个电子的轨道，但 KS 轨道实质上仍是单粒子
Schrodinger 方程的解，它能否代替体系真实的波函数仍需要 check ，本人不认为这两者等价。比如在
Ren Xinguo 老师的课件&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
里是这样描述的&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;KS orbitals are auxiliary variables, and have no strict physical meaning (except for HOMO and LUMO).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;即除了 HOMO 和 LUMO 之外， KS 波函数仅仅作为计算电子密度函数 \(\rho(\text r)\) 的辅助函数之用。
HOMO 和 LUMO 在一定程度上可以视作体系的真实轨道，此时体系的第一电离能即为 HOMO 的能量（Janak theorem, 1978）：&lt;/p&gt;
&lt;p&gt;\[
I = E_0(N-1) - E_0(N) = -\epsilon_N
\]&lt;/p&gt;
&lt;p&gt;下面来看一下电子密度函数的变化：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;simple-dft-rho_org_dft.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;simple-dft-rho_org_dft.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;很明显，经过自洽迭代后，体系的电子密度分布也发生了变化，对比占据态轨道的变化而言，电子密度的变化还是比较小的。&lt;/p&gt;
&lt;p&gt;如果考虑电子的自旋，我们需要修改交换关联泛函，即使用考虑电子自旋的 LSDA 泛函，此时体系的波函数表示也需要随之修改， \(\psi_i(x)\) 变为 \(\psi_i(x, \sigma)\) ，即增加了一个自旋维度 \(\sigma\) 。
具体的泛函形式比较复杂，这里作为一个 toy 介绍就不展开了，如果有兴趣可以去看 &lt;a href=&#34;http://lqcc.ustc.edu.cn/renxg/plus/list.php?tid=7&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Ren Xinguo 老师的课件&lt;/a&gt;
。&lt;/p&gt;
&lt;h2 id=&#34;总结与拓展&#34;&gt;总结与拓展&lt;/h2&gt;
&lt;p&gt;我们实现了一个简单的 DFT 计算程序，它可以使用自定义的外场势能函数，考虑 Hartree 势，并使用 LDA 近似。
通过求解 KS 方程，我们得到了 KS 波函数，并与无相互作用体系的波函数作对比，发现波函数的分布发生了显著的变化，同时波函数的能量也发生了不小的变化。在实现的过程中，本人对那句“通过 DFT 将多体系统映射到单粒子系统”
可能有了一些很浅薄的理解。&lt;/p&gt;
&lt;p&gt;尽管这是一个很简单的 toy ，但它也是包含了 DFT 计算所需的各种常见操作，比如构造电子密度函数，比如自洽迭代求解 KS 方程，再比如求 Hartree 势函数、使用 LDA 近似等等，这些都可以在常见的 DFT 软件里找到，那么此次 DIY 的过程也能加强对其它成熟 DFT 软件里运行时做了什么有了大概了理解。如果有人想要进一步拓展这个 toy ，我想到了以下几个方向：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;考虑上下自旋，使用 LSDA 近似&lt;/li&gt;
&lt;li&gt;使用 GGA 泛函（比如 PBE 泛函）&lt;/li&gt;
&lt;li&gt;考虑外加电场，这个比较好办，直接在修改外场势函数即可&lt;/li&gt;
&lt;li&gt;考虑外加磁场，这个需要修改 Hamiltonian 中的动能项表达式，添加矢势项&lt;/li&gt;
&lt;li&gt;考虑相对论效应，使用 Dirac 方程代替 Schrodinger 方程，看是否能算出自旋轨道耦合效应&lt;/li&gt;
&lt;li&gt;&amp;hellip;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;出于精力限制，本人可能没动力继续往下扩展，读者如果有兴趣，可以自行尝试。&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;tamuhey 的代码 &lt;a href=&#34;https://github.com/tamuhey/python_1d_dft&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://github.com/tamuhey/python_1d_dft&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;任老师的课件 &lt;a href=&#34;http://lqcc.ustc.edu.cn/renxg/plus/list.php?tid=7&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;http://lqcc.ustc.edu.cn/renxg/plus/list.php?tid=7&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
    <item>
      <title>使用数值方法求解单电子 Schrodinger 方程</title>
      <link>http://ionizing.page/post/schrodinger-equation-numerical-methods/</link>
      <pubDate>Fri, 06 Aug 2021 14:44:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/schrodinger-equation-numerical-methods/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8d%95%e7%b2%92%e5%ad%90%e5%ae%9a%e6%80%81-schrodinger-%e6%96%b9%e7%a8%8b&#34;&gt;单粒子定态 Schrodinger 方程&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%9c%89%e9%99%90%e5%b7%ae%e5%88%86%e6%b3%95&#34;&gt;有限差分法&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%b8%80%e9%98%b6%e5%af%bc%e6%95%b0%e7%9a%84%e7%a6%bb%e6%95%a3%e5%8c%96&#34;&gt;一阶导数的离散化&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%ba%8c%e9%98%b6%e5%af%bc%e6%95%b0%e7%9a%84%e7%a6%bb%e6%95%a3%e5%8c%96&#34;&gt;二阶导数的离散化&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%b8%80%e7%bb%b4%e7%b3%bb%e7%bb%9f-hamiltonian-%e7%9a%84%e6%9e%84%e9%80%a0%e5%8f%8a%e6%b1%82%e8%a7%a3&#34;&gt;一维系统 Hamiltonian 的构造及求解&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%b8%80%e7%bb%b4%e5%8a%bf%e7%ae%b1%e6%a8%a1%e5%9e%8b%e7%b3%bb%e7%bb%9f%e7%9a%84%e6%b1%82%e8%a7%a3&#34;&gt;一维势箱模型系统的求解&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%b8%a6%e6%9c%89-chulkov-%e5%8a%bf%e7%9a%84%e4%b8%80%e7%bb%b4%e5%8a%bf%e7%ae%b1%e7%b3%bb%e7%bb%9f%e6%b1%82%e8%a7%a3&#34;&gt;带有 Chulkov 势的一维势箱系统求解&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%ba%8c%e7%bb%b4%e5%8f%8a%e6%9b%b4%e9%ab%98%e7%bb%b4%e7%b3%bb%e7%bb%9f%e7%9a%84-hamiltonian-%e6%9e%84%e9%80%a0%e4%b8%8e%e6%b1%82%e8%a7%a3&#34;&gt;二维及更高维系统的 Hamiltonian 构造与求解&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%ab%98%e7%bb%b4-laplacian-%e7%9a%84%e7%a6%bb%e6%95%a3%e5%8c%96&#34;&gt;高维 Laplacian 的离散化&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%ab%98%e7%bb%b4-hamiltonian-%e7%9a%84%e6%9e%84%e9%80%a0%e4%b8%8e%e6%b1%82%e8%a7%a3&#34;&gt;高维 Hamiltonian 的构造与求解&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%9c%89%e9%99%90%e5%85%83%e6%b3%95&#34;&gt;有限元法&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%ae%9a%e6%80%81-schrodinger-%e6%96%b9%e7%a8%8b%e7%9a%84%e5%8f%98%e5%88%86%e5%bc%b1%e8%a7%a3%e5%bd%a2%e5%bc%8f&#34;&gt;定态 Schrodinger 方程的变分弱解形式&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%a8%8b%e5%ba%8f%e5%ae%9e%e7%8e%b0%e5%8f%8a%e7%bb%93%e6%9e%9c%e9%aa%8c%e8%af%81&#34;&gt;程序实现及结果验证&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93%e5%8f%8a%e5%90%90%e6%a7%bd&#34;&gt;总结及吐槽&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%90%90%e6%a7%bd&#34;&gt;吐槽&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;经常有人觉得会解薛定谔方程会给人一种很厉害的感觉（尤其是对还没学过 QM QC 等课程中学生小朋友而言），
确实，现在能写出解析解的 Schrodinger 方程屈指可数；
而且仅仅增加粒子数量不考虑各种修正就足以使求解的难度上升一大截。
不过在这里我们不考虑多个粒子的情况，也不考虑什么相对论效应 blabla ，
我们只考虑一个电子在一个任意势场下的定态 Schrodinger 方程，
然后来用数值方法求解这个方程，得到电子的波函数并可视化，
顺便验证一下教材上各种电子轨道的分布图，体验一把亲手解 Schrodinger 方程的感觉。&lt;/p&gt;
&lt;p&gt;这里本文是在实空间的笛卡尔坐标系进行求解。&lt;/p&gt;
&lt;h2 id=&#34;单粒子定态-schrodinger-方程&#34;&gt;单粒子定态 Schrodinger 方程&lt;/h2&gt;
&lt;p&gt;考虑一个电子在势场 \(V\) 中，它的定态 Schrodinger 方程是&lt;/p&gt;
&lt;p&gt;\begin{equation}
\hat{H} \Psi(x, y, z) = E\Psi(x, y, z)
\end{equation}&lt;/p&gt;
&lt;p&gt;如果这个势场是 \(V = 0\) ，并且限定这个电子在一个边长为 \(a\) 的箱子内，此时 Schrodinger 方程就变成了&lt;/p&gt;
&lt;p&gt;\begin{equation}
-\frac{\hbar^2}{2m} \left( \frac{\partial^2}{\partial x^2} +
\frac{\partial^2}{\partial y^2} +
\frac{\partial^2}{\partial z^2} \right)
\Psi(x, y, z) = E\Psi(x, y, z)
\end{equation}&lt;/p&gt;
&lt;p&gt;这个方程可以写出解析解&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
（参加过考试的同学应该能默写这个公式了）：&lt;/p&gt;
&lt;p&gt;\[E = (n_x^2 + n_y^2 + n_z^2) \frac{h^2}{8ma^2}\]&lt;/p&gt;
&lt;p&gt;\[ \begin{aligned}
\Psi(x, y, z) &amp;amp;={} X(x)Y(y)Z(z) \newline
&amp;amp;={} \sqrt{\frac{8}{a^3}}\sin(\frac{n_x \pi x}{a})\sin(\frac{n_y \pi y}{a})\sin(\frac{n_z \pi z}{a})
\end{aligned} \]&lt;/p&gt;
&lt;p&gt;这是三维情况下的解，如果体系只有一维，它的能级表达式是&lt;/p&gt;
&lt;p&gt;\[
E = \frac{n^2 h^2}{8ma^2} \newline
\Psi(x) = \sqrt{\frac{2}{a}} \sin(\frac{n \pi x}{a})
\]&lt;/p&gt;
&lt;p&gt;这是它们的解析解，也是我们后面验证结果正确性的参考。
以上结果的推导请参考任意一本《量子力学》或《量子化学》或者《结构化学》。&lt;/p&gt;
&lt;h2 id=&#34;有限差分法&#34;&gt;有限差分法&lt;/h2&gt;
&lt;p&gt;所谓有限差分法，就是有限差分来近似导数，从而寻求微分方程近似解的方法。针对导数的有限差分操作可以参考 &lt;a href=&#34;https://en.wikipedia.org/wiki/Finite_difference_coefficient&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Wikipedia&lt;/a&gt;
 &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;，
简单来说就是用各种近似方法来逼近导数的值。&lt;/p&gt;
&lt;p&gt;假设存在一个离散的函数 \(f(x), x = x_1, x_2, &amp;hellip; , x_n\) ，并且 \(x_{i+1} - x_{i} = \Delta x\) 为一定值，
根据有限差分的推导，可以得到下面的结论：&lt;/p&gt;
&lt;h3 id=&#34;一阶导数的离散化&#34;&gt;一阶导数的离散化&lt;/h3&gt;
&lt;p&gt;这里使用一种最为常见的离散化方法来近似一阶导数：&lt;/p&gt;
&lt;p&gt;\begin{equation}
f&#39;(x_i) \approx \frac{f(x_i+\Delta x) - f(x_i - \Delta x)}{2\Delta x}
= \frac{f(x_{i+1}) - f(x_{i-1})}{2\Delta x}
\end{equation}&lt;/p&gt;
&lt;p&gt;再假设 \(f(x)\) 可以写成一个列向量 \(\ket{f} = \begin{bmatrix} f(x_1), f(x_2),
\cdots, f(x_n) \end{bmatrix}^T\) ，那么一阶导数算符 \(\dfrac{d}{dx}\) 可以写成&lt;/p&gt;
&lt;p&gt;\[\frac{d}{dx}
\begin{bmatrix} f(x_1)\newline f(x_2) \newline \vdots \newline f(x_n) \end{bmatrix} =
\frac{1}{2\Delta x}
\begin{bmatrix}
0 &amp;amp; 1 &amp;amp;   &amp;amp;  &amp;amp;   \newline
-1 &amp;amp; 0 &amp;amp; 1 &amp;amp;  &amp;amp;   \newline
&amp;amp; -1 &amp;amp; 0 &amp;amp; \ddots &amp;amp;   \newline
&amp;amp;   &amp;amp; \ddots &amp;amp; \ddots  &amp;amp; 1 \newline
&amp;amp;   &amp;amp;   &amp;amp; -1 &amp;amp; 0
\end{bmatrix} \cdot
\begin{bmatrix} f(x_1)\newline f(x_2) \newline \vdots \newline f(x_n) \end{bmatrix} \]&lt;/p&gt;
&lt;p&gt;这是在没有处理边界条件的情况下的一阶导数算符，
如果考虑周期性边界条件，上式矩阵的左下角和右上角分别为 1 和 -1  。
此外这种方法近似得到的一阶导的精度是 \(O((\Delta x)^2)\) ，
更高阶的近似及其它非对称的方法请参考本节之前提到的 Wikipedia 。&lt;/p&gt;
&lt;h3 id=&#34;二阶导数的离散化&#34;&gt;二阶导数的离散化&lt;/h3&gt;
&lt;p&gt;比较常见的二阶导数离散化方法如下：&lt;/p&gt;
&lt;p&gt;\begin{equation}\begin{aligned}
f&#39;(x_i+\frac{1}{2} \Delta x) &amp;amp;\approx{} \frac{f(x_i + \Delta x) - f(x_i)}{\Delta x}
= \frac{f(x_{i+1}) - f(x_i)}{\Delta x} \newline
f&#39;(x_i-\frac{1}{2} \Delta x) &amp;amp;\approx{} \frac{f(x_i) - f(x_i - \Delta x)}{\Delta x}
= \frac{f(x_i) - f(x_{i-1})}{\Delta x} \newline
f&#39;&#39;(x_i) &amp;amp;\approx{} \frac{ f&#39;(x_i+\frac{1}{2} \Delta x) - f&#39;(x_i-\frac{1}{2} \Delta x) }{\Delta x} \newline
&amp;amp;={} \frac{ f(x_{i+1}) + f(x_{i-1}) - 2f(x_i) }{(\Delta x)^2}
\end{aligned}\end{equation}&lt;/p&gt;
&lt;p&gt;同样，它也可以用矩阵的形式表达出来：&lt;/p&gt;
&lt;p&gt;\[ \frac{d^2}{dx^2}
\begin{bmatrix} f(x_1)\newline f(x_2) \newline \vdots \newline f(x_n) \end{bmatrix} =
\frac{1}{(\Delta x)^2}
\begin{bmatrix}
-2 &amp;amp; 1 &amp;amp;   &amp;amp;  &amp;amp;   \newline
1 &amp;amp; -2 &amp;amp; 1 &amp;amp;  &amp;amp;   \newline
&amp;amp; 1 &amp;amp; -2 &amp;amp; \ddots &amp;amp;   \newline
&amp;amp;   &amp;amp; \ddots &amp;amp; \ddots  &amp;amp; 1 \newline
&amp;amp;   &amp;amp;   &amp;amp; 1 &amp;amp; -2
\end{bmatrix} \cdot
\begin{bmatrix} f(x_1)\newline f(x_2) \newline \vdots \newline f(x_n) \end{bmatrix} \]&lt;/p&gt;
&lt;p&gt;如果需要考虑周期性边界条件，矩阵的左下角和右上角都应为 1 。
这种方法近似的精度是 \(O((\Delta x)^2)\) 。&lt;/p&gt;
&lt;h3 id=&#34;一维系统-hamiltonian-的构造及求解&#34;&gt;一维系统 Hamiltonian 的构造及求解&lt;/h3&gt;
&lt;h4 id=&#34;一维势箱模型系统的求解&#34;&gt;一维势箱模型系统的求解&lt;/h4&gt;
&lt;p&gt;Hamiltonian 的整体表达式为&lt;/p&gt;
&lt;p&gt;\[ H = T + V \]&lt;/p&gt;
&lt;p&gt;如果系统只有一维，那么 Hamiltonian 很好构造，直接在 \(T\) 的基础上加上势能即可&lt;/p&gt;
&lt;p&gt;\[H = \frac{1}{(\Delta x)^2}
\begin{bmatrix}
-2 &amp;amp; 1 &amp;amp;   &amp;amp;  &amp;amp;   \newline
1 &amp;amp; -2 &amp;amp; 1 &amp;amp;  &amp;amp;   \newline
&amp;amp; 1 &amp;amp; -2 &amp;amp; \ddots &amp;amp;   \newline
&amp;amp;   &amp;amp; \ddots &amp;amp; \ddots  &amp;amp; 1 \newline
&amp;amp;   &amp;amp;   &amp;amp; 1 &amp;amp; -2
\end{bmatrix} +
\begin{bmatrix}
V_1 &amp;amp; &amp;amp; &amp;amp; \newline
&amp;amp; V_2 &amp;amp; &amp;amp; \newline
&amp;amp; &amp;amp; \ddots &amp;amp; \newline
&amp;amp; &amp;amp; &amp;amp; V_n
\end{bmatrix} \]&lt;/p&gt;
&lt;p&gt;然后我们的问题就变成了&lt;/p&gt;
&lt;p&gt;\[
H \ket{\psi} = E\ket{\psi}
\]&lt;/p&gt;
&lt;p&gt;这是一个典型的本征值问题，只要对 \(H\) 进行对角化就可以得到我们想到的能量 \(E\) 和波函数 \(\ket{\psi}\) 。
下面是它的程序实现（本文使用 Julia 作为有限差分法的实现语言）&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;c&#34;&gt;#!/usr/bin/env julia&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LinearAlgebra&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SparseArrays&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Arpack&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Plots&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                           Constants Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;                 &lt;span class=&#34;c&#34;&gt;# sample points&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;                &lt;span class=&#34;c&#34;&gt;# box length&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8099821161548593&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;c&#34;&gt;# hbar^2 / (2*m_e) = (Å^2) / eV&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;                  &lt;span class=&#34;c&#34;&gt;# relative mass of electron&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;                  &lt;span class=&#34;c&#34;&gt;# number of eigen values to be covered&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;LinRange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                           Hamiltonian Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deepcopy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Hamiltonian constructed, start solving ...&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@time&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;λ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eigs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;which&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;:LM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sigma&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@show&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;λ&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                           Hamiltonian Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;norm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c&#34;&gt;# Normalization&lt;/span&gt;
    &lt;span class=&#34;nd&#34;&gt;@assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;≈&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;    &lt;span class=&#34;c&#34;&gt;# verify the norm: ∫ |ϕ|² dx == 1&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

&lt;span class=&#34;nd&#34;&gt;@show&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;maximum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;layout&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;800&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;savefig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;./1D-particle-in-a-box-eigvec.svg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;Hamiltonian ready, start solving ...
  1.991257 seconds (7.25 M allocations: 439.625 MiB, 8.56% gc time, 99.53% compilation time)
λ = [37.58797833051402, 150.3518984879221, 338.29171597315013, 601.4073566198176]
maximum(ϕ[:, 1]) = 1.4140720924720651
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;下面我们来验证一下程序的结果：&lt;/p&gt;
&lt;p&gt;程序中有 \(k = \hbar^2 / 2m_e = 3.80998 (\mathrm{Å^2/eV})\) ，它把一些物理常数打包处理并化为原子单位制，
因此在和解析解对比时也要以此为准，此外程序中定义 \(a=1Å\) ，没有显式处理边界条件。势箱模型中解析解为&lt;/p&gt;
&lt;p&gt;\[
E = \frac{n^2 h^2}{8ma^2} = \frac{\hbar^2}{2m} \cdot \frac{4\pi^2 n^2}{4a^2} = \frac{kn^2\pi^2}{a^2}
\]&lt;/p&gt;
&lt;p&gt;代入 \(k\) 和 \(a\) ，得到 \(E_1 = 37.6029953761\) ，与数值解 \(\lambda_1=37.58797833051402\) 对比相当接近，
继续验证 \(\lambda_2\) 、 \(\lambda_3\) 等可以发现它们也符合 \(n^2\) 的增长曲线（读者可自行验证）。&lt;/p&gt;
&lt;p&gt;再来验证一下波函数：
&lt;img src=&#34;1D-particle-in-a-box-eigvec.svg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;它显然符合正弦曲线的特征，并且在边界处为 0 ，最大值为 1.414072 与归一化因子 \(\sqrt{2} = 1.414213\)
相差也在允许范围内，因此现在可以放心地说，如果 \(T\) 没有特殊边界条件处理，
它的边界条件就是使边界处的波函数为 0 ，这在后面的计算中可以得到进一步验证。&lt;/p&gt;
&lt;h4 id=&#34;带有-chulkov-势的一维势箱系统求解&#34;&gt;带有 Chulkov 势的一维势箱系统求解&lt;/h4&gt;
&lt;p&gt;上面的系统中电子不受束缚， Hamiltonian 里没有势能这一项，这也就没有验证势能项加在对角线上的合理性，
下面我们使用一种于二十年前被提出的势能函数来验证这一点。&lt;/p&gt;
&lt;p&gt;Chulkov &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;
等于 1997 年提出一种势能用于模拟出金属表面的镜像态。它以金属表面为 0 点， 0 以下使用正弦函数模拟金属的体相内的势能， 0 及以上使用正弦及指数函数等模拟金属表面以外的镜像势，它有如下形式：&lt;/p&gt;
&lt;p&gt;\[
V_m(z) = \begin{cases}
-A_{10} + A_1 \cos \left( \frac{2\pi}{d_m} z \right) &amp;amp; z \le 0 \newline
-A_{20} + A_2 \cos(\beta z) &amp;amp; 0 &amp;lt; z \le z_1 \newline
-A_3 \exp\left[-\alpha(z-z_1)\right]  &amp;amp; z_1 &amp;lt; z \le z_\mathrm{im} \newline
\dfrac{\exp\left[ -\lambda (z-z_\mathrm{im}) \right]-1}{4(z-z_\mathrm{im})} &amp;amp; z &amp;gt; z_\mathrm{im}
\end{cases}
\]&lt;/p&gt;
&lt;p&gt;体现在图像上是这个样子的：&lt;/p&gt;

&lt;link rel=&#34;stylesheet&#34; href=&#34;http://ionizing.page/css/hugo-easy-gallery.css&#34; /&gt;
&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;1D-chulkov-pot.png&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;1D-chulkov-pot.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;这里选择用于 Ag(111) 表面的各参数，代码如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;89
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;90
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;91
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;92
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;93
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;c&#34;&gt;#!/usr/bin/env julia&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Reference: Image potential states on metal surfaces: binding energies and wave functions&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#             https://www.sciencedirect.com/science/article/pii/S0039602899006688&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LinearAlgebra&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SparseArrays&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Arpack&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Plots&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;15000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;150.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8099821161548593&lt;/span&gt;    &lt;span class=&#34;c&#34;&gt;# hbar^2 / (2*m_e) /(Å^2) / eV&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k_c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;14.39964547842567&lt;/span&gt;   &lt;span class=&#34;c&#34;&gt;# (e*e / (4 * np.pi * epsilon_0))  # measured in eV / Å&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;                   &lt;span class=&#34;c&#34;&gt;# mass of electron&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                                Potential Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;cm&#34;&gt;#=
&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;#
&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;# V1(z) = -A10 + A1*cos(2pi*z/dm)    z &amp;lt;= 0
&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;# V2(z) = -A20 + A2*cos(beta*z)      0 &amp;lt; z &amp;lt;= z1
&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;# V3(z) = -A3 * exp(-alpha*(z-z1))   z1 &amp;lt; z &amp;lt;= zim
&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;# V4(z) = (exp(-lambda*(z-zim))-1.0) / (4.0*(z-zim))  z &amp;gt; zim
&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;#
&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;=#&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.529&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# A, bohr raidus&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;4.43&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# a.u.&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A10&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;9.64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# eV&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;4.30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# eV&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8442&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# eV&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;beta0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;2.5649&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# 1/a.u.&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;zim0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;2.35&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# a.u.&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dm&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# A&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A20&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A10&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# eV&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;beta&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;beta0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# A^-1&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;zim&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;zim0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# A&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;# const A3 = A2 / sqrt(2); # eV&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;pi&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# A&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A20&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# eV&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beta&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# A^-1&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;A3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zim&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k_c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# A^-1&lt;/span&gt;

&lt;span class=&#34;nd&#34;&gt;@show&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A10&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A1&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dm&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A20&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A2&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;beta&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A3&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z1&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;zim&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;LinRange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;similar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;nd&#34;&gt;@.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;A10&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;pi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;A20&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beta&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;zim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;4.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;zim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k_c&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                           Hamiltonian Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;Ident&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deepcopy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Vmin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;λ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eigs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;which&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;:LM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sigma&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Vmin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@show&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;λ&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;norm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;      &lt;span class=&#34;c&#34;&gt;# normalization&lt;/span&gt;
    &lt;span class=&#34;nd&#34;&gt;@assert&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;≈&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;      &lt;span class=&#34;c&#34;&gt;# test norm&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;layout&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;800&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;savefig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;./1D-chulkov-eigvec.svg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;下面是计算结果与文献值对比&lt;/p&gt;
&lt;div class=&#34;table-caption&#34;&gt;
  &lt;span class=&#34;table-number&#34;&gt;Table 1:&lt;/span&gt;
  有限差分法计算 Chulkov 势结果与文献值对比
&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;λ&lt;/th&gt;
&lt;th&gt;计算结果(eV)&lt;/th&gt;
&lt;th&gt;文献值(eV)&lt;/th&gt;
&lt;th&gt;实验值(eV)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-0.788&lt;/td&gt;
&lt;td&gt;−0.77&lt;/td&gt;
&lt;td&gt;-0.77&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;-0.674&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-0.533&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;-0.330&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;-0.208&lt;/td&gt;
&lt;td&gt;-0.22&lt;/td&gt;
&lt;td&gt;-0.23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;-0.103&lt;/td&gt;
&lt;td&gt;-0.095&lt;/td&gt;
&lt;td&gt;-0.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;-0.061&lt;/td&gt;
&lt;td&gt;-0.053&lt;/td&gt;
&lt;td&gt;-0.052&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;-0.031&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;上面表中有一些态主要分布在体相内，文献和实验中没有测到。为更明显地对比镜像态与 bulk 态的区别，
这里使用 \(|\phi|^2\) 作图：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;1D-chulkov-eigvec.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;1D-chulkov-eigvec.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;显然， \(\phi_2\) 、 \(\phi_3\) 和 \(\phi_4\) 大部分都处于体相内，从包络线的形状看，
它们类似于刚刚讨论过的势箱内的态，但这些态不属于镜像态，所以在与实验对比时应排除在外。
而 \(\phi_1\) 、 \(\phi_5\) 、 \(\phi_6\) 和 \(\phi_7\) 在真空中的部分存在波包，且波包的数量刚好对应主量子数 \(n\) ，如 \(\phi_5\) 在 \(x\ge 0\) 的部分有两个波包，它就是 \(n=2\) 对应的本征态。&lt;/p&gt;
&lt;h3 id=&#34;二维及更高维系统的-hamiltonian-构造与求解&#34;&gt;二维及更高维系统的 Hamiltonian 构造与求解&lt;/h3&gt;
&lt;p&gt;一维情况下我们可以直接使用二阶导而无需其它处理即可构造出动能算符，但在更高维度下要如何构造动能算符，
以及 Hamiltonian 呢？&lt;/p&gt;
&lt;h4 id=&#34;高维-laplacian-的离散化&#34;&gt;高维 Laplacian 的离散化&lt;/h4&gt;
&lt;p&gt;根据 &lt;a href=&#34;https://en.wikipedia.org/wiki/Kronecker_sum_of_discrete_Laplacians&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Wikipedia&lt;/a&gt;
 &lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;
上关于离散 Laplacian （拉普拉斯算符）的描述，多维离散 Laplacian 是一维离散 Laplacian
的 Kronecker Sum （克罗内克和）。&lt;/p&gt;
&lt;p&gt;例如对于一个二维系统：&lt;/p&gt;
&lt;p&gt;\[
L = \bold{D}_\bold{xx} \oplus \bold{D}_\bold{yy} = \bold{D}_\bold{xx} \otimes \bold{I} + \bold{I} \otimes \bold{D}_\bold{yy}
\]&lt;/p&gt;
&lt;p&gt;其中 \(\bold{D}_\bold{xx}\) 、 \(\bold{D}_\bold{yy}\) 表示在 \(x\) 、 \(y\) 方向上的 Laplacian 矩阵， \(\bold{I}\) 是单位矩阵。&lt;/p&gt;
&lt;p&gt;注意，上式中 &amp;ldquo;\(\oplus\)&amp;rdquo; 表示 Kronecker Sum 操作而不表示矩阵 Direct Sum （直和）操作，尽管它们所用的符号是一样的；
而 &amp;ldquo;\(\otimes\)&amp;rdquo; 则可以理解为 Kronecker Product 或者 Direct Product （直积）操作，因为在此处可以认为两种操作等价。&lt;/p&gt;
&lt;p&gt;相应地，对于一个三维系统，它的 Laplacian 应该是&lt;/p&gt;
&lt;p&gt;\[
L = \bold{D}_\bold{xx} \otimes \bold{I} \otimes \bold{I} +
\bold{I} \otimes \bold{D}_\bold{yy} \otimes \bold{I} +
\bold{I} \otimes \bold{I} \otimes \bold{D}_\bold{zz}
\]&lt;/p&gt;
&lt;p&gt;下面通过计算二维势箱内的电子能级来验证上面式子的正确性。&lt;/p&gt;
&lt;p&gt;假设二维势箱是边长 \(a = 1 \rm{Å}\) 的正方形，其中的电子满足 Schrodinger 方程：&lt;/p&gt;
&lt;p&gt;\[\begin{aligned}
-\frac{\hbar^2}{2m_e}(\frac{\partial^2}{\partial x^2} + \frac{\partial^2}{\partial y^2}) \psi = E\psi
\end{aligned}\]&lt;/p&gt;
&lt;p&gt;它的 Hamiltonian 只包含 Laplacian ，解析解为&lt;/p&gt;
&lt;p&gt;\[\begin{aligned}
E &amp;amp;={} (n_x^2 + n_y^2)\frac{h^2}{8ma^2} \newline
\psi(x, y) &amp;amp;={} \frac{2}{a}\sin(\frac{n_x \pi x}{a}) \sin(\frac{n_y \pi y}{a})
\end{aligned}\]&lt;/p&gt;
&lt;p&gt;程序实现如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;74
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;c&#34;&gt;#!/usr/bin/env julia&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LinearAlgebra&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SparseArrays&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Arpack&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Plots&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                           Constants Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;                 &lt;span class=&#34;c&#34;&gt;# sample points&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;                &lt;span class=&#34;c&#34;&gt;# box length&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8099821161548593&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;c&#34;&gt;# hbar^2 / (2*m_e) = (Å^2) / eV&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;                  &lt;span class=&#34;c&#34;&gt;# relative mass of electron&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;                  &lt;span class=&#34;c&#34;&gt;# number of eigen values to be covered&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;LinRange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;LinRange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;len&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                           Hamiltonian Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;Tx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Tx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Tx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Tx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Tx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Tx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Ix&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;Ty&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Ty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Ty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Ty&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Iy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kron&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Tx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Iy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kron&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Ty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deepcopy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Hamiltonian constructed, start solving ...&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@time&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;λ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eigs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;which&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;:LM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sigma&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@show&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;λ&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                           Visualization Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;norm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;   &lt;span class=&#34;c&#34;&gt;# Normalization&lt;/span&gt;
    &lt;span class=&#34;nd&#34;&gt;@assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;≈&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;    &lt;span class=&#34;c&#34;&gt;# verify the norm: ∫ |ϕ|² dx == 1&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

&lt;span class=&#34;nd&#34;&gt;@show&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;maximum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reshape&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;p1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;surface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;ψ_1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;p2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;surface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;ψ_2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;p3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;surface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;ψ_3&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;p4&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;surface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ψ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;ψ_4&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;layout&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;800&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;savefig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;./2D-particle-in-a-box-eigvec.svg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解得本征值与解析解对比如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;\(\lambda\)&lt;/th&gt;
&lt;th&gt;\(n_x^2 + n_y^2\)&lt;/th&gt;
&lt;th&gt;\(E_{\rm numerical}\) (eV)&lt;/th&gt;
&lt;th&gt;\(E_{\rm analytical}\) (eV)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1 + 1 = 2&lt;/td&gt;
&lt;td&gt;74.458&lt;/td&gt;
&lt;td&gt;75.206&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4 + 1 = 5&lt;/td&gt;
&lt;td&gt;186.136&lt;/td&gt;
&lt;td&gt;187.961&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1 + 4 = 5&lt;/td&gt;
&lt;td&gt;186.136&lt;/td&gt;
&lt;td&gt;187.961&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4 + 4 = 8&lt;/td&gt;
&lt;td&gt;297.814&lt;/td&gt;
&lt;td&gt;300.737&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;9 + 1 = 10&lt;/td&gt;
&lt;td&gt;372.236&lt;/td&gt;
&lt;td&gt;375.922&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;1 + 9 = 10&lt;/td&gt;
&lt;td&gt;372.236&lt;/td&gt;
&lt;td&gt;375.922&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;9 + 4 = 13&lt;/td&gt;
&lt;td&gt;483.914&lt;/td&gt;
&lt;td&gt;488.698&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;4 + 9 = 13&lt;/td&gt;
&lt;td&gt;483.914&lt;/td&gt;
&lt;td&gt;488.698&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;解得的本征值相差还是不小的，但总体趋势是一致的。
解得波函数如下（限于篇幅原因只列举前四个）:
&lt;img src=&#34;2D-particle-in-a-box-eigvec.svg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;根据波函数形状判断，它们与量子数的对应关系如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;\(\psi\)&lt;/th&gt;
&lt;th&gt;\(n_x\)&lt;/th&gt;
&lt;th&gt;\(n_y\)&lt;/th&gt;
&lt;th&gt;\(E\) (eV)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;74.458&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;186.136&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;186.136&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;297.814&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;在归一化波函数后，求得振幅为 1.990 ，与 \(\dfrac{2}{a} = 2\) 相差无几。&lt;/p&gt;
&lt;p&gt;由此可见，使用 Kronecker Sum 构造的 Laplacian 解出的结果是正确的。&lt;/p&gt;
&lt;h4 id=&#34;高维-hamiltonian-的构造与求解&#34;&gt;高维 Hamiltonian 的构造与求解&lt;/h4&gt;
&lt;p&gt;已经有了高维的 Laplacian ，我们需要把势能项和 Laplacian 组合起来得到 Hamiltonian 。
显然，我们需要把势能加到对角项上，但要注意一个问题，就是 Laplacian 的对角项与格点的对应关系：&lt;/p&gt;
&lt;p&gt;\[
L = \bold{D}_\bold{xx} \otimes \bold{I} \otimes \bold{I} +
\bold{I} \otimes \bold{D}_\bold{yy} \otimes \bold{I} +
\bold{I} \otimes \bold{I} \otimes \bold{D}_\bold{zz}
\]&lt;/p&gt;
&lt;p&gt;我们不妨令 \(\bold{D}_\bold{xx}\) 为 \(\bold{X}\) ， \(\bold{D}_\bold{yy}\) 为 \(\bold{Y}\) ，
\(\bold{D}_\bold{zz}\) 为 \(\bold{Z}\)，
根据 Kronecker Product 的运算过程（详见 Wiki），最后得到的矩阵对角线应该是&lt;/p&gt;
&lt;p&gt;\[\begin{bmatrix}
\bold{X}_{11} \bold{Y}_{11} \bold{Z}_{11} &amp;amp; &amp;amp; &amp;amp; \newline
&amp;amp; \bold{X}_{11} \bold{Y}_{11} \bold{Z}_{22} &amp;amp; &amp;amp; \newline
&amp;amp; &amp;amp; \bold{X}_{11} \bold{Y}_{11} \bold{Z}_{33} &amp;amp; \newline
&amp;amp; &amp;amp; &amp;amp; &amp;amp; \ddots
\end{bmatrix}\]&lt;/p&gt;
&lt;p&gt;上式中 \(\bold{Z}\) 的对角线，即最后一个维度的下标增长得最快；对应地，在加和势能项时，
也应该是最后一个维度增长最快，这恰好是访问一个行主序的多维数组元素时的访问顺序。
也就是说我们只需要按照行主序的顺序把多维的势能数组展开为一维数组，然后加和到 Laplacian 上即可得到 Hamiltonain ：&lt;/p&gt;
&lt;p&gt;\[H = T +
\begin{bmatrix}
V_{111} &amp;amp; &amp;amp; &amp;amp; \newline
&amp;amp; V_{112} &amp;amp; &amp;amp; \newline
&amp;amp; &amp;amp; V_{113} &amp;amp; \newline
&amp;amp; &amp;amp; &amp;amp; \ddots
\end{bmatrix}\]&lt;/p&gt;
&lt;p&gt;此处我们选取静态氢原子的电子为求解对象，它的 Shrodinger 方程是这个形式&lt;/p&gt;
&lt;p&gt;\[
-\frac{\hbar^2}{2m_e} \nabla^2 \psi - \frac{e^2}{4\pi \epsilon_0} \frac{1}{r} \psi = E\psi
\]&lt;/p&gt;
&lt;p&gt;下面是程序实现，注意 Julia 的数组是列主序，因此在组合 Hamiltonian 时需要转换；
除此之外受计算机性能和辣鸡 &lt;code&gt;ARPACK&lt;/code&gt; 的限制，这里每个维度只取 50 个点，每个维度各取 30Å 的长度。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;  1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 89
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 90
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 91
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 92
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 93
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 94
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 95
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 96
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 97
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 98
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 99
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;100
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;101
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-julia&#34; data-lang=&#34;julia&#34;&gt;&lt;span class=&#34;c&#34;&gt;#!/usr/bin/env julia&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LinearAlgebra&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SparseArrays&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Arpack&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;WriteVTK&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Auxiliary function&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mgrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;it&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Iterators&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;product&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[];&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;push!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;getindex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;it&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;


&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                                Constants Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8099821161548593&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;# hbar^2 / (2*m_e) /(Å^2) / eV&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k_c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;14.39964547842567&lt;/span&gt;   &lt;span class=&#34;c&#34;&gt;# (e*e / (4 * np.pi * epsilon_0))  # measured in eV / Å&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;                 &lt;span class=&#34;c&#34;&gt;# mass of electron&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xlen&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;30.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ylen&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xlen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;zlen&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xlen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xlen&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# generate the grid&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xlen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xlen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ylen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ylen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zlen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;zlen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                                Potential Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;gx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gz&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mgrid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;potential&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gz&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;AbstractArray&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gz&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.&amp;lt;&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0001&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0001&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k_c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;potential&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gz&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Vmin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;minimum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;


&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                                Hamiltonian Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Kinetic part&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;Identity&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;I&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.*=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kron&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kron&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Identity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Identity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;kron&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Identity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kron&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Identity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;kron&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Identity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kron&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Identity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;T_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Hamiltonian&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deepcopy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;permutedims&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;


&lt;span class=&#34;c&#34;&gt;# Solve the equation Hψ = Eψ&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@time&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;λ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eigs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;which&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;:LM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sigma&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Vmin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@show&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;λ&lt;/span&gt;


&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#                                Visualization Part&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;################################################################################&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;vtk_grid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;HydrogenAtom&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vtk&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nev&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;./=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;norm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
        &lt;span class=&#34;nd&#34;&gt;@assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;≈&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;vtk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;phi_&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reshape&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ϕ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;结果与解析值对比&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;\(\lambda\)&lt;/th&gt;
&lt;th&gt;\(n\)&lt;/th&gt;
&lt;th&gt;\(E_{\rm numernical}\) (eV)&lt;/th&gt;
&lt;th&gt;\(E_{\rm analytical}\) (eV)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-10.713&lt;/td&gt;
&lt;td&gt;-13.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;-3.417&lt;/td&gt;
&lt;td&gt;-3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;-3.417&lt;/td&gt;
&lt;td&gt;-3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;-3.417&lt;/td&gt;
&lt;td&gt;-3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;-3.031&lt;/td&gt;
&lt;td&gt;-3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-1.515&lt;/td&gt;
&lt;td&gt;-1.51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-1.515&lt;/td&gt;
&lt;td&gt;-1.51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-1.515&lt;/td&gt;
&lt;td&gt;-1.51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-1.474&lt;/td&gt;
&lt;td&gt;-1.51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-1.474&lt;/td&gt;
&lt;td&gt;-1.51&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;本征值与解析值对应得并不好，尤其是基态的能量，与解析解相差了近 3eV ，这是因为 \(1s\) 态主要局域在原子核附近，而求数值解时每个维度只取了 50 个点，&lt;/p&gt;
&lt;p&gt;本征态如下（这里只取前五个态）：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;3D-hydrogen-eigvec.png&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;3D-hydrogen-eigvec.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;它们分别对应氢原子的 \(1s\) 态、 \(2p_y\) 态、 \(2p_z\) 态、 \(2p_x\) 态和 \(2s\) 态，抛去过于粗糙的格点和不太准的本征值不谈，
它们的形状与实验上符合得还是很好的。&lt;/p&gt;
&lt;p&gt;以上结果可以证明 Hamiltonian 的构造是合理的。&lt;/p&gt;
&lt;h2 id=&#34;有限元法&#34;&gt;有限元法&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;注：本人刚刚接触 FEM ，这里只是简单谈谈有限元法，以能通过改示例跑通自己的问题为标准
，因此对它的各项论述十分粗浅且可能存在错误，欢迎专业人士指正。&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;上面我们讨论了使用有限差分法求解 Schrodinger 方程的过程，除了有限差分法，
还有一种在 CAE 领域应用非常广泛的方法——有限元法，也能用来求解 Schrodinger 方程。
简单且不负责任地说，有限元与有限差分最大的区别在于有限元的元素是大小、形状均可变，
并且它可以随意调整求解空间的形状以及网格的形状、局部疏密等等，
这使得它可以对各种奇怪的体系进行求解。&lt;/p&gt;
&lt;h3 id=&#34;定态-schrodinger-方程的变分弱解形式&#34;&gt;定态 Schrodinger 方程的变分弱解形式&lt;/h3&gt;
&lt;p&gt;之前本文给出过定态 Schrodinger 方程&lt;/p&gt;
&lt;p&gt;\[
-\frac{\hbar^2}{2m}\nabla^2 \psi + V\psi = E\psi
\]&lt;/p&gt;
&lt;p&gt;它其实是偏微分方程的 Strong Form （强解形式），而在 FEM 领域中常常使用 Weak Form
（弱解形式）来描述一个偏微分方程。经过查阅资料，我找到的 Shrodinger 方程的弱解形式如下：&lt;/p&gt;
&lt;p&gt;\[\begin{aligned}
\frac{\hbar^2}{2m} \int_{\Omega} \left(
\frac{\partial u}{\partial x} \frac{\partial v}{\partial x} +
\frac{\partial u}{\partial y} \frac{\partial v}{\partial y} +
\frac{\partial u}{\partial z} \frac{\partial v}{\partial z}
\right) + \int_{\Omega} Vuv = \int_{\Omega} Euv
\end{aligned}\]&lt;/p&gt;
&lt;p&gt;上式中 \(u\) 是我们要求解的波函数， \(v\) 是测试函数， \(\Omega\) 是有限元空间。
看起来这个式子和 Schrodinger 方程的强解形式差不多，只是动能项前面没有负号了。
具体推导过程详见 &lt;a href=&#34;https://en.wikipedia.org/wiki/Weak_formulation#Example_2:_Poisson%27s_equation%20&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Weak formulation of Poisson&amp;rsquo;s equation&lt;/a&gt;
 &lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;
或 &lt;a href=&#34;https://en.wikiversity.org/wiki/User:Tclamb/FEniCS#Quantum_Harmonic_Oscillator&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Weak formulation of quantum harmonic oscillator&lt;/a&gt;
 &lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;h3 id=&#34;程序实现及结果验证&#34;&gt;程序实现及结果验证&lt;/h3&gt;
&lt;p&gt;有了弱解形式的 Schrodinger Equation 后就可以开始使用有限元法求解了，这里使用
&lt;a href=&#34;https://freefem.org&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;FreeFEM++&lt;/a&gt;
 &lt;sup id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;7&lt;/a&gt;&lt;/sup&gt; 作为实现语言。&lt;/p&gt;
&lt;p&gt;使用 FreeFEM++ 求解本征值问题时主要有以下步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;定义网格；&lt;/li&gt;
&lt;li&gt;定义有限元空间；&lt;/li&gt;
&lt;li&gt;定义需要解决的问题，即用代码表达弱解形式的偏微分方程；&lt;/li&gt;
&lt;li&gt;调用求解器求解；&lt;/li&gt;
&lt;li&gt;输出结果以及可视化结果等。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这里以求解氢原子为例，求解空间为 30Åx30Åx30Å 的正方体，边缘格点数为 40x40x40 ，使用 P1 有限元空间。
下面是代码&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;load &amp;#34;msh3&amp;#34;
load &amp;#34;iovtk&amp;#34;

int nn = 40;

real ka = 3.8099821161548593; // hbar^2 / 2m_e
real kc = 14.39964547842567; // e^2 / (4pi epsilon_0)

mesh3 Th = cube(nn, nn, nn, [30*x-15, 30*y-15, 30*z-15]);
plot(Th, wait=1);

fespace Vh(Th, P1);

cout &amp;lt;&amp;lt; &amp;#34;Th :  nv = &amp;#34; &amp;lt;&amp;lt; Th.nv &amp;lt;&amp;lt; &amp;#34; nt = &amp;#34; &amp;lt;&amp;lt; Th.nt &amp;lt;&amp;lt; endl;

real sigma = -13;

macro Grad(u) [dx(u), dy(u), dz(u)] // EOM
varf a(u1, u2) = int3d(Th) (
    Grad(u1)&amp;#39; * Grad(u2) * ka
    - 1.0 / sqrt(x^2 + y^2 + z^2)  * u1 * u2 * kc
    - sigma * u1 * u2
    )
    //+ on(1, 2, 3, 4, 5, 6, u1=0.0)   // boundary condition
    ;

varf b([u1], [u2]) = int3d(Th) ( u1 * u2 ) ;

matrix A = a(Vh, Vh);
matrix B = b(Vh, Vh);

int nev = 20;
real[int] ev(nev);
Vh[int] eV(nev);

int k = EigenValue(A, B, sym=true, sigma=sigma, value=ev, vector=eV, tol=1e-10);

k = min(k, nev);

for (int i=0; i&amp;lt;k; ++i) {
    cout &amp;lt;&amp;lt; &amp;#34; ---- &amp;#34; &amp;lt;&amp;lt; i &amp;lt;&amp;lt; &amp;#34; &amp;#34; &amp;lt;&amp;lt; ev[i] &amp;lt;&amp;lt; &amp;#34; == &amp;#34; &amp;lt;&amp;lt; endl;
    plot(eV[i], cmm=&amp;#34;#&amp;#34; + i + &amp;#34; EigenValue=&amp;#34; + ev[i], wait=true);
    savevtk(&amp;#34;Eigen_&amp;#34; + i + &amp;#34;.vtk&amp;#34;, Th, eV[i], dataname=&amp;#34;EigenValue=&amp;#34; + ev[i]);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;求得本征值如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;\(\lambda\)&lt;/th&gt;
&lt;th&gt;\(E_{\rm numerical}\) (eV)&lt;/th&gt;
&lt;th&gt;\(E_{\rm analytical}\) (eV)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-10.390&lt;/td&gt;
&lt;td&gt;-13.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;-3.163&lt;/td&gt;
&lt;td&gt;-3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-3.163&lt;/td&gt;
&lt;td&gt;-3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;-2.980&lt;/td&gt;
&lt;td&gt;-3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;-2.776&lt;/td&gt;
&lt;td&gt;-3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;-1.475&lt;/td&gt;
&lt;td&gt;-1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;-1.475&lt;/td&gt;
&lt;td&gt;-1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;-1.444&lt;/td&gt;
&lt;td&gt;-1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;-1.444&lt;/td&gt;
&lt;td&gt;-1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;-1.423&lt;/td&gt;
&lt;td&gt;-1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可见在这个格点密度下它的精度还是不太高，有些态甚至还比不上有限差分法的精度。&lt;/p&gt;
&lt;p&gt;它们的本征态如下：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;3D-hydrogen-eigenvec-FEM.png&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;3D-hydrogen-eigenvec-FEM.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;和有限差分法相比，它的本征态似乎更粗糙一些，实际上这是由于取的网格不够密，
以及势能项 \(1/r\) 在 0 处存在奇点难以近似导致的。&lt;/p&gt;
&lt;p&gt;尽管有这样的缺陷，但它胜在是一个成熟的开源软件，比之前随便写的 toy 要正式许多，
而且它还能使用其它设计软件来建模定义求解的空间，甚至读取其它软件生成的网格进行后续的计算，
最重要的一点，它可以集成并行的本征值求解器 SLEPc &lt;sup id=&#34;fnref:8&#34;&gt;&lt;a href=&#34;#fn:8&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;8&lt;/a&gt;&lt;/sup&gt; 。
经过测试，求解一个 150x150x75 的网格时，在 32 核的服务器上可以用 18 分钟跑完，效率还是令人满意的。&lt;/p&gt;
&lt;h2 id=&#34;总结及吐槽&#34;&gt;总结及吐槽&lt;/h2&gt;
&lt;p&gt;总之，本文使用了两种不同的方法在实空间直接求解单电子的 Schrodinger 方程，
总体的结果还算满意。有限差分法的算法学习自 GithHub 的一个项目
&lt;a href=&#34;https://github.com/quantum-visualizations/qmsolve&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;qmsolve&lt;/a&gt;
 &lt;sup id=&#34;fnref:9&#34;&gt;&lt;a href=&#34;#fn:9&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;9&lt;/a&gt;&lt;/sup&gt;，
作者甚至还把我拉到了这个项目的 Discord 讨论群（现在已经开放）继续讨论。&lt;/p&gt;
&lt;h3 id=&#34;吐槽&#34;&gt;吐槽&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;有限差分法的 Hamiltonian 矩阵大小随维度的升高而急剧升高，
如果一个问题能在较低的维度解决，不要使用更高的维度，通常情况后者解不动：
一维问题的 Hamiltonian 大小是 \(O(N^2)\) ，而三维问题的 Hamiltonian 大小是 \(O(N^6)\)
&lt;del&gt;，如果后面有空的话我会考虑写一下柱坐标系内 Schrodinger 方程的求解&lt;/del&gt; 。&lt;/li&gt;
&lt;li&gt;在使用有限差分法时格点越密，求解所需的时间越多，且耗时呈指数级增长。
为此我花了将近一周多的时间在寻找 Julia 能用的并行本征值求解器上，
最后发现没有能满足要求的，有几个 C++ / Python 能用的并行求解器，如 SLEPc 和 Trilinos ，但我没去尝试；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Arpack&lt;/code&gt; 在处理 60x60x60 的格点时就已经有点力不从心了，
超算上显示它只能通过调用 &lt;code&gt;BLAS&lt;/code&gt; 来实现部分的并行操作，且最多只有 6 个线程在跑，
而且 &lt;code&gt;Arpack&lt;/code&gt; 也确实很久没有更新了；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scipy.sparse.eigsh&lt;/code&gt; 的效率还不如 Julia 里的 &lt;code&gt;Arpack.eigs&lt;/code&gt; ，前者算 50x50x50
的体系就算不动了，而且似乎在超算上用并行也没什么加速效果，尽管所有核都是满载；&lt;/li&gt;
&lt;li&gt;FreeFEM++ 的语言乍一看挺像 C++ ，但其实区别还是相当大的，令人惊喜的是它的文档还有一个中文翻译版；&lt;/li&gt;
&lt;li&gt;在服务器上编译 FreeFEM++ 也花了我不少时间，这个东西的 Makefile 写得让人头疼：
&lt;code&gt;configure&lt;/code&gt; 文件直接就是一个 Python 脚本，而且层层套娃，想改什么参数都不好找，
那两天被弄得脑壳疼；&lt;/li&gt;
&lt;li&gt;FreeFEM++ 支持并行操作，用更密的 Mesh 可以重复出文献上的结果；更重要的是它可以更灵活地指定边界条件；&lt;/li&gt;
&lt;li&gt;在可视化 FreeFEM++ 的输出，即 vtk 文件时也遇到了不少麻烦，因为之前从没接触过 vtk 文件，
只是听说 ParaView&lt;sup id=&#34;fnref:10&#34;&gt;&lt;a href=&#34;#fn:10&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;10&lt;/a&gt;&lt;/sup&gt; 效果最好，于是从头开始学 ParaView 。
不得不说，入门时还是看视频学最快，找谷歌翻论坛很可能不知所云；&lt;/li&gt;
&lt;li&gt;实验组最后还要求用求得的波函数计算一下位置算符的期望值，于是我又不得不去翻 ParaView 的手册找怎么操作数据。
这个软件和 Python 以及 VTK 深度集成，里面自带一个 Python 解释器，
但没有提供内置对象的文档，导致你面对一个 Script 框时连输入是啥都不知道，
此外它的一些数据结构在原版 VTK 内还没有，那就只能靠 &lt;code&gt;dir(obj)&lt;/code&gt; 来看它的方法列表了，
通过不断地翻论坛（2018 年以前的论坛还是在邮件列表上），
还是在一个人的回答中找到了相关的信息，算是顺利解决了问题，不得不说这个过程还是挺恶心人的。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这些东西可能读起来几分钟就读完了，但从接到相关的任务，到给出令实验组满意的结果，
再到写出这篇博文，整整用掉了一个多月的时间，这期间试了尝试过很多次，
不管是有限差分还是有限元，写过很多测试的代码但结果不正确，身边又没有可以请教人时，
内心还是有一点绝望的（尤其在 6 月下半旬还夹着报账那个事），
中途想过放弃，想着不如直接找个力学系的同学抛给他用 COMSOL 解出来，
但最后还是通过翻论坛，厚着脸皮问 developer 等手段把想要的结果算出来了，
此时觉得前面的努力还是没有白费，就是对当初对实验组的老师打包票说几天就能算出来，
但实际花了近一个月这一点还是有点惭愧的。&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Particle_in_a_box&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Particle_in_a_box&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Finite_difference_coefficient&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Finite_difference_coefficient&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.sciencedirect.com/science/article/pii/S0039602899006688&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://www.sciencedirect.com/science/article/pii/S0039602899006688&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Kronecker%5Fsum%5Fof%5Fdiscrete%5FLaplacians&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Kronecker%5Fsum%5Fof%5Fdiscrete%5FLaplacians&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Weak%5Fformulation#Example%5F2:%5FPoisson%27s%5Fequation%20&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Weak%5Fformulation#Example%5F2:%5FPoisson&#39;s%5Fequation%20&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikiversity.org/wiki/User:Tclamb/FEniCS#Quantum%5FHarmonic%5FOscillator&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikiversity.org/wiki/User:Tclamb/FEniCS#Quantum%5FHarmonic%5FOscillator&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:7&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://freefem.org&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://freefem.org&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:7&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:8&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://slepc.upv.es&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://slepc.upv.es&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:8&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:9&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/quantum-visualizations/qmsolve&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://github.com/quantum-visualizations/qmsolve&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:9&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:10&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.paraview.org&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://www.paraview.org&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:10&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
    <item>
      <title>镜像态的那些坑</title>
      <link>http://ionizing.page/post/issues-with-ips/</link>
      <pubDate>Thu, 06 May 2021 00:18:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/issues-with-ips/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%a1%a8%e9%9d%a2%e6%80%81%e4%b8%8e%e9%95%9c%e5%83%8f%e6%80%81&#34;&gt;表面态与镜像态&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%a1%a8%e9%9d%a2%e6%80%81--surface-states-ss&#34;&gt;表面态(Surface States, SS)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%95%9c%e5%83%8f%e6%80%81--image-potential-states-ips&#34;&gt;镜像态(Image Potential States, IPS)&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%ae%a1%e7%ae%97%e8%bf%87%e7%a8%8b&#34;&gt;计算过程&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%ae%a1%e7%ae%97%e5%8f%82%e6%95%b0&#34;&gt;计算参数&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%b6%b3%e5%a4%9f%e7%9a%84%e7%a9%ba%e5%b8%a6&#34;&gt;足够的空带&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%b6%b3%e5%a4%9f%e7%9a%84%e7%9c%9f%e7%a9%ba%e5%b1%82&#34;&gt;足够的真空层&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%81%b6%e6%9e%81%e6%a0%a1%e6%ad%a3&#34;&gt;偶极校正&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%aa%8c%e8%af%81%e8%ae%a1%e7%ae%97%e7%bb%93%e6%9e%9c&#34;&gt;验证计算结果&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#pdos-%e6%b3%95&#34;&gt;PDOS 法&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%ae%9e%e7%a9%ba%e9%97%b4%e5%88%86%e5%b8%83%e6%b3%95&#34;&gt;实空间分布法&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%83%bd%e5%b8%a6%e6%b3%95&#34;&gt;能带法&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%99%84%e5%bd%95&#34;&gt;附录&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%95%9c%e5%83%8f%e5%8a%bf%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%8e%a8%e5%af%bc&#34;&gt;镜像势表达式的推导&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;本文是帮实验组计算表面态与镜像态相关性质时所遇到一些坑的总结。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;限于 DFT 理论上的缺陷（使用指数函数逼近库仑势，从而加速收敛）， DFT 并不能算准
IPS 的能级（误差在 \(\pm 0.3eV\)左右），但有的实验又需要从 DFT 计算获得一些关于
IPS 的信息，于是即使 DFT 不能算准，也无大碍。在这个过程中本人似乎不止一次掉入坑
中，于是把这个过程记录下来，即便对后人没什么帮助，也算是对自己学习印迹的一丝收藏
吧。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;表面态与镜像态&#34;&gt;表面态与镜像态&lt;/h2&gt;
&lt;h3 id=&#34;表面态--surface-states-ss&#34;&gt;表面态(Surface States, SS)&lt;/h3&gt;
&lt;p&gt;顾名思义，表面态就是在物体 &lt;strong&gt;表面&lt;/strong&gt; 附近存在的电子态&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;。表面意味着边界的存在，
边界外是真空，边界内是原子。正因为存在从体相到真空的剧烈变化，表面的原子存在不饱和键，即悬挂键。这些悬挂键由那些在体相内本应成键的电子贡献，受这些电子影响，物体的 &lt;strong&gt;表面&lt;/strong&gt; 会出现一些新的、相对弥散的电子态，这些电子态被称为表面态。&lt;/p&gt;
&lt;h3 id=&#34;镜像态--image-potential-states-ips&#34;&gt;镜像态(Image Potential States, IPS)&lt;/h3&gt;
&lt;p&gt;将一个电荷放在无限大的导体表面（这里假设表面是平面），导体内部会发生极化，导致内部电荷重新分布，从而产生一个静电势。这个静电势等效于导体内一个带相反电性的镜像电荷产生的静电势，因而被称为镜像势。电子因镜像势会在导体表面 &lt;strong&gt;外&lt;/strong&gt; 形成一些相对弥散的态，这些态就是镜像态。&lt;/p&gt;

&lt;link rel=&#34;stylesheet&#34; href=&#34;http://ionizing.page/css/hugo-easy-gallery.css&#34; /&gt;
&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;ips1.svg&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 1: &amp;lt;/span&amp;gt;镜像电荷示意图， 0&amp;#43; 侧是真空， 0- 侧是相对介电常数为 epsilon_r 的导体内部&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;ips1.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 1: &lt;/span&gt;镜像电荷示意图， 0+ 侧是真空， 0- 侧是相对介电常数为 epsilon_r 的导体内部&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;镜像势的势能曲线是反比例曲线：&lt;/p&gt;
&lt;p&gt;\[ V(z) = - \frac{\beta e^2}{4\pi \epsilon_{0} \cdot 4z} \]&lt;/p&gt;
&lt;p&gt;上式中 \(\beta = \displaystyle\frac{\epsilon_r-1}{\epsilon_r+1}\)&lt;/p&gt;
&lt;p&gt;所以电子满足方程：&lt;/p&gt;
&lt;p&gt;\[ \begin{aligned}
\frac{\hbar^2}{2m_e} \nabla^2 \Psi + V(z)\Psi &amp;amp;={} E\Psi \newline
\frac{\hbar^2}{2m_e} \nabla^2 \Psi - \frac{\beta e^2}{4\pi \epsilon_{0} \cdot 4z} \Psi &amp;amp;={} E\Psi
\end{aligned} \]&lt;/p&gt;
&lt;p&gt;这个方程看起来很眼熟，它十分类似于氢原子 Schrodinger 方程。由于这个电子只在
\(z\) 方向上受镜像电荷作用，因而在 \(xy\) 方向上是自由的，所以它能量可以通过求解一维氢原子 Schrodinger 方程得到：&lt;/p&gt;
&lt;p&gt;\[ E_n = -\frac{0.85}{n^2}\frac{(\epsilon_r-1)^2}{(\epsilon_r+1)^2} \quad \text{eV} \]&lt;/p&gt;
&lt;p&gt;其中 \(n\) 是主量子数，分子 0.85eV 正好是氢原子基态能量的 \(\dfrac{1}{4^2}\) 。
所以镜像态也可以根据主量子数的不同来区分出不同的能级。求解过程可以在一篇文章&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;中查到；镜像势的表达式的推导过程详见附录。&lt;/p&gt;
&lt;p&gt;严格地说，镜像态也是表面态的一种&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;。一般而言，镜像态在真空能级以下 1eV 以内，
DFT 算出的 IPS 能级可能会超过真空能级，但在实际上是不太可能的，即使真的有，实验上也不大能测得到。&lt;/p&gt;
&lt;h2 id=&#34;计算过程&#34;&gt;计算过程&lt;/h2&gt;
&lt;p&gt;事实上计算出镜像态，并不需要改太多的东西。下面在介绍如何设置计算参数的同时以
Ag(111) 上吸附苯分子为例阐述如何从结果中分析是否存在 IPS 。&lt;/p&gt;
&lt;h3 id=&#34;计算参数&#34;&gt;计算参数&lt;/h3&gt;
&lt;p&gt;这里使用的晶格是 Ag(111) 的 \(3\times3\) 表面，上表面放置了一个苯分子，结构如图：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;AgBenzene-structure.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 2: &amp;lt;/span&amp;gt;Benzene on Ag(111)&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;AgBenzene-structure.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 2: &lt;/span&gt;Benzene on Ag(111)&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;h4 id=&#34;足够的空带&#34;&gt;足够的空带&lt;/h4&gt;
&lt;p&gt;如果体系比较小， VASP 默认取的 &lt;code&gt;NBANDS&lt;/code&gt; 是足够找到 IPS 的；但当体系特别大的时候，
默认的 &lt;code&gt;NBANDS&lt;/code&gt; 可能不太会覆盖到 IPS ，这时需要增加 &lt;code&gt;NBANDS&lt;/code&gt; ，一般加到真空能级以上 3eV 就足够了，实际上这里只是需要 VASP 能较为 &lt;em&gt;精确&lt;/em&gt; 地算对真空能级附近的态，
而标号接近 NBANDS 的能带不准确，表现在能带图上就是色散关系就像被生生截断了一样，
且呈锯齿状；此外，如果在实空间展开这个态会发现这个它像是随机生成的一样，没用使用价值分布。关于真空能级怎么算，详见之前的博文。&lt;/p&gt;
&lt;p&gt;这里使用的体系里因为原子数比较适中，不用额外增加 &lt;code&gt;NBANDS&lt;/code&gt; 。&lt;/p&gt;
&lt;h4 id=&#34;足够的真空层&#34;&gt;足够的真空层&lt;/h4&gt;
&lt;p&gt;镜像态在真空层中，因此需要足够的真空层来容纳它，一般而言 30A 真空层可能还不算够。
但要注意 VASP 在算高度超过 70A 的晶格时会很难收敛。&lt;/p&gt;
&lt;p&gt;这里使用的体系加了 50A 的真空层，已经足够放下上表面的 IPS 。&lt;/p&gt;
&lt;h4 id=&#34;偶极校正&#34;&gt;偶极校正&lt;/h4&gt;
&lt;p&gt;如果 Slab 表面没有吸附其它原子/分子，则不必对体系进行偶极校正，否则需要校正，具体过程参见之前的博文。&lt;/p&gt;
&lt;p&gt;偶极校正效果如图：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;AgBenzene-workfunc.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 3: &amp;lt;/span&amp;gt;Benzene on Ag111 偶极校正后功函数图像&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;AgBenzene-workfunc.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 3: &lt;/span&gt;Benzene on Ag111 偶极校正后功函数图像&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;h3 id=&#34;验证计算结果&#34;&gt;验证计算结果&lt;/h3&gt;
&lt;p&gt;这里的「验证」与其说是验证，不如说是寻找。前面提到， IPS 是一种相对「弥散」的态，
它「弥散」的性质决定了怎么去 Identify IPS 。这里总结了几种「找」 IPS 的方法。&lt;/p&gt;
&lt;h4 id=&#34;pdos-法&#34;&gt;PDOS 法&lt;/h4&gt;
&lt;p&gt;一个态比较「弥散」说明它的局域性（locality）比较低，反映在物理图像里就是它投影在原子上的态比较少。因此我们可以在通过不同能带在原子上的投影大小来判断它是否是 IPS。&lt;/p&gt;
&lt;p&gt;幸运地是 VASP 可以通过 &lt;code&gt;LORBIT = .TRUE.&lt;/code&gt; 来输出 &lt;code&gt;PROCAR&lt;/code&gt; 文件，它包含了每个能带在所有原子上的投影大小，顺便说一句， &lt;code&gt;PROCAR&lt;/code&gt; 还包含不同角动量的投影大小。&lt;/p&gt;
&lt;p&gt;先结构弛豫，再进行自恰计算得到 &lt;code&gt;PROCAR&lt;/code&gt; 后，可以通过以下方法查看这个态在所有原子上的投影之和：&lt;/p&gt;
&lt;p&gt;打开 &lt;code&gt;PROCAR&lt;/code&gt; ，定位到真空能级 &lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt; 附近 \(\Gamma\) 点的能带&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;band    35 # energy    3.23957699 # occ.  0.00000000

ion      s     py     pz     px    dxy    dyz    dz2    dxz  x2-y2    tot
    1  0.002  0.000  0.000  0.000  0.000  0.000  0.002  0.000  0.000  0.004
    2  0.001  0.000  0.001  0.000  0.000  0.000  0.000  0.000  0.000  0.002
    ......
tot    0.005  0.000  0.004  0.000  0.000  0.000  0.004  0.000  0.000  0.013
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;看最后一行 &lt;code&gt;tot 0.005 ...&lt;/code&gt; ，最右边也有一个 &lt;code&gt;tot&lt;/code&gt; ，两者交叉的的值 &lt;code&gt;0.013&lt;/code&gt; 即为这条能带在整个系统上的投影大小，换言之，局域度的大小。那么这个值越小则它是 IPS
的可能性越高。比如上面的能带 PDOS 中整体的 PDOS 之和只有 0.013 ，说明它的局域度很小，那么这个态非常弥散，有可能是 IPS 。&lt;/p&gt;
&lt;h4 id=&#34;实空间分布法&#34;&gt;实空间分布法&lt;/h4&gt;
&lt;p&gt;仅仅是通过能带的 PDOS 还不足以确认这条带是不是 IPS ，有些费米能级附近的带总体
PDOS 也很小，但不是 IPS 。这时就需要其它方法来看了，比如本节要介绍的实空间分布法。&lt;/p&gt;
&lt;p&gt;IPS 在实空间的分布特征相当明显：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;它们在表面以外，并且随着主量子数的升高有着对应个数的波包；&lt;/li&gt;
&lt;li&gt;每个波包对应的空间分布呈明显的近自由电子态的特征。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如下图&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;所示：&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:ips-ref1&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;ips_ref1.jpg&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 4: &amp;lt;/span&amp;gt;IPS 的实空间分布曲线，最下面的曲线是镜像势的曲线。&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;ips_ref1.jpg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 4: &lt;/span&gt;IPS 的实空间分布曲线，最下面的曲线是镜像势的曲线。&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;上面图中 \(n=1\) 的 IPS 只有一个波包， \(n=2\) 时有两个波包， \(n=3\) 时有三个，
以此类推下去……&lt;/p&gt;
&lt;p&gt;对于第一个特征，我们可以对波函数的模平方作 \(z\) 方向上的分布，数出表面外有多少个峰，注意区分 Slab 的上表面和下表面，只有上表面的波包应该被计入在内。&lt;/p&gt;
&lt;p&gt;在 Benzene on Ag(111) 体系中，对应的 IPS 实空间分布曲线如下：&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:ips-AgBenzene-ips1&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;AgBenzene-ips1.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 5: &amp;lt;/span&amp;gt;Benzene on Ag(111) 表面 IPS 的实空间分布曲线&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;AgBenzene-ips1.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 5: &lt;/span&gt;Benzene on Ag(111) 表面 IPS 的实空间分布曲线&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;如果只看 \(z\) 方向上的波函数觉得不放心，可以把某条带在实空间的分布画出来，如果它在真空中，并且上下表面近似为平面，即在水平方向上为近自由电子，也就可认为它是
IPS ，如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:ips-AgBenzene-realspace&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;AgBenzene-ipsrealspace.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 6: &amp;lt;/span&amp;gt;Benzene on Ag(111) 体系 IPS 的实空间分布，这里每张图的等值面 Level 不同，以体现出对应数量的波包&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;AgBenzene-ipsrealspace.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 6: &lt;/span&gt;Benzene on Ag(111) 体系 IPS 的实空间分布，这里每张图的等值面 Level 不同，以体现出对应数量的波包&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;实际上，图上所标 \(n=4\) 的曲线并不真的是 IPS ，它的能量在真空能级以上，并且它的能量也不符合 \(\dfrac{1}{n^2}\) 的规律。如果仔细验证的话， \(n=1,2,3\) 的能量也并不符合这个规律，这就是 DFT 理论的局限所致，想要再算得更准，需要更大的代价。&lt;/p&gt;
&lt;h4 id=&#34;能带法&#34;&gt;能带法&lt;/h4&gt;
&lt;p&gt;以上是在单点能静态计算的基础上进行的分析，如果已经画出了这个体系的能带图，从能带图上可以更加清晰地反映出 IPS 的特征。&lt;/p&gt;
&lt;p&gt;能带图的横坐标量纲是动量，纵坐标是能量。一个自由电子的能量全部由动能贡献，因此它的能量与动量的关系就是&lt;/p&gt;
&lt;p&gt;\[ E = E_k = \frac{p^2}{2m} = \frac{g^2}{2m_e} \]&lt;/p&gt;
&lt;p&gt;\(E\) 与 \(g\) 呈二次函数式色散关系，那么只要某个带的色散关系与抛物线相似，就有理由认为某能带可能是 IPS ，比如下面的图中 4 eV 附近 \(\Gamma\) 点的能带明显呈抛物线色散关系，而它们也确实算是 IPS 。&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;AgBenzene-band.png&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;AgBenzene-band.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;如果更有耐心的话，可以算一下那几条带的相对有效质量，如果接近 1 ，就可以很明确地说明这几条带是 IPS ，可惜本人不太想再算这个（实际就是懒），这个就算作「读者自证不难」吧2333。&lt;/p&gt;
&lt;h2 id=&#34;附录&#34;&gt;附录&lt;/h2&gt;
&lt;h3 id=&#34;镜像势表达式的推导&#34;&gt;镜像势表达式的推导&lt;/h3&gt;
&lt;p&gt;这里更一般地推导一下两种介质界面处镜像势的表达式，过程参考自&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;假设有两种介质 1 和 2，它们的介电常数分别为 \(\epsilon_1\) 和 \(\epsilon_2\) ，有电荷
\(q\) 在介质 1 中，如下图所示：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;ips2.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;ips2.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;现在将问题分成两部分来看：分别计算介质 1 和介质 2 中电场强度。&lt;/p&gt;
&lt;p&gt;在介质 1 中任取一点 \(P\) ，同时认为 \(q\) 的镜像电荷等效带电量为 \(q&#39;\) ，则
\(P\) 点的受力如下图所示&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;ips3.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;ips3.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;此处的电场强度为&lt;/p&gt;
&lt;p&gt;\[\begin{aligned}
V_1 &amp;amp;={} \frac{1}{4\pi \epsilon_1} \left( \frac{q}{R_1} + \frac{q&#39;}{R_2} \right) \newline
R_1 &amp;amp;={} \sqrt{(z-d)^2 + r^2} \newline
R_2 &amp;amp;={} \sqrt{(z+d)^2 + r^2} \newline
E_z &amp;amp;={} -\frac{\partial V_1}{\partial z} = \frac{1}{4\pi\epsilon_1}
\left[ \frac{q(z-d)}{R_1^3} + \frac{q&#39;(z-d)}{R_2^3} \right] \newline
E_r &amp;amp;={} -\frac{\partial V_1}{\partial r} = \frac{1}{4\pi\epsilon_1}
\left[ \frac{qr}{R_1^3} + \frac{q&#39; r}{R_2^3} \right] \newline
\end{aligned}\]&lt;/p&gt;
&lt;p&gt;现在考虑介质 2 中的电场强度，由于经过一个介面，介电常数分布发生了改变，所以在介质 2 中所感受到的原来电荷的等效电荷为 \(q&#39;&#39;\) 。&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;ips4.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;ips4.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;P 点的电场强度可以计算出来：&lt;/p&gt;
&lt;p&gt;\[\begin{aligned}
V_2 &amp;amp;={} \frac{1}{4\pi\epsilon_2} \frac{q&#39;&#39;}{R_3} \newline
R_3 &amp;amp;={} \sqrt{(z-d)^2 + r^2} \newline
E_z^{(2)} &amp;amp;={} -\frac{\partial V_2}{\partial z} =
\frac{1}{4\pi\epsilon_2} \frac{q&#39;&#39; (z-d)}{R_3^3} \newline
E_r^{(2)} &amp;amp;={} -\frac{\partial V_2}{\partial r} =
\frac{1}{4\pi\epsilon_2} \frac{q&#39;&#39; r}{R_3^3} \newline
\end{aligned}\]&lt;/p&gt;
&lt;p&gt;在界面处应用导体介质界面上的边界条件：&lt;/p&gt;
&lt;p&gt;\[\begin{cases}
z = 0 \implies R_1 = R_2 = R_3 = R \newline
D_z^{(1)} = D_z^{(2)} \newline
E_r^{(1)} = E_r^{(2)} \newline
\end{cases}\]&lt;/p&gt;
&lt;p&gt;即：&lt;/p&gt;
&lt;p&gt;\[\begin{aligned}
\epsilon_1 E_z^{(1)} &amp;amp; = {} \epsilon_2 E_z^{(2)} \newline
\implies \epsilon_1 \frac{1}{4\pi\epsilon_1} \frac{(q-q&#39;)d}{R^3} &amp;amp; = {}
\epsilon_2 \frac{1}{4\pi\epsilon_2} \frac{q&#39;&#39; d}{R^3} \newline
\implies q - q&#39; &amp;amp;={} q&#39;&#39;
\end{aligned}\]&lt;/p&gt;
&lt;p&gt;\[\begin{aligned}
E_r^{(1)} &amp;amp;={} E_r^{(2)} \newline
\implies \frac{1}{4\pi\epsilon_1} \frac{(q+q&#39;)r}{R^3} &amp;amp;={}
\frac{1}{4\pi\epsilon_2} \frac{q&#39;&#39; r}{R^2} \newline
\implies \frac{q+q&#39;}{\epsilon_1} &amp;amp;={} \frac{q&#39;&#39;}{\epsilon_2}
\end{aligned}\]&lt;/p&gt;
&lt;p&gt;联立上面两式，可以得到&lt;/p&gt;
&lt;p&gt;\[ q&#39; = -\frac{\epsilon_2 - \epsilon_1}{\epsilon_2 + \epsilon_1} q \]&lt;/p&gt;
&lt;p&gt;如果用相对介电常数 \(\epsilon_r = \dfrac{\epsilon_2}{\epsilon_1}\) ，上面式子还能简化为&lt;/p&gt;
&lt;p&gt;\[ q&#39; = -\frac{\epsilon_r - 1}{\epsilon_r + 1} q = -\beta q \]&lt;/p&gt;
&lt;p&gt;这就是前文中镜像电荷表达式中 \(\beta\) 的来源。可以看出，如果 \(\epsilon_r &amp;lt; 1\)
，镜像电荷的符号与原来电荷相同。&lt;/p&gt;
&lt;p&gt;电荷 \(q\) 的受力以及势能表达式：&lt;/p&gt;
&lt;p&gt;\[\begin{aligned}
F(z) &amp;amp;={} -\frac{\beta q^2}{4\pi \epsilon_0 (2z)^2} \quad \beta = \frac{\epsilon_r-1}{\epsilon_r+1} \newline
V(z) &amp;amp;={} -\frac{\beta q^2}{4\pi \epsilon_r \cdot 4z}
\end{aligned}\]&lt;/p&gt;
&lt;p&gt;文中第一节的表达式得证。&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Wikipedia Surface States item &lt;a href=&#34;https://en.wikipedia.org/wiki/Surface_states&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Surface_states&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;One-dimensional hydrogen atom &lt;a href=&#34;https://royalsocietypublishing.org/doi/10.1098/rspa.2015.0534&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://royalsocietypublishing.org/doi/10.1098/rspa.2015.0534&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Image potential surface states
&lt;a href=&#34;https://iopscience.iop.org/article/10.1088/0031-8949/36/4/009/pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://iopscience.iop.org/article/10.1088/0031-8949/36/4/009/pdf&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;真空能级可以在 &lt;code&gt;OUTCAR&lt;/code&gt; 里找到（ &lt;code&gt;grep vacuum OUTCAR&lt;/code&gt; ）&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;图片来自 Image-potential-induced states at metal surfaces &lt;a href=&#34;https://www.sciencedirect.com/science/article/pii/S0368204802001500&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://www.sciencedirect.com/science/article/pii/S0368204802001500&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Classical Electrodynamics, From Image Charges to the Photon Mass and
Magnetic monopoles, Francesco Lacava &lt;a href=&#34;https://www.springer.com/gp/book/9783319394732&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://www.springer.com/gp/book/9783319394732&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
    <item>
      <title>VASP 偶极校正及功函数的计算</title>
      <link>http://ionizing.page/post/vasp-dipol-correction-work-function/</link>
      <pubDate>Fri, 23 Apr 2021 16:44:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/vasp-dipol-correction-work-function/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%a6%82%e5%bf%b5%e8%a7%a3%e9%87%8a&#34;&gt;概念解释&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8a%9f%e5%87%bd%e6%95%b0&#34;&gt;功函数&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%9c%9f%e7%a9%ba%e8%83%bd%e7%ba%a7&#34;&gt;真空能级&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%81%b6%e6%9e%81%e6%a0%a1%e6%ad%a3&#34;&gt;偶极校正&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%a6%82%e4%bd%95%e8%ae%a1%e7%ae%97&#34;&gt;如何计算&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%81%b6%e6%9e%81%e6%a0%a1%e6%ad%a3&#34;&gt;偶极校正&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8a%9f%e5%87%bd%e6%95%b0&#34;&gt;功函数&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%9c%9f%e7%a9%ba%e8%83%bd%e7%ba%a7&#34;&gt;真空能级&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;水文一篇，介绍了如何用 VASP 添加偶极校正参数、计算 Slab 体系的功函数，以及如何找真空能级。&lt;/p&gt;
&lt;h2 id=&#34;概念解释&#34;&gt;概念解释&lt;/h2&gt;
&lt;h3 id=&#34;功函数&#34;&gt;功函数&lt;/h3&gt;
&lt;p&gt;将一个固体内部的电子移动到真空所需的能量。（类似于光电效应方程中的逸出功）。&lt;/p&gt;
&lt;h3 id=&#34;真空能级&#34;&gt;真空能级&lt;/h3&gt;
&lt;p&gt;固体表面外真空中自由电子所具有的能量。换句话说，电子跑出固体表面并达到这个能级后即可认为它自由 &lt;del&gt;免费&lt;/del&gt; 了。&lt;/p&gt;
&lt;h3 id=&#34;偶极校正&#34;&gt;偶极校正&lt;/h3&gt;
&lt;p&gt;因 VASP 所适用的体系是周期性体系，使用它来模拟实验中的 Slab 模型时会取一个相当大的真空层来隔绝相信两个周期中 Slab 的相互作用。理想情况下，真空层中的功函数应当是一条水平的直线（函数值为定值）。但如果表面的两侧并非对称，即其中一侧吸附了分子时，
这两侧的功函数存在差异，此时如果不进行偶极校正，真空中的功函数会是一条斜线；而经过偶极校正后，功函数会出现一个阶梯，阶梯两侧附近的曲接近水平。下图&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;是一个例子。&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:DFT-DC1&#34;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;link rel=&#34;stylesheet&#34; href=&#34;http://ionizing.page/css/hugo-easy-gallery.css&#34; /&gt;
&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;VCL-2.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 1: &amp;lt;/span&amp;gt;DFT 曲线为未经过偶极校正的功函数， DFT-DC 曲线是经过偶极校正后的功函数&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;VCL-2.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 1: &lt;/span&gt;DFT 曲线为未经过偶极校正的功函数， DFT-DC 曲线是经过偶极校正后的功函数&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;h2 id=&#34;如何计算&#34;&gt;如何计算&lt;/h2&gt;
&lt;h3 id=&#34;偶极校正&#34;&gt;偶极校正&lt;/h3&gt;
&lt;p&gt;VASP 中直接使用 &lt;code&gt;LDIPOL&lt;/code&gt; 和 &lt;code&gt;IDPOL&lt;/code&gt; 即可开启它的偶极校正功能。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LDIPOL = .TRUE.&lt;/code&gt; 表示打开偶极校正；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IDIPOL = 3&lt;/code&gt; 表示偶极校正所修正的方向为第 3 个晶格矢量方向对应的方向，一般来说就是 \(z\) 轴；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DIPOL = &amp;lt;3 float values&amp;gt;&lt;/code&gt; 表示体系的中心，以分数坐标表示；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上面几个 Flag 中一般来说 DIPOL 不用填，因为 VASP 手册中&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;有一句&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If the flag is not set, VASP determines, where the charge density averaged over
one plane drops to a minimum and calculates the center of the charge
distribution by adding half of the lattice vector perpendicular to the plane
where the charge density has a minimum (this is a rather reliable approach for
orthorhombic cells).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;不过有时不填它会导致体系 &lt;strong&gt;非常&lt;/strong&gt; 难以收敛，如果遇到这各情况，最好还是手动算一下所有原子 \(z\) 坐标的平均值，然后 &lt;code&gt;DIPOL = 0.5 0.5 &amp;lt;averaged z&amp;gt;&lt;/code&gt; ，此时修正效果可能并不好，读者需要：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开偶极校正和 &lt;code&gt;DIPOL = 0.5 0.5 &amp;lt;averaged z&amp;gt;&lt;/code&gt; ，并弛豫结构到稳定；&lt;/li&gt;
&lt;li&gt;关闭 &lt;code&gt;DIPOL&lt;/code&gt; ，并弛豫到结构稳定；&lt;/li&gt;
&lt;li&gt;关闭 &lt;code&gt;DIPOL&lt;/code&gt; ，打开 &lt;code&gt;LVHAR = .TRUE.&lt;/code&gt; ，并做静态计算，得到功函数；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;偶极校正的标准是功函数出现台阶，并且台阶两边为水平，如果画出的功函数图不是这样，
就要考虑调整参数了。&lt;/p&gt;
&lt;h3 id=&#34;功函数&#34;&gt;功函数&lt;/h3&gt;
&lt;p&gt;在 VASP 中 &lt;code&gt;LVHAR&lt;/code&gt; &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;参数可以使 VASP 输出体系的功函数文件 &lt;code&gt;LOCPOT&lt;/code&gt; 。LOCPOT
文件本身是 Volumetric data ，它的格式与 CHGCAR 一样&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;。一般而言，用户关心的功函数是垂直于表面方向上的数据，因此在得到 LOCPOT 后需要对它做一点工作，即对 \(xy\)
平面内的数据做平均，然后乘以晶胞的体积，就得到我们需要的功函数信息。这里给出一个脚本&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;来完成这项工作：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;locpot_mean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fname&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;LOCPOT&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;z&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;savefile&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;locpot.dat&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;outcar&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;OUTCAR&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&amp;#39;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;    Reads the LOCPOT file and calculate the average potential along `axis`.
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;     @in: See function argument.
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;    @out:
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;          - xvals: grid data along selected axis;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;          - mean: averaged potential corresponding to `xvals`.
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_efermi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;outcar&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;OUTCAR&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isfile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;outcar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;logger&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;warning&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;OUTCAR file not found. E-fermi set to 0.0eV&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;txt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;outcar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;efermi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;re&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;search&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;E-fermi :\s*([-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?)&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;txt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;groups&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;logger&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Found E-fermi = &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;efermi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;efermi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;logger&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Loading LOCPOT file &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fname&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;locd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VaspChargeDensity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fname&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;locd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;atoms&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;latlens&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;linalg&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;norm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;vol&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;linalg&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;det&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;iaxis&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;z&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;remove&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iaxis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;locpot&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;locd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;chg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# must multiply with cell volume, similar to CHGCAR&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;logger&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Calculating workfunction along &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; axis&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;mean&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locpot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vol&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;xvals&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;linspace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;latlens&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iaxis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;locpot&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shape&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iaxis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;# save to &amp;#39;locpot.dat&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;efermi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_efermi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;outcar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;logger&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Saving raw data to &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;savefile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;efermi&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;savetxt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;savefile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xvals&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                   &lt;span class=&#34;n&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%13.5f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Distance(A) Potential(eV) # E-fermi not corrected&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;mean&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;efermi&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;savetxt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;savefile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xvals&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
                   &lt;span class=&#34;n&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%13.5f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Distance(A) Potential(eV) # E-fermi shifted to 0.0eV&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;完整的脚本文件已经放 Gist&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt; 上，当然你也可以直接点击&lt;a href=&#34;vasp-dipol-correction-work-function/plot-workfunc.py&#34;&gt;它&lt;/a&gt;
来下载。运行这个脚本后得到的 Workfunction.pdf 和 locpot.dat 就是 \(z\) 方向上的功函数信息。&lt;/p&gt;
&lt;p&gt;&lt;a id=&#34;figure--fig:Workfunction&#34;&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;Workfunction.png&#34; alt=&#34;&amp;lt;span class=&amp;#34;figure-number&amp;#34;&amp;gt;Figure 2: &amp;lt;/span&amp;gt;Workfunction.png 示例&#34;/&gt;
    &lt;/div&gt;
    &lt;a href=&#34;Workfunction.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;
          &lt;p&gt;
              &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 2: &lt;/span&gt;Workfunction.png 示例&lt;/p&gt;
          &lt;/p&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;h2 id=&#34;真空能级&#34;&gt;真空能级&lt;/h2&gt;
&lt;p&gt;前面已经提到，真空能级可以读取 locpot.dat 真空部分的数据得到，其实当你打开
&lt;code&gt;LVHAR&lt;/code&gt; 时，它也可以通过读取 OUTCAR 得到，比如&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ grep vacuum OUTCAR
 vacuum level on the upper side and lower side of the slab         2.807         3.188
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里的 upper side vacuum level 是指 Slab 上表面的真空能级（图 &lt;a href=&#34;#figure--fig:Workfunction&#34;&gt;2&lt;/a&gt;

中 30A 处的平台）， lower side vacuum level 自然就是下表面的真空能级了
（图 &lt;a href=&#34;#figure--fig:Workfunction&#34;&gt;2&lt;/a&gt;
 中 35A 处的平台）。&lt;/p&gt;
&lt;p&gt;需要注意的是，从 OUTCAR 中 grep 出的真空能级没有经过费米能级修正，它需要减去
OUTCAR 中的 E-fermi 才是实验中测得的功函数的值。所幸的是 plot-workfunc.py 已经做了这个工作，用 locpot.dat 画出来的图就对应实验所测结果。&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;图源： &lt;a href=&#34;http://exciting-code.org/nitrogen-dipole-correction&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;http://exciting-code.org/nitrogen-dipole-correction&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.vasp.at/wiki/index.php/DIPOL&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://www.vasp.at/wiki/index.php/DIPOL&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;在 VASP 5.2.12 之前的版本中 &lt;code&gt;LVTOT&lt;/code&gt; 输出的文件是静电势的贡献；但在 VASP
5.2.12 及之后的版本中，交换关联势的贡献也会被写入 &lt;code&gt;LOCPOT&lt;/code&gt; 中， &lt;code&gt;LVHAR&lt;/code&gt; 输出的部
分才是真正静电势的贡献，也就是我们想要的部分；&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;CHGCAR 的格式请见 VASP 手册 &lt;a href=&#34;https://www.vasp.at/wiki/index.php/CHGCAR&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://www.vasp.at/wiki/index.php/CHGCAR&lt;/a&gt;
 ；&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;完整脚本见 &lt;a href=&#34;https://gist.github.com/Ionizing/1ac92f98e8b00a1cf6f16bd57694ff03&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://gist.github.com/Ionizing/1ac92f98e8b00a1cf6f16bd57694ff03&lt;/a&gt;
 。&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
    <item>
      <title>VASP 收敛性测试的小脚本</title>
      <link>http://ionizing.page/post/vasp-convergence-test-scripts/</link>
      <pubDate>Fri, 16 Apr 2021 20:57:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/vasp-convergence-test-scripts/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#sigma-%e7%9a%84%e6%b5%8b%e8%af%95&#34;&gt;&lt;code&gt;SIGMA&lt;/code&gt; 的测试&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#encut-%e7%9a%84%e6%b5%8b%e8%af%95&#34;&gt;&lt;code&gt;ENCUT&lt;/code&gt; 的测试&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%99%b6%e6%a0%bc%e5%8f%82%e6%95%b0%e7%9a%84%e6%b5%8b%e8%af%95&#34;&gt;晶格参数的测试&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%99%b6%e6%a0%bc%e5%b8%b8%e6%95%b0%e7%9a%84%e6%b5%8b%e8%af%95&#34;&gt;晶格常数的测试&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%99%b6%e6%a0%bc%e9%95%bf%e5%ba%a6%e7%9a%84%e6%b5%8b%e8%af%95&#34;&gt;晶格长度的测试&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#slab-%e8%a1%ac%e5%ba%95%e5%b1%82%e6%95%b0%e7%9a%84%e6%b5%8b%e8%af%95&#34;&gt;Slab 衬底层数的测试&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;一般而言，在使用 VASP 计算体系之前都需要对一些参数做收敛性测试，侯老师&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
曾写过一本VASP 入门手册，里面给了一些测试计算参数的小脚本，这里我也给出一些我经常用的收敛性测试脚本，权当抛砖引玉了。&lt;/p&gt;
&lt;p&gt;本文提供的测试脚本可以写进提交任务的脚本中，进而充分利用超算上多核、多节点的计算资源。需要注意的是，这些脚本本身并不产生 VASP 的输入文件，而是在已有的文件基础上进行修改。&lt;/p&gt;
&lt;h2 id=&#34;sigma-的测试&#34;&gt;&lt;code&gt;SIGMA&lt;/code&gt; 的测试&lt;/h2&gt;
&lt;p&gt;和上面的使用前提一样， INCAR 应提前准备好。 SIGMA 收敛的标准通常是 dE 绝对值小于
1.0meV/atom 。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;#SBATCH xx&lt;/span&gt;
...

&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -e
&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -o pipefail

&lt;span class=&#34;nv&#34;&gt;VASP_EXEC&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;srun /path/to/vasp&amp;#34;&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# &amp;#34;mpirun -np xxx&amp;#34; is also ok&lt;/span&gt;

date &amp;gt;&amp;gt; sigma.txt
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; i in 0.8 0.5 0.3 0.1 0.08 0.05 &lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;
    sed -i &lt;span class=&#34;s2&#34;&gt;&amp;#34;s/^.*\\bSIGMA\\b.*&lt;/span&gt;$&lt;span class=&#34;s2&#34;&gt;/        SIGMA = &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; INCAR
    &lt;span class=&#34;nb&#34;&gt;eval&lt;/span&gt; &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;VASP_EXEC&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;nv&#34;&gt;TS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;grep &lt;span class=&#34;s2&#34;&gt;&amp;#34;EENTRO&amp;#34;&lt;/span&gt; OUTCAR &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; tail -1 &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;{print $5}&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TS&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; sigma.txt
&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;

&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;NIONS = &amp;#34;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;grep NIONS OUTCAR &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;{print $12}&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &amp;gt;&amp;gt; sigma.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;encut-的测试&#34;&gt;&lt;code&gt;ENCUT&lt;/code&gt; 的测试&lt;/h2&gt;
&lt;p&gt;使用前请先写好一个 INCAR ，并确保里面包含 &lt;code&gt;ENCUT&lt;/code&gt; 字段，且 &lt;code&gt;ENCUT&lt;/code&gt; 单独占一行
（否则同一行内的其它参数会被舍去）。通常而言，达到收敛的标志是相邻两次迭代的能量小于 1.0meV/atom 。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;#SBATCH xx&lt;/span&gt;
...

&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -e
&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -o pipefail

&lt;span class=&#34;nv&#34;&gt;VASP_EXEC&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;srun /path/to/vasp&amp;#34;&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# &amp;#34;mpirun -np xxx&amp;#34; is also ok&lt;/span&gt;

date &amp;gt;&amp;gt; encut.txt
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; i in &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;200..500..50&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
    sed -i &lt;span class=&#34;s2&#34;&gt;&amp;#34;s/^.*\\bENCUT\\b.*&lt;/span&gt;$&lt;span class=&#34;s2&#34;&gt;/        ENCUT = &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; INCAR
    &lt;span class=&#34;nb&#34;&gt;eval&lt;/span&gt; &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;VASP_EXEC&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;nv&#34;&gt;E&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;grep TOTEN OUTCAR &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; tail -1 &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;{printf &amp;#34;%12.6f&amp;#34;, $5}&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# Extract TOTEN from OUTCAR&lt;/span&gt;
    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$E&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; encut.txt
&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;

&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;NIONS = &amp;#34;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;grep NIONS OUTCAR &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;{print $12}&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &amp;gt;&amp;gt; encut.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;晶格参数的测试&#34;&gt;晶格参数的测试&lt;/h2&gt;
&lt;h3 id=&#34;晶格常数的测试&#34;&gt;晶格常数的测试&lt;/h3&gt;
&lt;p&gt;执行这个测试需要准备好 POSCAR ，这个测试不依赖 ASE 等包，因为它实质上是在更改
POSCAR 第二行的 scale factor 。这个测试只是相对粗糙的测试，因此这里就直接在原位覆盖前一次的计算结果了。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;#SBATCH xx&lt;/span&gt;
...

&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -e
&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -o pipefail

&lt;span class=&#34;nv&#34;&gt;VASP_EXEC&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;srun /path/to/vasp&amp;#34;&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# &amp;#34;mpirun -np xxx&amp;#34; is also ok&lt;/span&gt;

date &amp;gt;&amp;gt; a.txt
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; i in &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;seq 0.99 0.001 1.01&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
  sed -i &lt;span class=&#34;s2&#34;&gt;&amp;#34;2c &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; POSCAR
  &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;a = &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; angstrom&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;nb&#34;&gt;eval&lt;/span&gt; &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;VASP_EXEC&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;nv&#34;&gt;E&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;grep &lt;span class=&#34;s2&#34;&gt;&amp;#34;TOTEN&amp;#34;&lt;/span&gt; OUTCAR &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; tail -1 &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;{printf &amp;#34;%12.6f&amp;#34;, $5 }&amp;#39;&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
  &lt;span class=&#34;nv&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;grep &lt;span class=&#34;s2&#34;&gt;&amp;#34;volume&amp;#34;&lt;/span&gt; OUTCAR &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; tail -1 &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;{printf &amp;#34;%12.4f&amp;#34;, $5}&amp;#39;&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
  &lt;span class=&#34;nb&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;a = %6.3f Vol = %10.4f Energy = %18.10f\n&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$i&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$V&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$E&lt;/span&gt; &amp;gt;&amp;gt; a.txt
  tail -1 a.txt
&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;\n\n&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; a.txt#+end_src
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;晶格长度的测试&#34;&gt;晶格长度的测试&lt;/h3&gt;
&lt;p&gt;在测试晶格的角度、长度时就不得不使用其它包了，Python 的 ASE 包提供了相对完善的基础设施，这里在使用它来辅助完成晶格测试的工作。另外，在测试 Slab 的真空层厚度时也可以使用这个脚本&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;ch&#34;&gt;#!/usr/bin/env python3&lt;/span&gt;

&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;ase.io&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;read&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;poscar_reader&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;poscar&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;poscar_reader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;POSCAR&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;poscar&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_cell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;copy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;5.0&lt;/span&gt;             &lt;span class=&#34;c1&#34;&gt;# Increase length along z axis by 5 angstroms each time&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;poscar&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set_cell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;dirname&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{:02}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exists&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dirname&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mkdir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dirname&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;           &lt;span class=&#34;c1&#34;&gt;# create directories for each test&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;poscar&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dirname&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/POSCAR&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vasp5&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;direct&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;infile&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;INCAR&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;POTCAR&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;KPOINTS&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;sub_vasp_tahoma&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;abspath&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;abspath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;infile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;symlink&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;abspath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dirname&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;infile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;pass&lt;/span&gt;
    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;POSCAR saved in &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dirname&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/POSCAR&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;用户可以根据自己需要随意更改晶格的参数，具体的需求可以通过阅读 ASE 的文档&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;来实现，这里就不一一列举了。&lt;/p&gt;
&lt;h2 id=&#34;slab-衬底层数的测试&#34;&gt;Slab 衬底层数的测试&lt;/h2&gt;
&lt;p&gt;一般而言，结构建模都是在 Materials Studio 上完成的（我现在也是如此），但如果有对
Slab 衬底做收敛性测试的需求，还是要借助一下 ASE ，它也内置一了些常见的 Slab 。&lt;/p&gt;
&lt;p&gt;下面是一个生成不同层数 Ag(111) Slab 的脚本：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;ch&#34;&gt;#!/usr/bin/env python3&lt;/span&gt;

&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;numpy&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;np&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;ase.build&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fcc111&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;ase.constraints&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FixAtoms&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;numstr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;# generate 1x1 slab along a and b axis, this slab has `i` layers&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# vacuum is 20 angstrom&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;slab&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fcc111&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Ag&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vacuum&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;# Relax the first 2 layers and fix the others.&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FixAtoms&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mask&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;atom&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tag&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;atom&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;slab&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;# Apply the constraint&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;slab&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set_constraint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slab&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exists&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numstr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;makedirs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numstr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/opt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;makedirs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numstr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/band&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;pass&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;slab&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numstr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/opt/POSCAR&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vasp5&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;direct&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对于其它金属， ASE 也有支持，详细说明请看它的文档&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/orivenlikon/vaspDoc/blob/master/%5Bmuchong.com%5Dvasp%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97-%E5%A4%8D%E6%97%A6-%E4%BE%AF%E6%9F%B1%E5%B3%B0.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://github.com/orivenlikon/vaspDoc/blob/master/%5Bmuchong.com%5Dvasp%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97-%E5%A4%8D%E6%97%A6-%E4%BE%AF%E6%9F%B1%E5%B3%B0.pdf&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;这个脚本要求晶格的 c 轴垂直于 a 轴和 b 轴&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wiki.fysik.dtu.dk/ase/ase/atoms.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://wiki.fysik.dtu.dk/ase/ase/atoms.html&lt;/a&gt;
 和
&lt;a href=&#34;https://wiki.fysik.dtu.dk/ase/ase/geometry.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://wiki.fysik.dtu.dk/ase/ase/geometry.html&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wiki.fysik.dtu.dk/ase/ase/build/build.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://wiki.fysik.dtu.dk/ase/ase/build/build.html&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
    <item>
      <title>记一次 Julia 代码性能优化过程</title>
      <link>http://ionizing.page/post/a-try-on-julia-code-optimization/</link>
      <pubDate>Fri, 16 Apr 2021 13:06:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/a-try-on-julia-code-optimization/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%bf%90%e8%a1%8c%e7%8e%af%e5%a2%83&#34;&gt;运行环境&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%bc%98%e5%8c%96%e8%bf%87%e7%a8%8b&#34;&gt;优化过程&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8e%9f%e5%a7%8b%e7%89%88%e6%9c%ac&#34;&gt;原始版本&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%bd%bf%e7%94%a8-c-ffi-%e7%9a%84-rgamma-%e4%b8%8e-rnorm&#34;&gt;使用 C-ffi 的 &lt;code&gt;rgamma&lt;/code&gt; 与 &lt;code&gt;rnorm&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8e%bb%e9%99%a4%e5%a4%96%e9%83%a8%e4%be%9d%e8%b5%96&#34;&gt;去除外部依赖&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%86%85%e5%ad%98%e5%88%86%e9%85%8d%e6%83%85%e5%86%b5%e5%88%86%e6%9e%90&#34;&gt;内存分配情况分析&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8e%bb%e9%99%a4%e5%86%85%e5%b1%82%e5%be%aa%e7%8e%af%e7%9a%84%e5%86%85%e5%ad%98%e5%88%86%e9%85%8d&#34;&gt;去除内层循环的内存分配&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8e%bb%e9%99%a4%e5%a4%96%e5%b1%82%e5%be%aa%e7%8e%af%e7%9a%84%e5%86%85%e5%ad%98%e5%88%86%e9%85%8d&#34;&gt;去除外层循环的内存分配&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%bd%bf%e7%94%a8%e5%a4%9a%e7%ba%bf%e7%a8%8b%e5%8a%a0%e9%80%9f&#34;&gt;使用多线程加速&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34;&gt;总结&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;这是和某三爷讨论后对交流内容的整理。&lt;/p&gt;
&lt;p&gt;众所周知， Julia 是一种高级通用动态编程语言，它专为科学计算而生。为了方便科研人员使用，它的语法被设计得很像 MATLAB ，但比 MATLAB 更合理（譬如数组引用使用 &lt;code&gt;[]&lt;/code&gt;
，而不是 &lt;code&gt;()&lt;/code&gt; ）。作为一门很年轻的语言，它吸收了前辈们的很多优点，也有着自己的特色，但最受人青睐的一点在于：尽管它是一门动态语言，却宣称拥有 C/C++ 一般的性能。
一般而言，动态语言的表现能力更为出色，能用更少的代码做更多的事，开发效率高；而静态语言的编译器后端更容易优化，运行效率高。Julia 有动态性，开发效率毋庸置疑，一些测评也显示 Julia 确实拥有很强的性能，但这是否意味着你随手写的一段代码就能有很高并且达到预期的性能？我看未必。&lt;/p&gt;
&lt;h2 id=&#34;运行环境&#34;&gt;运行环境&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Processor&lt;/th&gt;
&lt;th&gt;Intel Core i5 9600KF&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;16GB 3200MHz&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OS&lt;/td&gt;
&lt;td&gt;macOS 10.15.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Julia&lt;/td&gt;
&lt;td&gt;1.5.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;优化过程&#34;&gt;优化过程&lt;/h2&gt;
&lt;h3 id=&#34;原始版本&#34;&gt;原始版本&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;p&gt;废话不多说，直接开始正题，先来看今天的主角&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;using Rmath;
using BenchmarkTools;

function JGibbs1(N::Int, thin::Int)
    mat = zeros(Float64, N, 2)
    x   = 0.
    y   = 0.
    for i = 1:N
        for j = 1:thin
            x = rgamma(1, 3, 1/(y*y + 4))[1]
            y = rnorm(1, 1/(x+1), 1/sqrt(2(x + 1)))[1]
        end
        mat[i,:] = [x,y]
    end
    mat
end;

@btime JGibbs1(20000, 200);
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这是一段关于 Gibbs 采样的代码，它主要由两个循环组成，外部循环一次产生两个值，内部循环是迭代式的，即下一次循环要用到上次循环的结果。很明显它引入了 R 的库，并用
R 的 &lt;code&gt;rgamma&lt;/code&gt; 和 &lt;code&gt;rnorm&lt;/code&gt; 实现，那么它的性能是怎样的呢？&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;501.798 ms (8020002 allocations: 734.56 MiB)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;根据原文的说法，它的性能已经比 &lt;code&gt;Rgibbs&lt;/code&gt; 快 17 倍，比 &lt;code&gt;RCgibbs&lt;/code&gt; 快 13 倍，已经是比较令人满意的结果了。&lt;/p&gt;
&lt;h3 id=&#34;使用-c-ffi-的-rgamma-与-rnorm&#34;&gt;使用 C-ffi 的 &lt;code&gt;rgamma&lt;/code&gt; 与 &lt;code&gt;rnorm&lt;/code&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;p&gt;由于直接用 R 写的代码可能并不是最快的，而且它还在内层循环里，所以我们有理由相信使用 C-ffi&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; 版的 &lt;code&gt;rgamma&lt;/code&gt; 与 &lt;code&gt;rnorm&lt;/code&gt; 会更快。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;using Rmath
import Rmath: libRmath
using BenchmarkTools
function JGibbs2(N::Int, thin::Int)
    mat = zeros(Float64, N, 2)
    x   = 0.
    y   = 0.
    for i = 1:N
        for j = 1:thin
            x = ccall((:rgamma, libRmath), Float64, (Float64, Float64), 3., 1/(y*y + 4))
            y = ccall((:rnorm, libRmath), Float64, (Float64, Float64), 1/(x+1), 1/sqrt(2*(x + 1)))
        end
        mat[i,:] = [x,y]
    end
    mat
end

@btime JGibbs2(20000, 200);
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;JGibbs2 (generic function with 1 method)
  259.387 ms (20002 allocations: 2.14 MiB)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;果然，使用 C-ffi 版的函数后性能又提升了一倍！&lt;/p&gt;
&lt;h3 id=&#34;去除外部依赖&#34;&gt;去除外部依赖&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;p&gt;尽管使用 C 的实现后， &lt;code&gt;JGibbs&lt;/code&gt; 性能提升巨大，但依赖外部库多少有点让人感觉不爽，
毕竟它和 Julia 所宣称的高性能关系不是很大（核心部分是 C 的贡献，而不是 Julia）。
既然 Julia 也是高性能语言，何不拿纯 Julia 写一个 &lt;code&gt;JGibbs&lt;/code&gt; 来比比？&lt;/p&gt;
&lt;p&gt;Julia 是为科学计算而生，它的社区维护了一个统计学库 &lt;code&gt;Distributions&lt;/code&gt; ，里面包含了
&lt;code&gt;gamma&lt;/code&gt; 与 &lt;code&gt;norm&lt;/code&gt; 分布的函数，可以用来替换 &lt;code&gt;rgamma&lt;/code&gt; 和 &lt;code&gt;rnorm&lt;/code&gt; ，写完之后是这个样子：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;using BenchmarkTools;
using Distributions;

function JGibbs3(N::Int, thin::Int)
    mat = zeros(Float64, N, 2)
    x   = 0.
    y   = 0.
    for i = 1:N
        for j = 1:thin
            x = rand(Gamma(3, 1/(y^2 + 4)), 1)[1]
            y = rand(Normal(1/(x + 1), 1/sqrt(2*(x + 1))), 1)[1]
        end
        mat[i,:] = [x,y]
    end
    mat
end

@btime JGibbs3(20000, 200);
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;JGibbs3 (generic function with 1 method)
  550.624 ms (8020002 allocations: 734.56 MiB)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;咦？看起来它还没有使用 R-ffi 的函数快！&lt;/p&gt;
&lt;p&gt;那么问题出在哪呢？仔细看结果，除了时间之外还有两个数据，一个是执行一次该函数时所分配内存的次数，另一个是函数执行期间分配内存的总量。我们回头看一下使用 C-ffi 的版本，它的测试结果显示除了性能更强外，内存分配的次数和总量也更少！而且 8020002
恰好是 20002 的 400 倍左右，正好是 &lt;code&gt;thin=200&lt;/code&gt; 的 2 倍。据此，我们可以猜想，在
&lt;code&gt;for j=1:thin ... end&lt;/code&gt; 内部存在不必要的内存分配。&lt;/p&gt;
&lt;p&gt;下面来进行验证。&lt;/p&gt;
&lt;h3 id=&#34;内存分配情况分析&#34;&gt;内存分配情况分析&lt;/h3&gt;
&lt;p&gt;取出循环内的一行代码，对它进行 profile ：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;using BenchmarkTools;
using Distributions;

@btime rand(Gamma(1.0, 1.0), 1)[1];
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;39.136 ns (1 allocation: 96 bytes)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;奇怪，一个只返回一个 Float64 值的函数怎么会存在内存分配？仔细看 &lt;code&gt;[1]&lt;/code&gt; 这个细节，
问题可能出在这里。通过查看文档，发现 &lt;code&gt;rand(Gamma(...), 1)&lt;/code&gt; 中最后一个参数表示返回一个一维的 Array ，并且 Array 的大小是 1 ：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;using BenchmarkTools;
using Distributions;

@btime rand(Gamma(1.0, 1.0), 1)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;  37.541 ns (1 allocation: 96 bytes)
1-element Array{Float64,1}:
 0.2929698750637693
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;一个 Float64 的值有 64 位，共 8 字节（bytes），而刚刚代码中所返回只有一个
Float64 元素的 Array 竟然有 96 字节！既然我们每次只需要返回一个值，那为什么要画蛇添足去生成一个 Array 呢，直接调用只生成一个值的原型不好吗？&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;using BenchmarkTools;
using Distributions;

@btime rand(Gamma(1.0, 1.0), 1)
@btime rand(Gamma(1.0, 1.0))
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;  37.217 ns (1 allocation: 96 bytes)
1-element Array{Float64,1}:
 0.9938638399122478
  8.116 ns (0 allocations: 0 bytes)
1.8038508272928604
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;看，直接使用 &lt;code&gt;rand(Gamma(...))&lt;/code&gt; 耗时只有 &lt;code&gt;rand(Gamma(...), 1)&lt;/code&gt; 的 22% ，并且内存的分配是 0 ！&lt;/p&gt;
&lt;p&gt;有了这些结论，我们对 &lt;code&gt;JGibbs3&lt;/code&gt; 修改后，有了下面的代码。&lt;/p&gt;
&lt;h3 id=&#34;去除内层循环的内存分配&#34;&gt;去除内层循环的内存分配&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;using BenchmarkTools;
using Distributions;

function JGibbs4(N::Int, thin::Int)
    mat = zeros(Float64, N, 2)
    x   = 0.
    y   = 0.
    for i = 1:N
        for j = 1:thin
            x = rand(Gamma(3, 1/(y*y + 4)))
            y = rand(Normal(1/(x + 1), 1/sqrt(2*(x + 1))))
        end
        mat[i,:] = [x,y]
    end
    mat
end

@btime JGibbs4(20000, 200);
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;JGibbs4 (generic function with 1 method)
  251.144 ms (20002 allocations: 2.14 MiB)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个耗时结果就正常多了，而且比调用 C-ffi 的版本还快了一丢丢；内存的分配也没那么夸张了。&lt;/p&gt;
&lt;h3 id=&#34;去除外层循环的内存分配&#34;&gt;去除外层循环的内存分配&lt;/h3&gt;
&lt;p&gt;但这并不是它的性能极限：它依然有 20002 次的内存分配。仔细观察外层循环部分，只有一个 &lt;code&gt;mat[i,:] = [x,y]&lt;/code&gt; ，通常人们会认为编译器把它循环展开，不涉及内存分配，但事实并非如此：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;using BenchmarkTools

mat = zeros(Int, 2, 2);
@btime mat[1, :] = [1, 2];
@btime mat[:, 1] = [1, 2];
@btime begin
    mat[1, 1] = 1;
    mat[1, 2] = 2;
    end;
@btime begin
    mat[1, 1] = 1;
    mat[2, 1] = 2;
    end;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;259.485 ns (2 allocations: 112 bytes)
220.621 ns (2 allocations: 112 bytes)
28.665 ns (0 allocations: 0 bytes)
27.603 ns (0 allocations: 0 bytes)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;我们可以得出三个结论：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在使用切片赋值时会涉及内存分配，直接使用循环则不会；&lt;/li&gt;
&lt;li&gt;小矩阵赋值时使用循环甚至手动展开循环性能更高；&lt;/li&gt;
&lt;li&gt;Julia 的 Array 使用列主序，对第一个维度操作比对其它维度操作性能更高，但提升幅
度有限。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;于是我们把 &lt;code&gt;JGibbs4&lt;/code&gt; 中外层循环的矩阵赋值展开，得到 &lt;code&gt;JGibbs5&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;using BenchmarkTools;
using Distributions;

function JGibbs5(N::Int, thin::Int)
    mat = zeros(Float64, N, 2)
    x   = 0.
    y   = 0.
    for i = 1:N
        for j = 1:thin
            x = rand(Gamma(3, 1/(y*y + 4)))
            y = rand(Normal(1/(x + 1), 1/sqrt(2*(x + 1))))
        end
        mat[i,1] = x;
        mat[i,2] = y;
    end
    mat
end

@btime JGibbs5(20000, 200);
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;JGibbs5 (generic function with 1 method)
  229.861 ms (2 allocations: 312.58 KiB)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它比 &lt;code&gt;JGibbs4&lt;/code&gt; 又快了 20ms ！而且其中内存分配只有两次，已经相当令人满意了。如果要进一步压榨它的性能潜力，我们可以交换 &lt;code&gt;mat&lt;/code&gt; 的行列，使外层循环每次赋值时都在访问第一个维度，限于篇幅原因，这里就不展开了。&lt;/p&gt;
&lt;h3 id=&#34;使用多线程加速&#34;&gt;使用多线程加速&lt;/h3&gt;
&lt;p&gt;上面使用的方法都是在一个线程内操作，现在的机器普遍都用上的多核处理器，而超算上更是单节点上配备了数十个处理器，如此多的计算资源不利用好岂不是暴殄天物。&lt;/p&gt;
&lt;p&gt;那么 &lt;code&gt;JGibbs&lt;/code&gt; 函数能被并行化吗？答案是肯定的。&lt;/p&gt;
&lt;p&gt;它的内层循环粒度太小，线程切换的耗时占比太高，因此内层循环不适合并行化。而外层循环的粒度适中，我们试试将它并行化。&lt;/p&gt;
&lt;!--list-separator--&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;直接使用 &lt;code&gt;Threads.@threads&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Julia 原生支持多线程编程，并且提供了 &lt;code&gt;Threads.@threads&lt;/code&gt; 宏来方便对循环并行化，于
是就有了下面的代码&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;println(&amp;#34;nthreads = &amp;#34;, Threads.nthreads())

using BenchmarkTools;
using Distributions;

function JGibbs6(N::Int, thin::Int)
    mat = zeros(Float64, N, 2)
    x   = 0.
    y   = 0.
    Threads.@threads for i = 1:N
        for j = 1:thin
            x = rand(Gamma(3, 1/(y*y + 4)))
            y = rand(Normal(1/(x + 1), 1/sqrt(2*(x + 1))))
        end
        mat[i,1] = x;
        mat[i,2] = y;
    end
    mat
end

@btime JGibbs6(20000, 200);
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;nthreads = 6
JGibbs6 (generic function with 1 method)
  420.151 ms (52000035 allocations: 915.84 MiB)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;这个结果很离谱。先不谈运行时间，单看它的内存分配量就知道它绝对是有问题的（至于为
什么多出来这么多的内存分配，我也还在寻找原因，如果您有什么见解，请务必发邮件告诉
我 ^_^）， &lt;code&gt;Julia&lt;/code&gt; 一共开了 6 个线程来加速，但结果显示它反而使运行效率降低了，问
题出在哪呢？仔细看代码&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;    x   = 0.
    y   = 0.
    Threads.@threads for i = 1:N
        for j = 1:thin
            x = rand(Gamma(3, 1/(y*y + 4)))
            y = rand(Normal(1/(x + 1), 1/sqrt(2*(x + 1))))
        end
        ...
    end
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;每个线程内，都要对全局变量 &lt;code&gt;x&lt;/code&gt; 和 &lt;code&gt;y&lt;/code&gt; 进行修改，并且还要读取它们的值，这显然存在
竞争的现象。那如果把 &lt;code&gt;x&lt;/code&gt; 和 &lt;code&gt;y&lt;/code&gt; 移动到每个线程内部定义呢？&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;println(&amp;#34;nthreads = &amp;#34;, Threads.nthreads())

using BenchmarkTools;
using Distributions;

function JGibbs6_1(N::Int, thin::Int)
    mat = zeros(Float64, N, 2)
    Threads.@threads for i = 1:N
        x   = rand()
        y   = rand()
        for j = 1:thin
            x = rand(Gamma(3, 1/(y*y + 4)))
            y = rand(Normal(1/(x + 1), 1/sqrt(2*(x + 1))))
        end
        mat[i,1] = x;
        mat[i,2] = y;
    end
    mat
end

@btime JGibbs6_1(20000, 200);
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;nthreads = 6
JGibbs6_1 (generic function with 1 method)
  39.926 ms (33 allocations: 316.75 KiB)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个结果相当令人满意了，内存的分配降低很多，看来读写全局的变量对并发程序性能影响
还是不容忽略！&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;!--list-separator--&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;对外层循环分组后并行&lt;/p&gt;
&lt;p&gt;除了直接用 &lt;code&gt;@threads&lt;/code&gt; ，我们还可以手动对外部循环分组嘛，然后每个线程分配到一小段
连续的外层循环，相当于粒度更大。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Iterators&lt;/code&gt; 提供了对 &lt;code&gt;Array&lt;/code&gt; 分组的方法：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;help?&amp;gt; Iterators.partition
  partition(collection, n)

  Iterate over a collection n elements at a time.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia&amp;gt; collect(Iterators.partition([1,2,3,4,5], 2))
  3-element Array{SubArray{Int64,1,Array{Int64,1},Tuple{UnitRange{Int64}},true},1}:
   [1, 2]
   [3, 4]
   [5]
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;利用这个函数，我们对外层循环的下标分组，然后每个线程只操作一组下标，这样有效避免了数据竞争发生。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;using BenchmarkTools;
using Distributions;

println(&amp;#34;nthreads = &amp;#34;, Threads.nthreads())

function JGibbs7(N::Int, thin::Int)
  nt = Threads.nthreads()

  # mat = zeros(Float64, N, 2)
  mat = zeros(Float64, N, 2)

  # partition
  parts = Iterators.partition(1:N, N ÷ Threads.nthreads() + 1) |&amp;gt; collect

  Threads.@threads for p in parts
    x   = 0.
    y   = 0.
    for i in p
      for j in 1:thin
        x = rand(Gamma(3, 1/(y^2 + 4)))
        y = rand(Normal(1/(x + 1), 1/sqrt(2*(x + 1))))
      end
      mat[i,1] = x
      mat[i,2] = y
    end
  end

  mat
end

@btime JGibbs7(20000, 200);
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;nthreads = 6
JGibbs7 (generic function with 1 method)
  41.631 ms (34 allocations: 316.91 KiB)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个结果和 &lt;code&gt;JGibbs6_1&lt;/code&gt; 相差不大，都是已经充分利用了 6 个线程的计算资源。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;本文从一名用户的角度，浅显地阐述了如何对一个函数进行优化，以及如何使用各类工具来帮助我们分析程序的运行状况。我得出以下几个结论，供大家参考：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用纯 Julia 编写的程序性能的 &lt;strong&gt;上限&lt;/strong&gt; 很高，完全不输于调用 FFI ，因此大家对此
不应有过多的顾虑，直接用就完事了；&lt;/li&gt;
&lt;li&gt;尽管我们认为处理器的计算是耗时大头，程序运行时的内存反复分配也可能成为程序运
行的瓶颈；&lt;/li&gt;
&lt;li&gt;在使用并发加速时应格外小心是否存在竞争的风险，能做到内聚就尽量做到内聚，否则
将来总会掉到坑里；&lt;/li&gt;
&lt;li&gt;想发挥出 Julia 真正的性能，还是需要下一些功夫的，随手一写还真不一定比其它语言
快；好在 Julia 社区提供了实用的性能分析工具，大大简化了优化的流程，这一点我十
分赞赏。&lt;/li&gt;
&lt;/ol&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;代码来自三爷的 gist :
&lt;a href=&#34;https://gist.github.com/MitsuhaMiyamizu/5edf031a36cfb260381a70060a3fea4a&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://gist.github.com/MitsuhaMiyamizu/5edf031a36cfb260381a70060a3fea4a&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;这里使用 BenchmarkTools 中的 &lt;code&gt;@btime&lt;/code&gt; 而不是 &lt;code&gt;@time&lt;/code&gt; 是因为后者并不能将代 码编译的时间去掉，前者则能多次执行，取耗时最小值，有效避免了 AOT 对计时的影响。&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;ffi 即 Foreign function interface ，用于跨语言调函数，详见
&lt;a href=&#34;https://en.wikipedia.org/wiki/Foreign_function_interface&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://en.wikipedia.org/wiki/Foreign_function_interface&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;我在启动 &lt;code&gt;julia&lt;/code&gt; 前对环境变量进行了修改 &lt;code&gt;export JULIA_NUM_THREADS=6&lt;/code&gt; ，这
样 Julia 在运行时支持最大 6 个线程操作。&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
    <item>
      <title>新的旅程</title>
      <link>http://ionizing.page/post/a-new-journey/</link>
      <pubDate>Wed, 14 Apr 2021 16:15:00 +0800</pubDate>
      
      <guid>http://ionizing.page/post/a-new-journey/</guid>
      
        <description>&lt;div class=&#34;ox-hugo-toc toc&#34;&gt;
&lt;div class=&#34;heading&#34;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%9b%9e%e5%bd%92&#34;&gt;回归&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%8d%9a%e5%ae%a2%e7%9b%b8%e5%85%b3&#34;&gt;博客相关&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e9%85%8d%e7%bd%ae-%e6%a8%a1%e6%9d%bf&#34;&gt;配置、模板&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%9b%be%e7%89%87%e7%ad%89%e5%a4%96%e9%83%a8%e6%96%87%e4%bb%b6%e7%9a%84%e5%bc%95%e7%94%a8&#34;&gt;图片等外部文件的引用&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%bd%bf%e7%94%a8-tikz-%e9%85%8d%e5%90%88-orgmode-%e8%bf%9b%e8%a1%8c%e7%94%bb%e5%9b%be-%e6%9b%b4%e6%96%b0&#34;&gt;使用 TikZ 配合 Orgmode 进行画图 &lt;span class=&#34;timestamp-wrapper&#34;&gt;&lt;span class=&#34;timestamp&#34;&gt;[2021-04-29 Thu] &lt;/span&gt;&lt;/span&gt; 更新&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%be%93%e5%87%ba-png-%e6%a0%bc%e5%bc%8f%e7%9a%84%e5%9b%be%e7%89%87&#34;&gt;输出 PNG 格式的图片&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e8%be%93%e5%87%ba-svg-%e6%a0%bc%e5%bc%8f%e7%9a%84%e5%9b%be%e7%89%87&#34;&gt;输出 SVG 格式的图片&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;p&gt;这是回归博客写作后的第一篇文章&lt;/p&gt;
&lt;h2 id=&#34;回归&#34;&gt;回归&lt;/h2&gt;
&lt;p&gt;时光荏冉，已经好久没有更新博客了，上一次写博客还是去年寒假疫情在家时期。&lt;/p&gt;
&lt;p&gt;这一年多以来总算把与实验组合作的几个工作结束了（第一次实践使用 VASP ），这几个工作感觉能总结的地方不多，都是细节居多，但坑还是不少的。我自己的工作做了快两年了
（看来平时没少摸鱼），在去年底它的进度有了 180 度转变，这还多亏了导师的嘱托，让我在补充图表时 Review 了一下之后的结果，一看就发现之前的结论完全错误，于是重新跑了一下 NAMD ，这次的结果终于符合「预期」了，但现在似乎又遇到了一些不大不小的问题，
即能带交叉的处理，目测解决它又要费些时间了（而且还中间还有其它实验组的东西要做）。&lt;/p&gt;
&lt;p&gt;说了这段时间自己在做什么，下面就该讲博客相关的东西了。&lt;/p&gt;
&lt;h2 id=&#34;博客相关&#34;&gt;博客相关&lt;/h2&gt;
&lt;p&gt;关于博客，我这次决心将它迁移到 Hugo 框架下，配合 Org-mode 和 ox-hugo 使用，至少到现在体验挺好：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hugo 很快，生成静态页面耗时在 ms 量级，比 Hexo 不知道高到哪里去了；&lt;/li&gt;
&lt;li&gt;Org-mode 很强大，谁用谁知道；&lt;/li&gt;
&lt;li&gt;私以为 Jane 主题足够简约，也留了足够的空间折腾。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;近期做了些工作，我会把心得总结起来放到博客上，供自己和小伙伴们参考～&lt;/p&gt;
&lt;h3 id=&#34;配置-模板&#34;&gt;配置、模板&lt;/h3&gt;
&lt;p&gt;以下是写博客时可能要用到的一些模板/配置，仅供自己参考了。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Org-mode 中 CJK 文档的 soft space 问题，已经有人给出了解决方案&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; ：&lt;/li&gt;
&lt;/ul&gt;
&lt;!--listend--&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defun&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;clear-single-linebreak-in-cjk-string&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;s&#34;&gt;&amp;#34;clear single line-break between cjk characters that is usually soft line-breaks&amp;#34;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;let*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;regexp&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\\([\u4E00-\u9FA5]\\)\n\\([\u4E00-\u9FA5]\\)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;start&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;string-match&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;regexp&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;start&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;setq&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;replace-match&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\\1\\2&amp;#34;&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;nv&#34;&gt;start&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;string-match&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;regexp&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;start&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defun&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ox-html-clear-single-linebreak-for-cjk&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;backend&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;when&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;org-export-derived-backend-p&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;backend&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;&amp;#39;html&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;clear-single-linebreak-in-cjk-string&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;eval-after-load&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;ox&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;add-to-list&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;&amp;#39;org-export-filter-final-output-functions&lt;/span&gt;
                &lt;span class=&#34;ss&#34;&gt;&amp;#39;ox-html-clear-single-linebreak-for-cjk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;添加链接时使用 &lt;span class=&#34;inline-src language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;code&gt;C-c C-l&lt;/code&gt;&lt;/span&gt; ， Doom-Emacs 会提示你输入链
接的 URL 和 description；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用 Inline code 时，参考它&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;： &lt;code&gt;src_sh[:exports code]{echo -e &amp;quot;test&amp;quot;}&lt;/code&gt; ；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;:PROPERTIES:&lt;/code&gt; 中 &lt;code&gt;:@cat:&lt;/code&gt; 定义了一个 category &lt;code&gt;cat&lt;/code&gt; ， &lt;code&gt;:foo:&lt;/code&gt; 定义了一个 tag &lt;code&gt;foo&lt;/code&gt; ，
&lt;code&gt;:@cat:foo:bar:&lt;/code&gt; 则分别定义了一个 category &lt;code&gt;cat&lt;/code&gt; ，两个 tags &lt;code&gt;foo&lt;/code&gt; 、 &lt;code&gt;bar&lt;/code&gt; ；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;每篇文章标题前使用 &lt;code&gt;S-left&lt;/code&gt; 或 &lt;code&gt;S-right&lt;/code&gt; 可以切换 &lt;code&gt;TODO&lt;/code&gt; 和 &lt;code&gt;DONE&lt;/code&gt; 的状态；输
入数学公式时，需要在 subtree 的 &lt;code&gt;:PROPERTIES:&lt;/code&gt; 里加上
&lt;code&gt;:EXPORT_HUGO_CUSTOM_FRONT_MATTER+: :markup goldmark&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;此时 &lt;code&gt;\(F=ma\)&lt;/code&gt; 表示 inline equation ，输出 \(F=ma\) ； &lt;code&gt;\[F=ma\]&lt;/code&gt; 表示
displaystyle equation 。（冷知识&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;： Orgmode 支持
即时渲染公式： &lt;code&gt;C-c C-x C-l&lt;/code&gt; 会把当前公式渲染好并以 png 的形式插入当前窗口，重
复这个操作可以关闭预览）&lt;/p&gt;
&lt;p&gt;现在试试一个稍稍复杂点的公式：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;\[ \begin{aligned} \nabla \times \vec{\mathbf{B}} - \frac1c
\frac{\partial\vec{\mathbf{E}}}{\partial t} &amp;amp; = \frac{4\pi}{c}\vec{\mathbf{j}}
\newline \nabla \cdot \vec{\mathbf{E}} &amp;amp; = 4 \pi \rho \newline \nabla \times
\vec{\mathbf{E}} + \frac1c \frac{\partial\vec{\mathbf{B}}}{\partial t} &amp;amp; =
\vec{\mathbf{0}} \newline \nabla \cdot \vec{\mathbf{B}} &amp;amp; = 0 \end{aligned} \]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;使用脚注来代替文献的上标&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;
，有三种方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;声明和定义分离的脚注：在要添加脚注的地方声明 &lt;code&gt;[fn:NAME]&lt;/code&gt; ，然后在其它地方定
义这个脚注 &lt;code&gt;[fn:NAME] some description here ...&lt;/code&gt; ；&lt;/li&gt;
&lt;li&gt;行内定义的脚注：直接使用 &lt;code&gt;[fn:: some description here ... ]&lt;/code&gt; ，这种方法不需要命名，可谓对程序员十分友好了 23333 ；&lt;/li&gt;
&lt;li&gt;带名字的行内脚注： &lt;code&gt;[fn:NAME: some description here ...]&lt;/code&gt; 。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在每篇博客开头的 &lt;code&gt;:PROPERTIES:&lt;/code&gt; 部分加上下面的代码，可以让每篇文章都独立为一个目录，
并把引用的文件自动复制到这个目录，避免都扔在 &lt;code&gt;static&lt;/code&gt; 里导致可能的文件名碰撞。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;!--listend--&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-org&#34; data-lang=&#34;org&#34;&gt;&lt;span class=&#34;c&#34;&gt;:PROPERTIES:
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cs&#34;&gt;:EXPORT_FILE_NAME: index
&lt;/span&gt;&lt;span class=&#34;cs&#34;&gt;:EXPORT_HUGO_BUNDLE: title
&lt;/span&gt;&lt;span class=&#34;cs&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;:END:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;图片等外部文件的引用&#34;&gt;图片等外部文件的引用&lt;/h3&gt;
&lt;p&gt;这一节单独列出来是因为它比数学公式还要难处理，根据 &lt;code&gt;ox-hugo&lt;/code&gt;&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt; 的说明，现在有三种引用图片的方法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用相对路径：直接把图片放到 &lt;code&gt;&amp;lt;HUGO_BASE_DIR&amp;gt;/static/&lt;/code&gt; 里，然后引用时可以省略
&lt;code&gt;&amp;lt;HUGO_BASE_DIR&amp;gt;/static/&lt;/code&gt; 前缀，例如有一个文件路径是
&lt;code&gt;&amp;lt;HUGO_BASE_DIR&amp;gt;/static/image/foo.png&lt;/code&gt; ，引用它时可以这样写：
&lt;code&gt;[[image/foo.png]]&lt;/code&gt; ；&lt;/li&gt;
&lt;li&gt;使用绝对路径：例如有一个路径是 &lt;code&gt;~/some/path/foo.png&lt;/code&gt; ，引用它时可以使用
&lt;code&gt;[[~/some/path/foo.png]]&lt;/code&gt; ，此时不光在 orgmode 里可以直接预览图片， &lt;code&gt;ox-hugo&lt;/code&gt;
在导出时还会把它复制到 &lt;code&gt;&amp;lt;HUGO_BASE_DIR&amp;gt;/static/ox-hugo/&lt;/code&gt; 里并生成链接；&lt;/li&gt;
&lt;li&gt;使用图床：现在 GitHub ， GitLab 等也可以用作图床，并且有成熟的软件来做这件事
比如 PicGo&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt; 。把图片传给图床后，图
床会返回一个链接，直接把它贴在 orgmode 里就能实现引用图片的效果。但之前我用七
牛云的图床一段时间后七牛云直接拒绝被薅，改了域名，我也就对图床产生一些顾虑
&lt;del&gt;，而且使用图床后一个缺点是，它降低了每篇文章的内聚度，增加了对外部的耦合（掉个
书袋233）&lt;/del&gt; 。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此我还是决定把图片等外部文件放在 &lt;code&gt;&amp;lt;HUGO_BASE_DIR&amp;gt;/content-org/&lt;/code&gt; 里，每篇文章单独建一个文件夹，然后使用相对路径引用。下面是效果展示（它使用了
&lt;code&gt;[[./a-new-journey/himehina.jpeg]]&lt;/code&gt; ）：&lt;img src=&#34;himehina.jpeg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;使用-tikz-配合-orgmode-进行画图-更新&#34;&gt;使用 TikZ 配合 Orgmode 进行画图 &lt;span class=&#34;timestamp-wrapper&#34;&gt;&lt;span class=&#34;timestamp&#34;&gt;[2021-04-29 Thu] &lt;/span&gt;&lt;/span&gt; 更新&lt;/h3&gt;
&lt;p&gt;Orgmode 原生支持内嵌 \(\LaTeX\) 代码，自然也支持用 TikZ 画图。不过如果想要在利用
TikZ 的输出嵌入到博客中，还需要一点工作要做。&lt;/p&gt;
&lt;h4 id=&#34;输出-png-格式的图片&#34;&gt;输出 PNG 格式的图片&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;确保机器上已经安装了 ImageMagick 和 \(\LaTeX\) ；&lt;/li&gt;
&lt;li&gt;在 config 中加入 &lt;code&gt;(setq org-latex-create-formula-image-program &#39;imagemagick)&lt;/code&gt; ；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;接下来就可以愉快玩耍了：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-org&#34; data-lang=&#34;org&#34;&gt;&lt;span class=&#34;cs&#34;&gt;#+header&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;: :headers &amp;#39;(&amp;#34;\\usepackage{tikz}&amp;#34;)&lt;/span&gt;
&lt;span class=&#34;cs&#34;&gt;#+header&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;: :results file graphics :file ./a-new-journey/test.png&lt;/span&gt;
&lt;span class=&#34;cs&#34;&gt;#+header&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;: :exports results&lt;/span&gt;
&lt;span class=&#34;cs&#34;&gt;#+header&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;: :fit yes :imoutoptions -geometry 400 :iminoptions -density 600&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#+begin_src &lt;/span&gt;&lt;span class=&#34;cs&#34;&gt;latex&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;\begin&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;tikzpicture&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;\draw&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;[-&amp;gt;]&lt;/span&gt; (-3,0) -- (-2,0) arc[radius=0.5cm,start angle=-180,end angle=0]
    (-1,0) -- (1,0) arc[radius=0.5cm,start angle=180,end angle=0] (2,0) -- (3,0);
&lt;span class=&#34;k&#34;&gt;\filldraw&lt;/span&gt; (-1.5,0) circle[radius=1mm];
&lt;span class=&#34;k&#34;&gt;\filldraw&lt;/span&gt; (1.5,0) circle[radius=1mm];
&lt;span class=&#34;k&#34;&gt;\end&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;tikzpicture&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#+end_src&lt;/span&gt;

&lt;span class=&#34;cs&#34;&gt;#+RESULTS&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;:&lt;/span&gt;
[[&lt;span class=&#34;na&#34;&gt;file:./a-new-journey/test.png&lt;/span&gt;]]
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Eval 这个 source block 后即可得到：&lt;/p&gt;

&lt;link rel=&#34;stylesheet&#34; href=&#34;http://ionizing.page/css/hugo-easy-gallery.css&#34; /&gt;
&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;test.png&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;test.png&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;h4 id=&#34;输出-svg-格式的图片&#34;&gt;输出 SVG 格式的图片&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;确保机器上已经安装了 \(\LaTeX\)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;接下来的工作不那么优雅，我们需要修改一下 &lt;code&gt;ob-latex.el&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;因为在 Orgmode 中 Eval 代码块时 Orgmode 会自动把代码块的内容加入预告写好的
Preamble 里生成一个临时文件，但当使用 &lt;code&gt;.svg&lt;/code&gt; 结尾的输出文件名时它的 Preamble 是这样的：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-latex&#34; data-lang=&#34;latex&#34;&gt;&lt;span class=&#34;k&#34;&gt;\documentclass&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;[preview]&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;standalone&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;\def\pgfsysdriver&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;pgfsys-tex4ht.def&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;%% Your \usepackage here
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;\begin&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;document&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;%% Your code here
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;\end&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;document&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;第二行的 &lt;code&gt;\def\pgfsysdriver&lt;/code&gt; 需要放在 &lt;code&gt;\usepackage{tikz}&lt;/code&gt; 后，或者使用 &lt;code&gt;htlatex&lt;/code&gt;
才能编译，但 ob-latex 使用的是 &lt;code&gt;latex&lt;/code&gt; ，而且这个过程只会提示 &lt;code&gt;PDF produced with errors&lt;/code&gt; ，导致输出的 SVG 是乱码。&lt;/p&gt;
&lt;p&gt;查询 &lt;code&gt;ob-latex.el&lt;/code&gt; 发现，这个 Preamble 是硬编码在 &lt;code&gt;org-babel-execute:latex&lt;/code&gt; 里的：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defcustom&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;org-babel-latex-preamble&lt;/span&gt;
   &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
     &lt;span class=&#34;s&#34;&gt;&amp;#34;\\documentclass[preview]{standalone}
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;\\def\\pgfsysdriver{pgfsys-tex4ht.def}
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
   &lt;span class=&#34;s&#34;&gt;&amp;#34;Closure which evaluates at runtime to the LaTeX preamble.&amp;#34;&lt;/span&gt;

&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;

          &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;with-temp-file&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;tex-file&lt;/span&gt;
            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;insert&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;concat&lt;/span&gt;
                     &lt;span class=&#34;s&#34;&gt;&amp;#34;\\documentclass[preview]{standalone}
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;\\def\\pgfsysdriver{pgfsys-tex4ht.def}
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt; &amp;#34;&lt;/span&gt;
                     &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;mapconcat&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;pkg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
                                  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;concat&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\\usepackage&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;pkg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;那问题就好办了，直接删掉两处 &lt;code&gt;\\def\\pgfsysdriver{pgfsys-tex4ht.def}&lt;/code&gt; ，并重新
build （我使用的是 DoomEmacs ，运行 &lt;code&gt;~/.emacs.d/bin/doom build&lt;/code&gt; ），然后就可以正常导出了。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-org&#34; data-lang=&#34;org&#34;&gt;&lt;span class=&#34;cs&#34;&gt;#+header&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;: :headers &amp;#39;(&amp;#34;\\usepackage{tikz}&amp;#34;)&lt;/span&gt;
&lt;span class=&#34;cs&#34;&gt;#+header&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;: :results file graphics :file ./a-new-journey/test.svg&lt;/span&gt;
&lt;span class=&#34;cs&#34;&gt;#+header&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;: :exports results&lt;/span&gt;
&lt;span class=&#34;cs&#34;&gt;#+header&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;: :fit yes :imoutoptions -geometry 400 :iminoptions -density 600&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#+begin_src &lt;/span&gt;&lt;span class=&#34;cs&#34;&gt;latex&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;\begin&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;tikzpicture&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;\draw&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;[-&amp;gt;]&lt;/span&gt; (-3,0) -- (-2,0) arc[radius=0.5cm,start angle=-180,end angle=0]
    (-1,0) -- (1,0) arc[radius=0.5cm,start angle=180,end angle=0] (2,0) -- (3,0);
&lt;span class=&#34;k&#34;&gt;\filldraw&lt;/span&gt; (-1.5,0) circle[radius=1mm];
&lt;span class=&#34;k&#34;&gt;\filldraw&lt;/span&gt; (1.5,0) circle[radius=1mm];
&lt;span class=&#34;k&#34;&gt;\end&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;tikzpicture&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;#+end_src&lt;/span&gt;

&lt;span class=&#34;cs&#34;&gt;#+RESULTS&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;:&lt;/span&gt;
[[&lt;span class=&#34;na&#34;&gt;file:./a-new-journey/test.svg&lt;/span&gt;]]
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;输出以下图形：&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;test.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;test.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;其实看 &lt;code&gt;ob-latex.el&lt;/code&gt; 似乎可以通过用户定义 &lt;code&gt;org-babel-latex-preamble&lt;/code&gt; 来绕过硬编码的 Preamble ，但经过测试发现并没有起作用，如果读者有更好方案，请务必联系我。&lt;/p&gt;
&lt;p&gt;上面测试用的 TikZ 代码圴来自 Jonny Evans&lt;sup id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;7&lt;/a&gt;&lt;/sup&gt;，同时感谢群组内&lt;sup id=&#34;fnref:8&#34;&gt;&lt;a href=&#34;#fn:8&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;8&lt;/a&gt;&lt;/sup&gt;大佬们的帮助。&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;http://zwz.github.io&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;http://zwz.github.io&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/16186843/inline-code-in-org-mode/16193498#16193498&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://stackoverflow.com/questions/16186843/inline-code-in-org-mode/16193498#16193498&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://orgmode.org/worg/org-tutorials/org-latex-preview.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://orgmode.org/worg/org-tutorials/org-latex-preview.html&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://orgmode.org/manual/Creating-Footnotes.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://orgmode.org/manual/Creating-Footnotes.html&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://ox-hugo.scripter.co&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://ox-hugo.scripter.co&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/Molunerfinn/PicGo&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://github.com/Molunerfinn/PicGo&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:7&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.homepages.ucl.ac.uk/~ucahjde/blog/tikz.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://www.homepages.ucl.ac.uk/~ucahjde/blog/tikz.html&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:7&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:8&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://t.me/emacs_zh&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://t.me/emacs_zh&lt;/a&gt;
&amp;#160;&lt;a href=&#34;#fnref:8&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
      
    </item>
    
  </channel>
</rss>
