Files
lammps/doc/html/Developer_write_command.html
2025-01-13 14:55:48 +00:00

503 lines
56 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.8.8. Writing a new command style &mdash; 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_write_command.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.9. Notes for developers and code maintainers" href="Developer_notes.html" />
<link rel="prev" title="4.8.7. Writing a new fix style" href="Developer_write_fix.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 &amp; 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"><a class="reference internal" href="Developer_code_design.html">4.3. Code design</a></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 current"><a class="reference internal" href="Developer_write.html">4.8. Writing new styles</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="Developer_write_pair.html">4.8.1. Writing new pair styles</a></li>
<li class="toctree-l3"><a class="reference internal" href="Developer_write_pair.html#package-and-build-system-considerations">4.8.2. Package and build system considerations</a></li>
<li class="toctree-l3"><a class="reference internal" href="Developer_write_pair.html#case-1-a-pairwise-additive-model">4.8.3. Case 1: a pairwise additive model</a></li>
<li class="toctree-l3"><a class="reference internal" href="Developer_write_pair.html#case-2-a-many-body-potential">4.8.4. Case 2: a many-body potential</a></li>
<li class="toctree-l3"><a class="reference internal" href="Developer_write_pair.html#case-3-a-potential-requiring-communication">4.8.5. Case 3: a potential requiring communication</a></li>
<li class="toctree-l3"><a class="reference internal" href="Developer_write_pair.html#case-4-potentials-without-a-compute-function">4.8.6. Case 4: potentials without a compute() function</a></li>
<li class="toctree-l3"><a class="reference internal" href="Developer_write_fix.html">4.8.7. Writing a new fix style</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">4.8.8. Writing a new command style</a></li>
<li class="toctree-l3"><a class="reference internal" href="#case-1-implementing-the-geturl-command">4.8.9. Case 1: Implementing the geturl command</a></li>
</ul>
</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"><a href="Developer_write.html"><span class="section-number">4.8. </span>Writing new styles</a></li>
<li class="breadcrumb-item active"><span class="section-number">4.8.8. </span>Writing a new command style</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_write_fix.html" class="btn btn-neutral float-left" title="4.8.7. Writing a new fix style" accesskey="p"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="Developer_notes.html" class="btn btn-neutral float-right" title="4.9. Notes for developers and code maintainers" 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="writing-a-new-command-style">
<h1><span class="section-number">4.8.8. </span>Writing a new command style<a class="headerlink" href="#writing-a-new-command-style" title="Link to this heading"></a></h1>
<p>Command styles allow to do system manipulations or interfaces to the
operating system.</p>
<p>In the text below, we will discuss the implementation of one example. As
shown on the page for <a class="reference internal" href="Modify_command.html"><span class="doc">writing or extending command styles</span></a>, in order to implement a new command style, a new class
must be written that is either directly or indirectly derived from the
<code class="docutils literal notranslate"><span class="pre">Command</span></code> class. There is just one method that must be implemented:
<code class="docutils literal notranslate"><span class="pre">Command::command()</span></code>. In addition, a custom constructor is needed to get
access to the members of the <code class="docutils literal notranslate"><span class="pre">LAMMPS</span></code> class like the <code class="docutils literal notranslate"><span class="pre">Error</span></code> class to
print out error messages. The <code class="docutils literal notranslate"><span class="pre">Command::command()</span></code> method processes the
arguments passed to the command in the input and executes it. Any other
methods would be for the convenience of implementation of the new command.</p>
<p>In general, new command styles should be added to the <a class="reference internal" href="Packages_details.html#pkg-extra-command"><span class="std std-ref">EXTRA-COMMAND
package</span></a>. If you feel that your contribution should be
added to a different package, please consult with the <a class="reference internal" href="Intro_authors.html"><span class="doc">LAMMPS
developers</span></a> first. The contributed code needs to support
the <a class="reference internal" href="Build_make.html"><span class="doc">traditional GNU make build process</span></a> <strong>and</strong> the
<a class="reference internal" href="Build_cmake.html"><span class="doc">CMake build process</span></a>.</p>
</section>
<hr class="docutils" />
<section id="case-1-implementing-the-geturl-command">
<h1><span class="section-number">4.8.9. </span>Case 1: Implementing the geturl command<a class="headerlink" href="#case-1-implementing-the-geturl-command" title="Link to this heading"></a></h1>
<p>In this section, we will describe the procedure of adding a simple command
style to LAMMPS: the <a class="reference internal" href="geturl.html"><span class="doc">geturl command</span></a> that allows to download
files directly without having to rely on an external program like “wget” or
“curl”. The complete implementation can be found in the files
<code class="docutils literal notranslate"><span class="pre">src/EXTRA-COMMAND/geturl.cpp</span></code> and <code class="docutils literal notranslate"><span class="pre">src/EXTRA-COMMAND/geturl.h</span></code> of the
LAMMPS source code.</p>
<section id="interfacing-the-libcurl-library">
<h2>Interfacing the <em>libcurl</em> library<a class="headerlink" href="#interfacing-the-libcurl-library" title="Link to this heading"></a></h2>
<p>Rather than implementing the various protocols for downloading files, we
rely on an external library: <a class="reference external" href="https:://curl.se/libcurl/">libcurl library</a>.
This requires that the library and its headers are installed. For the
traditional GNU make build system, this simply requires edits to the machine
makefile to add compilation flags like for other libraries. For the CMake
based build system, we need to add some lines to the file
<code class="docutils literal notranslate"><span class="pre">cmake/Modules/Packages/EXTRA-COMMAND.cmake</span></code>:</p>
<div class="highlight-cmake notranslate"><div class="highlight"><pre><span></span><span class="nb">find_package</span><span class="p">(</span><span class="s">CURL</span><span class="w"> </span><span class="s">QUIET</span><span class="w"> </span><span class="s">COMPONENTS</span><span class="w"> </span><span class="s">HTTP</span><span class="w"> </span><span class="s">HTTPS</span><span class="p">)</span>
<span class="nb">option</span><span class="p">(</span><span class="s">WITH_CURL</span><span class="w"> </span><span class="s2">&quot;Enable libcurl support&quot;</span><span class="w"> </span><span class="o">${</span><span class="nv">CURL_FOUND</span><span class="o">}</span><span class="p">)</span>
<span class="nb">if</span><span class="p">(</span><span class="s">WITH_CURL</span><span class="p">)</span>
<span class="w"> </span><span class="nb">find_package</span><span class="p">(</span><span class="s">CURL</span><span class="w"> </span><span class="s">REQUIRED</span><span class="w"> </span><span class="s">COMPONENTS</span><span class="w"> </span><span class="s">HTTP</span><span class="w"> </span><span class="s">HTTPS</span><span class="p">)</span>
<span class="w"> </span><span class="nb">target_compile_definitions</span><span class="p">(</span><span class="s">lammps</span><span class="w"> </span><span class="s">PRIVATE</span><span class="w"> </span><span class="s">-DLAMMPS_CURL</span><span class="p">)</span>
<span class="w"> </span><span class="nb">target_link_libraries</span><span class="p">(</span><span class="s">lammps</span><span class="w"> </span><span class="s">PRIVATE</span><span class="w"> </span><span class="s">CURL::libcurl</span><span class="p">)</span>
<span class="nb">endif</span><span class="p">()</span>
</pre></div>
</div>
<p>The first <code class="docutils literal notranslate"><span class="pre">find_package()</span></code> command uses a built-in CMake module to find
an existing <em>libcurl</em> installation with development headers and support for
using the HTTP and HTTPS protocols. The “QUIET” flag ensures that there is
no screen output and no error if the search fails. The status of the search
is recorded in the “${CURL_FOUND}” variable. That variable sets the default
of the WITH_CURL option, which toggles whether support for <em>libcurl</em> is included
or not.</p>
<p>The second <code class="docutils literal notranslate"><span class="pre">find_package()</span></code> uses the “REQUIRED” flag to produce an error
if the WITH_CURL option was set to <code class="docutils literal notranslate"><span class="pre">True</span></code>, but no suitable <em>libcurl</em>
implementation with development support was found. This construct is used
so that the CMake script code inside the <code class="docutils literal notranslate"><span class="pre">if(WITH_CURL)</span></code> and <code class="docutils literal notranslate"><span class="pre">endif()</span></code>
block can be expanded later to download and compile <em>libcurl</em> as part of the
LAMMPS build process, if it is not found locally. The
<code class="docutils literal notranslate"><span class="pre">target_compile_definitions()</span></code> function added the define <code class="docutils literal notranslate"><span class="pre">-DLAMMPS_CURL</span></code>
to the compilation flags when compiling objects for the LAMMPS library.
This allows to always compile the <a class="reference internal" href="geturl.html"><span class="doc">geturl command</span></a>, but use
pre-processing to compile in the interface to <em>libcurl</em> only when it is
present and usable and otherwise stop with an error message about the
unavailability of <em>libcurl</em> to execute the functionality of the command.</p>
</section>
<section id="header-file">
<h2>Header file<a class="headerlink" href="#header-file" title="Link to this heading"></a></h2>
<p>The first segment of any LAMMPS source should be the copyright and
license statement. Note the marker in the first line to indicate to
editors like emacs that this file is a C++ source, even though the .h
extension suggests a C source (this is a convention inherited from the
very beginning of the C++ version of LAMMPS).</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="cm">/* -*- c++ -*- ----------------------------------------------------------</span>
<span class="cm"> LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator</span>
<span class="cm"> https://www.lammps.org/, Sandia National Laboratories</span>
<span class="cm"> LAMMPS development team: developers@lammps.org</span>
<span class="cm"> Copyright (2003) Sandia Corporation. Under the terms of Contract</span>
<span class="cm"> DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains</span>
<span class="cm"> certain rights in this software. This software is distributed under</span>
<span class="cm"> the GNU General Public License.</span>
<span class="cm"> See the README file in the top-level LAMMPS directory.</span>
<span class="cm">------------------------------------------------------------------------- */</span>
</pre></div>
</div>
<p>Every command style must be registered in LAMMPS by including the following
lines of code in the second part of the header after the copyright
message and before the include guards for the class definition:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="cp">#ifdef COMMAND_CLASS</span>
<span class="c1">// clang-format off</span>
<span class="n">CommandStyle</span><span class="p">(</span><span class="n">geturl</span><span class="p">,</span><span class="n">GetURL</span><span class="p">);</span>
<span class="c1">// clang-format on</span>
<span class="cp">#else</span>
</pre></div>
</div>
<p>This block between <code class="docutils literal notranslate"><span class="pre">#ifdef</span> <span class="pre">COMMAND_CLASS</span></code> and <code class="docutils literal notranslate"><span class="pre">#else</span></code> will be
included by the <code class="docutils literal notranslate"><span class="pre">Input</span></code> class in <code class="docutils literal notranslate"><span class="pre">input.cpp</span></code> to build a map of
“factory functions” that will create an instance of a Command class
and call its <code class="docutils literal notranslate"><span class="pre">command()</span></code> method. The map connects the name of the
command <code class="docutils literal notranslate"><span class="pre">geturl</span></code> with the name of the class <code class="docutils literal notranslate"><span class="pre">GetURL</span></code>. During
compilation, LAMMPS constructs a file <code class="docutils literal notranslate"><span class="pre">style_command.h</span></code> that contains
<code class="docutils literal notranslate"><span class="pre">#include</span></code> statements for all “installed” command styles. Before
including <code class="docutils literal notranslate"><span class="pre">style_command.h</span></code> into <code class="docutils literal notranslate"><span class="pre">input.cpp</span></code>, the <code class="docutils literal notranslate"><span class="pre">COMMAND_CLASS</span></code>
define is set and the <code class="docutils literal notranslate"><span class="pre">CommandStyle(name,class)</span></code> macro defined. The
code of the macro adds the installed command styles to the “factory map”
which enables the <code class="docutils literal notranslate"><span class="pre">Input</span></code> to execute the command.</p>
<p>The list of header files to include in <code class="docutils literal notranslate"><span class="pre">style_command.h</span></code> is automatically
updated by the build system if there are new files, so the presence of the
new header file in the <code class="docutils literal notranslate"><span class="pre">src/EXTRA-COMMAND</span></code> folder and the enabling of the
EXTRA-COMMAND package will trigger LAMMPS to include the new command style
when it is (re-)compiled. The “// clang-format” format comments are needed
so that running <a class="reference internal" href="Build_development.html#clang-format"><span class="std std-ref">clang-format</span></a> on the file will not
insert unwanted blanks which would break the <code class="docutils literal notranslate"><span class="pre">CommandStyle</span></code> macro.</p>
<p>The third part of the header file is the actual class definition of the
<code class="docutils literal notranslate"><span class="pre">GetURL</span></code> class. This has the custom constructor and the <code class="docutils literal notranslate"><span class="pre">command()</span></code>
method implemented by this command style. For the constructor there is
nothing to do but to pass the <code class="docutils literal notranslate"><span class="pre">lmp</span></code> pointer to the base class. Since the
<code class="docutils literal notranslate"><span class="pre">command()</span></code> method is labeled “virtual” in the base class, it must be
given the “override” property.</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="cp">#ifndef LMP_GETURL_H</span>
<span class="cp">#define LMP_GETURL_H</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&quot;command.h&quot;</span>
<span class="k">namespace</span><span class="w"> </span><span class="nn">LAMMPS_NS</span><span class="w"> </span><span class="p">{</span>
<span class="k">class</span><span class="w"> </span><span class="nc">GetURL</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">Command</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">public</span><span class="o">:</span>
<span class="w"> </span><span class="n">GetURL</span><span class="p">(</span><span class="k">class</span><span class="w"> </span><span class="nc">LAMMPS</span><span class="w"> </span><span class="o">*</span><span class="n">lmp</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">Command</span><span class="p">(</span><span class="n">lmp</span><span class="p">)</span><span class="w"> </span><span class="p">{};</span>
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">command</span><span class="p">(</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">**</span><span class="p">)</span><span class="w"> </span><span class="k">override</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span><span class="w"> </span><span class="c1">// namespace LAMMPS_NS</span>
<span class="cp">#endif</span>
<span class="cp">#endif</span>
</pre></div>
</div>
<p>The “override” property helps to detect unexpected mismatches because
compilation will stop with an error in case the signature of a function
is changed in the base class without also changing it in all derived
classes.</p>
</section>
<section id="implementation-file">
<h2>Implementation file<a class="headerlink" href="#implementation-file" title="Link to this heading"></a></h2>
<p>We move on to the implementation of the <code class="docutils literal notranslate"><span class="pre">GetURL</span></code> class in the
<code class="docutils literal notranslate"><span class="pre">geturl.cpp</span></code> file. This file also starts with a LAMMPS copyright and
license header. Below that notice is typically the space where comments may
be added with additional information about this specific file, the
author(s), affiliation(s), and email address(es). This way the contributing
author(s) can be easily contacted, when there are questions about the
implementation later. Since the file(s) may be around for a long time, it
is beneficial to use some kind of “permanent” email address, if possible.</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="cm">/* ----------------------------------------------------------------------</span>
<span class="cm"> LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator</span>
<span class="cm"> https://www.lammps.org/, Sandia National Laboratories</span>
<span class="cm"> LAMMPS development team: developers@lammps.org</span>
<span class="cm"> Copyright (2003) Sandia Corporation. Under the terms of Contract</span>
<span class="cm"> DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains</span>
<span class="cm"> certain rights in this software. This software is distributed under</span>
<span class="cm"> the GNU General Public License.</span>
<span class="cm"> See the README file in the top-level LAMMPS directory.</span>
<span class="cm">------------------------------------------------------------------------- */</span>
<span class="cm">/* ----------------------------------------------------------------------</span>
<span class="cm"> Contributing authors: Axel Kohlmeyer (Temple U),</span>
<span class="cm">------------------------------------------------------------------------- */</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&quot;geturl.h&quot;</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&quot;comm.h&quot;</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&quot;error.h&quot;</span>
<span class="cp">#if defined(LAMMPS_CURL)</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;curl/curl.h&gt;</span>
<span class="cp">#endif</span>
<span class="k">using</span><span class="w"> </span><span class="k">namespace</span><span class="w"> </span><span class="nn">LAMMPS_NS</span><span class="p">;</span>
</pre></div>
</div>
<p>The second section of the implementation file has various include
statements. The include file for the class header has to come first, then a
couple of LAMMPS classes (sorted alphabetically) followed by the header for
the <em>libcurl</em> interface. This is wrapped into an <code class="docutils literal notranslate"><span class="pre">#ifdef</span></code> block so that
LAMMPS will compile this file without error when the <em>libcurl</em> header is not
available and thus the define not set. The final statement of this segment
imports the <code class="docutils literal notranslate"><span class="pre">LAMMPS_NS::</span></code> namespace globally for this file. This way, all
LAMMPS specific functions and classes do not have to be prefixed with
<code class="docutils literal notranslate"><span class="pre">LAMMPS_NS::</span></code>.</p>
</section>
<section id="the-command-function-required">
<h2>The command() function (required)<a class="headerlink" href="#the-command-function-required" title="Link to this heading"></a></h2>
<p>Since the required custom constructor is trivial and implemented in the
header, there is only one function that must be implemented for a command
style and that is the <code class="docutils literal notranslate"><span class="pre">command()</span></code> function.</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="kt">void</span><span class="w"> </span><span class="nf">GetURL::command</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">narg</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">**</span><span class="n">arg</span><span class="p">)</span>
<span class="p">{</span>
<span class="cp">#if !defined(LAMMPS_CURL)</span>
<span class="w"> </span><span class="n">error</span><span class="o">-&gt;</span><span class="n">all</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;LAMMPS has not been compiled with libcurl support&quot;</span><span class="p">);</span>
<span class="cp">#else</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">narg</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="n">utils</span><span class="o">::</span><span class="n">missing_cmd_args</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;geturl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">error</span><span class="p">);</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">verify</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">overwrite</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">verbose</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
</pre></div>
</div>
<p>This first part also has the <code class="docutils literal notranslate"><span class="pre">#ifdef</span></code> block depending on the LAMMPS_CURL
define. This way the command will simply print an error, if <em>libcurl</em> is
not available but will not fail to compile. Furthermore, it sets the
defaults for the following optional arguments.</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="c1">// process arguments</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arg</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="c1">// sanity check</span>
<span class="k">if</span><span class="w"> </span><span class="p">((</span><span class="n">url</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="sc">&#39;:&#39;</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="n">url</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="sc">&#39;/&#39;</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">))</span>
<span class="w"> </span><span class="n">error</span><span class="o">-&gt;</span><span class="n">all</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;URL &#39;{}&#39; is not a supported URL&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="p">);</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="w"> </span><span class="n">output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">url</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="n">url</span><span class="p">.</span><span class="n">find_last_of</span><span class="p">(</span><span class="sc">&#39;/&#39;</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">output</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span><span class="w"> </span><span class="n">error</span><span class="o">-&gt;</span><span class="n">all</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;URL &#39;{}&#39; must end in a file string&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="p">);</span>
</pre></div>
</div>
<p>This block stores the positional, i.e. non-optional argument of the URL to
be downloaded and adds a couple of sanity checks on the string to make sure it is
a valid URL. Also it derives the default name of the output file from the URL.</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">iarg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">iarg</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">narg</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">arg</span><span class="p">[</span><span class="n">iarg</span><span class="p">],</span><span class="w"> </span><span class="s">&quot;output&quot;</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="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">iarg</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">narg</span><span class="p">)</span><span class="w"> </span><span class="n">utils</span><span class="o">::</span><span class="n">missing_cmd_args</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;geturl output&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">error</span><span class="p">);</span>
<span class="w"> </span><span class="n">output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arg</span><span class="p">[</span><span class="n">iarg</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">];</span>
<span class="w"> </span><span class="o">++</span><span class="n">iarg</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">arg</span><span class="p">[</span><span class="n">iarg</span><span class="p">],</span><span class="w"> </span><span class="s">&quot;overwrite&quot;</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="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">iarg</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">narg</span><span class="p">)</span><span class="w"> </span><span class="n">utils</span><span class="o">::</span><span class="n">missing_cmd_args</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;geturl overwrite&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">error</span><span class="p">);</span>
<span class="w"> </span><span class="n">overwrite</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">utils</span><span class="o">::</span><span class="n">logical</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">[</span><span class="n">iarg</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="nb">false</span><span class="p">,</span><span class="w"> </span><span class="n">lmp</span><span class="p">);</span>
<span class="w"> </span><span class="o">++</span><span class="n">iarg</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">arg</span><span class="p">[</span><span class="n">iarg</span><span class="p">],</span><span class="w"> </span><span class="s">&quot;verify&quot;</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="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">iarg</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">narg</span><span class="p">)</span><span class="w"> </span><span class="n">utils</span><span class="o">::</span><span class="n">missing_cmd_args</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;geturl verify&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">error</span><span class="p">);</span>
<span class="w"> </span><span class="n">verify</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">utils</span><span class="o">::</span><span class="n">logical</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">[</span><span class="n">iarg</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="nb">false</span><span class="p">,</span><span class="w"> </span><span class="n">lmp</span><span class="p">);</span>
<span class="w"> </span><span class="o">++</span><span class="n">iarg</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">arg</span><span class="p">[</span><span class="n">iarg</span><span class="p">],</span><span class="w"> </span><span class="s">&quot;verbose&quot;</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="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">iarg</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">narg</span><span class="p">)</span><span class="w"> </span><span class="n">utils</span><span class="o">::</span><span class="n">missing_cmd_args</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;geturl verbose&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">error</span><span class="p">);</span>
<span class="w"> </span><span class="n">verbose</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">utils</span><span class="o">::</span><span class="n">logical</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">[</span><span class="n">iarg</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="nb">false</span><span class="p">,</span><span class="w"> </span><span class="n">lmp</span><span class="p">);</span>
<span class="w"> </span><span class="o">++</span><span class="n">iarg</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">error</span><span class="o">-&gt;</span><span class="n">all</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;Unknown geturl keyword: {}&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">[</span><span class="n">iarg</span><span class="p">]);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">++</span><span class="n">iarg</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This block parses the optional arguments following the URL and stops with an
error if there are arguments missing or an unknown argument is encountered.</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="c1">// only download files from rank 0</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">comm</span><span class="o">-&gt;</span><span class="n">me</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="p">;</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">overwrite</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">platform</span><span class="o">::</span><span class="n">file_is_readable</span><span class="p">(</span><span class="n">output</span><span class="p">))</span><span class="w"> </span><span class="k">return</span><span class="p">;</span>
<span class="c1">// open output file for writing</span>
<span class="kt">FILE</span><span class="w"> </span><span class="o">*</span><span class="n">out</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fopen</span><span class="p">(</span><span class="n">output</span><span class="p">.</span><span class="n">c_str</span><span class="p">(),</span><span class="w"> </span><span class="s">&quot;wb&quot;</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">out</span><span class="p">)</span>
<span class="w"> </span><span class="n">error</span><span class="o">-&gt;</span><span class="n">all</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;Cannot open output file {} for writing: {}&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">output</span><span class="p">,</span><span class="w"> </span><span class="n">utils</span><span class="o">::</span><span class="n">getsyserror</span><span class="p">());</span>
</pre></div>
</div>
<p>Here all MPI ranks other than 0 will return, so that the URL download will
only happen from a single MPI rank. For that rank the output file is opened
for writing using the C library function <code class="docutils literal notranslate"><span class="pre">fopen()</span></code>.</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="c1">// initialize curl and perform download</span>
<span class="n">CURL</span><span class="w"> </span><span class="o">*</span><span class="n">curl</span><span class="p">;</span>
<span class="n">curl_global_init</span><span class="p">(</span><span class="n">CURL_GLOBAL_DEFAULT</span><span class="p">);</span>
<span class="n">curl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">curl_easy_init</span><span class="p">();</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">curl</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="n">curl_easy_setopt</span><span class="p">(</span><span class="n">curl</span><span class="p">,</span><span class="w"> </span><span class="n">CURLOPT_URL</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="p">.</span><span class="n">c_str</span><span class="p">());</span>
<span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="n">curl_easy_setopt</span><span class="p">(</span><span class="n">curl</span><span class="p">,</span><span class="w"> </span><span class="n">CURLOPT_WRITEDATA</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="n">out</span><span class="p">);</span>
<span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="n">curl_easy_setopt</span><span class="p">(</span><span class="n">curl</span><span class="p">,</span><span class="w"> </span><span class="n">CURLOPT_FILETIME</span><span class="p">,</span><span class="w"> </span><span class="mf">1L</span><span class="p">);</span>
<span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="n">curl_easy_setopt</span><span class="p">(</span><span class="n">curl</span><span class="p">,</span><span class="w"> </span><span class="n">CURLOPT_FAILONERROR</span><span class="p">,</span><span class="w"> </span><span class="mf">1L</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">verbose</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">screen</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="n">curl_easy_setopt</span><span class="p">(</span><span class="n">curl</span><span class="p">,</span><span class="w"> </span><span class="n">CURLOPT_VERBOSE</span><span class="p">,</span><span class="w"> </span><span class="mf">1L</span><span class="p">);</span>
<span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="n">curl_easy_setopt</span><span class="p">(</span><span class="n">curl</span><span class="p">,</span><span class="w"> </span><span class="n">CURLOPT_STDERR</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="n">screen</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">verify</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="n">curl_easy_setopt</span><span class="p">(</span><span class="n">curl</span><span class="p">,</span><span class="w"> </span><span class="n">CURLOPT_SSL_VERIFYPEER</span><span class="p">,</span><span class="w"> </span><span class="mf">0L</span><span class="p">);</span>
<span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="n">curl_easy_setopt</span><span class="p">(</span><span class="n">curl</span><span class="p">,</span><span class="w"> </span><span class="n">CURLOPT_SSL_VERIFYHOST</span><span class="p">,</span><span class="w"> </span><span class="mf">0L</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">curl_easy_perform</span><span class="p">(</span><span class="n">curl</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">res</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">CURLE_OK</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">response</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0L</span><span class="p">;</span>
<span class="w"> </span><span class="n">curl_easy_getinfo</span><span class="p">(</span><span class="n">curl</span><span class="p">,</span><span class="w"> </span><span class="n">CURLINFO_RESPONSE_CODE</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">response</span><span class="p">);</span>
<span class="w"> </span><span class="n">error</span><span class="o">-&gt;</span><span class="n">one</span><span class="p">(</span><span class="n">FLERR</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;Download of {} failed with: {} {}&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">output</span><span class="p">,</span><span class="w"> </span><span class="n">curl_easy_strerror</span><span class="p">(</span><span class="n">res</span><span class="p">),</span>
<span class="w"> </span><span class="n">response</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">curl_easy_cleanup</span><span class="p">(</span><span class="n">curl</span><span class="p">);</span>
</pre></div>
</div>
<p>This block now implements the actual URL download with the selected options
via the “easy” interface of <em>libcurl</em>. For the details of what these
function calls do, please have a look at the <a class="reference external" href="https://curl.se/libcurl/c/allfuncs.html">*libcurl documentation</a>.</p>
<blockquote>
<div><div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">curl_global_cleanup</span><span class="p">();</span>
<span class="w"> </span><span class="n">fclose</span><span class="p">(</span><span class="n">out</span><span class="p">);</span>
<span class="cp">#endif</span>
<span class="p">}</span>
</pre></div>
</div>
</div></blockquote>
<p>Finally, the previously opened file is closed and the command is complete.</p>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="Developer_write_fix.html" class="btn btn-neutral float-left" title="4.8.7. Writing a new fix style" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="Developer_notes.html" class="btn btn-neutral float-right" title="4.9. Notes for developers and code maintainers" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; 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>