Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2014-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 : 26 : //+PLUMEDOC FUNCTION FLATTEN 27 : /* 28 : Convert a matrix into a vector 29 : 30 : This action can be used to convert an input matrix to a vector. The input matrix is flattened 31 : in row-major order so if the input matrix is $N \times $M$ the output vector has $N\times M$ elements. 32 : The first $M$ of these elements contain the first row of the input matrix, the second $M$ contain the 33 : second row of the input matrix and so on. 34 : 35 : The following example illustrates how we can convert a $5\times 5$ contact matrix into a vector with 36 : 25 elements: 37 : 38 : ```plumed 39 : c1: CONTACT_MATRIX GROUP=1,2,3,4,5 SWITCH={RATIONAL R_0=0.1} 40 : f: FLATTEN ARG=c1 41 : PRINT ARG=f FILE=colvar 42 : ``` 43 : 44 : 45 : */ 46 : //+ENDPLUMEDOC 47 : 48 : namespace PLMD { 49 : namespace valtools { 50 : 51 : class Flatten : 52 : public ActionWithValue, 53 : public ActionWithArguments { 54 : public: 55 : static void registerKeywords( Keywords& keys ); 56 : /// Constructor 57 : explicit Flatten(const ActionOptions&); 58 : /// Get the number of derivatives 59 10 : unsigned getNumberOfDerivatives() override { 60 10 : return 0; 61 : } 62 : /// Do the calculation 63 : void calculate() override; 64 : /// 65 : void apply() override; 66 : }; 67 : 68 : PLUMED_REGISTER_ACTION(Flatten,"FLATTEN") 69 : 70 20 : void Flatten::registerKeywords( Keywords& keys ) { 71 20 : Action::registerKeywords( keys ); 72 20 : ActionWithValue::registerKeywords( keys ); 73 20 : ActionWithArguments::registerKeywords( keys ); 74 40 : keys.addInputKeyword("compulsory","ARG","matrix","the label for the matrix that you would like to flatten to a vector"); 75 40 : keys.setValueDescription("vector","a vector containing all the elements of the input matrix"); 76 20 : } 77 : 78 9 : Flatten::Flatten(const ActionOptions& ao): 79 : Action(ao), 80 : ActionWithValue(ao), 81 9 : ActionWithArguments(ao) { 82 9 : if( getNumberOfArguments()!=1 ) { 83 0 : error("should only be one argument for this action"); 84 : } 85 9 : if( getPntrToArgument(0)->getRank()!=2 || getPntrToArgument(0)->hasDerivatives() ) { 86 0 : error("input to this action should be a matrix"); 87 : } 88 9 : getPntrToArgument(0)->buildDataStore(true); 89 9 : std::vector<unsigned> inshape( getPntrToArgument(0)->getShape() ); 90 9 : std::vector<unsigned> shape( 1 ); 91 9 : shape[0]=inshape[0]*inshape[1]; 92 9 : addValue( shape ); 93 9 : setNotPeriodic(); 94 9 : getPntrToComponent(0)->buildDataStore(); 95 9 : } 96 : 97 9 : void Flatten::calculate() { 98 9 : Value* myval = getPntrToComponent(0); 99 9 : unsigned ss=getPntrToArgument(0)->getShape()[1]; 100 : std::vector<double> vals; 101 : std::vector<std::pair<unsigned,unsigned> > pairs; 102 : bool symmetric=getPntrToArgument(0)->isSymmetric(); 103 9 : unsigned nedge=0; 104 9 : getPntrToArgument(0)->retrieveEdgeList( nedge, pairs, vals ); 105 8139 : for(unsigned l=0; l<nedge; ++l ) { 106 8130 : unsigned i=pairs[l].first, j=pairs[l].second; 107 8130 : myval->set( i*ss + j, vals[l] ); 108 8130 : if( symmetric ) { 109 0 : myval->set( j*ss + i, vals[l] ); 110 : } 111 : } 112 9 : } 113 : 114 7 : void Flatten::apply() { 115 7 : if( doNotCalculateDerivatives() || !getPntrToComponent(0)->forcesWereAdded() ) { 116 4 : return; 117 : } 118 : 119 3 : Value* myval=getPntrToComponent(0); 120 : Value* myarg=getPntrToArgument(0); 121 3 : unsigned nvals=myval->getNumberOfValues(); 122 22 : for(unsigned j=0; j<nvals; ++j) { 123 19 : myarg->addForce( j, myval->getForce(j) ); 124 : } 125 : } 126 : 127 : } 128 : }