<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Multidimensional Integrals using the Monte Carlo Technique | Bose Research Group</title><link>https://bose-research-group.github.io/courses/computational-sciences-hands-on/03-monte-carlo/</link><atom:link href="https://bose-research-group.github.io/courses/computational-sciences-hands-on/03-monte-carlo/index.xml" rel="self" type="application/rss+xml"/><description>Multidimensional Integrals using the Monte Carlo Technique</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Mon, 07 Apr 2025 00:00:00 +0000</lastBuildDate><image><url>https://bose-research-group.github.io/media/icon_hu_9bd251d90a98e6b2.png</url><title>Multidimensional Integrals using the Monte Carlo Technique</title><link>https://bose-research-group.github.io/courses/computational-sciences-hands-on/03-monte-carlo/</link></image><item><title>MC Simulation of Lennard-Jones Fluid: A Project</title><link>https://bose-research-group.github.io/courses/computational-sciences-hands-on/03-monte-carlo/ljfluid/</link><pubDate>Mon, 07 Apr 2025 00:00:00 +0000</pubDate><guid>https://bose-research-group.github.io/courses/computational-sciences-hands-on/03-monte-carlo/ljfluid/</guid><description>&lt;p>A Lennard-Jones fluid, in its simplest form, is a monoatomic fluid with the constituent particles interacting in a pair-wise fashion using the famous &lt;a href="https://en.wikipedia.org/wiki/Lennard-Jones_potential#Overview" target="_blank" rel="noopener">Lennard-Jones potential&lt;/a>:
$$V_\text{LJ}(r_{ij}) = 4\epsilon \left(\left(\frac{\sigma}{r_{ij}}\right)^{12}-\left(\frac{\sigma}{r_{ij}}\right)^6\right),$$
where $r_{ij}$ is the distance between the $i$th and the $j$th atom, $r_{ij} = \sqrt{(x_i-x_j)^2 + (y_i-y_j)^2 + (z_i-z_j)^2}$.&lt;/p>
&lt;p>This will be a guided tutorial in exploring the thermodynamics of the Lennard-Jones fluid using Metropolis Monte Carlo. The simulations are going to use &lt;strong>periodic boundary conditions&lt;/strong>, with the potential evaluated using the &lt;strong>minimum image convention&lt;/strong>.&lt;/p>
&lt;h2 id="configuration-space-definition-and-convention">Configuration Space Definition and Convention&lt;/h2>
&lt;p>Because Julia is a column-major language, we are going to store the coordinates of any given frame with $N$ atoms in a $(3\times N)$ matrix, with the $j$th column giving the position vector of the $j$ atom.&lt;/p>
&lt;h2 id="implement-the-lennard-jones-potential">Implement the Lennard-Jones Potential&lt;/h2>
&lt;p>The evaluation of the potential for the full box of particles will proceed in three steps:&lt;/p>
&lt;ol>
&lt;li>Write a function, &lt;code>Vpair&lt;/code> to calculate the Lennard-Jones potential for a distance.&lt;/li>
&lt;li>In addition write a &lt;code>get_distance&lt;/code> function which will take the $3\times N$ position matrix and two indices $i$ and $j$, and return the distance between the $i$th and the $j$th atoms (columns) under the minimum image convention.&lt;/li>
&lt;li>Write a function, &lt;code>Vtot&lt;/code>, which takes in the position matrix and calculates the total potential energy as a sum of all the pair-wise potential energies obtained using the &lt;code>Vpair&lt;/code> function.&lt;/li>
&lt;/ol>
&lt;h2 id="implement-mc-moves">Implement MC Moves&lt;/h2>
&lt;p>Because this is a mono-atomic system, the only possible move is a translation. We will evaluate two different moves and try to understand what are the pros and cons.&lt;/p>
&lt;ol>
&lt;li>Write a &lt;code>move_single&lt;/code> function that takes in a position matrix, chooses one random atom and moves one of its dimensions at random. Is this the most efficient way of constructing moves? No! However, its the simplest.&lt;/li>
&lt;li>Write a &lt;code>move_all&lt;/code> function which basically moves all the atoms in every move.&lt;/li>
&lt;/ol>
&lt;p>Remember to enforce periodic boundary conditions in your move as well.&lt;/p>
&lt;h2 id="implement-the-mc-function">Implement the MC function&lt;/h2>
&lt;p>In the spirit of what has been discussed previously, implement the actual MC code which takes in a starting initial configuration and returns a series of frames using the &lt;code>Vtot&lt;/code> function for a particular temperature. Each frame is a $3\times N$ matrix. If there are $F$ frames, you may choose to store them as a $F\times 3\times N$ tensor.&lt;/p>
&lt;h2 id="analysis-and-runs">Analysis and Runs&lt;/h2>
&lt;p>Now we should have all the ingredients ready. How does one do a real simulation?&lt;/p>
&lt;ol>
&lt;li>Choose all the parameters for the Lennard-Jones potential, the box size $L$, and the number of particles $N$.&lt;/li>
&lt;li>Create a random initial configuration. This in principle can be obtained in any way. For real problems, one could use the crystal structure of the system, a previous molecular dynamics run, or electronic structure minimization. In our case, we will just use a random placement of molecules.&lt;/li>
&lt;li>Run a single MC run evaluating the total potential energy at each frame to see if you are equilibrated. This is called the &lt;strong>equilibration run&lt;/strong>.
&lt;ol>
&lt;li>How many MC steps does equilibration take when using &lt;code>move_single&lt;/code>?&lt;/li>
&lt;li>How many MC steps does equilibration take starting from the same initial configuration when using &lt;code>move_all&lt;/code>?&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>You can choose 5 or 10 different frames from the &lt;strong>post-equilibration part&lt;/strong> of the equilibration trajectory and launch multiple MC runs to obtain error analysis. These would be called the production runs. Do a comparison between &lt;code>move_single&lt;/code> and &lt;code>move_all&lt;/code>. Some sample observables are discussed in &lt;a href="#observables">Observables&lt;/a>.&lt;/li>
&lt;li>Choose one of the production runs and visualize using VMD / PyMol.&lt;/li>
&lt;/ol>
&lt;h3 id="observables">Observables&lt;/h3>
&lt;p>We are interested in understanding a few bulk observables at different temperatures and number densities. The simplest are the interatomic distance, or the total potential energy. In addition to just looking at the average with some MC error, one should also plot the histograms to understand the distribution of these quantities.&lt;/p>
&lt;p>Apart from that one simple but very important observable is the &lt;a href="https://en.wikipedia.org/wiki/Radial_distribution_function" target="_blank" rel="noopener">Radial Distribution Function&lt;/a>, which tells us about the local packing and particle distribution with respect to the bulk density. To calculate the radial distribution function:&lt;/p>
&lt;ol>
&lt;li>Define the average density at a distance $r$, $\langle \rho(r)\rangle$, as the local density of particles at a distance $r$ away from another particle. The number of particles at distance $r$ from another particle is therefore $4\pi r^2 \langle\rho(r)\rangle$.
&lt;ol>
&lt;li>Calculate $\langle\rho(r)\rangle$ by finding the average number of particles at a distance $r$ from any particle and dividing it by $4\pi r^2$.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>The radial distribution function, $g(r)$, is defined as $g(r) = \frac{\langle\rho(r)\rangle}{\rho}$ where $\rho$ is the bulk density.&lt;/li>
&lt;/ol>
&lt;h2 id="putting-it-all-together">Putting It All Together&lt;/h2>
&lt;p>Write a full program, that can be run in two different modes:&lt;/p>
&lt;ol>
&lt;li>the &lt;strong>equilibration&lt;/strong> mode&lt;/li>
&lt;li>the &lt;strong>run&lt;/strong> mode&lt;/li>
&lt;/ol>
&lt;p>The input would be in the form of a &lt;a href="https://toml.io/en/" target="_blank" rel="noopener">TOML file&lt;/a> which can be parsed very easily in Julia using the &lt;a href="https://docs.julialang.org/en/v1/stdlib/TOML/" target="_blank" rel="noopener">TOML standard library&lt;/a>.&lt;/p>
&lt;p>A sample input structure, without the exact values provided, may be:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">system&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">N&lt;/span> &lt;span class="p">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">L&lt;/span> &lt;span class="p">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">epsilon&lt;/span> &lt;span class="p">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">sigma&lt;/span> &lt;span class="p">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">temperature&lt;/span> &lt;span class="p">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">simulation&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">mc_steps&lt;/span> &lt;span class="p">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">Deltax&lt;/span> &lt;span class="p">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">output_traj&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;traj.xyz&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">mode&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;equilibration&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>[system]&lt;/code> block encodes everything about our LJ fluid, while the &lt;code>[simulation]&lt;/code> block tells the program what to do and how to run. The &lt;code>mode&lt;/code> variable specifies the running mode, and one might read in different parameters based on the running mode. For instance, one may choose to have a &lt;code>nbins&lt;/code> parameter for the &lt;strong>run&lt;/strong> mode and not for the &lt;strong>equilibration&lt;/strong> mode. Similarly, one may ask for a list of thermodynamic observables to be output along with error bars for the &lt;strong>run&lt;/strong> mode and not for the &lt;strong>equilibration&lt;/strong> mode.&lt;/p>
&lt;p>This input format is just a suggestion. Feel free to use your imagination.&lt;/p></description></item></channel></rss>