1 /*
2 * Copyright 2009-2021 The VOTCA Development Team (http://www.votca.org)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #ifndef VOTCA_CSG_CSGAPPLICATION_H
19 #define VOTCA_CSG_CSGAPPLICATION_H
20
21 // VOTCA includes
22 #include <memory>
23 #include <votca/tools/application.h>
24 #include <votca/tools/mutex.h>
25 #include <votca/tools/thread.h>
26
27 // Local VOTCA includes
28 #include "cgobserver.h"
29 #include "topology.h"
30 #include "topologymap.h"
31 #include "trajectoryreader.h"
32
33 namespace votca {
34 namespace csg {
35
36 class CsgApplication : public tools::Application {
37 public:
38 CsgApplication() = default;
39 ~CsgApplication() override = default;
40
41 void Initialize() override;
42 bool EvaluateOptions() override;
43
44 void Run(void) override;
45
46 void ShowHelpText(std::ostream &out) override;
47
48 /// \brief overload and return true to enable mapping command line options
49
DoMapping(void)50 virtual bool DoMapping(void) { return false; }
51 /// \brief if DoMapping is true, will by default require mapping or not
52
DoMappingDefault(void)53 virtual bool DoMappingDefault(void) { return true; }
54 /// \brief overload and return true to enable trajectory command line options
55
DoTrajectory(void)56 virtual bool DoTrajectory(void) { return false; }
57
58 /* \brief overload and return true to enable threaded calculations */
DoThreaded(void)59 virtual bool DoThreaded(void) { return false; }
60
61 /* \brief overload and return false to disable synchronized (while threaded)
62 * calculations */
SynchronizeThreads(void)63 virtual bool SynchronizeThreads(void) {
64 if (DoThreaded()) {
65 return true;
66 } else {
67 return false;
68 }
69 }
70
71 /// \brief if topology is always needed
NeedsTopology(void)72 virtual bool NeedsTopology(void) { return true; }
73
74 /// \brief called after topology was loaded
75
76 virtual bool EvaluateTopology(Topology *, Topology * = nullptr) {
77 return true;
78 }
79
80 void AddObserver(CGObserver *observer);
81
82 /// \brief called before the first frame
83 virtual void BeginEvaluate(Topology *top, Topology *top_ref = nullptr);
84 /// \brief called after the last frame
85 virtual void EndEvaluate();
86 // \brief called for each frame which is mapped
87 virtual void EvalConfiguration(Topology *top, Topology *top_ref = nullptr);
88
89 // thread related stuff follows
90
91 /**
92 \brief Worker, derived from Thread, does the work.
93 *
94 * Worker holds the information about the current frame, either in its
95 * own copy (e.g. Topology), or, by reference, from the parent CsgApplication.
96 * The computation is shifted from Run() into EvalConfiguration. The
97 * user is required to overload ForkWorker and Mergeworker and thereby
98 * define the initialization and merging of workers. By default, workers
99 * will be executed in correct order according to the frames. Also,
100 * output will follow the same order.
101 * Mutexes handle the locking of input/output and are also used to impose
102 * the correct order of frames for in/output.
103 *
104 */
105 class Worker : public tools::Thread {
106 public:
107 Worker() = default;
108
109 /// \brief overload with the actual computation
110 virtual void EvalConfiguration(Topology *top,
111 Topology *top_ref = nullptr) = 0;
112
113 /// \brief returns worker id
getId()114 Index getId() { return id_; }
115
116 protected:
117 CsgApplication *app_ = nullptr;
118 Topology top_, top_cg_;
119 std::unique_ptr<TopologyMap> map_;
120 Index id_ = -1;
121
122 void Run(void) override;
123
setApplication(CsgApplication * app)124 void setApplication(CsgApplication *app) { app_ = app; }
125
setId(Index id)126 void setId(Index id) { id_ = id; }
127
128 friend class CsgApplication;
129 };
130
131 /**
132 * \brief Gets frames from TrajectoryReader in an ordered way and, if
133 * successful, calls Worker::EvalConfiguration for that frame.
134 *
135 * @param worker
136 * @return True if frames left for calculation, else False
137 */
138 bool ProcessData(Worker *worker);
139
140 /**
141 *
142 * User is required to overload ForkWorker and initialize workers.
143 * @return worker
144 */
145 virtual std::unique_ptr<Worker> ForkWorker(void);
146
147 /**
148 * User is required to overload MergeWorker and merge data from each worker.
149 * @param worker
150 */
151 virtual void MergeWorker(Worker *worker);
152
153 protected:
154 std::list<CGObserver *> observers_;
155 bool do_mapping_;
156 std::vector<std::unique_ptr<Worker>> myWorkers_;
157 Index nframes_;
158 bool is_first_frame_;
159 Index nthreads_;
160 tools::Mutex nframesMutex_;
161 tools::Mutex traj_readerMutex_;
162
163 /// \brief stores Mutexes used to impose order for input
164 std::vector<std::unique_ptr<tools::Mutex>> threadsMutexesIn_;
165 /// \brief stores Mutexes used to impose order for output
166 std::vector<std::unique_ptr<tools::Mutex>> threadsMutexesOut_;
167 std::unique_ptr<TrajectoryReader> traj_reader_;
168 };
169
AddObserver(CGObserver * observer)170 inline void CsgApplication::AddObserver(CGObserver *observer) {
171 observers_.push_back(observer);
172 }
173
174 } // namespace csg
175 } // namespace votca
176
177 #endif // VOTCA_CSG_CSGAPPLICATION_H
178