
{"id":328,"date":"2025-04-03T23:36:48","date_gmt":"2025-04-03T15:36:48","guid":{"rendered":"https:\/\/www.shirui.me\/blog\/?p=328"},"modified":"2025-04-03T23:43:16","modified_gmt":"2025-04-03T15:43:16","slug":"calculating-sq-with-fft","status":"publish","type":"post","link":"https:\/\/www.shirui.me\/blog\/2025\/04\/03\/calculating-sq-with-fft\/","title":{"rendered":"Calculating SQ with FFT"},"content":{"rendered":"\n<p>The structure factor, commonly denoted as $S(\\mathbf{q})$, is an essential characterization quantity in molecular simulations. Its calculation is straightforward based on its definition. Since periodic boundary conditions are typically used in these simulations, we have<\/p>\n\n\n\n<p>$$S(\\mathbf{q}) := \\mathcal{FT}\\lbrace\\langle\\rho(\\mathbf{r})\\rho(\\mathbf{0})\\rangle\\rbrace(\\mathbf{q})$$<\/p>\n\n\n\n<p>which actually represents a circular convolution. This means that using the Fast Fourier Transform (FFT) can dramatically accelerate the computation compared to performing the calculation directly.<\/p>\n\n\n\n<p>The FFT-based procedure proceeds as follows:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Compute the density field $\\rho(\\mathbf{r})$, which is a sum of Dirac delta functions approximated by a histogram.<\/li>\n\n\n\n<li>Use the FFT to calculate the Fourier transform $\\hat{\\rho}(\\mathbf{q})$.<\/li>\n\n\n\n<li>Obtain the structure factor by taking the modulus squared of the transform:<br>$$ S(\\mathbf{q}) = |\\hat{\\rho}(\\mathbf{q})|^2. $$<\/li>\n\n\n\n<li>Average over the modulus to yield<br>$$ S(q) = \\frac{\\int S(\\mathbf{q})\\delta(|\\mathbf{q}|-q)\\,\\mathrm{d}\\mathbf{q}}{\\int\\delta(|\\mathbf{q}|-q)\\,\\mathrm{d}\\mathbf{q}}. $$<\/li>\n<\/ol>\n\n\n\n<p>In terms of efficiency, if the simulation box is divided into $N$ bins (for example, in 3D, $N = N_x N_y N_z$), the FFT has a computational complexity of $O(N\\log(N))$, and the averaging step is $O(N)$. By contrast, a direct method would involve a loop over all particles and $N$ bins in $\\mathbf{q}$ space\u2014and typically, the number of particles is much larger than $\\log(N)$. Moreover, because most simulation data are real-valued, employing an FFT designed for real inputs (rFFT) can further improve performance.<\/p>\n\n\n\n<p>Below is an example code for a 3D case, where the indices i, j, and k correspond to $N_x$, $N_y$, and $N_z$, respectively.<\/p>\n\n\n\n<pre class=\"python\"><code class=\"language-python\">fftn(a) == np.concatenate([rfftn(a), conj(rfftn(a))[-np.arange(i),-np.arange(j),np.arange(k-k\/\/2-1,0,-1)]], axis=-1)<\/code><\/pre>\n\n\n\n<p>Accuracy Considerations: Effect of Bin Size<\/p>\n\n\n\n<p>The histogram bin size should be smaller than half the minimum pairwise distance in the system, in accordance with the Nyquist-Shannon sampling theorem. For instance, in Lennard-Jones systems, a bin size of approximately $0.4\\sigma$ is advisable. However, if you are only interested in small $q$ values\u2014as is often the case in self-assembly systems\u2014full pairwise resolution is not necessary; a sampling interval that is just smaller than half of the domain of interest may suffice.<\/p>\n\n\n\n<p>Randomness Within Bins<\/p>\n\n\n\n<p>Particles are assumed to be randomly distributed within each bin, especially when employing large bins. The Fourier transform of the particle positions is given by<\/p>\n\n\n\n<p>$$\\sum_i \\exp(-\\mathrm{i}\\mathbf{q}\\cdot\\mathbf{r}_i)$$<\/p>\n\n\n\n<p>This sum can be decomposed as<\/p>\n\n\n\n<p>$$\\sum_\\mathrm{bin} \\exp(-\\mathrm{i}\\mathbf{q}\\cdot\\mathbf{r}_\\mathrm{bin})\\left(\\sum_i \\exp(-\\mathrm{i}\\mathbf{q}\\cdot\\delta\\mathbf{r}_i)\\right)$$<\/p>\n\n\n\n<p>where each particle&#8217;s position is written as<\/p>\n\n\n\n<p>$$\\mathbf{r}_i = \\mathbf{r}_\\mathrm{bin} + \\delta\\mathbf{r}_i$$<\/p>\n\n\n\n<p>Assuming the displacements $\\delta\\mathbf{r}_i$ are randomly distributed within the bin, the inner sum can be approximated by<\/p>\n\n\n\n<p>$$n_\\mathrm{bin}\\langle\\exp(-\\mathrm{i}\\mathbf{q}\\cdot\\delta\\mathbf{r})\\rangle$$<\/p>\n\n\n\n<p>with the average taken over the distribution of $\\delta\\mathbf{r}$. For a one-dimensional example, if $\\delta r$ is uniformly distributed in the interval $(-L\/2, L\/2)$ (where $L$ is the bin size), the average is given by $\\mathrm{sinc}(qL\/2)$. Multiplying by this sinc correction during step 4 yields a properly corrected $S(q)$.<\/p>\n\n\n\n<p>This strategy ensures that both efficiency and accuracy are maintained when computing the structure factor in molecular simulations.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The structure factor, commonly denoted as $S(\\mathbf{q})$, is an essential characterization quantity in molecular simulations. Its calculation is straightforward based on its definition. Since periodic boundary conditions are typically used in these simulations, we have $$S(\\mathbf{q}) := \\mathcal{FT}\\lbrace\\langle\\rho(\\mathbf{r})\\rho(\\mathbf{0})\\rangle\\rbrace(\\mathbf{q})$$ which actually represents a circular convolution. This means that using the Fast Fourier Transform (FFT) can dramatically [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[16],"class_list":["post-328","post","type-post","status-publish","format-standard","hentry","category-notes","tag-molecular-dynamics"],"_links":{"self":[{"href":"https:\/\/www.shirui.me\/blog\/wp-json\/wp\/v2\/posts\/328","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.shirui.me\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.shirui.me\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.shirui.me\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.shirui.me\/blog\/wp-json\/wp\/v2\/comments?post=328"}],"version-history":[{"count":4,"href":"https:\/\/www.shirui.me\/blog\/wp-json\/wp\/v2\/posts\/328\/revisions"}],"predecessor-version":[{"id":333,"href":"https:\/\/www.shirui.me\/blog\/wp-json\/wp\/v2\/posts\/328\/revisions\/333"}],"wp:attachment":[{"href":"https:\/\/www.shirui.me\/blog\/wp-json\/wp\/v2\/media?parent=328"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shirui.me\/blog\/wp-json\/wp\/v2\/categories?post=328"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shirui.me\/blog\/wp-json\/wp\/v2\/tags?post=328"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}