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 33 : void GatherReplicas::registerKeywords( Keywords& keys ) { 56 33 : Action::registerKeywords( keys ); 57 33 : ActionWithValue::registerKeywords( keys ); 58 33 : ActionWithArguments::registerKeywords( keys ); 59 33 : keys.remove("ARG"); 60 66 : keys.add("compulsory","ARG","the argument from the various replicas that you would like to gather"); 61 66 : keys.addOutputComponent("rep","default","the input arguments for each of the replicas"); 62 33 : } 63 : 64 15 : GatherReplicas::GatherReplicas( const ActionOptions& ao ): 65 : Action(ao), 66 : ActionWithValue(ao), 67 15 : ActionWithArguments(ao) { 68 15 : if( getNumberOfArguments()!=1 ) { 69 0 : error("you can only gather one argument at a time with GatherReplicas"); 70 : } 71 : 72 15 : std::vector<unsigned> shape( getPntrToArgument(0)->getShape() ); 73 : std::string min, max; 74 15 : nreplicas=multi_sim_comm.Get_size(); 75 : bool periodic=false; 76 15 : if( getPntrToArgument(0)->isPeriodic() ) { 77 : periodic=true; 78 0 : getPntrToArgument(0)->getDomain( min, max ); 79 : } 80 : 81 90 : for(unsigned i=0; i<nreplicas; ++i) { 82 : std::string num; 83 75 : Tools::convert( i+1, num); 84 75 : if( getPntrToArgument(0)->hasDerivatives() ) { 85 148 : addComponentWithDerivatives( "rep-" + num, shape ); 86 : } else { 87 2 : addComponent( "rep-" + num, shape ); 88 : } 89 75 : if( periodic ) { 90 0 : componentIsPeriodic( "rep-" + num, min, max ); 91 : } else { 92 150 : componentIsNotPeriodic( "rep-" + num ); 93 : } 94 : } 95 15 : } 96 : 97 4226 : unsigned GatherReplicas::getNumberOfDerivatives() { 98 : const Value* arg = getPntrToArgument(0); 99 4226 : return arg->hasDerivatives() ? arg->getNumberOfDerivatives() : 0; 100 : } 101 : 102 4226 : void GatherReplicas::calculate() { 103 : Value* myarg = getPntrToArgument(0); 104 4226 : std::size_t nvals = myarg->getNumberOfValues(), nder = getNumberOfDerivatives(); 105 4226 : std::vector<double> dval( nvals*(1+nder) ), datap(nreplicas*nvals*(1+nder) ); 106 8452 : for(unsigned i=0; i<nvals; ++i) { 107 4226 : dval[i*(1+nder)] = myarg->get(i); 108 4226 : if( myarg->getRank()==0 ) { 109 8450 : for(unsigned j=0; j<nder; ++j) { 110 4224 : dval[i*(1+nder)+1+j] = myarg->getDerivative(j); 111 : } 112 0 : } else if( myarg->hasDerivatives() ) { 113 0 : for(unsigned j=0; j<nder; ++j) { 114 0 : dval[i*(1+nder)+1+j] = myarg->getGridDerivative( i, j ); 115 : } 116 : } 117 : } 118 4226 : if(comm.Get_rank()==0) { 119 4226 : multi_sim_comm.Allgather(dval.data(),dval.size(),datap.data(),dval.size()); 120 : } 121 : 122 29572 : for(unsigned k=0; k<nreplicas; k++) { 123 25346 : Value* myout = getPntrToComponent(k); 124 25346 : if( myout->hasDerivatives() && myout->getNumberOfDerivatives()!=nder ) { 125 72 : myout->resizeDerivatives( nder ); 126 : } 127 25346 : unsigned sstart=k*nvals*(1+nder); 128 50692 : for(unsigned i=0; i<nvals; ++i) { 129 25346 : myout->set( i, datap[sstart+i*(1+nder)] ); 130 25346 : if( myarg->getRank()==0 ) { 131 50690 : for(unsigned j=0; j<nder; ++j) { 132 25344 : myout->setDerivative( j, dval[i*(1+nder)+1+j] ); 133 : } 134 0 : } else if( myarg->hasDerivatives() ) { 135 0 : for(unsigned j=0; j<nder; ++j) { 136 0 : myout->addGridDerivatives( i, j, dval[i*(1+nder)+1+j] ); 137 : } 138 : } 139 : } 140 : } 141 4226 : } 142 : 143 4224 : void GatherReplicas::apply() { 144 4224 : if( doNotCalculateDerivatives() ) { 145 4224 : return; 146 : } 147 0 : error("apply has not been implemented for GatherReplicas"); 148 : } 149 : 150 : } 151 : }