572 lines
48 KiB
HTML
572 lines
48 KiB
HTML
<!DOCTYPE html>
|
||
<html class="writer-html5" lang="en" >
|
||
<head>
|
||
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>4.3. Code design — LAMMPS documentation</title>
|
||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
|
||
<link rel="stylesheet" href="_static/sphinx-design.min.css" type="text/css" />
|
||
<link rel="stylesheet" href="_static/css/lammps.css" type="text/css" />
|
||
<link rel="shortcut icon" href="_static/lammps.ico"/>
|
||
<link rel="canonical" href="https://docs.lammps.org/Developer_code_design.html" />
|
||
<!--[if lt IE 9]>
|
||
<script src="_static/js/html5shiv.min.js"></script>
|
||
<![endif]-->
|
||
|
||
<script src="_static/jquery.js?v=5d32c60e"></script>
|
||
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
||
<script src="_static/documentation_options.js?v=5929fcd5"></script>
|
||
<script src="_static/doctools.js?v=9bcbadda"></script>
|
||
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
|
||
<script src="_static/design-tabs.js?v=f930bc37"></script>
|
||
<script async="async" src="_static/mathjax/es5/tex-mml-chtml.js?v=cadf963e"></script>
|
||
<script src="_static/js/theme.js"></script>
|
||
<link rel="index" title="Index" href="genindex.html" />
|
||
<link rel="search" title="Search" href="search.html" />
|
||
<link rel="next" title="4.4. Parallel algorithms" href="Developer_parallel.html" />
|
||
<link rel="prev" title="4.1. Source files" href="Developer_org.html" />
|
||
</head>
|
||
|
||
<body class="wy-body-for-nav">
|
||
<div class="wy-grid-for-nav">
|
||
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
|
||
<div class="wy-side-scroll">
|
||
<div class="wy-side-nav-search" >
|
||
|
||
|
||
|
||
<a href="Manual.html">
|
||
|
||
<img src="_static/lammps-logo.png" class="logo" alt="Logo"/>
|
||
</a>
|
||
<div class="lammps_version">Version: <b>19 Nov 2024</b></div>
|
||
<div class="lammps_release">git info: </div>
|
||
<div role="search">
|
||
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
|
||
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
|
||
<p class="caption" role="heading"><span class="caption-text">User Guide</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">1. Introduction</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Install.html">2. Install LAMMPS</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Build.html">3. Build LAMMPS</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Run_head.html">4. Run LAMMPS</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Commands.html">5. Commands</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Packages.html">6. Optional packages</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Speed.html">7. Accelerate performance</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Howto.html">8. Howto discussions</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Examples.html">9. Example scripts</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Tools.html">10. Auxiliary tools</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Errors.html">11. Errors</a></li>
|
||
</ul>
|
||
<p class="caption" role="heading"><span class="caption-text">Programmer Guide</span></p>
|
||
<ul class="current">
|
||
<li class="toctree-l1"><a class="reference internal" href="Library.html">1. LAMMPS Library Interfaces</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Python_head.html">2. Use Python with LAMMPS</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Modify.html">3. Modifying & extending LAMMPS</a></li>
|
||
<li class="toctree-l1 current"><a class="reference internal" href="Developer.html">4. Information for Developers</a><ul class="current">
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_org.html">4.1. Source files</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_org.html#class-topology">4.2. Class topology</a></li>
|
||
<li class="toctree-l2 current"><a class="current reference internal" href="#">4.3. Code design</a><ul>
|
||
<li class="toctree-l3"><a class="reference internal" href="#object-oriented-code">4.3.1. Object-oriented code</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="#i-o-and-output-formatting">4.3.2. I/O and output formatting</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="#memory-management">4.3.3. Memory management</a></li>
|
||
</ul>
|
||
</li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_parallel.html">4.4. Parallel algorithms</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_atom.html">4.5. Accessing per-atom data</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_comm_ops.html">4.6. Communication patterns</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_flow.html">4.7. How a timestep works</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_write.html">4.8. Writing new styles</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_notes.html">4.9. Notes for developers and code maintainers</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_updating.html">4.10. Notes for updating code written for older LAMMPS versions</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_plugins.html">4.11. Writing plugins</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_unittest.html">4.12. Adding tests for unit testing</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Classes.html">4.13. C++ base classes</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_platform.html">4.14. Platform abstraction functions</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html">4.15. Utility functions</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#special-math-functions">4.16. Special Math functions</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#tokenizer-classes">4.17. Tokenizer classes</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#argument-parsing-classes">4.18. Argument parsing classes</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#file-reader-classes">4.19. File reader classes</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#memory-pool-classes">4.20. Memory pool classes</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#eigensolver-functions">4.21. Eigensolver functions</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#communication-buffer-coding-with-ubuf">4.22. Communication buffer coding with <em>ubuf</em></a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="Developer_grid.html">4.23. Use of distributed grids within style classes</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<p class="caption" role="heading"><span class="caption-text">Command Reference</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="commands_list.html">Commands</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="fixes.html">Fix Styles</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="computes.html">Compute Styles</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="pairs.html">Pair Styles</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="bonds.html">Bond Styles</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="angles.html">Angle Styles</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="dihedrals.html">Dihedral Styles</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="impropers.html">Improper Styles</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="dumps.html">Dump Styles</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="fix_modify_atc_commands.html">fix_modify AtC commands</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="Bibliography.html">Bibliography</a></li>
|
||
</ul>
|
||
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
|
||
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||
<a href="Manual.html">LAMMPS</a>
|
||
</nav>
|
||
|
||
<div class="wy-nav-content">
|
||
<div class="rst-content style-external-links">
|
||
<div role="navigation" aria-label="Page navigation">
|
||
<ul class="wy-breadcrumbs">
|
||
<li><a href="Manual.html" class="icon icon-home" aria-label="Home"></a></li>
|
||
<li class="breadcrumb-item"><a href="Developer.html"><span class="section-number">4. </span>Information for Developers</a></li>
|
||
<li class="breadcrumb-item active"><span class="section-number">4.3. </span>Code design</li>
|
||
<li class="wy-breadcrumbs-aside">
|
||
<a href="https://www.lammps.org"><img src="_static/lammps-logo.png" width="64" height="16" alt="LAMMPS Homepage"></a> | <a href="Commands_all.html">Commands</a>
|
||
</li>
|
||
</ul><div class="rst-breadcrumbs-buttons" role="navigation" aria-label="Sequential page navigation">
|
||
<a href="Developer_org.html" class="btn btn-neutral float-left" title="4.1. Source files" accesskey="p"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
|
||
<a href="Developer_parallel.html" class="btn btn-neutral float-right" title="4.4. Parallel algorithms" accesskey="n">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
|
||
</div>
|
||
<hr/>
|
||
</div>
|
||
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||
<div itemprop="articleBody">
|
||
|
||
<p><span class="math notranslate nohighlight">\(\renewcommand{\AA}{\text{Å}}\)</span></p>
|
||
<section id="code-design">
|
||
<h1><span class="section-number">4.3. </span>Code design<a class="headerlink" href="#code-design" title="Link to this heading"></a></h1>
|
||
<p>This section explains some code design choices in LAMMPS with the goal
|
||
of helping developers write new code similar to the existing code.
|
||
Please see the section on <a class="reference internal" href="Modify_style.html"><span class="doc">Requirements for contributed code</span></a> for more specific recommendations and guidelines. While
|
||
that section is organized more in the form of a checklist for code
|
||
contributors, the focus here is on overall code design strategy, choices
|
||
made between possible alternatives, and discussing some relevant C++
|
||
programming language constructs.</p>
|
||
<p>Historically, the basic design philosophy of the LAMMPS C++ code was a
|
||
“C with classes” style. The motivation was to make it easy to modify
|
||
LAMMPS for people without significant training in C++ programming. Data
|
||
structures and code constructs were used that resemble the previous
|
||
implementation(s) in Fortran. A contributing factor to this choice was
|
||
that at the time, C++ compilers were often not mature and some advanced
|
||
features contained bugs or did not function as the standard required.
|
||
There were also disagreements between compiler vendors as to how to
|
||
interpret the C++ standard documents.</p>
|
||
<p>However, C++ compilers and the C++ programming language have advanced
|
||
significantly. In 2020, the LAMMPS developers decided to require the
|
||
C++11 standard as the minimum C++ language standard for LAMMPS. Since
|
||
then, we have begun to replace C-style constructs with equivalent C++
|
||
functionality. This was taken either from the C++ standard library or
|
||
implemented as custom classes or functions. The goal is to improve
|
||
readability of the code and to increase code reuse through abstraction
|
||
of commonly used functionality.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Please note that as of spring 2023 there is still a sizable chunk of
|
||
legacy code in LAMMPS that has not yet been refactored to reflect
|
||
these style conventions in full. LAMMPS has a large code base and
|
||
many contributors. There is also a hierarchy of precedence in which
|
||
the code is adapted. Highest priority has been the code in the
|
||
<code class="docutils literal notranslate"><span class="pre">src</span></code> folder, followed by code in packages in order of their
|
||
popularity and complexity (simpler code gets adapted sooner), followed
|
||
by code in the <code class="docutils literal notranslate"><span class="pre">lib</span></code> folder. Source code that is downloaded from
|
||
external packages or libraries during compilation is not subject to
|
||
the conventions discussed here.</p>
|
||
</div>
|
||
<section id="object-oriented-code">
|
||
<h2><span class="section-number">4.3.1. </span>Object-oriented code<a class="headerlink" href="#object-oriented-code" title="Link to this heading"></a></h2>
|
||
<p>LAMMPS is designed to be an object-oriented code. Each simulation is
|
||
represented by an instance of the LAMMPS class. When running in
|
||
parallel, each MPI process creates such an instance. This can be seen
|
||
in the <code class="docutils literal notranslate"><span class="pre">main.cpp</span></code> file where the core steps of running a LAMMPS
|
||
simulation are the following 3 lines of code:</p>
|
||
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">LAMMPS</span><span class="w"> </span><span class="o">*</span><span class="n">lammps</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">LAMMPS</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span><span class="w"> </span><span class="n">argv</span><span class="p">,</span><span class="w"> </span><span class="n">lammps_comm</span><span class="p">);</span>
|
||
<span class="n">lammps</span><span class="o">-></span><span class="n">input</span><span class="o">-></span><span class="n">file</span><span class="p">();</span>
|
||
<span class="k">delete</span><span class="w"> </span><span class="n">lammps</span><span class="p">;</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The first line creates a LAMMPS class instance and passes the command
|
||
line arguments and the global communicator to its constructor. The
|
||
second line triggers the LAMMPS instance to process the input (either
|
||
from standard input or a provided input file) until the simulation
|
||
ends. The third line deletes the LAMMPS instance. The remainder of
|
||
the main.cpp file has code for error handling, MPI configuration, and
|
||
other special features.</p>
|
||
<p>The basic LAMMPS class hierarchy which is created by the LAMMPS class
|
||
constructor is shown in <a class="reference internal" href="Developer_org.html#id1"><span class="std std-ref">LAMMPS class topology</span></a>. When input commands
|
||
are processed, additional class instances are created, or deleted, or
|
||
replaced. Likewise, specific member functions of specific classes are
|
||
called to trigger actions such as creating atoms, computing forces,
|
||
computing properties, time-propagating the system, or writing output.</p>
|
||
<section id="compositing-and-inheritance">
|
||
<h3>Compositing and Inheritance<a class="headerlink" href="#compositing-and-inheritance" title="Link to this heading"></a></h3>
|
||
<p>LAMMPS makes extensive use of the object-oriented programming (OOP)
|
||
principles of <em>compositing</em> and <em>inheritance</em>. Classes like the
|
||
<code class="docutils literal notranslate"><span class="pre">LAMMPS</span></code> class are a <strong>composite</strong> containing pointers to instances
|
||
of other classes like <code class="docutils literal notranslate"><span class="pre">Atom</span></code>, <code class="docutils literal notranslate"><span class="pre">Comm</span></code>, <code class="docutils literal notranslate"><span class="pre">Force</span></code>, <code class="docutils literal notranslate"><span class="pre">Neighbor</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">Modify</span></code>, and so on. Each of these classes implements certain
|
||
functionality by storing and manipulating data related to the
|
||
simulation and providing member functions that trigger certain
|
||
actions. Some of those classes like <code class="docutils literal notranslate"><span class="pre">Force</span></code> are themselves
|
||
composites, containing instances of classes describing different force
|
||
interactions. Similarly, the <code class="docutils literal notranslate"><span class="pre">Modify</span></code> class contains a list of
|
||
<code class="docutils literal notranslate"><span class="pre">Fix</span></code> and <code class="docutils literal notranslate"><span class="pre">Compute</span></code> classes. If the input commands that
|
||
correspond to these classes include the word <em>style</em>, then LAMMPS
|
||
stores only a single instance of that class. E.g. <em>atom_style</em>,
|
||
<em>comm_style</em>, <em>pair_style</em>, <em>bond_style</em>. If the input command does
|
||
<strong>not</strong> include the word <em>style</em>, then there may be many instances of
|
||
that class defined, for example <em>region</em>, <em>fix</em>, <em>compute</em>, <em>dump</em>.</p>
|
||
<p><strong>Inheritance</strong> enables creation of <em>derived</em> classes that can share
|
||
common functionality in their base class while providing a consistent
|
||
interface. The derived classes replace (dummy or pure) functions in
|
||
the base class. The higher level classes can then call those methods
|
||
of the instantiated classes without having to know which specific
|
||
derived class variant was instantiated. In LAMMPS these derived
|
||
classes are often referred to as “styles”, e.g. pair styles, fix
|
||
styles, atom styles and so on.</p>
|
||
<p>This is the origin of the flexibility of LAMMPS. For example, pair
|
||
styles implement a variety of different non-bonded interatomic
|
||
potentials functions. All details for the implementation of a
|
||
potential are stored and executed in a single class.</p>
|
||
<p>As mentioned above, there can be multiple instances of classes derived
|
||
from the <code class="docutils literal notranslate"><span class="pre">Fix</span></code> or <code class="docutils literal notranslate"><span class="pre">Compute</span></code> base classes. They represent a
|
||
different facet of LAMMPS’ flexibility, as they provide methods which
|
||
can be called at different points within a timestep, as explained in
|
||
the <a class="reference internal" href="Developer_flow.html"><span class="doc">How a timestep works</span></a> doc page. This allows
|
||
the input script to tailor how a specific simulation is run, what
|
||
diagnostic computations are performed, and how the output of those
|
||
computations is further processed or output.</p>
|
||
<p>Additional code sharing is possible by creating derived classes from the
|
||
derived classes (e.g., to implement an accelerated version of a pair
|
||
style) where only a subset of the derived class methods are replaced
|
||
with accelerated versions.</p>
|
||
</section>
|
||
<section id="polymorphism">
|
||
<h3>Polymorphism<a class="headerlink" href="#polymorphism" title="Link to this heading"></a></h3>
|
||
<p>Polymorphism and dynamic dispatch are another OOP feature that play an
|
||
important role in how LAMMPS selects what code to execute. In a
|
||
nutshell, this is a mechanism where the decision of which member
|
||
function to call from a class is determined at runtime and not when
|
||
the code is compiled. To enable it, the function has to be declared
|
||
as <code class="docutils literal notranslate"><span class="pre">virtual</span></code> and all corresponding functions in derived classes
|
||
should use the <code class="docutils literal notranslate"><span class="pre">override</span></code> property. Below is a brief example.</p>
|
||
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Base</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="k">public</span><span class="o">:</span>
|
||
<span class="w"> </span><span class="k">virtual</span><span class="w"> </span><span class="o">~</span><span class="n">Base</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">call</span><span class="p">();</span>
|
||
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">normal</span><span class="p">();</span>
|
||
<span class="w"> </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">poly</span><span class="p">();</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="kt">void</span><span class="w"> </span><span class="nf">Base::call</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="n">normal</span><span class="p">();</span>
|
||
<span class="w"> </span><span class="n">poly</span><span class="p">();</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="k">class</span><span class="w"> </span><span class="nc">Derived</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">Base</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="k">public</span><span class="o">:</span>
|
||
<span class="w"> </span><span class="o">~</span><span class="n">Derived</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">normal</span><span class="p">();</span>
|
||
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">poly</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="p">;</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="c1">// [....]</span>
|
||
|
||
<span class="n">Base</span><span class="w"> </span><span class="o">*</span><span class="n">base1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Base</span><span class="p">();</span>
|
||
<span class="n">Base</span><span class="w"> </span><span class="o">*</span><span class="n">base2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Derived</span><span class="p">();</span>
|
||
|
||
<span class="n">base1</span><span class="o">-></span><span class="n">call</span><span class="p">();</span>
|
||
<span class="n">base2</span><span class="o">-></span><span class="n">call</span><span class="p">();</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The difference in behavior of the <code class="docutils literal notranslate"><span class="pre">normal()</span></code> and the <code class="docutils literal notranslate"><span class="pre">poly()</span></code> member
|
||
functions is which of the two member functions is called when executing
|
||
<cite>base1->call()</cite> versus <cite>base2->call()</cite>. Without polymorphism, a
|
||
function within the base class can only call member functions within the
|
||
same scope: that is, <code class="docutils literal notranslate"><span class="pre">Base::call()</span></code> will always call
|
||
<code class="docutils literal notranslate"><span class="pre">Base::normal()</span></code>. But for the <cite>base2->call()</cite> case, the call of the
|
||
virtual member function will be dispatched to <code class="docutils literal notranslate"><span class="pre">Derived::poly()</span></code>
|
||
instead. This mechanism results in calling functions that are within
|
||
the scope of the class that was used to <em>create</em> the instance, even if
|
||
they are assigned to a pointer for their base class. This is the
|
||
desired behavior, and this way LAMMPS can even use styles that are loaded
|
||
at runtime from a shared object file with the <a class="reference internal" href="plugin.html"><span class="doc">plugin command</span></a>.</p>
|
||
<p>A special case of virtual functions are so-called pure functions. These
|
||
are virtual functions that are initialized to 0 in the class declaration
|
||
(see example below).</p>
|
||
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Base</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="k">public</span><span class="o">:</span>
|
||
<span class="w"> </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">pure</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
|
||
<span class="p">};</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This has the effect that an instance of the base class cannot be
|
||
created and that derived classes <strong>must</strong> implement these functions.
|
||
Many of the functions listed with the various class styles in the
|
||
section <a class="reference internal" href="Modify.html"><span class="doc">Modifying & extending LAMMPS</span></a> are pure functions. The motivation for this is
|
||
to define the interface or API of the functions, but defer their
|
||
implementation to the derived classes.</p>
|
||
<p>However, there are downsides to this. For example, calls to virtual
|
||
functions from within a constructor, will <em>not</em> be in the scope of the
|
||
derived class, and thus it is good practice to either avoid calling them
|
||
or to provide an explicit scope such as <code class="docutils literal notranslate"><span class="pre">Base::poly()</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">Derived::poly()</span></code>. Furthermore, any destructors in classes containing
|
||
virtual functions should be declared virtual too, so they will be
|
||
processed in the expected order before types are removed from dynamic
|
||
dispatch.</p>
|
||
<div class="admonition-important-notes admonition">
|
||
<p class="admonition-title">Important Notes</p>
|
||
<p>In order to be able to detect incompatibilities at compile time and
|
||
to avoid unexpected behavior, it is crucial that all member functions
|
||
that are intended to replace a virtual or pure function use the
|
||
<code class="docutils literal notranslate"><span class="pre">override</span></code> property keyword. For the same reason, the use of
|
||
overloads or default arguments for virtual functions should be
|
||
avoided, as they lead to confusion over which function is supposed to
|
||
override which, and which arguments need to be declared.</p>
|
||
</div>
|
||
</section>
|
||
<section id="style-factories">
|
||
<h3>Style Factories<a class="headerlink" href="#style-factories" title="Link to this heading"></a></h3>
|
||
<p>In order to create class instances for different styles, LAMMPS often
|
||
uses a programming pattern called <cite>Factory</cite>. Those are functions that
|
||
create an instance of a specific derived class, say <code class="docutils literal notranslate"><span class="pre">PairLJCut</span></code> and
|
||
return a pointer to the type of the common base class of that style,
|
||
<code class="docutils literal notranslate"><span class="pre">Pair</span></code> in this case. To associate the factory function with the
|
||
style keyword, a <code class="docutils literal notranslate"><span class="pre">std::map</span></code> class is used with function pointers
|
||
indexed by their keyword (for example “lj/cut” for <code class="docutils literal notranslate"><span class="pre">PairLJCut</span></code> and
|
||
“morse” for <code class="docutils literal notranslate"><span class="pre">PairMorse</span></code>). A couple of typedefs help keep the code
|
||
readable, and a template function is used to implement the actual
|
||
factory functions for the individual classes. Below is an example
|
||
of such a factory function from the <code class="docutils literal notranslate"><span class="pre">Force</span></code> class as declared in
|
||
<code class="docutils literal notranslate"><span class="pre">force.h</span></code> and implemented in <code class="docutils literal notranslate"><span class="pre">force.cpp</span></code>. The file <code class="docutils literal notranslate"><span class="pre">style_pair.h</span></code>
|
||
is generated during compilation and includes all main header files
|
||
(i.e. those starting with <code class="docutils literal notranslate"><span class="pre">pair_</span></code>) of pair styles and then the
|
||
macro <code class="docutils literal notranslate"><span class="pre">PairStyle()</span></code> will associate the style name “lj/cut”
|
||
with a factory function creating an instance of the <code class="docutils literal notranslate"><span class="pre">PairLJCut</span></code>
|
||
class.</p>
|
||
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="c1">// from force.h</span>
|
||
<span class="k">typedef</span><span class="w"> </span><span class="n">Pair</span><span class="w"> </span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="n">PairCreator</span><span class="p">)(</span><span class="n">LAMMPS</span><span class="w"> </span><span class="o">*</span><span class="p">);</span>
|
||
<span class="k">typedef</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o"><</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span><span class="w"> </span><span class="n">PairCreator</span><span class="o">></span><span class="w"> </span><span class="n">PairCreatorMap</span><span class="p">;</span>
|
||
<span class="n">PairCreatorMap</span><span class="w"> </span><span class="o">*</span><span class="n">pair_map</span><span class="p">;</span>
|
||
|
||
<span class="c1">// from force.cpp</span>
|
||
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">typename</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">></span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">S</span><span class="w"> </span><span class="o">*</span><span class="n">style_creator</span><span class="p">(</span><span class="n">LAMMPS</span><span class="w"> </span><span class="o">*</span><span class="n">lmp</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">T</span><span class="p">(</span><span class="n">lmp</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="c1">// [...]</span>
|
||
|
||
<span class="n">pair_map</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">PairCreatorMap</span><span class="p">();</span>
|
||
|
||
<span class="cp">#define PAIR_CLASS</span>
|
||
<span class="cp">#define PairStyle(key, Class) (*pair_map)[#key] = &style_creator<Pair, Class>;</span>
|
||
<span class="cp">#include</span><span class="w"> </span><span class="cpf">"style_pair.h"</span>
|
||
<span class="cp">#undef PairStyle</span>
|
||
<span class="cp">#undef PAIR_CLASS</span>
|
||
|
||
<span class="c1">// from pair_lj_cut.h</span>
|
||
|
||
<span class="cp">#ifdef PAIR_CLASS</span>
|
||
<span class="n">PairStyle</span><span class="p">(</span><span class="n">lj</span><span class="o">/</span><span class="n">cut</span><span class="p">,</span><span class="n">PairLJCut</span><span class="p">);</span>
|
||
<span class="cp">#else</span>
|
||
<span class="c1">// [...]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Similar code constructs are present in other files like <code class="docutils literal notranslate"><span class="pre">modify.cpp</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">modify.h</span></code> or <code class="docutils literal notranslate"><span class="pre">neighbor.cpp</span></code> and <code class="docutils literal notranslate"><span class="pre">neighbor.h</span></code>. Those contain
|
||
similar macros and include <code class="docutils literal notranslate"><span class="pre">style_*.h</span></code> files for creating class instances
|
||
of styles they manage.</p>
|
||
</section>
|
||
</section>
|
||
<section id="i-o-and-output-formatting">
|
||
<h2><span class="section-number">4.3.2. </span>I/O and output formatting<a class="headerlink" href="#i-o-and-output-formatting" title="Link to this heading"></a></h2>
|
||
<section id="c-style-stdio-versus-c-style-iostreams">
|
||
<h3>C-style stdio versus C++ style iostreams<a class="headerlink" href="#c-style-stdio-versus-c-style-iostreams" title="Link to this heading"></a></h3>
|
||
<p>LAMMPS uses the “stdio” library of the standard C library for reading
|
||
from and writing to files and console instead of C++ “iostreams”.
|
||
This is mainly motivated by better performance, better control over
|
||
formatting, and less effort to achieve specific formatting.</p>
|
||
<p>Since mixing “stdio” and “iostreams” can lead to unexpected behavior,
|
||
use of the latter is strongly discouraged. Output to the screen should
|
||
<em>not</em> use the predefined <code class="docutils literal notranslate"><span class="pre">stdout</span></code> FILE pointer, but rather the
|
||
<code class="docutils literal notranslate"><span class="pre">screen</span></code> and <code class="docutils literal notranslate"><span class="pre">logfile</span></code> FILE pointers managed by the LAMMPS class.
|
||
Furthermore, output should generally only be done by MPI rank 0
|
||
(<code class="docutils literal notranslate"><span class="pre">comm->me</span> <span class="pre">==</span> <span class="pre">0</span></code>). Output that is sent to both <code class="docutils literal notranslate"><span class="pre">screen</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">logfile</span></code> should use the <a class="reference internal" href="Developer_utils.html#_CPPv4IDpEN9LAMMPS_NS5utils7logmesgEvP6LAMMPSRKNSt6stringEDpRR4Args" title="LAMMPS_NS::utils::logmesg"><code class="xref cpp cpp-func docutils literal notranslate"><span class="pre">utils::logmesg()</span> <span class="pre">convenience</span>
|
||
<span class="pre">function</span></code></a>.</p>
|
||
<p>We discourage the use of stringstreams because the bundled {fmt} library
|
||
and the customized tokenizer classes provide the same functionality in a
|
||
cleaner way with better performance. This also helps maintain a
|
||
consistent programming syntax with code from many different
|
||
contributors.</p>
|
||
</section>
|
||
<section id="formatting-with-the-fmt-library">
|
||
<h3>Formatting with the {fmt} library<a class="headerlink" href="#formatting-with-the-fmt-library" title="Link to this heading"></a></h3>
|
||
<p>The LAMMPS source code includes a copy of the <a class="reference external" href="https://fmt.dev">{fmt} library</a>, which is preferred over formatting with the
|
||
“printf()” family of functions. The primary reason is that it allows
|
||
a typesafe default format for any type of supported data. This is
|
||
particularly useful for formatting integers of a given size (32-bit or
|
||
64-bit) which may require different format strings depending on
|
||
compile time settings or compilers/operating systems. Furthermore,
|
||
{fmt} gives better performance, has more functionality, a familiar
|
||
formatting syntax that has similarities to <code class="docutils literal notranslate"><span class="pre">format()</span></code> in Python, and
|
||
provides a facility that can be used to integrate format strings and a
|
||
variable number of arguments into custom functions in a much simpler
|
||
way than the varargs mechanism of the C library. Finally, {fmt} has
|
||
been included into the C++20 language standard, so changes to adopt it
|
||
are future-proof.</p>
|
||
<p>Formatted strings are frequently created by calling the
|
||
<code class="docutils literal notranslate"><span class="pre">fmt::format()</span></code> function, which will return a string as a
|
||
<code class="docutils literal notranslate"><span class="pre">std::string</span></code> class instance. In contrast to the <code class="docutils literal notranslate"><span class="pre">%</span></code> placeholder in
|
||
<code class="docutils literal notranslate"><span class="pre">printf()</span></code>, the {fmt} library uses <code class="docutils literal notranslate"><span class="pre">{}</span></code> to embed format descriptors.
|
||
In the simplest case, no additional characters are needed, as {fmt} will
|
||
choose the default format based on the data type of the argument.
|
||
Otherwise, the <code class="docutils literal notranslate"><span class="pre">fmt::print()</span></code> function may be used instead of
|
||
<code class="docutils literal notranslate"><span class="pre">printf()</span></code> or <code class="docutils literal notranslate"><span class="pre">fprintf()</span></code>. In addition, several LAMMPS output
|
||
functions, that originally accepted a single string as argument have
|
||
been overloaded to accept a format string with optional arguments as
|
||
well (e.g., <code class="docutils literal notranslate"><span class="pre">Error::all()</span></code>, <code class="docutils literal notranslate"><span class="pre">Error::one()</span></code>, <code class="docutils literal notranslate"><span class="pre">utils::logmesg()</span></code>).</p>
|
||
</section>
|
||
<section id="summary-of-the-fmt-format-syntax">
|
||
<h3>Summary of the {fmt} format syntax<a class="headerlink" href="#summary-of-the-fmt-format-syntax" title="Link to this heading"></a></h3>
|
||
<p>The syntax of the format string is “{[<argument id>][:<format spec>]}”,
|
||
where either the argument id or the format spec (separated by a colon
|
||
‘:’) is optional. The argument id is usually a number starting from 0
|
||
that is the index to the arguments following the format string. By
|
||
default, these are assigned in order (i.e. 0, 1, 2, 3, 4 etc.). The
|
||
most common case for using argument id would be to use the same argument
|
||
in multiple places in the format string without having to provide it as
|
||
an argument multiple times. The argument id is rarely used in the LAMMPS
|
||
source code.</p>
|
||
<p>More common is the use of a format specifier, which starts with a colon.
|
||
This may optionally be followed by a fill character (default is ‘ ‘). If
|
||
provided, the fill character <strong>must</strong> be followed by an alignment
|
||
character (‘<’, ‘^’, ‘>’ for left, centered, or right alignment
|
||
(default)). The alignment character may be used without a fill
|
||
character. The next important format parameter would be the minimum
|
||
width, which may be followed by a dot ‘.’ and a precision for floating
|
||
point numbers. The final character in the format string would be an
|
||
indicator for the “presentation”, i.e. ‘d’ for decimal presentation of
|
||
integers, ‘x’ for hexadecimal, ‘o’ for octal, ‘c’ for character etc.
|
||
This mostly follows the “printf()” scheme, but without requiring an
|
||
additional length parameter to distinguish between different integer
|
||
widths. The {fmt} library will detect those and adapt the formatting
|
||
accordingly. For floating point numbers there are correspondingly, ‘g’
|
||
for generic presentation, ‘e’ for exponential presentation, and ‘f’ for
|
||
fixed point presentation.</p>
|
||
<p>The format string “{:8}” would thus represent <em>any</em> type argument and be
|
||
replaced by at least 8 characters; “{:<8}” would do this as left
|
||
aligned, “{:^8}” as centered, “{:>8}” as right aligned. If a specific
|
||
presentation is selected, the argument type must be compatible or else
|
||
the {fmt} formatting code will throw an exception. Some format string
|
||
examples are given below:</p>
|
||
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">auto</span><span class="w"> </span><span class="n">mesg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fmt</span><span class="o">::</span><span class="n">format</span><span class="p">(</span><span class="s">" CPU time: {:4d}:{:02d}:{:02d}</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">cpuh</span><span class="p">,</span><span class="w"> </span><span class="n">cpum</span><span class="p">,</span><span class="w"> </span><span class="n">cpus</span><span class="p">);</span>
|
||
<span class="n">mesg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fmt</span><span class="o">::</span><span class="n">format</span><span class="p">(</span><span class="s">"{:<8s}| {:<10.5g} | {:<10.5g} | {:<10.5g} |{:6.1f} |{:6.2f}</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="n">label</span><span class="p">,</span><span class="w"> </span><span class="n">time_min</span><span class="p">,</span><span class="w"> </span><span class="n">time</span><span class="p">,</span><span class="w"> </span><span class="n">time_max</span><span class="p">,</span><span class="w"> </span><span class="n">time_sq</span><span class="p">,</span><span class="w"> </span><span class="n">tmp</span><span class="p">);</span>
|
||
<span class="n">utils</span><span class="o">::</span><span class="n">logmesg</span><span class="p">(</span><span class="n">lmp</span><span class="p">,</span><span class="s">"{:>6} = max # of 1-2 neighbors</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">maxall</span><span class="p">);</span>
|
||
<span class="n">utils</span><span class="o">::</span><span class="n">logmesg</span><span class="p">(</span><span class="n">lmp</span><span class="p">,</span><span class="s">"Lattice spacing in x,y,z = {:.8} {:.8} {:.8}</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="n">xlattice</span><span class="p">,</span><span class="n">ylattice</span><span class="p">,</span><span class="n">zlattice</span><span class="p">);</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>which will create the following output lines:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>CPU time: 0:02:16
|
||
Pair | 2.0133 | 2.0133 | 2.0133 | 0.0 | 84.21
|
||
4 = max # of 1-2 neighbors
|
||
Lattice spacing in x,y,z = 1.6795962 1.6795962 1.6795962
|
||
</pre></div>
|
||
</div>
|
||
<p>Finally, a special feature of the {fmt} library is that format
|
||
parameters like the width or the precision may be also provided as
|
||
arguments. In that case a nested format is used where a pair of curly
|
||
braces (with an optional argument id) “{}” are used instead of the
|
||
value, for example “{:{}d}” will consume two integer arguments, the
|
||
first will be the value shown and the second the minimum width.</p>
|
||
<p>For more details and examples, please consult the <a class="reference external" href="https://fmt.dev/latest/syntax.html">{fmt} syntax
|
||
documentation</a> website.</p>
|
||
</section>
|
||
</section>
|
||
<section id="memory-management">
|
||
<h2><span class="section-number">4.3.3. </span>Memory management<a class="headerlink" href="#memory-management" title="Link to this heading"></a></h2>
|
||
<p>Dynamical allocation of small data and objects can be done with the C++
|
||
commands “new” and “delete/delete[]”. Large data should use the member
|
||
functions of the <code class="docutils literal notranslate"><span class="pre">Memory</span></code> class, most commonly, <code class="docutils literal notranslate"><span class="pre">Memory::create()</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">Memory::grow()</span></code>, and <code class="docutils literal notranslate"><span class="pre">Memory::destroy()</span></code>, which provide variants
|
||
for vectors, 2d arrays, 3d arrays, etc. These can also be used for
|
||
small data.</p>
|
||
<p>The use of <code class="docutils literal notranslate"><span class="pre">malloc()</span></code>, <code class="docutils literal notranslate"><span class="pre">calloc()</span></code>, <code class="docutils literal notranslate"><span class="pre">realloc()</span></code> and <code class="docutils literal notranslate"><span class="pre">free()</span></code>
|
||
directly is strongly discouraged. To simplify adapting legacy code
|
||
into the LAMMPS code base the member functions <code class="docutils literal notranslate"><span class="pre">Memory::smalloc()</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">Memory::srealloc()</span></code>, and <code class="docutils literal notranslate"><span class="pre">Memory::sfree()</span></code> are available, which
|
||
perform additional error checks for safety.</p>
|
||
<p>Use of these custom memory allocation functions is motivated by the
|
||
following considerations:</p>
|
||
<ul class="simple">
|
||
<li><p>Memory allocation failures on <em>any</em> MPI rank during a parallel run
|
||
will trigger an immediate abort of the entire parallel calculation.</p></li>
|
||
<li><p>A failing “new” will trigger an exception, which is also captured by
|
||
LAMMPS and triggers a global abort.</p></li>
|
||
<li><p>Allocation of multidimensional arrays will be done in a C compatible
|
||
fashion, but such that the storage of the actual data is stored in one
|
||
large contiguous block. Thus, when MPI communication is needed,
|
||
the data can be communicated directly (similar to Fortran arrays).</p></li>
|
||
<li><p>The “destroy()” and “sfree()” functions may safely be called on NULL
|
||
pointers.</p></li>
|
||
<li><p>The “destroy()” functions will nullify the pointer variables, thus
|
||
making “use after free” errors easy to detect.</p></li>
|
||
<li><p>It is possible to use a larger than default memory alignment (not on
|
||
all operating systems, since the allocated storage pointers must be
|
||
compatible with <code class="docutils literal notranslate"><span class="pre">free()</span></code> for technical reasons).</p></li>
|
||
</ul>
|
||
<p>In the practical implementation of code this means, that any pointer
|
||
variables, that are class members should be initialized to a <code class="docutils literal notranslate"><span class="pre">nullptr</span></code>
|
||
value in their respective constructors. That way, it is safe to call
|
||
<code class="docutils literal notranslate"><span class="pre">Memory::destroy()</span></code> or <code class="docutils literal notranslate"><span class="pre">delete[]</span></code> on them before <em>any</em> allocation
|
||
outside the constructor. This helps prevent memory leaks.</p>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
|
||
<a href="Developer_org.html" class="btn btn-neutral float-left" title="4.1. Source files" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
|
||
<a href="Developer_parallel.html" class="btn btn-neutral float-right" title="4.4. Parallel algorithms" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
|
||
</div>
|
||
|
||
<hr/>
|
||
|
||
<div role="contentinfo">
|
||
<p>© Copyright 2003-2025 Sandia Corporation.</p>
|
||
</div>
|
||
|
||
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
|
||
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
|
||
provided by <a href="https://readthedocs.org">Read the Docs</a>.
|
||
|
||
|
||
</footer>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<script>
|
||
jQuery(function () {
|
||
SphinxRtdTheme.Navigation.enable(false);
|
||
});
|
||
</script>
|
||
|
||
</body>
|
||
</html> |