Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2013-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 "FunctionVessel.h" 23 : #include "core/ActionWithValue.h" 24 : 25 : namespace PLMD { 26 : namespace vesselbase { 27 : 28 347 : void FunctionVessel::registerKeywords( Keywords& keys ) { 29 347 : ValueVessel::registerKeywords( keys ); 30 347 : } 31 : 32 347 : FunctionVessel::FunctionVessel( const VesselOptions& da ): 33 : ValueVessel(da), 34 347 : norm(false), 35 347 : usetol(false) { 36 347 : diffweight=getAction()->weightHasDerivatives; 37 347 : } 38 : 39 978 : void FunctionVessel::resize() { 40 978 : if( getAction()->derivativesAreRequired() ) { 41 588 : unsigned nderivatives=getAction()->getNumberOfDerivatives(); 42 588 : getFinalValue()->resizeDerivatives( nderivatives ); 43 588 : resizeBuffer( (1+nderivatives)*2 ); 44 588 : diffweight=getAction()->weightHasDerivatives; 45 : } else { 46 : resizeBuffer(2); 47 390 : diffweight=false; // Don't need to worry about differentiable weights if no derivatives 48 : } 49 978 : } 50 : 51 293384 : void FunctionVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const { 52 293384 : unsigned nderivatives=getFinalValue()->getNumberOfDerivatives(); 53 : double weight=myvals.get(0); 54 : plumed_dbg_assert( weight>=getTolerance() ); 55 : 56 : // This deals with the value 57 293384 : double dval, f=calcTransform( myvals.get(mycomp), dval ); 58 : 59 293384 : if( norm ) { 60 82908 : if( usetol && weight<getTolerance() ) { 61 : return; 62 : } 63 82908 : buffer[bufstart+1+nderivatives] += weight; 64 82908 : if( getAction()->derivativesAreRequired() && diffweight ) { 65 19503 : myvals.chainRule( 0, 1, 1, 0, 1.0, bufstart, buffer ); 66 : } 67 : } 68 : 69 293384 : double contr=weight*f; 70 293384 : if( usetol && contr<getTolerance() ) { 71 : return; 72 : } 73 288462 : buffer[bufstart] += contr; 74 : 75 288462 : if( diffweight ) { 76 76994 : myvals.chainRule( 0, 0, 1, 0, f, bufstart, buffer ); 77 : } 78 288462 : if( getAction()->derivativesAreRequired() && std::fabs(dval)>0.0 ) { 79 221240 : myvals.chainRule( mycomp, 0, 1, 0, weight*dval, bufstart, buffer ); 80 : } 81 : 82 : return; 83 : } 84 : 85 0 : double FunctionVessel::calcTransform( const double&, double& ) const { 86 0 : plumed_error(); 87 : } 88 : 89 26724 : void FunctionVessel::finish( const std::vector<double>& buffer ) { 90 26724 : unsigned nderivatives=getFinalValue()->getNumberOfDerivatives(); 91 26724 : if( norm && diffweight ) { 92 5114 : double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; 93 5114 : getFinalValue()->set( val / weight ); 94 417911 : for(unsigned i=0; i<nderivatives; ++i) { 95 412797 : getFinalValue()->addDerivative( i, buffer[bufstart+1+i]/weight - val*buffer[bufstart+1+nderivatives+1+i]/(weight*weight) ); 96 : } 97 26724 : } else if( norm ) { 98 1227 : double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; 99 1227 : getFinalValue()->set( val / weight ); 100 156783 : for(unsigned i=0; i<nderivatives; ++i) { 101 155556 : getFinalValue()->addDerivative( i, buffer[bufstart+1+i]/weight ); 102 : } 103 : } else { 104 20383 : double dv, val=finalTransform( buffer[bufstart], dv); 105 : getFinalValue()->set( val ); 106 1764447 : for(unsigned i=0; i<nderivatives; ++i) { 107 1744064 : getFinalValue()->addDerivative( i, dv*buffer[bufstart+1+i] ); 108 : } 109 : } 110 26724 : } 111 : 112 22886 : double FunctionVessel::finalTransform( const double& val, double& dv ) { 113 22886 : dv=1.0; 114 22886 : return val; 115 : } 116 : 117 : } 118 : } 119 :