Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2023 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : plumed 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
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 : #include "GREX.h"
23 : #include "PlumedMain.h"
24 : #include "tools/Tools.h"
25 : #include "tools/Communicator.h"
26 : #include <sstream>
27 :
28 : namespace PLMD {
29 :
30 204 : GREX::GREX(PlumedMain&p):
31 204 : initialized(false),
32 204 : plumedMain(p),
33 204 : partner(-1), // = unset
34 204 : localDeltaBias(0),
35 204 : foreignDeltaBias(0),
36 204 : localUNow(0),
37 204 : localUSwap(0),
38 204 : myreplica(-1) // = unset
39 : {
40 204 : p.setSuffix(".NA");
41 204 : }
42 :
43 408 : GREX::~GREX() {
44 : // empty destructor to delete unique_ptr
45 408 : }
46 :
47 : #define CHECK_INIT(ini,word) plumed_assert(ini) << "cmd(\"" << word <<"\") should be only used after GREX initialization"
48 : #define CHECK_NOTINIT(ini,word) plumed_assert(!(ini)) << "cmd(\"" << word <<"\") should be only used before GREX initialization"
49 : #define CHECK_NOTNULL(val,word) plumed_assert(val) << "NULL pointer received in cmd(\"GREX " << word << "\")"
50 :
51 1077 : void GREX::cmd(std::string_view key,const TypesafePtr & val) {
52 : // Enumerate all possible commands:
53 : enum {
54 : #include "GREXEnum.inc"
55 : };
56 :
57 : // Static object (initialized once) containing the map of commands:
58 : const static Tools::FastStringUnorderedMap<int> word_map = {
59 : #include "GREXMap.inc"
60 1077 : };
61 :
62 : gch::small_vector<std::string_view> words;
63 1077 : Tools::getWordsSimple(words,key);
64 1077 : unsigned nw=words.size();
65 1077 : if(nw==0) {
66 : // do nothing
67 : } else {
68 : int iword=-1;
69 : const auto it=word_map.find(words[0]);
70 1077 : if(it!=word_map.end()) iword=it->second;
71 1077 : switch(iword) {
72 : case cmd_initialized:
73 0 : CHECK_NOTNULL(val,key);
74 0 : val.set(int(initialized));
75 : break;
76 204 : case cmd_setMPIIntracomm:
77 204 : CHECK_NOTINIT(initialized,key);
78 408 : intracomm.Set_comm(val.get<const void*>());
79 204 : break;
80 156 : case cmd_setMPIIntercomm:
81 156 : CHECK_NOTINIT(initialized,key);
82 312 : intercomm.Set_comm(val.get<const void*>());
83 312 : plumedMain.multi_sim_comm.Set_comm(val.get<const void*>());
84 156 : break;
85 0 : case cmd_setMPIFIntracomm:
86 0 : CHECK_NOTINIT(initialized,key);
87 0 : intracomm.Set_fcomm(val.get<const void*>());
88 0 : break;
89 0 : case cmd_setMPIFIntercomm:
90 0 : CHECK_NOTINIT(initialized,key);
91 0 : intercomm.Set_fcomm(val.get<const void*>());
92 0 : plumedMain.multi_sim_comm.Set_fcomm(val.get<const void*>());
93 0 : break;
94 204 : case cmd_init:
95 204 : CHECK_NOTINIT(initialized,key);
96 204 : initialized=true;
97 : // note that for PEs!=root this is automatically 0 (comm defaults to MPI_COMM_SELF)
98 204 : myreplica=intercomm.Get_rank();
99 204 : intracomm.Sum(myreplica);
100 : {
101 : std::string s;
102 204 : Tools::convert(myreplica,s);
103 408 : plumedMain.setSuffix("."+s);
104 : }
105 204 : break;
106 57 : case cmd_prepare:
107 57 : CHECK_INIT(initialized,key);
108 57 : if(intracomm.Get_rank()==0) return;
109 57 : intracomm.Bcast(partner,0);
110 57 : calculate();
111 : break;
112 57 : case cmd_setPartner:
113 57 : CHECK_INIT(initialized,key);
114 57 : partner=val.get<int>();
115 57 : break;
116 114 : case cmd_savePositions:
117 114 : CHECK_INIT(initialized,key);
118 114 : savePositions();
119 : break;
120 57 : case cmd_calculate:
121 57 : CHECK_INIT(initialized,key);
122 57 : if(intracomm.Get_rank()!=0) return;
123 57 : intracomm.Bcast(partner,0);
124 57 : calculate();
125 : break;
126 0 : case cmd_getLocalDeltaBias:
127 0 : CHECK_INIT(initialized,key);
128 0 : CHECK_NOTNULL(val,key);
129 0 : plumedMain.plumedQuantityToMD("energy",localDeltaBias,val);
130 0 : break;
131 0 : case cmd_cacheLocalUNow:
132 0 : CHECK_INIT(initialized,key);
133 0 : CHECK_NOTNULL(val,key);
134 : {
135 0 : localUNow=plumedMain.MDQuantityToPLUMED("energy",val);
136 0 : intracomm.Sum(localUNow);
137 : }
138 : break;
139 0 : case cmd_cacheLocalUSwap:
140 0 : CHECK_INIT(initialized,key);
141 0 : CHECK_NOTNULL(val,key);
142 : {
143 0 : localUSwap=plumedMain.MDQuantityToPLUMED("energy",val);
144 0 : intracomm.Sum(localUSwap);
145 : }
146 : break;
147 0 : case cmd_getForeignDeltaBias:
148 0 : CHECK_INIT(initialized,key);
149 0 : CHECK_NOTNULL(val,key);
150 0 : plumedMain.plumedQuantityToMD("energy",foreignDeltaBias,val);
151 0 : break;
152 57 : case cmd_shareAllDeltaBias:
153 57 : CHECK_INIT(initialized,key);
154 57 : if(intracomm.Get_rank()!=0) return;
155 57 : allDeltaBias.assign(intercomm.Get_size(),0.0);
156 57 : allDeltaBias[intercomm.Get_rank()]=localDeltaBias;
157 57 : intercomm.Sum(allDeltaBias);
158 : break;
159 171 : case cmd_getDeltaBias:
160 171 : CHECK_INIT(initialized,key);
161 171 : CHECK_NOTNULL(val,key);
162 171 : plumed_assert(nw==2);
163 171 : plumed_massert(allDeltaBias.size()==static_cast<unsigned>(intercomm.Get_size()),
164 : "to retrieve bias with cmd(\"GREX getDeltaBias\"), first share it with cmd(\"GREX shareAllDeltaBias\")");
165 : {
166 : unsigned rep;
167 171 : Tools::convert(std::string(words[1]),rep);
168 171 : plumed_massert(rep<allDeltaBias.size(),"replica index passed to cmd(\"GREX getDeltaBias\") is out of range");
169 171 : plumedMain.plumedQuantityToMD("energy",allDeltaBias[rep],val);
170 : }
171 171 : break;
172 0 : default:
173 0 : plumed_error() << "cannot interpret cmd(\" GREX" << key << "\"). check plumed developers manual to see the available commands.";
174 : break;
175 : }
176 : }
177 : }
178 :
179 114 : void GREX::savePositions() {
180 114 : plumedMain.prepareDependencies();
181 114 : plumedMain.resetActive(true);
182 114 : plumedMain.shareAll();
183 114 : plumedMain.waitData();
184 114 : std::ostringstream o;
185 114 : plumedMain.writeBinary(o);
186 114 : buffer=o.str();
187 114 : }
188 :
189 114 : void GREX::calculate() {
190 : unsigned nn=buffer.size();
191 114 : std::vector<char> rbuf(nn);
192 114 : localDeltaBias=-plumedMain.getBias();
193 114 : if(intracomm.Get_rank()==0) {
194 57 : Communicator::Request req=intercomm.Isend(buffer,partner,1066);
195 57 : intercomm.Recv(rbuf,partner,1066);
196 57 : req.wait();
197 : }
198 114 : intracomm.Bcast(rbuf,0);
199 114 : std::istringstream i(std::string(&rbuf[0],rbuf.size()));
200 114 : plumedMain.readBinary(i);
201 114 : plumedMain.setExchangeStep(true);
202 114 : plumedMain.prepareDependencies();
203 114 : plumedMain.justCalculate();
204 114 : plumedMain.setExchangeStep(false);
205 114 : localDeltaBias+=plumedMain.getBias();
206 114 : localDeltaBias+=localUSwap-localUNow;
207 114 : if(intracomm.Get_rank()==0) {
208 57 : Communicator::Request req=intercomm.Isend(localDeltaBias,partner,1067);
209 57 : intercomm.Recv(foreignDeltaBias,partner,1067);
210 57 : req.wait();
211 : }
212 114 : intracomm.Bcast(foreignDeltaBias,0);
213 228 : }
214 :
215 : }
|