From fb6f1dffdf749960efafdcb3e35847cee524b76c Mon Sep 17 00:00:00 2001
From: Gareth Tribello <gareth.tribello@gmail.com>
Date: Sat, 12 Oct 2013 18:19:45 +0100
Subject: [PATCH] Added max vessel

---
 CHANGES/v2.1.txt                        |  5 +-
 src/multicolvar/CoordinationNumbers.cpp |  2 +-
 src/multicolvar/Distances.cpp           |  2 +-
 src/vesselbase/Max.cpp                  | 86 +++++++++++++++++++++++++
 4 files changed, 92 insertions(+), 3 deletions(-)
 create mode 100644 src/vesselbase/Max.cpp

diff --git a/CHANGES/v2.1.txt b/CHANGES/v2.1.txt
index c1ae623c0..5bba238bb 100644
--- a/CHANGES/v2.1.txt
+++ b/CHANGES/v2.1.txt
@@ -9,12 +9,15 @@ Changes from version 2.0 which are relevant for users:
 - Added NDX_FILE and NDX_GROUP to action GROUP, allowing to import atom lists from ndx files
 - Several optimizations in the following actions: WHOLEMOLECULES, ...
 - Faster atom scattering with domain decomposition.
+- SPRINT topological collective variables
+- Improved multicolvar neighbor lists
+- Maximum colvar as well as minimum colvar is now possible
 
 Changes from version 2.0 which are relevant for developers:
 - Added regtests for plumed as a library (e.g. basic/rt-make-0). plumed command has an additional
   flag (--is-installed) to probe if running from a compilation directory or from a fully installed copy
   (this is needed for regtests to work properly).
-- Improved class Communicator. Many operations can now be done directly on Vectors, Tensors, and std::vector.
+- Improved class Communicator. Many operations can now be done directly on Vectors, Tensors, std::vector and PLMD::Matrix.
 - Patches for GPL codes (QuantumEspresso and Gromacs) now also include
   original code so as to simplify their modification.
 
diff --git a/src/multicolvar/CoordinationNumbers.cpp b/src/multicolvar/CoordinationNumbers.cpp
index d21784b00..86d52042b 100644
--- a/src/multicolvar/CoordinationNumbers.cpp
+++ b/src/multicolvar/CoordinationNumbers.cpp
@@ -89,7 +89,7 @@ void CoordinationNumbers::registerKeywords( Keywords& keys ){
                                "The following provides information on the \\ref switchingfunction that are available. "
                                "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords.");
   // Use actionWithDistributionKeywords
-  keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN");
+  keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); keys.use("MAX");
   keys.use("MIN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS");
 }
 
diff --git a/src/multicolvar/Distances.cpp b/src/multicolvar/Distances.cpp
index f05995752..1bf16e36d 100644
--- a/src/multicolvar/Distances.cpp
+++ b/src/multicolvar/Distances.cpp
@@ -91,7 +91,7 @@ PLUMED_REGISTER_ACTION(Distances,"DISTANCES")
 void Distances::registerKeywords( Keywords& keys ){
   MultiColvar::registerKeywords( keys );
   keys.use("ATOMS"); 
-  keys.use("MEAN"); keys.use("MIN"); keys.use("LESS_THAN"); keys.use("DHENERGY");
+  keys.use("MEAN"); keys.use("MIN"); keys.use("MAX"); keys.use("LESS_THAN"); keys.use("DHENERGY");
   keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS");
   keys.add("atoms-1","GROUP","Calculate the distance between each distinct pair of atoms in the group");
   keys.add("atoms-2","GROUPA","Calculate the distances between all the atoms in GROUPA and all "
diff --git a/src/vesselbase/Max.cpp b/src/vesselbase/Max.cpp
new file mode 100644
index 000000000..2d134c506
--- /dev/null
+++ b/src/vesselbase/Max.cpp
@@ -0,0 +1,86 @@
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   Copyright (c) 2013 The plumed team
+   (see the PEOPLE file at the root of the distribution for a list of names)
+
+   See http://www.plumed-code.org for more information.
+
+   This file is part of plumed, version 2.0.
+
+   plumed is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   plumed is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with plumed.  If not, see <http://www.gnu.org/licenses/>.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+#include "VesselRegister.h"
+#include "FunctionVessel.h"
+#include "ActionWithVessel.h"
+
+namespace PLMD {
+namespace vesselbase{
+
+class Max : public FunctionVessel {
+private:
+  std::vector<double> df;
+  double beta;
+public:
+  static void registerKeywords( Keywords& keys );
+  static void reserveKeyword( Keywords& keys );
+  Max( const VesselOptions& da );
+  std::string function_description();
+  bool calculate();
+  void finish();
+};
+
+PLUMED_REGISTER_VESSEL(Max,"MAX")
+
+void Max::registerKeywords( Keywords& keys ){
+  FunctionVessel::registerKeywords( keys );
+  keys.add("compulsory","BETA","the value of beta for the equation in the manual");
+}
+
+void Max::reserveKeyword( Keywords& keys ){
+  keys.reserve("optional","MAX","calculate the maximum value. "
+                                "To make this quantity continuous the maximum is calculated using "
+                                "\\f$ \\textrm{max} = \\beta \\log \\sum_i \\exp\\left( \\frac{s_i}{\\beta}\\right) } \\f$ "
+                                "The value of \\f$\\beta\\f$ in this function is specified using (BETA=\\f$\\beta\\f$)",true);
+}
+
+Max::Max( const VesselOptions& da ) :
+FunctionVessel(da),
+df(2)
+{
+  if( getAction()->isPeriodic() ) error("max is not a meaningful option for periodic variables");
+  parse("BETA",beta);
+
+  if( diffweight ) error("can't calculate max if weight is differentiable");
+}
+
+std::string Max::function_description(){
+  std::string str_beta; Tools::convert( beta, str_beta );
+  return "the maximum value. Beta is equal to " + str_beta;
+}
+
+bool Max::calculate(){
+  double val=getAction()->getElementValue(0);
+  double dval, f = exp(val/beta); dval=f/beta;
+  addValueIgnoringTolerance(0,f);
+  getAction()->chainRuleForElementDerivatives( 0, 0, dval, this );
+  return true;
+}
+
+void Max::finish(){
+  double valin=getFinalValue(0); double dist=beta*std::log( valin );
+  setOutputValue( dist ); df[0]=beta/valin; df[1]=0.0;  
+  mergeFinalDerivatives( df );
+}
+
+}
+}
-- 
GitLab