Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2014-2019 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/ActionAtomistic.h"
23 : #include "core/ActionPilot.h"
24 : #include "core/ActionRegister.h"
25 : #include "tools/Pbc.h"
26 : #include "tools/File.h"
27 : #include "core/PlumedMain.h"
28 : #include "core/Atoms.h"
29 : #include "tools/Units.h"
30 : #include <cstdio>
31 : #include "core/SetupMolInfo.h"
32 : #include "core/ActionSet.h"
33 : #include "MultiColvarBase.h"
34 : #include "vesselbase/ActionWithInputVessel.h"
35 : #include "vesselbase/StoreDataVessel.h"
36 :
37 : using namespace std;
38 :
39 : namespace PLMD
40 : {
41 : namespace multicolvar {
42 :
43 : //+PLUMEDOC PRINTANALYSIS DUMPMULTICOLVAR
44 : /*
45 : Dump atom positions and multicolvar on a file.
46 :
47 : \par Examples
48 :
49 : In this examples we calculate the distances between the atoms of the first and the second
50 : group and we write them in the file MULTICOLVAR.xyz. For each couple it writes the
51 : coordinates of their geometric center and their distance.
52 :
53 : \plumedfile
54 : pos: GROUP ATOMS=220,221,235,236,247,248,438,439,450,451,534,535
55 : neg: GROUP ATOMS=65,68,138,182,185,267,270,291,313,316,489,583,621,711
56 : DISTANCES GROUPA=pos GROUPB=neg LABEL=slt
57 :
58 : DUMPMULTICOLVAR DATA=slt FILE=MULTICOLVAR.xyz
59 : \endplumedfile
60 :
61 : (see also \ref DISTANCES)
62 :
63 : */
64 : //+ENDPLUMEDOC
65 :
66 : class DumpMultiColvar:
67 : public ActionPilot,
68 : public ActionAtomistic,
69 : public vesselbase::ActionWithInputVessel
70 : {
71 : OFile of;
72 : double lenunit;
73 : MultiColvarBase* mycolv;
74 : std::string fmt_xyz;
75 : public:
76 : explicit DumpMultiColvar(const ActionOptions&);
77 : ~DumpMultiColvar();
78 : static void registerKeywords( Keywords& keys );
79 59 : void calculate() {}
80 0 : void calculateNumericalDerivatives( ActionWithValue* vv ) { plumed_error(); }
81 59 : void apply() {}
82 : void update();
83 : };
84 :
85 6469 : PLUMED_REGISTER_ACTION(DumpMultiColvar,"DUMPMULTICOLVAR")
86 :
87 18 : void DumpMultiColvar::registerKeywords( Keywords& keys ) {
88 18 : Action::registerKeywords( keys );
89 18 : ActionAtomistic::registerKeywords( keys );
90 18 : ActionPilot::registerKeywords( keys );
91 18 : ActionWithInputVessel::registerKeywords( keys );
92 90 : keys.add("compulsory","STRIDE","1","the frequency with which the atoms should be output");
93 72 : keys.add("compulsory", "FILE", "file on which to output coordinates");
94 90 : keys.add("compulsory", "UNITS","PLUMED","the units in which to print out the coordinates. PLUMED means internal PLUMED units");
95 72 : keys.add("optional","PRECISION","The number of digits in trajectory file");
96 72 : keys.add("atoms","ORIGIN","You can use this keyword to specify the position of an atom as an origin. The positions output will then be displayed relative to that origin");
97 18 : }
98 :
99 17 : DumpMultiColvar::DumpMultiColvar(const ActionOptions&ao):
100 : Action(ao),
101 : ActionPilot(ao),
102 : ActionAtomistic(ao),
103 17 : ActionWithInputVessel(ao)
104 : {
105 34 : readArgument("store");
106 17 : mycolv = dynamic_cast<MultiColvarBase*>( getDependencies()[0] );
107 17 : plumed_assert( getDependencies().size()==1 );
108 17 : if(!mycolv) error("action labeled " + mycolv->getLabel() + " is not a multicolvar");
109 34 : log.printf(" printing colvars calculated by action %s \n",mycolv->getLabel().c_str() );
110 :
111 : std::vector<AtomNumber> atom;
112 34 : parseAtomList("ORIGIN",atom);
113 17 : if( atom.size()>1 ) error("should only be one atom specified");
114 19 : if( atom.size()==1 ) log.printf(" origin is at position of atom : %d\n",atom[0].serial() );
115 :
116 34 : string file; parse("FILE",file);
117 17 : if(file.length()==0) error("name out output file was not specified");
118 17 : std::string type=Tools::extension(file);
119 17 : log<<" file name "<<file<<"\n";
120 17 : if(type!="xyz") error("can only print xyz file type with DUMPMULTICOLVAR");
121 :
122 : fmt_xyz="%f";
123 :
124 34 : string precision; parse("PRECISION",precision);
125 17 : if(precision.length()>0) {
126 8 : int p; Tools::convert(precision,p);
127 8 : log<<" with precision "<<p<<"\n";
128 : string a,b;
129 8 : Tools::convert(p+5,a);
130 8 : Tools::convert(p,b);
131 40 : fmt_xyz="%"+a+"."+b+"f";
132 : }
133 :
134 34 : std::string unitname; parse("UNITS",unitname);
135 17 : if(unitname!="PLUMED") {
136 2 : Units myunit; myunit.setLength(unitname);
137 2 : lenunit=plumed.getAtoms().getUnits().getLength()/myunit.getLength();
138 : }
139 16 : else lenunit=1.0;
140 :
141 17 : checkRead();
142 17 : of.link(*this);
143 17 : of.open(file);
144 34 : log.printf(" printing atom positions in %s units \n", unitname.c_str() );
145 17 : requestAtoms(atom); addDependency( mycolv );
146 17 : }
147 :
148 59 : void DumpMultiColvar::update() {
149 118 : of.printf("%u\n",mycolv->getCurrentNumberOfActiveTasks());
150 118 : const Tensor & t(mycolv->getPbc().getBox());
151 118 : if(mycolv->getPbc().isOrthorombic()) {
152 472 : of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2));
153 : } else {
154 0 : of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),
155 0 : lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2),
156 0 : lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2),
157 0 : lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2)
158 : );
159 : }
160 59 : vesselbase::StoreDataVessel* stash=dynamic_cast<vesselbase::StoreDataVessel*>( getPntrToArgument() );
161 : plumed_dbg_assert( stash );
162 59 : std::vector<double> cvals( mycolv->getNumberOfQuantities() );
163 27334 : for(unsigned i=0; i<mycolv->getCurrentNumberOfActiveTasks(); ++i) {
164 : const char* defname="X";
165 : const char* name=defname;
166 :
167 27216 : Vector apos = mycolv->getCentralAtomPos( mycolv->getPositionInFullTaskList(i) );
168 24766 : if( getNumberOfAtoms()>0 ) apos=pbcDistance( getPosition(0), apos );
169 95256 : of.printf(("%s "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz).c_str(),name,lenunit*apos[0],lenunit*apos[1],lenunit*apos[2]);
170 13608 : stash->retrieveSequentialValue( i, true, cvals );
171 27216 : if( mycolv->weightWithDerivatives() ) {
172 9480 : for(unsigned j=0; j<cvals.size(); ++j) of.printf((" "+fmt_xyz).c_str(),cvals[j]);
173 : } else {
174 98046 : for(unsigned j=1; j<cvals.size(); ++j) of.printf((" "+fmt_xyz).c_str(),cvals[j]);
175 : }
176 13608 : of.printf("\n");
177 : }
178 59 : }
179 :
180 85 : DumpMultiColvar::~DumpMultiColvar() {
181 34 : }
182 :
183 :
184 : }
185 4839 : }
|