1 /*
2  *  Copyright (C) 2004-2021 Edward F. Valeev
3  *
4  *  This file is part of Libint.
5  *
6  *  Libint is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  Libint is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with Libint.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef _libint2_src_bin_libint_task_h_
22 #define _libint2_src_bin_libint_task_h_
23 
24 #include <string>
25 #include <vector>
26 #include <list>
27 #include <map>
28 #include <rr.h>
29 #include <default_params.h>
30 
31 namespace libint2 {
32 
33   class TaskExternSymbols;
34 
35   /**
36      A key idea introduced here is that of "task". By task I mean a
37      type of a computation that Libint performs. For example, computing ERIs is one task,
38      computing sets of integrals needed for the R12 theory is another task. The reason for speaking of separate tasks
39      is that the evaluator type must be specific to the task or tasks for which it was generated.
40      For example, all the intermediates needed in R12 computation are not necessary when computing ERIs.
41      If one evaluator type were to cover all tasks, it would be huge and performance would be likely hurt.
42      Thus we need to produce task-specific evaluator and associated functions (constructor, destructor,
43      memory query).
44   */
45   class LibraryTask {
46   public:
LibraryTask(const std::string & l,const SafePtr<TaskParameters> & p,const SafePtr<TaskExternSymbols> & s)47     LibraryTask(const std::string& l, const SafePtr<TaskParameters>& p, const SafePtr<TaskExternSymbols>& s) :
48       label_(l), params_(p), symbols_(s) {
49     }
~LibraryTask()50     ~LibraryTask() {
51     }
label()52     const std::string& label() const { return label_; }
params()53     const SafePtr<TaskParameters>& params() const { return params_; }
symbols()54     const SafePtr<TaskExternSymbols>& symbols() const { return symbols_; }
55 
56   private:
57     std::string label_;
58     SafePtr<TaskParameters> params_;
59     SafePtr<TaskExternSymbols> symbols_;
60   };
61 
62   /// Manages tasks. This is a Singleton.
63   class LibraryTaskManager {
64     typedef std::vector<LibraryTask> Tasks;
65     typedef Tasks::const_iterator tasks_citer;
66 
67   public:
68     typedef Tasks::const_iterator TasksCIter;
69     typedef Tasks::iterator TasksIter;
70 
71     /// LibraryTaskManager is a Singleton
72     static LibraryTaskManager& Instance();
~LibraryTaskManager()73     ~LibraryTaskManager() {}
74 
75     /// Number of tasks
ntask()76     unsigned int ntask() const { return tasks_.size(); }
77     /// returns iterator to the first task
first()78     TasksCIter first() const { return tasks_.begin(); }
79     /// returns iterator to past the last task
plast()80     TasksCIter plast() const { return tasks_.end(); }
81     /// i-th tasks
task(unsigned int i)82     LibraryTask& task(unsigned int i) { return tasks_.at(i); }
83     /// Adds a new task. Do nothing if the task exists already.
84     void add(const std::string& task_label);
85     /// @returns true if task \c task_label exists
86     bool exists(const std::string& task_label) const;
87     /// Find the task by name and return the iterator pointing to it. Throws ProgrammingError, if the task is not found.
88     TasksCIter find(const std::string& task_label) const;
89     /// Makes this task current (must have been added already)
90     void current(const std::string& task_label);
91     /// Returns the current task
92     LibraryTask& current();
93 
94   private:
95 
96     LibraryTaskManager();
97     Tasks tasks_;
98     int current_;
99 
100     static LibraryTaskManager LTM_obj_;
101   };
102 
103   /** This class maintains code symbols provided by the user, e.g. recurrence relation geometric and basis set prefactors.
104       Also needs to maintain references to recurrence relations used by this task -- since their code is generated
105       at the end of the compilation, must be able to recover the symbols somehow.
106    */
107   class TaskExternSymbols {
108   public:
109     typedef std::list<std::string> SymbolList;
110     /// Recurrence relations are maintained by RRStack and characterized by their unique numeric ID
111     typedef RRStack::InstanceID RRid;
112     typedef std::list<RRid> RRList;
113 
TaskExternSymbols()114     TaskExternSymbols() {}
~TaskExternSymbols()115     ~TaskExternSymbols() {}
116 
117     /// Add the symbols
118     void add(const SymbolList& symbols);
119     /** Return the symbols.
120      */
121     const SymbolList& symbols() const;
122     /// Add the RRs
123     void add(const RRList& rrlist);
124     /// Is this RR found in the list?
125     bool find(const RRid& rrid) const;
126     /// @return list of RRs references by this task
127     RRList rrlist() const;
128 
129   private:
130     // Maintain symbols as a map since each symbol only needs to appear once
131     typedef std::map<std::string,bool> Symbols;
132     Symbols symbols_;
133     mutable SymbolList symbollist_; // only used to return a list
134 
135     // Maintain RR list as a map, although RRStack already handles them that way -- hopefully this will speed up searching somewhat
136     typedef std::map<RRid,bool> RRmap;
137     RRmap rrmap_;
138 
139   };
140 
141 };
142 
143 #endif // header guard
144