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