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 { plumed_error(); } 48 : }; 49 : 50 : PLUMED_REGISTER_ACTION(GeometricPath,"GEOMETRIC_PATH") 51 : 52 10 : void GeometricPath::registerKeywords(Keywords& keys) { 53 10 : ActionWithVector::registerKeywords(keys); 54 10 : PathProjectionCalculator::registerKeywords(keys); 55 20 : keys.addInputKeyword("compulsory","PROPERTY","vector","the label of a value that contains the coordinates we are projecting these points onto"); 56 20 : keys.addOutputComponent("s","default","scalar","the position on the path"); 57 20 : keys.addOutputComponent("z","default","scalar","the distance from the path"); 58 20 : keys.needsAction("GEOMETRIC_PATH"); keys.needsAction("PDB2CONSTANT"); 59 10 : } 60 : 61 4 : GeometricPath::GeometricPath(const ActionOptions&ao): 62 : Action(ao), 63 : ActionWithVector(ao), 64 4 : path_projector(this) 65 : { 66 4 : plumed_assert( !actionInChain() ); 67 : // Get the coordinates in the low dimensional space 68 8 : std::vector<std::string> pcoord; parseVector("PROPERTY", pcoord ); std::vector<Value*> theprop; 69 4 : ActionWithArguments::interpretArgumentList( pcoord, plumed.getActionSet(), this, theprop ); 70 4 : if( theprop.size()!=1 ) error("did not find property to project on"); 71 4 : if( theprop[0]->getNumberOfValues()!=getPntrToArgument(0)->getShape()[0] ) error("mismatch between number of frames and property of interest"); 72 4 : log.printf(" projecting onto : %s \n", theprop[0]->getName().c_str() ); 73 4 : std::vector<Value*> args( getArguments() ); args.push_back( theprop[0] ); requestArguments( args ); 74 : // Create the values to store the output 75 12 : addComponentWithDerivatives("s"); componentIsNotPeriodic("s"); 76 12 : addComponentWithDerivatives("z"); componentIsNotPeriodic("z"); 77 4 : } 78 : 79 1677 : unsigned GeometricPath::getNumberOfDerivatives() { 80 1677 : return getPntrToArgument(0)->getShape()[0]*getPntrToArgument(0)->getShape()[1] + getPntrToArgument(1)->getShape()[0]; 81 : } 82 : 83 1665 : void GeometricPath::calculate() { 84 1665 : unsigned k=0, iclose1=0, iclose2=0; double v1v1=0, v3v3=0; 85 1665 : unsigned nrows = getPntrToArgument(0)->getShape()[0]; 86 1665 : unsigned ncols = getPntrToArgument(0)->getShape()[1]; 87 79201 : for(unsigned i=0; i<nrows; ++i) { 88 : double dist = 0; 89 1814580 : for(unsigned j=0; j<ncols; ++j) { 90 1737044 : double tmp = getPntrToArgument(0)->get(k); 91 1737044 : dist += tmp*tmp; k++; 92 : } 93 77536 : if( i==0 ) { v1v1 = dist; iclose1 = 0; } 94 75871 : else if( dist<v1v1 ) { v3v3=v1v1; v1v1=dist; iclose2=iclose1; iclose1=i; } 95 45571 : else if( i==1 ) { v3v3=dist; iclose2=1; } 96 45244 : else if( dist<v3v3 ) { v3v3=dist; iclose2=i; } 97 : } 98 : // And find third closest point 99 1665 : int isign = iclose1 - iclose2; 100 : if( isign>1 ) isign=1; else if( isign<-1 ) isign=-1; 101 1665 : int iclose3 = iclose1 + isign; 102 1665 : unsigned ifrom=iclose1, ito=iclose3; if( iclose3<0 || iclose3>=nrows ) { ifrom=iclose2; ito=iclose1; } 103 : 104 : // And calculate projection of vector connecting current point to closest frame on vector connecting nearest two frames 105 1665 : std::vector<double> displace; path_projector.getDisplaceVector( ifrom, ito, displace ); 106 1665 : double v2v2=0, v1v2=0; k=ncols*iclose1; 107 42661 : for(unsigned i=0; i<displace.size(); ++i) { v2v2 += displace[i]*displace[i]; v1v2 += displace[i]*getPntrToArgument(0)->get(k+i); } 108 : 109 : // This computes s value 110 1665 : double spacing = getPntrToArgument(1)->get(iclose1) - getPntrToArgument(1)->get(iclose2); 111 1665 : double root = sqrt( v1v2*v1v2 - v2v2 * ( v1v1 - v3v3) ); 112 1665 : double dx = 0.5 * ( (root + v1v2) / v2v2 - 1.); 113 1665 : double path_s = getPntrToArgument(1)->get(iclose1) + spacing * dx; 114 1665 : Value* sp = getPntrToComponent(0); sp->set( path_s ); 115 1665 : if( !doNotCalculateDerivatives() ) { 116 23478 : for(unsigned i=0; i<ncols; ++i) { 117 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 ); 118 22386 : sp->addDerivative( ncols*iclose2 + i, 0.5*spacing*getPntrToArgument(0)->get(ncols*iclose2 + i)/root ); 119 : } 120 : } 121 : 122 : // This computes z value 123 1665 : path_projector.getDisplaceVector( iclose2, iclose1, displace ); double v4v4=0, proj=0; k=ncols*iclose1; 124 42661 : for(unsigned i=0; i<displace.size(); ++i) { v4v4 += displace[i]*displace[i]; proj += displace[i]*getPntrToArgument(0)->get(k+i); } 125 1665 : double path_z = v1v1 + dx*dx*v4v4 - 2*dx*proj; path_z = sqrt(path_z); 126 1665 : Value* zp = getPntrToComponent(1); zp->set( path_z ); 127 1665 : if( !doNotCalculateDerivatives() ) { 128 23478 : for(unsigned i=0; i<ncols; ++i) { 129 22386 : zp->addDerivative( ncols*iclose1 + i, (1/path_z)*(getPntrToArgument(0)->get(ncols*iclose1 + i) + 130 22386 : (v4v4*dx-proj)*sp->getDerivative(ncols*iclose1 + i)/spacing - 131 22386 : dx*displace[i]) ); 132 22386 : zp->addDerivative( ncols*iclose2 + i, (v4v4*dx-proj)*sp->getDerivative(ncols*iclose2 + i)/(path_z*spacing) ); 133 : } 134 : } 135 1665 : } 136 : 137 : } 138 : }