Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2016,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/ActionWithVector.h" 23 : #include "core/ActionRegister.h" 24 : #include "core/ActionSet.h" 25 : #include "PathProjectionCalculator.h" 26 : 27 : //+PLUMEDOC COLVAR GEOMETRIC_PATH 28 : /* 29 : Distance along and from a path calculated using geometric formulas 30 : 31 : \par Examples 32 : 33 : */ 34 : //+ENDPLUMEDOC 35 : 36 : namespace PLMD { 37 : namespace mapping { 38 : 39 : class GeometricPath : public ActionWithVector { 40 : private: 41 : PathProjectionCalculator path_projector; 42 : public: 43 : static void registerKeywords(Keywords& keys); 44 : explicit GeometricPath(const ActionOptions&); 45 : unsigned getNumberOfDerivatives() override ; 46 : void calculate() override ; 47 0 : void performTask( const unsigned& current, MultiValue& myvals ) const override { 48 0 : plumed_error(); 49 : } 50 : }; 51 : 52 : PLUMED_REGISTER_ACTION(GeometricPath,"GEOMETRIC_PATH") 53 : 54 10 : void GeometricPath::registerKeywords(Keywords& keys) { 55 10 : ActionWithVector::registerKeywords(keys); 56 10 : keys.use("ARG"); 57 10 : PathProjectionCalculator::registerKeywords(keys); 58 20 : keys.add("compulsory","PROPERTY","the coordinates we are projecting these points onto"); 59 20 : keys.addOutputComponent("s","default","the position on the path"); 60 20 : keys.addOutputComponent("z","default","the distance from the path"); 61 10 : keys.needsAction("GEOMETRIC_PATH"); 62 10 : keys.needsAction("PDB2CONSTANT"); 63 10 : } 64 : 65 4 : GeometricPath::GeometricPath(const ActionOptions&ao): 66 : Action(ao), 67 : ActionWithVector(ao), 68 4 : path_projector(this) { 69 4 : plumed_assert( !actionInChain() ); 70 : // Get the coordinates in the low dimensional space 71 : std::vector<std::string> pcoord; 72 8 : parseVector("PROPERTY", pcoord ); 73 : std::vector<Value*> theprop; 74 4 : ActionWithArguments::interpretArgumentList( pcoord, plumed.getActionSet(), this, theprop ); 75 4 : if( theprop.size()!=1 ) { 76 0 : error("did not find property to project on"); 77 : } 78 4 : if( theprop[0]->getNumberOfValues()!=getPntrToArgument(0)->getShape()[0] ) { 79 0 : error("mismatch between number of frames and property of interest"); 80 : } 81 4 : log.printf(" projecting onto : %s \n", theprop[0]->getName().c_str() ); 82 4 : std::vector<Value*> args( getArguments() ); 83 4 : args.push_back( theprop[0] ); 84 4 : requestArguments( args ); 85 : // Create the values to store the output 86 8 : addComponentWithDerivatives("s"); 87 8 : componentIsNotPeriodic("s"); 88 8 : addComponentWithDerivatives("z"); 89 8 : componentIsNotPeriodic("z"); 90 4 : } 91 : 92 1677 : unsigned GeometricPath::getNumberOfDerivatives() { 93 1677 : return getPntrToArgument(0)->getShape()[0]*getPntrToArgument(0)->getShape()[1] + getPntrToArgument(1)->getShape()[0]; 94 : } 95 : 96 1665 : void GeometricPath::calculate() { 97 1665 : unsigned k=0, iclose1=0, iclose2=0; 98 : double v1v1=0, v3v3=0; 99 1665 : unsigned nrows = getPntrToArgument(0)->getShape()[0]; 100 1665 : unsigned ncols = getPntrToArgument(0)->getShape()[1]; 101 79201 : for(unsigned i=0; i<nrows; ++i) { 102 : double dist = 0; 103 1814580 : for(unsigned j=0; j<ncols; ++j) { 104 1737044 : double tmp = getPntrToArgument(0)->get(k); 105 1737044 : dist += tmp*tmp; 106 1737044 : k++; 107 : } 108 77536 : if( i==0 ) { 109 : v1v1 = dist; 110 1665 : iclose1 = 0; 111 75871 : } else if( dist<v1v1 ) { 112 : v3v3=v1v1; 113 : v1v1=dist; 114 30300 : iclose2=iclose1; 115 30300 : iclose1=i; 116 45571 : } else if( i==1 ) { 117 : v3v3=dist; 118 327 : iclose2=1; 119 45244 : } else if( dist<v3v3 ) { 120 : v3v3=dist; 121 1325 : iclose2=i; 122 : } 123 : } 124 : // And find third closest point 125 1665 : int isign = iclose1 - iclose2; 126 : if( isign>1 ) { 127 : isign=1; 128 : } else if( isign<-1 ) { 129 : isign=-1; 130 : } 131 1665 : int iclose3 = iclose1 + isign; 132 1665 : unsigned ifrom=iclose1, ito=iclose3; 133 1665 : if( iclose3<0 || iclose3>=nrows ) { 134 31 : ifrom=iclose2; 135 31 : ito=iclose1; 136 : } 137 : 138 : // And calculate projection of vector connecting current point to closest frame on vector connecting nearest two frames 139 : std::vector<double> displace; 140 1665 : path_projector.getDisplaceVector( ifrom, ito, displace ); 141 : double v2v2=0, v1v2=0; 142 1665 : k=ncols*iclose1; 143 42661 : for(unsigned i=0; i<displace.size(); ++i) { 144 40996 : v2v2 += displace[i]*displace[i]; 145 40996 : v1v2 += displace[i]*getPntrToArgument(0)->get(k+i); 146 : } 147 : 148 : // This computes s value 149 1665 : double spacing = getPntrToArgument(1)->get(iclose1) - getPntrToArgument(1)->get(iclose2); 150 1665 : double root = sqrt( v1v2*v1v2 - v2v2 * ( v1v1 - v3v3) ); 151 1665 : double dx = 0.5 * ( (root + v1v2) / v2v2 - 1.); 152 1665 : double path_s = getPntrToArgument(1)->get(iclose1) + spacing * dx; 153 1665 : Value* sp = getPntrToComponent(0); 154 : sp->set( path_s ); 155 1665 : if( !doNotCalculateDerivatives() ) { 156 23478 : for(unsigned i=0; i<ncols; ++i) { 157 22386 : sp->addDerivative( ncols*iclose1 + i, 0.5*spacing*(v1v2*displace[i]/v2v2 - getPntrToArgument(0)->get(ncols*iclose1 + i))/root + 0.5*spacing*displace[i]/v2v2 ); 158 22386 : sp->addDerivative( ncols*iclose2 + i, 0.5*spacing*getPntrToArgument(0)->get(ncols*iclose2 + i)/root ); 159 : } 160 : } 161 : 162 : // This computes z value 163 1665 : path_projector.getDisplaceVector( iclose2, iclose1, displace ); 164 : double v4v4=0, proj=0; 165 1665 : k=ncols*iclose1; 166 42661 : for(unsigned i=0; i<displace.size(); ++i) { 167 40996 : v4v4 += displace[i]*displace[i]; 168 40996 : proj += displace[i]*getPntrToArgument(0)->get(k+i); 169 : } 170 1665 : double path_z = v1v1 + dx*dx*v4v4 - 2*dx*proj; 171 1665 : path_z = sqrt(path_z); 172 1665 : Value* zp = getPntrToComponent(1); 173 : zp->set( path_z ); 174 1665 : if( !doNotCalculateDerivatives() ) { 175 23478 : for(unsigned i=0; i<ncols; ++i) { 176 22386 : zp->addDerivative( ncols*iclose1 + i, (1/path_z)*(getPntrToArgument(0)->get(ncols*iclose1 + i) + 177 22386 : (v4v4*dx-proj)*sp->getDerivative(ncols*iclose1 + i)/spacing - 178 22386 : dx*displace[i]) ); 179 22386 : zp->addDerivative( ncols*iclose2 + i, (v4v4*dx-proj)*sp->getDerivative(ncols*iclose2 + i)/(path_z*spacing) ); 180 : } 181 : } 182 1665 : } 183 : 184 : } 185 : }