Allow gmxapi.commandline.cli to check GMXBIN.
[alexxy/gromacs.git] / api / gmxapi / cpp / system.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2018,2020,2021, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35
36 #include "gmxapi/system.h"
37
38 #include <array>
39 #include <memory>
40
41 #include "gromacs/utility.h"
42 #include "gromacs/mdrun/runner.h"
43
44 #include "gmxapi/context.h"
45 #include "gmxapi/md.h"
46 #include "gmxapi/session.h"
47 #include "gmxapi/status.h"
48 #include "gmxapi/system.h"
49
50 #include "system_impl.h"
51 #include "workflow.h"
52
53 namespace gmxapi
54 {
55
56 //! \cond
57 System::Impl::~Impl() = default;
58
59 System::Impl::Impl(System::Impl&&) noexcept = default;
60
61 System::Impl& System::Impl::operator=(System::Impl&& source) noexcept
62 {
63     if (this != &source)
64     {
65         workflow_.swap(source.workflow_);
66     }
67     return *this;
68 }
69 //! \endcond
70
71 std::shared_ptr<Session> System::launch(const std::shared_ptr<Context>& context)
72 {
73     return impl_->launch(context);
74 }
75
76 //! \cond
77 System::System(std::unique_ptr<Impl> implementation) : impl_{ std::move(implementation) }
78 {
79     GMX_ASSERT(impl_, "Constructor requires valid implementation object.");
80 }
81
82 System::~System() = default;
83 //! \endcond
84
85 System::System(System&&) noexcept = default;
86
87 System& System::operator=(System&&) noexcept = default;
88
89 System fromTprFile(const std::string& filename)
90 {
91     // TODO Confirm the file is readable and parseable and note unique
92     // identifying information for when the work spec is used in a different
93     // environment.
94
95     // Create a new Workflow instance.
96     // TODO error handling
97     auto workflow = Workflow::create(filename);
98
99     // This may produce errors or throw exceptions in the future, but as of
100     // 0.0.3 only memory allocation errors are possible, and we do not have a
101     // plan for how to recover from them.
102     auto systemImpl = std::make_unique<System::Impl>(std::move(workflow));
103     GMX_ASSERT(systemImpl, "Could not create a valid implementation object.");
104     auto system = System(std::move(systemImpl));
105
106     // TODO Separate TPR information into appropriate abstractions.
107     // The TPR file has enough information for us to
108     //  1. choose an MD engine
109     //  2. Get structure information
110     //  3. Get topology information
111     //  4. Get a lot of simulation and runtime parameters, but not all.
112     // It does not have enough information on its own to determine much about the
113     // necessary computation environment. That comes from environment
114     // introspection and user runtime options.
115
116     return system;
117 }
118
119 System::Impl::Impl(std::unique_ptr<gmxapi::Workflow> workflow) noexcept :
120     workflow_(std::move(workflow)), spec_(std::make_shared<MDWorkSpec>())
121 {
122     GMX_ASSERT(workflow_, "Class invariant implies non-null workflow_ member");
123     GMX_ASSERT(spec_, "Class invariant implies non-null work specification member.");
124 }
125
126 std::shared_ptr<Session> System::Impl::launch(const std::shared_ptr<Context>& context)
127 {
128     std::shared_ptr<Session> session = nullptr;
129     if (context != nullptr)
130     {
131         // TODO: gmxapi::Workflow, gmxapi::MDWorkSpec, and gmxapi::MDModule need sensible consolidation.
132         session = context->launch(*workflow_);
133         GMX_ASSERT(session, "Context::launch() expected to produce non-null session.");
134
135         for (auto&& module : spec_->getModules())
136         {
137             // TODO: This should be the job of the launching code that produces the Session.
138             // Configure the restraints in a restraint manager made available to the session launcher.
139             addSessionRestraint(session.get(), module);
140         }
141     }
142     else
143     {
144         // we should log the error and return nullptr, but we have nowhere to set
145         // a status object, by the described behavior.
146     }
147
148     return session;
149 }
150
151 } // end namespace gmxapi