Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2016-2020 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/Random.h" 26 : 27 : namespace PLMD { 28 : namespace generic { 29 : 30 : //+PLUMEDOC DIMRED CREATE_MASK 31 : /* 32 : Create a mask vector to use for landmark selection 33 : 34 : \par Examples 35 : 36 : */ 37 : //+ENDPLUMEDOC 38 : 39 : class CreateMask : 40 : public ActionWithValue, 41 : public ActionWithArguments { 42 : private: 43 : Random r; 44 : unsigned nzeros; 45 : enum {nomask,stride,random} type; 46 : public: 47 : static void registerKeywords( Keywords& keys ); 48 : CreateMask( const ActionOptions& ); 49 0 : unsigned getNumberOfDerivatives() override { return 0; } 50 : void prepare() override ; 51 : void calculate() override ; 52 6 : void apply() override {} 53 : }; 54 : 55 : PLUMED_REGISTER_ACTION(CreateMask,"CREATE_MASK") 56 : 57 28 : void CreateMask::registerKeywords( Keywords& keys ) { 58 28 : Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); 59 28 : ActionWithArguments::registerKeywords( keys ); keys.use("ARG"); 60 56 : keys.add("compulsory","TYPE","the way the zeros are supposed to be set"); 61 56 : keys.add("compulsory","NZEROS","the number of zeros that you want to put in the mask"); 62 56 : keys.add("optional","SEED","the seed to use for the random number generator"); 63 28 : keys.setValueDescription("a vector of zeros and ones that is used that can be used to mask some of the elements in a time series"); 64 28 : } 65 : 66 : 67 15 : CreateMask::CreateMask( const ActionOptions& ao ) : 68 : Action(ao), 69 : ActionWithValue(ao), 70 : ActionWithArguments(ao), 71 15 : nzeros(0) 72 : { 73 15 : if( getNumberOfArguments()!=1 ) error("should only be one argument to this action"); 74 15 : if( getPntrToArgument(0)->getRank()!=1 ) error("argument should be a vector"); 75 39 : std::string stype; parse("TYPE",stype); if( stype!="nomask" ) parse("NZEROS",nzeros); 76 : 77 15 : if( stype=="nomask" ) { 78 6 : type=nomask; log.printf(" setting all points in output mask to zero \n"); 79 9 : } else if( stype=="stride" ) { 80 8 : type=stride; log.printf(" setting every %d equally spaced points in output mask to zero \n", nzeros ); 81 1 : } else if( stype=="random" ) { 82 2 : unsigned seed=230623; parse("SEED",seed); r.setSeed(-seed); getPntrToArgument(0)->buildDataStore(); 83 1 : type=random; log.printf(" choosing %d points to set to non-zero in mask in accordance with input weights \n", nzeros ); 84 0 : } else error( stype + " is not a valid way input for TYPE"); 85 15 : std::vector<unsigned> shape(1); shape[0] = getPntrToArgument(0)->getShape()[0]; 86 15 : addValue( shape ); setNotPeriodic(); getPntrToComponent(0)->buildDataStore(); 87 53 : for(unsigned i=0; i<shape[0]; ++i) getPntrToComponent(0)->set( i, 1.0 ); 88 15 : } 89 : 90 25 : void CreateMask::prepare() { 91 25 : Value* out=getPntrToComponent(0); Value* arg=getPntrToArgument(0); 92 25 : if( out->getShape()[0]!=arg->getShape()[0] ) { 93 11 : std::vector<unsigned> shape(1); shape[0] = arg->getShape()[0]; out->setShape( shape ); 94 : } 95 25 : if( type!=nomask ) { 96 325 : for(unsigned i=nzeros; i<out->getShape()[0]; ++i) out->set( i, 1 ); 97 : } 98 25 : } 99 : 100 21 : void CreateMask::calculate() { 101 21 : Value* out=getPntrToComponent(0); Value* arg=getPntrToArgument(0); 102 21 : unsigned ns = arg->getShape()[0]; 103 1171 : for(unsigned i=0; i<ns; ++i) out->set( i, 1.0 ); 104 : 105 21 : if( type==stride ) { 106 11 : std::size_t ss = int( std::floor( ns / nzeros ) ); 107 300 : for(unsigned i=0; i<nzeros; ++i) out->set( i*ss, 0.0 ); 108 10 : } else if( type==random ) { 109 20 : for(unsigned i=0; i<nzeros; ++i ) { 110 : double totweights = 0; 111 112 : for(unsigned j=0; j<ns; ++j) { 112 96 : if( out->get(j)>0 ) totweights += arg->get(j); 113 : } 114 16 : double rr = r.U01()*totweights; double accum=0; 115 55 : for(unsigned j=0; j<ns; ++j) { 116 55 : if( out->get(j)>0 ) accum += arg->get(j); 117 55 : if( accum<rr ) continue; 118 16 : out->set( j, 0 ); break; 119 : } 120 : } 121 6 : } else if( type==nomask ) { 122 555 : for(unsigned i=0; i<ns; ++i) out->set( i, 0.0 ); 123 0 : } else error("invalid mask creation type"); 124 21 : } 125 : 126 : } 127 : }