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 ); 60 56 : keys.addInputKeyword("compulsory","ARG","vector","the label of the vector that you would like to construct a mask for"); 61 56 : keys.add("compulsory","TYPE","the way the zeros are supposed to be set"); 62 56 : keys.add("compulsory","NZEROS","the number of zeros that you want to put in the mask"); 63 56 : keys.add("optional","SEED","the seed to use for the random number generator"); 64 56 : keys.setValueDescription("vector","a vector of zeros and ones that is used that can be used to mask some of the elements in a time series"); 65 28 : } 66 : 67 : 68 15 : CreateMask::CreateMask( const ActionOptions& ao ) : 69 : Action(ao), 70 : ActionWithValue(ao), 71 : ActionWithArguments(ao), 72 15 : nzeros(0) 73 : { 74 15 : if( getNumberOfArguments()!=1 ) error("should only be one argument to this action"); 75 15 : if( getPntrToArgument(0)->getRank()!=1 ) error("argument should be a vector"); 76 39 : std::string stype; parse("TYPE",stype); if( stype!="nomask" ) parse("NZEROS",nzeros); 77 : 78 15 : if( stype=="nomask" ) { 79 6 : type=nomask; log.printf(" setting all points in output mask to zero \n"); 80 9 : } else if( stype=="stride" ) { 81 8 : type=stride; log.printf(" setting every %d equally spaced points in output mask to zero \n", nzeros ); 82 1 : } else if( stype=="random" ) { 83 2 : unsigned seed=230623; parse("SEED",seed); r.setSeed(-seed); getPntrToArgument(0)->buildDataStore(); 84 1 : type=random; log.printf(" choosing %d points to set to non-zero in mask in accordance with input weights \n", nzeros ); 85 0 : } else error( stype + " is not a valid way input for TYPE"); 86 15 : std::vector<unsigned> shape(1); shape[0] = getPntrToArgument(0)->getShape()[0]; 87 15 : addValue( shape ); setNotPeriodic(); getPntrToComponent(0)->buildDataStore(); 88 53 : for(unsigned i=0; i<shape[0]; ++i) getPntrToComponent(0)->set( i, 1.0 ); 89 15 : } 90 : 91 25 : void CreateMask::prepare() { 92 25 : Value* out=getPntrToComponent(0); Value* arg=getPntrToArgument(0); 93 25 : if( out->getShape()[0]!=arg->getShape()[0] ) { 94 11 : std::vector<unsigned> shape(1); shape[0] = arg->getShape()[0]; out->setShape( shape ); 95 : } 96 25 : if( type!=nomask ) { 97 325 : for(unsigned i=nzeros; i<out->getShape()[0]; ++i) out->set( i, 1 ); 98 : } 99 25 : } 100 : 101 21 : void CreateMask::calculate() { 102 21 : Value* out=getPntrToComponent(0); Value* arg=getPntrToArgument(0); 103 21 : unsigned ns = arg->getShape()[0]; 104 1171 : for(unsigned i=0; i<ns; ++i) out->set( i, 1.0 ); 105 : 106 21 : if( type==stride ) { 107 11 : std::size_t ss = int( std::floor( ns / nzeros ) ); 108 300 : for(unsigned i=0; i<nzeros; ++i) out->set( i*ss, 0.0 ); 109 10 : } else if( type==random ) { 110 20 : for(unsigned i=0; i<nzeros; ++i ) { 111 : double totweights = 0; 112 112 : for(unsigned j=0; j<ns; ++j) { 113 96 : if( out->get(j)>0 ) totweights += arg->get(j); 114 : } 115 16 : double rr = r.U01()*totweights; double accum=0; 116 55 : for(unsigned j=0; j<ns; ++j) { 117 55 : if( out->get(j)>0 ) accum += arg->get(j); 118 55 : if( accum<rr ) continue; 119 16 : out->set( j, 0 ); break; 120 : } 121 : } 122 6 : } else if( type==nomask ) { 123 555 : for(unsigned i=0; i<ns; ++i) out->set( i, 0.0 ); 124 0 : } else error("invalid mask creation type"); 125 21 : } 126 : 127 : } 128 : }