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