Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2016-2019 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 "Bias.h"
23 : #include "core/PlumedMain.h"
24 : #include "core/Atoms.h"
25 : #include <string>
26 : #include <cstring>
27 : //#include "ActionRegister.h"
28 : #include "core/ActionRegister.h"
29 : #include "core/ActionWithValue.h"
30 : #include "tools/Communicator.h"
31 : #include "tools/File.h"
32 : #include <iostream>
33 :
34 : //#include "Analysis.h"
35 : //#include "core/PlumedMain.h"
36 : //#include "core/ActionRegister.h"
37 : //#include "tools/Grid.h"
38 : //#include "tools/KernelFunctions.h"
39 : //#include "tools/IFile.h"
40 : //#include "tools/OFile.h"
41 :
42 : // The original implementation of this method was contributed
43 : // by Andrea Cesari (andreacesari90@gmail.com).
44 : // Copyright has been then transferred to PLUMED developers
45 : // (see https://github.com/plumed/plumed2/blob/master/.github/CONTRIBUTING.md)
46 :
47 : using namespace std;
48 :
49 :
50 : namespace PLMD {
51 : namespace bias {
52 :
53 : //+PLUMEDOC BIAS MAXENT
54 : /*
55 : Add a linear biasing potential on one or more variables \f$f_{i}\left(\boldsymbol{x}\right)\f$ satisfying the maximum entropy principle as proposed in Ref. \cite cesari2016maxent .
56 :
57 : \warning
58 : Notice that syntax is still under revision and might change
59 :
60 : The resulting biasing potential is given by:
61 : \f[
62 : V_{BIAS}(\boldsymbol{x},t)=K_{B}T\sum_{i=1}^{\#arguments}f_{i}(\boldsymbol{x},t)\lambda_{i}(t)
63 : \f]
64 : Lagrangian multipliers \f$ \lambda_{i}\f$ are updated, every PACE steps, according to the following update rule:
65 : \f[
66 : \lambda_{i}=\lambda_{i}+\frac{k_{i}}{1+\frac{t}{\tau_{i}}}\left(f_{exp,i}+\xi_{i}\lambda_{i}-f_{i}(\boldsymbol{x})\right)
67 : \f]
68 : \f$k\f$ set the initial value of the learning rate and its units are \f$[observable]^{-2}ps^{-1}\f$. This can be set with the keyword KAPPA.
69 : The number of components for any KAPPA vector must be equal to the number of arguments of the action.
70 :
71 : Variable \f$ \xi_{i}(\lambda) \f$ is related to the choosen prior to model experimental errors. If a GAUSSIAN prior is used then:
72 : \f[
73 : \xi_{i}(\lambda)=-\lambda_{i}\sigma^{2}
74 : \f]
75 : where \f$ \sigma \f$ is the typical expected error on the observable \f$ f_i\f$.
76 : For a LAPLACE prior:
77 : \f[
78 : \xi_{i}(\lambda)=-\frac{\lambda_{i}\sigma^{2}}{1-\frac{\lambda^{2}\sigma^{2}}{2}}
79 :
80 : \f]
81 : The value of \f$ \xi(\lambda,t)\f$ is written in output as a component named: argument name followed by the string _error.
82 : Setting \f$ \sigma =0\f$ is equivalent to enforce a pure Maximum Entropy restraint without any noise modelling.
83 : This method can be also used to enforce inequality restraint as shown in following examples.
84 :
85 : Notice that a similar method is available as \ref EDS, although with different features and using a different optimization algorithm.
86 :
87 : \par Examples
88 :
89 : The following input tells plumed to restrain the distance between atoms 7 and 15
90 : and the distance between atoms 2 and 19, at different equilibrium
91 : values, and to print the energy of the restraint.
92 : Lagrangian multiplier will be printed on a file called restraint.LAGMULT with a stride set by the variable PACE to 200ps.
93 : Moreover plumed will compute the average of each lagrangian multiplier in the window [TSTART,TEND] and use that to continue the simulations with fixed Lagrangian multipliers.
94 : \plumedfile
95 : DISTANCE ATOMS=7,15 LABEL=d1
96 : DISTANCE ATOMS=2,19 LABEL=d2
97 : MAXENT ...
98 : ARG=d1,d2
99 : TYPE=EQUAL
100 : AT=0.2,0.5
101 : KAPPA=35000.0,35000.0
102 : TAU=0.02,0.02
103 : PACE=200
104 : TSTART=100
105 : TEND=500
106 : LABEL=restraint
107 : PRINT ARG=restraint.bias
108 : ... MAXENT
109 : \endplumedfile
110 : Lagrangian multipliers will be printed on a file called restraint.bias
111 : The following input tells plumed to restrain the distance between atoms 7 and 15
112 : to be greater than 0.2 and to print the energy of the restraint
113 : \plumedfile
114 : DISTANCE ATOMS=7,15 LABEL=d
115 : MAXENT ARG=d TYPE=INEQUAL> AT=0.02 KAPPA=35000.0 TAU= LABEL=restraint
116 : PRINT ARG=restraint.bias
117 : \endplumedfile
118 :
119 : (See also \ref DISTANCE and \ref PRINT).
120 :
121 : */
122 : //+ENDPLUMEDOC
123 :
124 : class MaxEnt : public Bias {
125 : std::vector<double> at;
126 : std::vector<double> kappa;
127 : std::vector<double> lambda;
128 : std::vector<double> avgx;
129 : std::vector<double> work;
130 : std::vector<double> oldlambda;
131 : std::vector<double> tau;
132 : std::vector<double> avglambda;
133 : std::vector<double> avglambda_restart;
134 : std::vector<double> expected_eps;
135 : std::vector<double> apply_weights;
136 : double sigma;
137 : double tstart;
138 : double tend;
139 : double avgstep; //current number of samples over which to compute the average. Check if could be replaced bu getStep()
140 : long int pace_;
141 : long int stride_;
142 : double totalWork;
143 : double BetaReweightBias;
144 : double simtemp;
145 : double reweight_bias2;
146 : vector<ActionWithValue*> biases;
147 : std::string type;
148 : std::string error_type;
149 : double alpha;
150 : double avg_counter;
151 : int learn_replica;
152 : Value* valueForce2;
153 : Value* valueWork;
154 : OFile lagmultOfile_;
155 : IFile ifile;
156 : string lagmultfname;
157 : string ifilesnames;
158 : string fmt;
159 : bool isFirstStep;
160 : bool reweight;
161 : bool no_broadcast;
162 : bool printFirstStep;
163 : std::vector<bool> done_average;
164 : int myrep,nrep;
165 : public:
166 : explicit MaxEnt(const ActionOptions&);
167 : ~MaxEnt();
168 : void calculate();
169 : void update();
170 : void update_lambda();
171 : static void registerKeywords(Keywords& keys);
172 : void ReadLagrangians(IFile &ifile);
173 : void WriteLagrangians(vector<double> &lagmult,OFile &file);
174 : double compute_error(string &err_type,double &l);
175 : double convert_lambda(string &type,double lold);
176 : void check_lambda_boundaries(string &err_type,double &l);
177 : };
178 6502 : PLUMED_REGISTER_ACTION(MaxEnt,"MAXENT")
179 :
180 51 : void MaxEnt::registerKeywords(Keywords& keys) {
181 51 : Bias::registerKeywords(keys);
182 51 : componentsAreNotOptional(keys);
183 102 : keys.use("ARG");
184 255 : keys.add("compulsory","KAPPA","0.0","specifies the initial value for the learning rate");
185 204 : keys.add("compulsory","TAU","Specify the dumping time for the learning rate.");
186 204 : keys.add("compulsory","TYPE","specify the restraint type. "
187 : "EQAUL to restrain the variable at a given equilibrium value"
188 : "INEQUAL< to restrain the variable to be smaller than a given value"
189 : "INEQUAL> to restrain the variable to be greater than a given value");
190 204 : keys.add("optional","ERROR_TYPE","specify the prior on the error to use."
191 : "GAUSSIAN: use a Gaussian prior"
192 : "LAPLACE: use a Laplace prior");
193 204 : keys.add("optional","TSTART","time in ps from where to start averaging the Lagrangian multiplier. By default no average is computed, hence lambda is updated every PACE steps");
194 204 : keys.add("optional","TEND","time in ps where to stop to compute the average of Lagrangian multiplier. From this time until the end of the simulation Lagrangian multipliers are kept fix to the average computed between TSTART and TEND;");
195 204 : keys.add("optional","ALPHA","default=1.0; To be used with LAPLACE KEYWORD, allows to choose a prior function proportional to a Gaussian times an exponential function. ALPHA=1 correspond to the LAPLACE prior.");
196 204 : keys.add("compulsory","AT","the position of the restraint");
197 204 : keys.add("optional","SIGMA","The typical erros expected on observable");
198 204 : keys.add("optional","FILE","Lagrangian multipliers output file. The default name is: label name followed by the string .LAGMULT ");
199 204 : keys.add("optional","LEARN_REPLICA","In a multiple replica environment specify which is the reference replica. By default replica 0 will be used.");
200 204 : keys.add("optional","APPLY_WEIGHTS","Vector of weights containing 1 in correspondece of each replica that will receive the lagrangian multiplier from the current one.");
201 204 : keys.add("optional","PACE","the frequency for Lagrangian multipliers update");
202 204 : keys.add("optional","PRINT_STRIDE","stride of Lagrangian multipliers output file. If no STRIDE is passed they are written every time they are updated (PACE).");
203 204 : keys.add("optional","FMT","specify format for Lagrangian multipliers files (usefulf to decrease the number of digits in regtests)");
204 153 : keys.addFlag("REWEIGHT",false,"to be used with plumed driver in order to reweight a trajectory a posteriori");
205 153 : keys.addFlag("NO_BROADCAST",false,"If active will avoid Lagrangian multipliers to be comunicated to other replicas.");
206 204 : keys.add("optional","TEMP","the system temperature. This is required if you are reweighting.");
207 204 : keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential");
208 204 : keys.addOutputComponent("work","default","the instantaneous value of the work done by the biasing force");
209 204 : keys.addOutputComponent("_work","default","the instantaneous value of the work done by the biasing force for each argument. "
210 : "These quantities will named with the arguments of the bias followed by "
211 : "the character string _work.");
212 204 : keys.addOutputComponent("_error","default","Instantaneous values of the discrepancy between the observable and the restraint center");
213 204 : keys.addOutputComponent("_coupling","default","Instantaneous values of Lagrangian multipliers. They are also written by default in a separate output file.");
214 102 : keys.use("RESTART");
215 51 : }
216 200 : MaxEnt::~MaxEnt() {
217 50 : lagmultOfile_.close();
218 100 : }
219 50 : MaxEnt::MaxEnt(const ActionOptions&ao):
220 : PLUMED_BIAS_INIT(ao),
221 : at(getNumberOfArguments()),
222 : kappa(getNumberOfArguments(),0.0),
223 : lambda(getNumberOfArguments(),0.0),
224 : avgx(getNumberOfArguments(),0.0),
225 : oldlambda(getNumberOfArguments(),0.0),
226 100 : tau(getNumberOfArguments(),getTimeStep()),
227 : avglambda(getNumberOfArguments(),0.0),
228 : avglambda_restart(getNumberOfArguments(),0.0),
229 : expected_eps(getNumberOfArguments(),0.0),
230 : sigma(0.0),
231 : pace_(100),
232 : stride_(100),
233 : alpha(1.0),
234 : avg_counter(0.0),
235 : isFirstStep(true),
236 : reweight(false),
237 : no_broadcast(false),
238 : printFirstStep(true),
239 950 : done_average(getNumberOfArguments(),false)
240 : {
241 50 : if(comm.Get_rank()==0) nrep=multi_sim_comm.Get_size();
242 50 : if(comm.Get_rank()==0) myrep=multi_sim_comm.Get_rank();
243 50 : comm.Bcast(nrep,0);
244 50 : comm.Bcast(myrep,0);
245 100 : parseFlag("NO_BROADCAST",no_broadcast);
246 : //if(no_broadcast){
247 : //for(int irep=0;irep<nrep;irep++){
248 : // if(irep!=myrep)
249 : // apply_weights[irep]=0.0;}
250 : //}
251 50 : avgstep=1.0;
252 50 : tstart=-1.0;
253 50 : tend=-1.0;
254 50 : totalWork=0.0;
255 50 : learn_replica=0;
256 :
257 100 : parse("LEARN_REPLICA",learn_replica);
258 100 : parseVector("APPLY_WEIGHTS",apply_weights);
259 50 : if(apply_weights.size()==0) apply_weights.resize(nrep,1.0);
260 100 : parseVector("KAPPA",kappa);
261 100 : parseVector("AT",at);
262 100 : parseVector("TAU",tau);
263 100 : parse("TYPE",type);
264 : error_type="GAUSSIAN";
265 100 : parse("ERROR_TYPE",error_type);
266 100 : parse("ALPHA",alpha);
267 100 : parse("SIGMA",sigma);
268 100 : parse("TSTART",tstart);
269 50 : if(tstart <0 && tstart != -1.0) error("TSTART should be a positive number");
270 100 : parse("TEND",tend);
271 50 : if(tend<0 && tend != -1.0) error("TSTART should be a positive number");
272 50 : if(tend<tstart) error("TEND should be >= TSTART");
273 100 : lagmultfname=getLabel()+".LAGMULT";
274 100 : parse("FILE",lagmultfname);
275 100 : parse("FMT",fmt);
276 100 : parse("PACE",pace_);
277 50 : if(pace_<=0 ) error("frequency for lagrangian multipliers update (PACE) is nonsensical");
278 50 : stride_=pace_; //if no STRIDE is passed, then Lagrangian multipliers willbe printed at each update
279 100 : parse("PRINT_STRIDE",stride_);
280 50 : if(stride_<=0 ) error("frequency for Lagrangian multipliers printing (STRIDE) is nonsensical");
281 50 : simtemp=0.;
282 100 : parse("TEMP",simtemp);
283 100 : if(simtemp>0) simtemp*=plumed.getAtoms().getKBoltzmann();
284 0 : else simtemp=plumed.getAtoms().getKbT();
285 100 : parseFlag("REWEIGHT",reweight);
286 50 : if(simtemp<=0 && reweight) error("Set the temperature (TEMP) if you want to do reweighting.");
287 :
288 50 : checkRead();
289 :
290 50 : log.printf(" at");
291 1546 : for(unsigned i=0; i<at.size(); i++) log.printf(" %f",at[i]);
292 50 : log.printf("\n");
293 50 : log.printf(" with initial learning rate for optimization of");
294 1546 : for(unsigned i=0; i<kappa.size(); i++) log.printf(" %f",kappa[i]);
295 50 : log.printf("\n");
296 50 : log.printf("Dumping times for the learning rates are (ps): ");
297 1546 : for(unsigned i=0; i<tau.size(); i++) log.printf(" %f",tau[i]);
298 50 : log.printf("\n");
299 50 : log.printf("Lagrangian multipliers are updated every %ld steps (PACE)\n",pace_);
300 100 : log.printf("Lagrangian multipliers output file %s\n",lagmultfname.c_str());
301 50 : log.printf("Lagrangian multipliers are written every %ld steps (PRINT_STRIDE)\n",stride_);
302 50 : if(fmt.length()>0)
303 100 : log.printf("The format for real number in Lagrangian multipliers file is %s\n",fmt.c_str());
304 50 : if(tstart >-1.0 && tend>-1.0)
305 14 : log.printf("Lagrangian multipliers are averaged from %lf ps to %lf ps\n",tstart,tend);
306 50 : if(no_broadcast)
307 0 : log.printf("Using NO_BROADCAST options. Lagrangian multipliers will not be comunicated to other replicas.\n");
308 : //for(int irep=0;irep<nrep;irep++){
309 : // if(apply_weights[irep]!=0)
310 : // log.printf("%d",irep);
311 : // }
312 150 : addComponent("force2"); componentIsNotPeriodic("force2");
313 150 : addComponent("work"); componentIsNotPeriodic("work");
314 100 : valueForce2=getPntrToComponent("force2");
315 100 : valueWork=getPntrToComponent("work");
316 :
317 : std::string comp;
318 1014 : for(unsigned i=0; i< getNumberOfArguments() ; i++) {
319 964 : comp=getPntrToArgument(i)->getName()+"_coupling";
320 482 : addComponent(comp); componentIsNotPeriodic(comp);
321 964 : comp=getPntrToArgument(i)->getName()+"_work";
322 482 : addComponent(comp); componentIsNotPeriodic(comp);
323 964 : work.push_back(0.); // initialize the work value
324 964 : comp=getPntrToArgument(i)->getName()+"_error";
325 482 : addComponent(comp); componentIsNotPeriodic(comp);
326 : }
327 : string fname;
328 : fname=lagmultfname;
329 50 : ifile.link(*this);
330 50 : if(ifile.FileExist(fname)) {
331 37 : ifile.open(fname);
332 37 : if(getRestart()) {
333 74 : log.printf(" Restarting from: %s\n",fname.c_str());
334 37 : ReadLagrangians(ifile);
335 37 : printFirstStep=false;
336 : }
337 37 : ifile.reset(false);
338 37 : ifile.close();
339 : }
340 :
341 50 : lagmultOfile_.link(*this);
342 50 : lagmultOfile_.open(fname);
343 100 : if(fmt.length()>0) {fmt=" "+fmt; lagmultOfile_.fmtField(fmt);}
344 50 : }
345 : ////MEMBER FUNCTIONS
346 37 : void MaxEnt::ReadLagrangians(IFile &ifile)
347 : {
348 : double dummy;
349 888 : while(ifile.scanField("time",dummy)) {
350 9009 : for(unsigned j=0; j<getNumberOfArguments(); ++j) {
351 12903 : ifile.scanField(getPntrToArgument(j)->getName()+"_coupling",lambda[j]);
352 4301 : if(dummy>=tstart && dummy <=tend)
353 84 : avglambda[j]+=lambda[j];
354 4301 : if(dummy>=tend) {
355 4231 : avglambda[j]=lambda[j];
356 : done_average[j]=true;
357 : }
358 : }
359 407 : if(dummy>=tstart && dummy <=tend)
360 6 : avg_counter++;
361 407 : ifile.scanField();
362 : }
363 37 : }
364 550 : void MaxEnt::WriteLagrangians(vector<double> &lagmult,OFile &file) {
365 550 : if(printFirstStep) {
366 143 : unsigned ncv=getNumberOfArguments();
367 286 : file.printField("time",getTimeStep()*getStep());
368 2145 : for(unsigned i=0; i<ncv; ++i)
369 4004 : file.printField(getPntrToArgument(i)->getName()+"_coupling",lagmult[i]);
370 143 : file.printField();
371 : } else {
372 407 : if(!isFirstStep) {
373 370 : unsigned ncv=getNumberOfArguments();
374 740 : file.printField("time",getTimeStep()*getStep());
375 8190 : for(unsigned i=0; i<ncv; ++i)
376 15640 : file.printField(getPntrToArgument(i)->getName()+"_coupling",lagmult[i]);
377 370 : file.printField();
378 : }
379 : }
380 550 : }
381 5302 : double MaxEnt::compute_error(string &err_type,double &l) {
382 5302 : double sigma2=pow(sigma,2.0);
383 5302 : double l2=convert_lambda(type,l);
384 : double return_error=0;
385 5302 : if(err_type=="GAUSSIAN" && sigma!=0.0)
386 0 : return_error=-l2*sigma2;
387 : else {
388 5302 : if(err_type=="LAPLACE" && sigma!=0) {
389 5302 : return_error=-l2*sigma2/(1.0-l2*l2*sigma2/(alpha+1));
390 : }
391 : }
392 5302 : return return_error;
393 : }
394 119118 : double MaxEnt::convert_lambda(string &type,double lold) {
395 : double return_lambda=0;
396 119118 : if(type=="EQUAL")
397 : return_lambda=lold;
398 : else {
399 5302 : if(type=="INEQUAL>") {
400 0 : if(lold>0.0)
401 : return_lambda=0.0;
402 : else
403 : return_lambda=lold;
404 : }
405 : else {
406 5302 : if(type=="INEQUAL<") {
407 0 : if(lold<0.0)
408 : return_lambda=0.0;
409 : else
410 : return_lambda=lold;
411 : }
412 : }
413 : }
414 119118 : return return_lambda;
415 : }
416 5302 : void MaxEnt::check_lambda_boundaries(string &err_type,double &l) {
417 5302 : if(err_type=="LAPLACE" && sigma !=0 ) {
418 5302 : double l2=convert_lambda(err_type,l);
419 5302 : if(l2 <-(sqrt(alpha+1)/sigma-0.01)) {
420 0 : l=-(sqrt(alpha+1)/sigma-0.01);
421 0 : log.printf("Lambda exceeded the allowed range\n");
422 : }
423 5302 : if(l2>(sqrt(alpha+1)/sigma-0.01)) {
424 0 : l=sqrt(alpha+1)/sigma-0.01;
425 0 : log.printf("Lambda exceeded the allowed range\n");
426 : }
427 : }
428 5302 : }
429 :
430 550 : void MaxEnt::update_lambda() {
431 :
432 : double totalWork_=0.0;
433 550 : const double time=getTime();
434 550 : const double step=getStep();
435 550 : double KbT=simtemp;
436 : double learning_rate;
437 550 : if(reweight)
438 396 : BetaReweightBias=plumed.getBias()/KbT;
439 : else
440 154 : BetaReweightBias=0.0;
441 :
442 11154 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
443 10604 : const double k=kappa[i];
444 10604 : double cv=(getArgument(i)+compute_error(error_type,lambda[i])-at[i]);
445 5302 : if(reweight)
446 4224 : learning_rate=1.0*k/(1+step/tau[i]);
447 : else
448 1078 : learning_rate=1.0*k/(1+time/tau[i]);
449 10604 : lambda[i]+=learning_rate*cv*exp(-BetaReweightBias); //update Lagrangian multipliers and reweight them if REWEIGHT is set
450 5302 : check_lambda_boundaries(error_type,lambda[i]); //check that Lagrangians multipliers not exceed the allowed range
451 5890 : if(time>=tstart && time <=tend && !done_average[i]) {
452 1092 : avglambda[i]+=convert_lambda(type,lambda[i]); //compute the average of Lagrangian multipliers over the required time window
453 : }
454 5302 : if(time>=tend && tend >=0) { //setting tend<0 will disable this feature
455 98 : if(!done_average[i]) {
456 91 : avglambda[i]=avglambda[i]/avg_counter;
457 : done_average[i]=true;
458 91 : lambda[i]=avglambda[i];
459 : }
460 : else
461 7 : lambda[i]=avglambda[i]; //keep Lagrangian multipliers fixed to the previously computed average.
462 : }
463 21208 : work[i]+=(convert_lambda(type,lambda[i])-oldlambda[i])*getArgument(i); //compute the work performed in updating lambda
464 5302 : totalWork_+=work[i];
465 5302 : totalWork=totalWork_;
466 10604 : oldlambda[i]=convert_lambda(type,lambda[i]);
467 : };
468 550 : if(time>=tstart && time <=tend)
469 84 : avg_counter++;
470 550 : }
471 :
472 5050 : void MaxEnt::calculate() {
473 : double totf2=0.0;
474 : double ene=0.0;
475 5050 : double KbT=simtemp;
476 102414 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
477 194728 : getPntrToComponent(getPntrToArgument(i)->getName()+"_error")->set(expected_eps[i]);
478 146046 : getPntrToComponent(getPntrToArgument(i)->getName()+"_work")->set(work[i]);
479 48682 : valueWork->set(totalWork);
480 146046 : getPntrToComponent(getPntrToArgument(i)->getName()+"_coupling")->set(lambda[i]);
481 146046 : const double f=-KbT*convert_lambda(type,lambda[i])*apply_weights[myrep];
482 48682 : totf2+=f*f;
483 146046 : ene+=KbT*convert_lambda(type,lambda[i])*getArgument(i)*apply_weights[myrep];
484 48682 : setOutputForce(i,f);
485 : }
486 : setBias(ene);
487 5050 : valueForce2->set(totf2);
488 5050 : }
489 :
490 5050 : void MaxEnt::update() {
491 :
492 5050 : if(getStep()%stride_ == 0)
493 550 : WriteLagrangians(lambda,lagmultOfile_);
494 5050 : if(getStep()%pace_ == 0) {
495 550 : update_lambda();
496 550 : if(!no_broadcast) {
497 550 : if(comm.Get_rank()==0) //Comunicate Lagrangian multipliers from reference replica to higher ones
498 462 : multi_sim_comm.Bcast(lambda,learn_replica);
499 : }
500 550 : comm.Bcast(lambda,0);
501 : }
502 5050 : isFirstStep=false;
503 5050 : }
504 :
505 : }
506 :
507 4839 : }
|