Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2015-2023 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/ActionRegister.h" 23 : #include "GridPrintingBase.h" 24 : #include "tools/OFile.h" 25 : 26 : //+PLUMEDOC GRIDANALYSIS DUMPCUBE 27 : /* 28 : Output a three dimensional grid using the Gaussian cube file format. 29 : 30 : Suppose you have calculated the value of a function on a three dimensional grid. 31 : This function might be a \ref HISTOGRAM or it might be a free energy energy surface 32 : that was calculated from this histogram by using \ref CONVERT_TO_FES. Alternatively, 33 : your function might be a phase-field that was calculated using \ref MULTICOLVARDENS. 34 : Whatever the function is, however, you obviously cannot show it using a typical contour 35 : plotting program such as gnuplot as you have three input variables. 36 : 37 : Tools like VMD have nice features for plotting these types of three dimensional functions 38 : but typically you are required to use a Gaussian cube file format to input the data. This 39 : action thus allows you to output a function evaluated on a grid to a Gaussian cube file format. 40 : 41 : \par Examples 42 : 43 : The input below can be used to post process a trajectory. A histogram as a function of the distance 44 : between atoms 1 and 2, the distance between atom 1 and 3 and the angle between the vector connecting atoms 1 and 45 : 2 and 1 and 3 is computed using kernel density estimation. Once all the data contained in the trajectory has been read in and 46 : all the kernels have been added the resulting histogram is output to a file called histoA1.cube. This file has the 47 : Gaussian cube file format. The histogram can thus be visualized using tools such as VMD. 48 : 49 : \plumedfile 50 : x1: DISTANCE ATOMS=1,2 51 : x2: DISTANCE ATOMS=1,3 52 : x3: ANGLE ATOMS=1,2,3 53 : 54 : hA1: HISTOGRAM ARG=x1,x2,x3 GRID_MIN=0.0,0.0,0.0 GRID_MAX=3.0,3.0,3.0 GRID_BIN=10,10,10 BANDWIDTH=1.0,1.0,1.0 55 : DUMPCUBE GRID=hA1 FILE=histoA1.cube 56 : \endplumedfile 57 : 58 : */ 59 : //+ENDPLUMEDOC 60 : 61 : namespace PLMD { 62 : namespace gridtools { 63 : 64 : class DumpCube : public GridPrintingBase { 65 : private: 66 : unsigned mycomp; 67 : public: 68 : static void registerKeywords( Keywords& keys ); 69 : explicit DumpCube(const ActionOptions&ao); 70 : void printGrid( OFile& ofile ) const override; 71 : }; 72 : 73 10431 : PLUMED_REGISTER_ACTION(DumpCube,"DUMPCUBE") 74 : 75 7 : void DumpCube::registerKeywords( Keywords& keys ) { 76 7 : GridPrintingBase::registerKeywords( keys ); 77 14 : keys.add("optional","COMPONENT","if your input is a vector field use this to specify the component of the input vector field for which you wish to output"); 78 7 : } 79 : 80 6 : DumpCube::DumpCube(const ActionOptions&ao): 81 : Action(ao), 82 6 : GridPrintingBase(ao) 83 : { 84 6 : fmt = fmt + " "; 85 12 : if( ingrid->getType()!="flat" ) error("cannot dump grid of type " + ingrid->getType() + " using DUMPCUBE"); 86 6 : if( ingrid->getDimension()!=3 ) error("cannot print cube file if grid does not contain three dimensional data"); 87 : 88 6 : if( ingrid->getNumberOfComponents()==1 ) { 89 6 : mycomp=0; 90 : } else { 91 0 : int tcomp=-1; parse("COMPONENT",tcomp); 92 0 : if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); 93 0 : mycomp=tcomp*(1+ingrid->getDimension()); if( ingrid->noDerivatives() ) mycomp=tcomp; 94 0 : log.printf(" using %dth component of grid \n",tcomp ); 95 : } 96 : 97 6 : checkRead(); 98 6 : } 99 : 100 8 : void DumpCube::printGrid( OFile& ofile ) const { 101 8 : double lunit = ingrid->getCubeUnits(); 102 : 103 8 : ofile.printf("PLUMED CUBE FILE\n"); 104 8 : ofile.printf("OUTER LOOP: X, MIDDLE LOOP: Y, INNER LOOP: Z\n"); 105 : // Number of atoms followed by position of origin (origin set so that center of grid is in center of cell) 106 16 : std::string ostr = "%d " + fmt + fmt + fmt + "\n"; 107 8 : ofile.printf(ostr.c_str(),1,-0.5*lunit*ingrid->getGridExtent(0),-0.5*lunit*ingrid->getGridExtent(1),-0.5*lunit*ingrid->getGridExtent(2)); 108 8 : ofile.printf(ostr.c_str(),ingrid->getNbin()[0],lunit*ingrid->getGridSpacing()[0],0.0,0.0); // Number of bins in each direction followed by 109 8 : ofile.printf(ostr.c_str(),ingrid->getNbin()[1],0.0,lunit*ingrid->getGridSpacing()[1],0.0); // shape of voxel 110 16 : ofile.printf(ostr.c_str(),ingrid->getNbin()[2],0.0,0.0,lunit*ingrid->getGridSpacing()[2]); 111 8 : ofile.printf(ostr.c_str(),1,0.0,0.0,0.0); // Fake atom otherwise VMD doesn't work 112 8 : std::vector<unsigned> pp(3); std::vector<unsigned> nbin( ingrid->getNbin() ); 113 112 : for(pp[0]=0; pp[0]<nbin[0]; ++pp[0]) { 114 1800 : for(pp[1]=0; pp[1]<nbin[1]; ++pp[1]) { 115 40184 : for(pp[2]=0; pp[2]<nbin[2]; ++pp[2]) { 116 38488 : ofile.printf(fmt.c_str(), ingrid->getGridElement( ingrid->getIndex(pp), mycomp ) ); 117 38488 : if(pp[2]%6==5) ofile.printf("\n"); 118 : } 119 1696 : ofile.printf("\n"); 120 : } 121 : } 122 8 : } 123 : 124 : } 125 : }