Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2014-2020 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 74 : void calculate() {}
80 0 : void calculateNumericalDerivatives( ActionWithValue* vv ) { plumed_error(); }
81 74 : void apply() {}
82 : void update();
83 : };
84 :
85 7400 : PLUMED_REGISTER_ACTION(DumpMultiColvar,"DUMPMULTICOLVAR")
86 :
87 23 : void DumpMultiColvar::registerKeywords( Keywords& keys ) {
88 23 : Action::registerKeywords( keys );
89 23 : ActionAtomistic::registerKeywords( keys );
90 23 : ActionPilot::registerKeywords( keys );
91 23 : ActionWithInputVessel::registerKeywords( keys );
92 115 : keys.add("compulsory","STRIDE","1","the frequency with which the atoms should be output");
93 92 : keys.add("compulsory", "FILE", "file on which to output coordinates");
94 115 : keys.add("compulsory", "UNITS","PLUMED","the units in which to print out the coordinates. PLUMED means internal PLUMED units");
95 92 : keys.add("optional","PRECISION","The number of digits in trajectory file");
96 92 : 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 23 : }
98 :
99 22 : DumpMultiColvar::DumpMultiColvar(const ActionOptions&ao):
100 : Action(ao),
101 : ActionPilot(ao),
102 : ActionAtomistic(ao),
103 22 : ActionWithInputVessel(ao)
104 : {
105 44 : readArgument("store");
106 22 : mycolv = dynamic_cast<MultiColvarBase*>( getDependencies()[0] );
107 22 : plumed_assert( getDependencies().size()==1 );
108 22 : if(!mycolv) error("action labeled " + mycolv->getLabel() + " is not a multicolvar");
109 44 : log.printf(" printing colvars calculated by action %s \n",mycolv->getLabel().c_str() );
110 :
111 : std::vector<AtomNumber> atom;
112 44 : parseAtomList("ORIGIN",atom);
113 22 : if( atom.size()>1 ) error("should only be one atom specified");
114 24 : if( atom.size()==1 ) log.printf(" origin is at position of atom : %d\n",atom[0].serial() );
115 :
116 44 : string file; parse("FILE",file);
117 22 : if(file.length()==0) error("name out output file was not specified");
118 22 : std::string type=Tools::extension(file);
119 22 : log<<" file name "<<file<<"\n";
120 22 : if(type!="xyz") error("can only print xyz file type with DUMPMULTICOLVAR");
121 :
122 : fmt_xyz="%f";
123 :
124 44 : string precision; parse("PRECISION",precision);
125 22 : if(precision.length()>0) {
126 11 : int p; Tools::convert(precision,p);
127 11 : log<<" with precision "<<p<<"\n";
128 : string a,b;
129 11 : Tools::convert(p+5,a);
130 11 : Tools::convert(p,b);
131 55 : fmt_xyz="%"+a+"."+b+"f";
132 : }
133 :
134 44 : std::string unitname; parse("UNITS",unitname);
135 22 : if(unitname!="PLUMED") {
136 2 : Units myunit; myunit.setLength(unitname);
137 2 : lenunit=plumed.getAtoms().getUnits().getLength()/myunit.getLength();
138 : }
139 21 : else lenunit=1.0;
140 :
141 22 : checkRead();
142 22 : of.link(*this);
143 22 : of.open(file);
144 44 : log.printf(" printing atom positions in %s units \n", unitname.c_str() );
145 22 : requestAtoms(atom); addDependency( mycolv );
146 22 : }
147 :
148 74 : void DumpMultiColvar::update() {
149 148 : of.printf("%u\n",mycolv->getCurrentNumberOfActiveTasks());
150 148 : const Tensor & t(mycolv->getPbc().getBox());
151 148 : if(mycolv->getPbc().isOrthorombic()) {
152 592 : 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 74 : vesselbase::StoreDataVessel* stash=dynamic_cast<vesselbase::StoreDataVessel*>( getPntrToArgument() );
161 : plumed_dbg_assert( stash );
162 74 : std::vector<double> cvals( mycolv->getNumberOfQuantities() );
163 27948 : for(unsigned i=0; i<mycolv->getCurrentNumberOfActiveTasks(); ++i) {
164 : const char* defname="X";
165 : const char* name=defname;
166 :
167 27800 : Vector apos = mycolv->getCentralAtomPos( mycolv->getPositionInFullTaskList(i) );
168 25058 : if( getNumberOfAtoms()>0 ) apos=pbcDistance( getPosition(0), apos );
169 97300 : of.printf(("%s "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz).c_str(),name,lenunit*apos[0],lenunit*apos[1],lenunit*apos[2]);
170 13900 : stash->retrieveSequentialValue( i, true, cvals );
171 27800 : if( mycolv->weightWithDerivatives() ) {
172 9480 : for(unsigned j=0; j<cvals.size(); ++j) of.printf((" "+fmt_xyz).c_str(),cvals[j]);
173 : } else {
174 100090 : for(unsigned j=1; j<cvals.size(); ++j) of.printf((" "+fmt_xyz).c_str(),cvals[j]);
175 : }
176 13900 : of.printf("\n");
177 : }
178 74 : }
179 :
180 110 : DumpMultiColvar::~DumpMultiColvar() {
181 44 : }
182 :
183 :
184 : }
185 5517 : }
|