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 "vesselbase/VesselRegister.h"
23 : #include "vesselbase/FunctionVessel.h"
24 : #include "vesselbase/ActionWithVessel.h"
25 : #include "multicolvar/ActionVolume.h"
26 : #include "VectorMultiColvar.h"
27 :
28 : namespace PLMD {
29 : namespace crystallization {
30 :
31 12 : class VectorMean : public vesselbase::FunctionVessel {
32 : private:
33 : unsigned nder;
34 : public:
35 : static void registerKeywords( Keywords& keys );
36 : static void reserveKeyword( Keywords& keys );
37 : explicit VectorMean( const vesselbase::VesselOptions& da );
38 : std::string value_descriptor();
39 : void resize();
40 : void calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const ;
41 : void finish( const std::vector<double>& buffer );
42 : };
43 :
44 6458 : PLUMED_REGISTER_VESSEL(VectorMean,"VMEAN")
45 :
46 6 : void VectorMean::registerKeywords( Keywords& keys ) {
47 6 : vesselbase::FunctionVessel::registerKeywords(keys);
48 6 : }
49 :
50 1613 : void VectorMean::reserveKeyword( Keywords& keys ) {
51 6452 : keys.reserve("vessel","VMEAN","calculate the norm of the mean vector.");
52 6452 : keys.addOutputComponent("vmean","VMEAN","the norm of the mean vector. The output component can be refererred to elsewhere in the input "
53 : "file by using the label.vmean");
54 1613 : }
55 :
56 6 : VectorMean::VectorMean( const vesselbase::VesselOptions& da ) :
57 : FunctionVessel(da),
58 6 : nder(0)
59 : {
60 6 : }
61 :
62 6 : std::string VectorMean::value_descriptor() {
63 6 : return "the norm of the mean vector";
64 : }
65 :
66 23 : void VectorMean::resize() {
67 23 : unsigned ncomp=getAction()->getNumberOfQuantities() - 2;
68 :
69 23 : if( getAction()->derivativesAreRequired() ) {
70 16 : nder=getAction()->getNumberOfDerivatives();
71 32 : resizeBuffer( (1+nder)*(ncomp+1) ); getFinalValue()->resizeDerivatives( nder );
72 : } else {
73 7 : nder=0; resizeBuffer(ncomp+1);
74 : }
75 23 : }
76 :
77 14712 : void VectorMean::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
78 14712 : unsigned ncomp=getAction()->getNumberOfQuantities()-2;
79 :
80 14712 : double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() );
81 29424 : buffer[bufstart] += weight;
82 154296 : for(unsigned i=0; i<ncomp; ++i) buffer[bufstart + (1+i)*(1+nder)] += weight*myvals.get(2+i);
83 14712 : if( !getAction()->derivativesAreRequired() ) return;
84 :
85 14712 : if( diffweight ) myvals.chainRule( 0, 0, 1, 0, 1.0, bufstart, buffer );
86 107768 : for(unsigned i=0; i<ncomp; ++i) {
87 93056 : double colvar=myvals.get(2+i);
88 46528 : myvals.chainRule( 2+i, 1+i, 1, 0, weight, bufstart, buffer );
89 46528 : if( diffweight ) myvals.chainRule( 0, 1+i, 1, 0, colvar, bufstart, buffer );
90 : }
91 : return;
92 : }
93 :
94 1828 : void VectorMean::finish( const std::vector<double>& buffer ) {
95 1828 : unsigned ncomp=getAction()->getNumberOfQuantities()-2;
96 3656 : double sum=0, ww=buffer[bufstart];
97 12888 : for(unsigned i=0; i<ncomp; ++i) {
98 11060 : double tmp = buffer[bufstart+(nder+1)*(i+1)] / ww;
99 5530 : sum+=tmp*tmp;
100 : }
101 1828 : setOutputValue( sqrt(sum) );
102 1828 : if( !getAction()->derivativesAreRequired() ) return;
103 :
104 1828 : Value* fval=getFinalValue(); double tw = 1.0 / sqrt(sum);
105 7358 : for(unsigned icomp=0; icomp<ncomp; ++icomp) {
106 11060 : double tmp = buffer[bufstart + (icomp+1)*(1+nder)] / ww;
107 5530 : unsigned bstart = bufstart + (1+icomp)*(nder+1) + 1;
108 1825954 : for(unsigned jder=0; jder<nder; ++jder) fval->addDerivative( jder, (tw*tmp/ww)*( buffer[bstart + jder] - tmp*buffer[bufstart + 1 + jder] ) );
109 : }
110 : }
111 :
112 : }
113 4839 : }
|