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 "MultiValue.h" 23 : 24 : namespace PLMD { 25 : 26 360231 : MultiValue::MultiValue( const size_t& nvals, const size_t& nder ): 27 360231 : values(nvals), 28 360231 : nderivatives(nder), 29 360231 : derivatives(nvals*nder), 30 360231 : tmpval(0), 31 360231 : tmpder(nder), 32 720462 : atLeastOneSet(false) 33 : { 34 360231 : std::vector<unsigned> myind( nder ); 35 10699694 : for(unsigned i=0; i<nder; ++i) myind[i]=i; 36 360231 : hasDerivatives.createIndexListFromVector( myind ); 37 360231 : } 38 : 39 41854 : void MultiValue::resize( const size_t& nvals, const size_t& nder ) { 40 41854 : values.resize(nvals); nderivatives=nder; derivatives.resize( nvals*nder ); 41 41854 : tmpder.resize( nder ); hasDerivatives.clear(); std::vector<unsigned> myind( nder ); 42 10856236 : for(unsigned i=0; i<nder; ++i) myind[i]=i; 43 41854 : hasDerivatives.createIndexListFromVector( myind ); 44 41854 : atLeastOneSet=false; 45 41854 : } 46 : 47 2098913 : void MultiValue::clearAll() { 48 2098913 : if( atLeastOneSet && !hasDerivatives.updateComplete() ) hasDerivatives.updateActiveMembers(); 49 10441330 : for(unsigned i=0; i<values.size(); ++i) clear(i); 50 2098913 : clearTemporyDerivatives(); hasDerivatives.deactivateAll(); atLeastOneSet=false; 51 2098913 : } 52 : 53 8342417 : void MultiValue::clear( const unsigned& ival ) { 54 8342417 : values[ival]=0; 55 8342417 : unsigned base=ival*nderivatives, ndert=hasDerivatives.getNumberActive(); 56 311768969 : for(unsigned i=0; i<ndert; ++i) derivatives[ base+hasDerivatives[i] ]=0.; 57 8342417 : } 58 : 59 2098913 : void MultiValue::clearTemporyDerivatives() { 60 2098913 : unsigned ndert=hasDerivatives.getNumberActive(); tmpval=0.; 61 82072301 : for(unsigned i=0; i<ndert; ++i) tmpder[ hasDerivatives[i] ]=0.; 62 2098913 : } 63 : 64 502652 : void MultiValue::chainRule( const unsigned& ival, const unsigned& iout, const unsigned& stride, const unsigned& off, 65 : const double& df, const unsigned& bufstart, std::vector<double>& buffer ) { 66 502652 : if( !hasDerivatives.updateComplete() ) hasDerivatives.updateActiveMembers(); 67 : 68 : plumed_dbg_assert( off<stride ); 69 502652 : unsigned base=nderivatives*ival, ndert=hasDerivatives.getNumberActive(); 70 502652 : unsigned start=bufstart+stride*(nderivatives+1)*iout + stride; 71 29225155 : for(unsigned i=0; i<ndert; ++i) { 72 : unsigned jder=hasDerivatives[i]; 73 28722503 : buffer[start+jder*stride] += df*derivatives[base+jder]; 74 : } 75 502652 : } 76 : 77 57565 : void MultiValue::copyValues( MultiValue& outvals ) const { 78 : plumed_dbg_assert( values.size()<=outvals.getNumberOfValues() ); 79 183225 : for(unsigned i=0; i<values.size(); ++i) outvals.setValue( i, values[i] ); 80 : 81 57565 : } 82 : 83 50656 : void MultiValue::copyDerivatives( MultiValue& outvals ) { 84 : plumed_dbg_assert( values.size()<=outvals.getNumberOfValues() && nderivatives<=outvals.getNumberOfDerivatives() ); 85 50656 : if( !hasDerivatives.updateComplete() ) hasDerivatives.updateActiveMembers(); 86 : 87 50656 : outvals.atLeastOneSet=true; unsigned ndert=hasDerivatives.getNumberActive(); 88 3766585 : for(unsigned j=0; j<ndert; ++j) { 89 3715929 : unsigned jder=hasDerivatives[j]; outvals.hasDerivatives.activate(jder); 90 : } 91 : 92 : unsigned base=0, obase=0; 93 162498 : for(unsigned i=0; i<values.size(); ++i) { 94 8330096 : for(unsigned j=0; j<ndert; ++j) { 95 : unsigned jder=hasDerivatives[j]; 96 8218254 : outvals.derivatives[obase+jder] += derivatives[base+jder]; 97 : } 98 111842 : obase+=outvals.nderivatives; base+=nderivatives; 99 : } 100 50656 : } 101 : 102 1869892 : void MultiValue::quotientRule( const unsigned& nder, const unsigned& oder ) { 103 : plumed_dbg_assert( nder<values.size() && oder<values.size() ); 104 1869892 : if( !hasDerivatives.updateComplete() ) hasDerivatives.updateActiveMembers(); 105 : 106 1869892 : unsigned ndert=hasDerivatives.getNumberActive(); double wpref; 107 1869892 : unsigned obase=oder*nderivatives, nbase=nder*nderivatives; 108 : 109 1869892 : if( std::fabs(tmpval)>epsilon ) { wpref=1.0/tmpval; } 110 : else { wpref=1.0; } 111 : 112 1869892 : double pref = values[nder]*wpref*wpref; 113 179899336 : for(unsigned j=0; j<ndert; ++j) { 114 : unsigned jder=hasDerivatives[j]; 115 178029444 : derivatives[obase+jder] = wpref*derivatives[nbase+jder] - pref*tmpder[jder]; 116 : } 117 1869892 : values[oder] = wpref*values[nder]; 118 1869892 : } 119 : 120 : }