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 360661 : MultiValue::MultiValue( const size_t& nvals, const size_t& nder ): 27 360661 : values(nvals), 28 360661 : nderivatives(nder), 29 360661 : derivatives(nvals*nder), 30 360661 : tmpval(0), 31 360661 : tmpder(nder), 32 721322 : atLeastOneSet(false) { 33 360661 : std::vector<unsigned> myind( nder ); 34 11615748 : for(unsigned i=0; i<nder; ++i) { 35 11255087 : myind[i]=i; 36 : } 37 360661 : hasDerivatives.createIndexListFromVector( myind ); 38 360661 : } 39 : 40 41860 : void MultiValue::resize( const size_t& nvals, const size_t& nder ) { 41 41860 : values.resize(nvals); 42 41860 : nderivatives=nder; 43 41860 : derivatives.resize( nvals*nder ); 44 41860 : tmpder.resize( nder ); 45 41860 : hasDerivatives.clear(); 46 41860 : std::vector<unsigned> myind( nder ); 47 10858510 : for(unsigned i=0; i<nder; ++i) { 48 10816650 : myind[i]=i; 49 : } 50 41860 : hasDerivatives.createIndexListFromVector( myind ); 51 41860 : atLeastOneSet=false; 52 41860 : } 53 : 54 2753493 : void MultiValue::clearAll() { 55 2753493 : if( atLeastOneSet && !hasDerivatives.updateComplete() ) { 56 14908 : hasDerivatives.updateActiveMembers(); 57 : } 58 12814438 : for(unsigned i=0; i<values.size(); ++i) { 59 10060945 : clear(i); 60 : } 61 2753493 : clearTemporyDerivatives(); 62 2753493 : hasDerivatives.deactivateAll(); 63 2753493 : atLeastOneSet=false; 64 2753493 : } 65 : 66 10060945 : void MultiValue::clear( const unsigned& ival ) { 67 10060945 : values[ival]=0; 68 10060945 : unsigned base=ival*nderivatives, ndert=hasDerivatives.getNumberActive(); 69 337680037 : for(unsigned i=0; i<ndert; ++i) { 70 327619092 : derivatives[ base+hasDerivatives[i] ]=0.; 71 : } 72 10060945 : } 73 : 74 2753493 : void MultiValue::clearTemporyDerivatives() { 75 2753493 : unsigned ndert=hasDerivatives.getNumberActive(); 76 2753493 : tmpval=0.; 77 90511305 : for(unsigned i=0; i<ndert; ++i) { 78 87757812 : tmpder[ hasDerivatives[i] ]=0.; 79 : } 80 2753493 : } 81 : 82 551204 : void MultiValue::chainRule( const unsigned& ival, const unsigned& iout, const unsigned& stride, const unsigned& off, 83 : const double& df, const unsigned& bufstart, std::vector<double>& buffer ) { 84 551204 : if( !hasDerivatives.updateComplete() ) { 85 8549 : hasDerivatives.updateActiveMembers(); 86 : } 87 : 88 : plumed_dbg_assert( off<stride ); 89 551204 : unsigned base=nderivatives*ival, ndert=hasDerivatives.getNumberActive(); 90 551204 : unsigned start=bufstart+stride*(nderivatives+1)*iout + stride; 91 34117477 : for(unsigned i=0; i<ndert; ++i) { 92 : unsigned jder=hasDerivatives[i]; 93 33566273 : buffer[start+jder*stride] += df*derivatives[base+jder]; 94 : } 95 551204 : } 96 : 97 57565 : void MultiValue::copyValues( MultiValue& outvals ) const { 98 : plumed_dbg_assert( values.size()<=outvals.getNumberOfValues() ); 99 183225 : for(unsigned i=0; i<values.size(); ++i) { 100 : outvals.setValue( i, values[i] ); 101 : } 102 : 103 57565 : } 104 : 105 50656 : void MultiValue::copyDerivatives( MultiValue& outvals ) { 106 : plumed_dbg_assert( values.size()<=outvals.getNumberOfValues() && nderivatives<=outvals.getNumberOfDerivatives() ); 107 50656 : if( !hasDerivatives.updateComplete() ) { 108 0 : hasDerivatives.updateActiveMembers(); 109 : } 110 : 111 50656 : outvals.atLeastOneSet=true; 112 50656 : unsigned ndert=hasDerivatives.getNumberActive(); 113 3766585 : for(unsigned j=0; j<ndert; ++j) { 114 : unsigned jder=hasDerivatives[j]; 115 3715929 : outvals.hasDerivatives.activate(jder); 116 : } 117 : 118 : unsigned base=0, obase=0; 119 162498 : for(unsigned i=0; i<values.size(); ++i) { 120 8330096 : for(unsigned j=0; j<ndert; ++j) { 121 : unsigned jder=hasDerivatives[j]; 122 8218254 : outvals.derivatives[obase+jder] += derivatives[base+jder]; 123 : } 124 111842 : obase+=outvals.nderivatives; 125 111842 : base+=nderivatives; 126 : } 127 50656 : } 128 : 129 1905928 : void MultiValue::quotientRule( const unsigned& nder, const unsigned& oder ) { 130 : plumed_dbg_assert( nder<values.size() && oder<values.size() ); 131 1905928 : if( !hasDerivatives.updateComplete() ) { 132 0 : hasDerivatives.updateActiveMembers(); 133 : } 134 : 135 1905928 : unsigned ndert=hasDerivatives.getNumberActive(); 136 : double wpref; 137 1905928 : unsigned obase=oder*nderivatives, nbase=nder*nderivatives; 138 : 139 1905928 : if( std::fabs(tmpval)>epsilon ) { 140 1905928 : wpref=1.0/tmpval; 141 : } else { 142 : wpref=1.0; 143 : } 144 : 145 1905928 : double pref = values[nder]*wpref*wpref; 146 183543652 : for(unsigned j=0; j<ndert; ++j) { 147 : unsigned jder=hasDerivatives[j]; 148 181637724 : derivatives[obase+jder] = wpref*derivatives[nbase+jder] - pref*tmpder[jder]; 149 : } 150 1905928 : values[oder] = wpref*values[nder]; 151 1905928 : } 152 : 153 : }