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 { 50 0 : return 0; 51 : } 52 : void prepare() override ; 53 : void calculate() override ; 54 6 : void apply() override {} 55 : }; 56 : 57 : PLUMED_REGISTER_ACTION(CreateMask,"CREATE_MASK") 58 : 59 30 : void CreateMask::registerKeywords( Keywords& keys ) { 60 30 : Action::registerKeywords( keys ); 61 30 : ActionWithValue::registerKeywords( keys ); 62 30 : ActionWithArguments::registerKeywords( keys ); 63 30 : keys.use("ARG"); 64 60 : keys.add("compulsory","TYPE","the way the zeros are supposed to be set"); 65 60 : keys.add("compulsory","NZEROS","the number of zeros that you want to put in the mask"); 66 60 : keys.add("optional","SEED","the seed to use for the random number generator"); 67 30 : 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"); 68 30 : } 69 : 70 : 71 15 : CreateMask::CreateMask( const ActionOptions& ao ) : 72 : Action(ao), 73 : ActionWithValue(ao), 74 : ActionWithArguments(ao), 75 15 : nzeros(0) { 76 15 : if( getNumberOfArguments()!=1 ) { 77 0 : error("should only be one argument to this action"); 78 : } 79 15 : if( getPntrToArgument(0)->getRank()!=1 ) { 80 0 : error("argument should be a vector"); 81 : } 82 : std::string stype; 83 30 : parse("TYPE",stype); 84 15 : if( stype!="nomask" ) { 85 18 : parse("NZEROS",nzeros); 86 : } 87 : 88 15 : if( stype=="nomask" ) { 89 6 : type=nomask; 90 6 : log.printf(" setting all points in output mask to zero \n"); 91 9 : } else if( stype=="stride" ) { 92 8 : type=stride; 93 8 : log.printf(" setting every %d equally spaced points in output mask to zero \n", nzeros ); 94 1 : } else if( stype=="random" ) { 95 1 : unsigned seed=230623; 96 1 : parse("SEED",seed); 97 1 : r.setSeed(-seed); 98 1 : getPntrToArgument(0)->buildDataStore(); 99 1 : type=random; 100 1 : log.printf(" choosing %d points to set to non-zero in mask in accordance with input weights \n", nzeros ); 101 : } else { 102 0 : error( stype + " is not a valid way input for TYPE"); 103 : } 104 15 : std::vector<unsigned> shape(1); 105 15 : shape[0] = getPntrToArgument(0)->getShape()[0]; 106 15 : addValue( shape ); 107 15 : setNotPeriodic(); 108 15 : getPntrToComponent(0)->buildDataStore(); 109 53 : for(unsigned i=0; i<shape[0]; ++i) { 110 38 : getPntrToComponent(0)->set( i, 1.0 ); 111 : } 112 15 : } 113 : 114 25 : void CreateMask::prepare() { 115 25 : Value* out=getPntrToComponent(0); 116 : Value* arg=getPntrToArgument(0); 117 25 : if( out->getShape()[0]!=arg->getShape()[0] ) { 118 11 : std::vector<unsigned> shape(1); 119 11 : shape[0] = arg->getShape()[0]; 120 11 : out->setShape( shape ); 121 : } 122 25 : if( type!=nomask ) { 123 325 : for(unsigned i=nzeros; i<out->getShape()[0]; ++i) { 124 306 : out->set( i, 1 ); 125 : } 126 : } 127 25 : } 128 : 129 21 : void CreateMask::calculate() { 130 21 : Value* out=getPntrToComponent(0); 131 : Value* arg=getPntrToArgument(0); 132 21 : unsigned ns = arg->getShape()[0]; 133 1171 : for(unsigned i=0; i<ns; ++i) { 134 1150 : out->set( i, 1.0 ); 135 : } 136 : 137 21 : if( type==stride ) { 138 11 : std::size_t ss = int( std::floor( ns / nzeros ) ); 139 300 : for(unsigned i=0; i<nzeros; ++i) { 140 289 : out->set( i*ss, 0.0 ); 141 : } 142 10 : } else if( type==random ) { 143 20 : for(unsigned i=0; i<nzeros; ++i ) { 144 : double totweights = 0; 145 112 : for(unsigned j=0; j<ns; ++j) { 146 96 : if( out->get(j)>0 ) { 147 72 : totweights += arg->get(j); 148 : } 149 : } 150 16 : double rr = r.U01()*totweights; 151 : double accum=0; 152 55 : for(unsigned j=0; j<ns; ++j) { 153 55 : if( out->get(j)>0 ) { 154 46 : accum += arg->get(j); 155 : } 156 55 : if( accum<rr ) { 157 : continue; 158 : } 159 16 : out->set( j, 0 ); 160 16 : break; 161 : } 162 : } 163 6 : } else if( type==nomask ) { 164 555 : for(unsigned i=0; i<ns; ++i) { 165 549 : out->set( i, 0.0 ); 166 : } 167 : } else { 168 0 : error("invalid mask creation type"); 169 : } 170 21 : } 171 : 172 : } 173 : }