Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2012-2017 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 "core/ActionWithValue.h" 23 : #include "core/ActionWithArguments.h" 24 : #include "core/ActionRegister.h" 25 : #include "tools/Communicator.h" 26 : 27 : //+PLUMEDOC ANALYSIS GATHER_REPLICAS 28 : /* 29 : Create a vector that contains the copies of the input quantities from all replicas 30 : 31 : \par Examples 32 : 33 : 34 : */ 35 : //+ENDPLUMEDOC 36 : 37 : namespace PLMD { 38 : namespace generic { 39 : 40 : class GatherReplicas : 41 : public ActionWithValue, 42 : public ActionWithArguments { 43 : private: 44 : unsigned nreplicas; 45 : public: 46 : static void registerKeywords( Keywords& keys ); 47 : explicit GatherReplicas( const ActionOptions& ); 48 : unsigned getNumberOfDerivatives(); 49 : void calculate(); 50 : void apply(); 51 : }; 52 : 53 : PLUMED_REGISTER_ACTION(GatherReplicas,"GATHER_REPLICAS") 54 : 55 31 : void GatherReplicas::registerKeywords( Keywords& keys ) { 56 31 : Action::registerKeywords( keys ); 57 31 : ActionWithValue::registerKeywords( keys ); 58 31 : ActionWithArguments::registerKeywords( keys ); 59 31 : keys.remove("ARG"); 60 62 : keys.add("compulsory","ARG","the argument from the various replicas that you would like to gather"); 61 62 : keys.addOutputComponent("rep","default","the input arguments for each of the replicas"); 62 31 : } 63 : 64 13 : GatherReplicas::GatherReplicas( const ActionOptions& ao ): 65 : Action(ao), 66 : ActionWithValue(ao), 67 13 : ActionWithArguments(ao) { 68 13 : if( getNumberOfArguments()!=1 ) { 69 0 : error("you can only gather one argument at a time with GatherReplicas"); 70 : } 71 : 72 13 : std::vector<unsigned> shape( getPntrToArgument(0)->getShape() ); 73 : std::string min, max; 74 13 : nreplicas=multi_sim_comm.Get_size(); 75 : bool periodic=false; 76 13 : if( getPntrToArgument(0)->isPeriodic() ) { 77 : periodic=true; 78 0 : getPntrToArgument(0)->getDomain( min, max ); 79 : } 80 : 81 86 : for(unsigned i=0; i<nreplicas; ++i) { 82 : std::string num; 83 73 : Tools::convert( i+1, num); 84 73 : if( getPntrToArgument(0)->hasDerivatives() ) { 85 146 : addComponentWithDerivatives( "rep-" + num, shape ); 86 : } else { 87 0 : addComponent( "rep-" + num, shape ); 88 : } 89 73 : if( periodic ) { 90 0 : componentIsPeriodic( "rep-" + num, min, max ); 91 : } else { 92 146 : componentIsNotPeriodic( "rep-" + num ); 93 : } 94 : } 95 13 : } 96 : 97 0 : unsigned GatherReplicas::getNumberOfDerivatives() { 98 0 : return getPntrToArgument(0)->getNumberOfDerivatives(); 99 : } 100 : 101 4224 : void GatherReplicas::calculate() { 102 : Value* myarg = getPntrToArgument(0); 103 4224 : unsigned nvals = myarg->getNumberOfValues(), nder = myarg->getNumberOfDerivatives(); 104 4224 : std::vector<double> dval( nvals*(1+nder) ), datap(nreplicas*nvals*(1+nder) ); 105 8448 : for(unsigned i=0; i<nvals; ++i) { 106 4224 : dval[i*(1+nder)] = myarg->get(i); 107 4224 : if( myarg->getRank()==0 ) { 108 8448 : for(unsigned j=0; j<nder; ++j) { 109 4224 : dval[i*(1+nder)+1+j] = myarg->getDerivative(j); 110 : } 111 0 : } else if( myarg->hasDerivatives() ) { 112 0 : for(unsigned j=0; j<nder; ++j) { 113 0 : dval[i*(1+nder)+1+j] = myarg->getGridDerivative( i, j ); 114 : } 115 : } 116 : } 117 4224 : if(comm.Get_rank()==0) { 118 4224 : multi_sim_comm.Allgather(dval,datap); 119 : } 120 : 121 29568 : for(unsigned k=0; k<nreplicas; k++) { 122 25344 : Value* myout = getPntrToComponent(k); 123 25344 : if( myout->getNumberOfDerivatives()!=myarg->getNumberOfDerivatives() ) { 124 72 : myout->resizeDerivatives( myarg->getNumberOfDerivatives() ); 125 : } 126 25344 : unsigned sstart=k*nvals*(1+nder); 127 50688 : for(unsigned i=0; i<nvals; ++i) { 128 25344 : myout->set( i, datap[sstart+i*(1+nder)] ); 129 25344 : if( myarg->getRank()==0 ) { 130 50688 : for(unsigned j=0; j<nder; ++j) { 131 25344 : myout->setDerivative( j, dval[i*(1+nder)+1+j] ); 132 : } 133 0 : } else if( myarg->hasDerivatives() ) { 134 0 : for(unsigned j=0; j<nder; ++j) { 135 0 : myout->addGridDerivatives( i, j, dval[i*(1+nder)+1+j] ); 136 : } 137 : } 138 : } 139 : } 140 4224 : } 141 : 142 4224 : void GatherReplicas::apply() { 143 4224 : if( doNotCalculateDerivatives() ) { 144 4224 : return; 145 : } 146 0 : error("apply has not been implemented for GatherReplicas"); 147 : } 148 : 149 : } 150 : }