From f4a66410bc251ad434ac616e1a021c9c620ba948 Mon Sep 17 00:00:00 2001
From: Giovanni Bussi <giovanni.bussi@gmail.com>
Date: Tue, 3 Jan 2012 16:50:02 +0100
Subject: [PATCH] Systematic replacement of many asserts with plumed_assert

I replaced many of the "low level" assertions, trying to add messages here and there.
Still, this is mostly for developers: errors in the input file should get better reports.
---
 src/Action.cpp                 |   9 +-
 src/ActionAtomistic.cpp        |  10 +-
 src/ActionSetup.cpp            |   1 +
 src/ActionWithArguments.cpp    |   1 +
 src/ActionWithValue.cpp        |   7 +-
 src/ActionWithValue.h          |   4 +-
 src/AtomNumber.h               |   5 +-
 src/Atoms.cpp                  |  20 ++--
 src/Atoms.h                    |   4 +-
 src/GREX.cpp                   |   1 +
 src/GenericDumpAtoms.cpp       |   1 +
 src/GenericDumpDerivatives.cpp |   1 +
 src/GenericDumpForces.cpp      |   1 +
 src/Log.cpp                    |   8 +-
 src/MDAtoms.cpp                |  15 +--
 src/Pbc.cpp                    |   3 +-
 src/PlumedCommunicator.cpp     |  20 ++--
 src/PlumedCommunicator.h       |  26 +++---
 src/PlumedMain.cpp             | 162 +++++++++++++++++----------------
 src/PlumedMainInitializer.cpp  |   6 +-
 src/SetupUnits.cpp             |   1 +
 src/SwitchingFunction.h        |   4 +-
 src/Tools.cpp                  |   8 +-
 src/Value.cpp                  |   5 +-
 src/Value.h                    |   5 +-
 25 files changed, 174 insertions(+), 154 deletions(-)

diff --git a/src/Action.cpp b/src/Action.cpp
index b8e286139..5b18efc92 100644
--- a/src/Action.cpp
+++ b/src/Action.cpp
@@ -1,7 +1,7 @@
 #include "Action.h"
 #include "PlumedMain.h"
 #include "Log.h"
-#include <cassert>
+#include "PlumedException.h"
 #include <iostream>
 
 using namespace PLMD;
@@ -28,7 +28,8 @@ Action::Action(const ActionOptions&ao):
     std::string s; Tools::convert(plumed.getActionSet().size(),s);
     label="@"+s;
   }
-  assert(!plumed.getActionSet().selectWithLabel<Action*>(label));
+  plumed_massert(!plumed.getActionSet().selectWithLabel<Action*>(label),
+                "label " + label + " has been already used");
   log.printf("  with label %s\n",label.c_str());
 }
 
@@ -67,7 +68,7 @@ void Action::parseFlag(const std::string&key,bool & t){
 }
 
 void Action::addDependency(Action*action){
-  assert(this->after.count(action)==action->before.count(this));
+  plumed_massert(this->after.count(action)==action->before.count(this),"internal consistency of dependencies");
   this->after.insert(action);
   action->before.insert(this);
 }
@@ -126,7 +127,7 @@ void Action::exit(int c){
 }
 
 void Action::calculateNumericalDerivatives(){
-  assert(0);
+  plumed_merror("if you get here it means that you are trying to use numerical derivatives for a class that does not implement them");
 }
 
 void Action::prepare(){
diff --git a/src/ActionAtomistic.cpp b/src/ActionAtomistic.cpp
index d09f5cfac..56c348f84 100644
--- a/src/ActionAtomistic.cpp
+++ b/src/ActionAtomistic.cpp
@@ -2,10 +2,10 @@
 #include "PlumedMain.h"
 #include <vector>
 #include <string>
-#include <cassert>
 #include "ActionWithValue.h"
 #include "Colvar.h"
 #include "ActionWithVirtualAtom.h"
+#include "PlumedException.h"
 
 using namespace std;
 using namespace PLMD;
@@ -23,7 +23,7 @@ lockRequestAtoms(false)
 }
 
 void ActionAtomistic::requestAtoms(const vector<AtomNumber> & a){
-  assert(!lockRequestAtoms);
+  plumed_massert(!lockRequestAtoms,"requested atom list can only be changed in the prepare() method");
   Atoms&atoms(plumed.getAtoms());
   int nat=a.size();
   indexes.resize(nat);
@@ -36,7 +36,7 @@ void ActionAtomistic::requestAtoms(const vector<AtomNumber> & a){
   clearDependencies();
   unique.clear();
   for(unsigned i=0;i<indexes.size();i++){
-    assert(indexes[i]<n);
+    plumed_massert(indexes[i]<n,"atom out of range");
     if(indexes[i]>=atoms.getNatoms()) addDependency(atoms.virtualAtomsActions[indexes[i]-atoms.getNatoms()]);
 // only real atoms are requested to lower level Atoms class
     else unique.insert(indexes[i]);
@@ -50,7 +50,7 @@ Vector ActionAtomistic::pbcDistance(const Vector &v1,const Vector &v2)const{
 
 void ActionAtomistic::calculateNumericalDerivatives(){
   ActionWithValue*a=dynamic_cast<ActionWithValue*>(this);
-  assert(a);
+  plumed_massert(a,"only Actions with a value can be derived");
   const int nval=a->getNumberOfValues();
   const int natoms=getNatoms();
   std::vector<Vector> value(nval*natoms);
@@ -130,7 +130,7 @@ void ActionAtomistic::parseAtomList(const std::string&key,std::vector<AtomNumber
        }
      }
    }
-   assert(ok);
+   plumed_massert(ok,"it was not possible to interpret atom name " + strings[i]);
   }
 }
 
diff --git a/src/ActionSetup.cpp b/src/ActionSetup.cpp
index d973ac4d3..1f9c31c00 100644
--- a/src/ActionSetup.cpp
+++ b/src/ActionSetup.cpp
@@ -1,5 +1,6 @@
 #include "ActionSetup.h"
 #include "PlumedMain.h"
+#include <cassert>
 
 using namespace PLMD;
 
diff --git a/src/ActionWithArguments.cpp b/src/ActionWithArguments.cpp
index a67186e39..011c4f498 100644
--- a/src/ActionWithArguments.cpp
+++ b/src/ActionWithArguments.cpp
@@ -1,6 +1,7 @@
 #include "ActionWithArguments.h"
 #include "ActionWithValue.h"
 #include "PlumedMain.h"
+#include <cassert>
 
 using namespace std;
 using namespace PLMD;
diff --git a/src/ActionWithValue.cpp b/src/ActionWithValue.cpp
index 18ee506e4..1a09ff8e3 100644
--- a/src/ActionWithValue.cpp
+++ b/src/ActionWithValue.cpp
@@ -1,5 +1,6 @@
 #include "ActionWithValue.h"
 #include "PlumedMain.h"
+#include "PlumedException.h"
 
 using namespace std;
 using namespace PLMD;
@@ -29,10 +30,10 @@ void ActionWithValue::check(const std::string&name){
   assertUnique(name);
   if(name==""){
     hasUnnamedValue=true;
-    assert(!hasMultipleValues);
+    plumed_massert(!hasMultipleValues,"cannot use unnamed components for a multicomponent Action");
   }else{
     hasMultipleValues=true;
-    assert(!hasUnnamedValue);
+    plumed_massert(!hasUnnamedValue,"cannot use unnamed components for a multicomponent Action");
   }
 }
 
@@ -57,7 +58,7 @@ bool ActionWithValue::hasNamedValue(const std::string&name)const{
 
 int ActionWithValue::getValueIndex(const std::string&name)const{
   for(unsigned i=0;i<values.size();++i) if(name==values[i]->getName()) return i;
-  assert(0);
+  plumed_merror("value not found" + name);
   return -1; // otherwise the compiler complains
 }
 
diff --git a/src/ActionWithValue.h b/src/ActionWithValue.h
index 7b7b236e5..4f51b3c31 100644
--- a/src/ActionWithValue.h
+++ b/src/ActionWithValue.h
@@ -3,8 +3,8 @@
 
 #include "Action.h"
 #include "Value.h"
+#include "PlumedException.h"
 #include <vector>
-#include <cassert>
 
 namespace PLMD{
 
@@ -91,7 +91,7 @@ double ActionWithValue::getForce(int n){
 
 inline
 void ActionWithValue::assertUnique(const std::string&name){
-  assert(!hasNamedValue(name));
+  plumed_massert(!hasNamedValue(name),"action " + getLabel() + " already has a value " + name);
 }
 
 inline
diff --git a/src/AtomNumber.h b/src/AtomNumber.h
index 998dd0485..c5f6d5954 100644
--- a/src/AtomNumber.h
+++ b/src/AtomNumber.h
@@ -1,6 +1,7 @@
 #ifndef __PLUMED_AtomNumber_h
 #define __PLUMED_AtomNumber_h
-#include <cassert>
+
+#include "PlumedException.h"
 
 namespace PLMD{
 
@@ -68,7 +69,7 @@ unsigned AtomNumber::index()const{
 
 inline
 AtomNumber & AtomNumber::setSerial(unsigned i){
-  assert(i!=0);
+  plumed_massert(i>0,"serial of an atom cannot be zero");
   index_=i-1;
   return *this;
 }
diff --git a/src/Atoms.cpp b/src/Atoms.cpp
index f50bda61c..fbdae4d9e 100644
--- a/src/Atoms.cpp
+++ b/src/Atoms.cpp
@@ -1,11 +1,9 @@
 #include "Atoms.h"
 #include "ActionAtomistic.h"
-#include <cassert>
-#include <algorithm>
-#include <string>
-
 #include "MDAtoms.h"
 #include "PlumedMain.h"
+#include <algorithm>
+#include <string>
 
 using namespace PLMD;
 using namespace std;
@@ -27,7 +25,7 @@ Atoms::Atoms(PlumedMain&plumed):
 }
 
 Atoms::~Atoms(){
-  assert(actions.size()==0);
+  plumed_massert(actions.size()==0,"there is some inconsistency in action added to atoms. some of them were not properly destroyed");
   delete mdatoms;
 }
 
@@ -195,7 +193,7 @@ void Atoms::add(const ActionAtomistic*a){
 
 void Atoms::remove(const ActionAtomistic*a){
   vector<const ActionAtomistic*>::iterator f=find(actions.begin(),actions.end(),a);
-  assert(f!=actions.end());
+  plumed_massert(f!=actions.end(),"cannot remove an action registered to atoms");
   actions.erase(f);
 }
 
@@ -239,10 +237,10 @@ int Atoms::getRealPrecision()const{
 }
 
 void Atoms::MD2double(const void*m,double&d)const{
-  assert(mdatoms); mdatoms->MD2double(m,d);
+  plumed_assert(mdatoms); mdatoms->MD2double(m,d);
 }
 void Atoms::double2MD(const double&d,void*m)const{
-  assert(mdatoms); mdatoms->double2MD(d,m);
+  plumed_assert(mdatoms); mdatoms->double2MD(d,m);
 }
 
 void Atoms::updateUnits(){
@@ -304,18 +302,18 @@ unsigned Atoms::addVirtualAtom(ActionWithVirtualAtom*a){
 
 void Atoms::removeVirtualAtom(ActionWithVirtualAtom*a){
   unsigned n=positions.size();
-  assert(a==virtualAtomsActions[virtualAtomsActions.size()-1]);
+  plumed_massert(a==virtualAtomsActions[virtualAtomsActions.size()-1],"virtual atoms should be destroyed in reverse creation order");
   resizeVectors(n-1);
   virtualAtomsActions.pop_back();
 }
 
 void Atoms::insertGroup(const std::string&name,const std::vector<unsigned>&a){
-  assert(groups.count(name)==0);
+  plumed_massert(groups.count(name)==0,"group named "+name+" already exists");
   groups[name]=a;
 }
 
 void Atoms::removeGroup(const std::string&name){
-  assert(groups.count(name)==1);
+  plumed_massert(groups.count(name)==1,"cannot remove group named "+name);
   groups.erase(name);
 }
 
diff --git a/src/Atoms.h b/src/Atoms.h
index 43c65bd4b..45ed1e8ff 100644
--- a/src/Atoms.h
+++ b/src/Atoms.h
@@ -4,9 +4,9 @@
 #include "PlumedCommunicator.h"
 #include "Tensor.h"
 #include "Units.h"
+#include "PlumedException.h"
 #include <vector>
 #include <set>
-#include <cassert>
 #include <map>
 #include <string>
 
@@ -131,7 +131,7 @@ public:
   void add(const ActionAtomistic*);
   void remove(const ActionAtomistic*);
 
-  double getEnergy()const{assert(collectEnergy);return energy;};
+  double getEnergy()const{plumed_assert(collectEnergy);return energy;};
 
   void setMDEnergyUnits(double d){MDUnits.energy=d;};
   void setMDLengthUnits(double d){MDUnits.length=d;};
diff --git a/src/GREX.cpp b/src/GREX.cpp
index 6e3c7ef0f..51b5eb79c 100644
--- a/src/GREX.cpp
+++ b/src/GREX.cpp
@@ -1,6 +1,7 @@
 #include "GREX.h"
 #include "sstream"
 #include "PlumedMain.h"
+#include <cassert>
 
 using namespace std;
 using namespace PLMD;
diff --git a/src/GenericDumpAtoms.cpp b/src/GenericDumpAtoms.cpp
index a622dca2e..1e4079d59 100644
--- a/src/GenericDumpAtoms.cpp
+++ b/src/GenericDumpAtoms.cpp
@@ -2,6 +2,7 @@
 #include "ActionPilot.h"
 #include "ActionRegister.h"
 #include <cstdio>
+#include <cassert>
 
 using namespace PLMD;
 using namespace std;
diff --git a/src/GenericDumpDerivatives.cpp b/src/GenericDumpDerivatives.cpp
index 99ba01660..334047e3e 100644
--- a/src/GenericDumpDerivatives.cpp
+++ b/src/GenericDumpDerivatives.cpp
@@ -2,6 +2,7 @@
 #include "ActionWithArguments.h"
 #include "ActionRegister.h"
 #include "PlumedCommunicator.h"
+#include <cassert>
 
 using namespace std;
 
diff --git a/src/GenericDumpForces.cpp b/src/GenericDumpForces.cpp
index aae4f1854..11eb24ad9 100644
--- a/src/GenericDumpForces.cpp
+++ b/src/GenericDumpForces.cpp
@@ -2,6 +2,7 @@
 #include "ActionWithArguments.h"
 #include "ActionRegister.h"
 #include "PlumedCommunicator.h"
+#include <cassert>
 
 using namespace std;
 
diff --git a/src/Log.cpp b/src/Log.cpp
index c4d8ec132..3840fb3cf 100644
--- a/src/Log.cpp
+++ b/src/Log.cpp
@@ -1,8 +1,8 @@
-#include "Log.h"
-#include "PlumedCommunicator.h"
 #include <cstdarg>
-#include <cassert>
 #include <cstring>
+#include "Log.h"
+#include "PlumedCommunicator.h"
+#include "PlumedException.h"
 
 using namespace std;
 using namespace PLMD;
@@ -14,7 +14,7 @@ int Log::printf(const char*fmt,...){
   va_start(arg, fmt);
   int r=vsnprintf(&buffer[pointer],buflen-pointer,fmt,arg);
   va_end(arg);
-  assert(r>-1 && r<buflen-pointer);
+  plumed_massert(r>-1 && r<buflen-pointer,"error using fmt string " + std::string(fmt));
 
 // Line is buffered until newline, then written with a PLUMED: prefix
   char*p1=buffer;
diff --git a/src/MDAtoms.cpp b/src/MDAtoms.cpp
index 39f6b57a4..eaa40e3fb 100644
--- a/src/MDAtoms.cpp
+++ b/src/MDAtoms.cpp
@@ -1,7 +1,8 @@
-#include <cassert>
 #include <algorithm>
 #include <string>
 #include "MDAtoms.h"
+#include "Tools.h"
+#include "PlumedException.h"
 
 using namespace PLMD;
 using namespace std;
@@ -63,7 +64,9 @@ MDAtomsBase* MDAtomsBase::create(int p){
   } else if (p==sizeof(float)){
     return new MDAtomsTyped<float>;
   }
-  assert(0);
+  std::string pp;
+  Tools::convert(p,pp);
+  plumed_merror("cannot create an MD interface with sizeof(real)=="+ pp);
   return NULL;
 }
 
@@ -136,7 +139,7 @@ int MDAtomsTyped<T>::getRealPrecision()const{
 template <class T>
 void MDAtomsTyped<T>::setp(void*pp){
   T*p=static_cast<T*>(pp);
-  assert(stride==0 || stride==3);
+  plumed_assert(stride==0 || stride==3);
   px=p;
   py=p+1;
   pz=p+2;
@@ -152,7 +155,7 @@ void MDAtomsTyped<T>::setBox(void*pp){
 template <class T>
 void MDAtomsTyped<T>::setf(void*ff){
   T*f=static_cast<T*>(ff);
-  assert(stride==0 || stride==3);
+  plumed_assert(stride==0 || stride==3);
   fx=f;
   fy=f+1;
   fz=f+2;
@@ -162,7 +165,7 @@ void MDAtomsTyped<T>::setf(void*ff){
 template <class T>
 void MDAtomsTyped<T>::setp(void*pp,int i){
   T*p=static_cast<T*>(pp);
-  assert(stride==0 || stride==1);
+  plumed_assert(stride==0 || stride==1);
   if(i==0)px=p;
   if(i==1)py=p;
   if(i==2)pz=p;
@@ -178,7 +181,7 @@ void MDAtomsTyped<T>::setVirial(void*pp){
 template <class T>
 void MDAtomsTyped<T>::setf(void*ff,int i){
   T*f=static_cast<T*>(ff);
-  assert(stride==0 || stride==1);
+  plumed_assert(stride==0 || stride==1);
   if(i==0)fx=f;
   if(i==1)fy=f;
   if(i==2)fz=f;
diff --git a/src/Pbc.cpp b/src/Pbc.cpp
index 7f7485e29..cee6bee76 100644
--- a/src/Pbc.cpp
+++ b/src/Pbc.cpp
@@ -1,5 +1,6 @@
 #include "Pbc.h"
 #include "Tools.h"
+#include "PlumedException.h"
 
 using namespace PLMD;
 
@@ -63,7 +64,7 @@ Vector Pbc::distance(const Vector&v1,const Vector&v2)const{
       }
     }
     d=best;
-  } else assert(0);
+  } else plumed_merror("unknown pbc type");
   return d;
 }
 
diff --git a/src/PlumedCommunicator.cpp b/src/PlumedCommunicator.cpp
index 63757aa1c..6cfb8e0a2 100644
--- a/src/PlumedCommunicator.cpp
+++ b/src/PlumedCommunicator.cpp
@@ -1,6 +1,6 @@
-#include "PlumedCommunicator.h"
 #include <cstdlib>
-#include <cassert>
+#include "PlumedCommunicator.h"
+#include "PlumedException.h"
 
 using namespace std;
 using namespace PLMD;
@@ -49,24 +49,24 @@ PlumedCommunicator::~PlumedCommunicator(){
 
 void PlumedCommunicator::Set_comm(void*val){
 #ifdef __PLUMED_MPI
- assert(initialized());
+ plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
  if(val) Set_comm(*(MPI_Comm*)val);
 #else
  (void) val;
- assert(0);
+ plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
 #endif
 }
 
 void PlumedCommunicator::Set_fcomm(void*val){
 #ifdef __PLUMED_MPI
- assert(initialized());
+ plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
   if(val){
     MPI_Comm comm=MPI_Comm_f2c(*(MPI_Fint*)val);
     Set_comm(comm);
   }
 #else
   (void) val;
-  assert(0);
+  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
 #endif
 }
 
@@ -102,20 +102,20 @@ bool PlumedCommunicator::initialized(){
 
 void PlumedCommunicator::Request::wait(){
 #ifdef __PLUMED_MPI
-  assert(initialized());
+ plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
   MPI_Wait(&r,MPI_STATUS_IGNORE);
 #else
-  assert(0);
+  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
 #endif
 }
 
 void PlumedCommunicator::Request::wait(Status&s){
 #ifdef __PLUMED_MPI
-  assert(initialized());
+ plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
   MPI_Wait(&r,&s.s);
 #else
   (void) s;
-  assert(0);
+  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
 #endif
 }
 
diff --git a/src/PlumedCommunicator.h b/src/PlumedCommunicator.h
index ecb0ef184..201eeb26c 100644
--- a/src/PlumedCommunicator.h
+++ b/src/PlumedCommunicator.h
@@ -4,7 +4,7 @@
 #include <mpi.h>
 #endif
 #include <cstdlib>
-#include <cassert>
+#include "PlumedException.h"
 
 namespace PLMD{
 
@@ -107,7 +107,7 @@ void PlumedCommunicator::Bcast(T*b,int count,int root){
 template<class T>
 void PlumedCommunicator::Allgatherv(const T*sendbuf,int sendcount,T*recvbuf,const int*recvcounts,const int*displs){
 #if defined(__PLUMED_MPI)
-  assert(initialized());
+  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
   void*s=const_cast<void*>((const void*)sendbuf);
   void*r=const_cast<void*>((const void*)recvbuf);
   int*rc=const_cast<int*>(recvcounts);
@@ -120,14 +120,14 @@ void PlumedCommunicator::Allgatherv(const T*sendbuf,int sendcount,T*recvbuf,cons
   (void) recvbuf;
   (void) recvcounts;
   (void) displs;
-  assert(0);
+  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
 #endif
 }
 
 template<class T>
 void PlumedCommunicator::Allgather(const T*sendbuf,int sendcount,T*recvbuf,int recvcount){
 #if defined(__PLUMED_MPI)
-  assert(initialized());
+  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
   void*s=const_cast<void*>((const void*)sendbuf);
   void*r=const_cast<void*>((const void*)recvbuf);
   if(s==NULL)s=MPI_IN_PLACE;
@@ -137,7 +137,7 @@ void PlumedCommunicator::Allgather(const T*sendbuf,int sendcount,T*recvbuf,int r
   (void) sendcount;
   (void) recvbuf;
   (void) recvcount;
-  assert(0);
+  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
 #endif
 }
 
@@ -145,7 +145,7 @@ template <class T>
 PlumedCommunicator::Request PlumedCommunicator::Isend(const T*buf,int count,int source,int tag){
   Request req;
 #ifdef __PLUMED_MPI
-  assert(initialized());
+  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
   void*s=const_cast<void*>((const void*)buf);
   MPI_Isend(s,count,getMPIType<T>(),source,tag,communicator,&req.r);
 #else
@@ -153,7 +153,7 @@ PlumedCommunicator::Request PlumedCommunicator::Isend(const T*buf,int count,int
   (void) count;
   (void) source;
   (void) tag;
-  assert(0);
+  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
 #endif
   return req;
 }
@@ -161,7 +161,7 @@ PlumedCommunicator::Request PlumedCommunicator::Isend(const T*buf,int count,int
 template <class T>
 void PlumedCommunicator::Recv(T*buf,int count,int source,int tag,Status&status){
 #ifdef __PLUMED_MPI
-  assert(initialized());
+  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
   MPI_Recv(buf,count,getMPIType<T>(),source,tag,communicator,&status.s);
 #else
   (void) buf;
@@ -169,21 +169,21 @@ void PlumedCommunicator::Recv(T*buf,int count,int source,int tag,Status&status){
   (void) source;
   (void) tag;
   (void) status;
-  assert(0);
+  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
 #endif
 }
 
 template <class T>
 void PlumedCommunicator::Recv(T*buf,int count,int source,int tag){
 #ifdef __PLUMED_MPI
-  assert(initialized());
+  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
   MPI_Recv(buf,count,getMPIType<T>(),source,tag,communicator,MPI_STATUS_IGNORE);
 #else
   (void) buf;
   (void) count;
   (void) source;
   (void) tag;
-  assert(0);
+  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
 #endif
 }
 
@@ -191,10 +191,10 @@ template<class T>
 int PlumedCommunicator::Status::Get_count()const{
   int i;
 #ifdef __PLUMED_MPI
-  assert(initialized());
+  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
   MPI_Get_count(const_cast<MPI_Status*>(&s),getMPIType<T>(),&i);
 #else
-  assert(0);
+  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
   i=0;
 #endif
   return i;
diff --git a/src/PlumedMain.cpp b/src/PlumedMain.cpp
index feb132653..03d3b0fe2 100644
--- a/src/PlumedMain.cpp
+++ b/src/PlumedMain.cpp
@@ -1,7 +1,6 @@
 #include "PlumedMain.h"
 #include "Tools.h"
 #include <cstring>
-#include <cassert>
 #include "ActionPilot.h"
 #include "ActionWithValue.h"
 #include "ActionAtomistic.h"
@@ -12,6 +11,7 @@
 #include <cstdlib>
 #include "ActionRegister.h"
 #include "GREX.h"
+#include "PlumedException.h"
 
 using namespace PLMD;
 using namespace std;
@@ -35,6 +35,10 @@ PlumedMain::~PlumedMain(){
 /////////////////////////////////////////////////////////////
 //  MAIN INTERPRETER
 
+#define CHECK_INIT(ini,word) plumed_massert(ini,"cmd(\"" + word +"\") should be only used after plumed initialization")
+#define CHECK_NOTINIT(ini,word) plumed_massert(!(ini),"cmd(\"" + word +"\") should be only used before plumed initialization")
+#define CHECK_NULL(val,word) plumed_massert(val,"NULL pointer received in cmd(\"" + word + "\")");
+
 void PlumedMain::cmd(const std::string & word,void*val){
 
   if(false){
@@ -42,126 +46,133 @@ void PlumedMain::cmd(const std::string & word,void*val){
 
 // words used at every MD steps:
   } else if(word=="setBox") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setBox(val);
   } else if(word=="setPositions") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setPositions(val);
   } else if(word=="setMasses") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setMasses(val);
   } else if(word=="setCharges") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setCharges(val);
   } else if(word=="setPositionsX") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setPositions(val,0);
   } else if(word=="setPositionsY") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setPositions(val,1);
   } else if(word=="setPositionsZ") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setPositions(val,2);
   } else if(word=="setVirial") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setVirial(val);
   } else if(word=="setEnergy") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setEnergy(val);
   } else if(word=="setForces") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setForces(val);
   } else if(word=="setForcesX") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setForces(val,0);
   } else if(word=="setForcesY") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setForces(val,1);
   } else if(word=="setForcesZ") {
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setForces(val,2);
   } else if(word=="calc") {
-       assert(initialized);
+       CHECK_INIT(initialized,word);
        calc();
   } else if(word=="prepareDependencies") {
-       assert(initialized);
+       CHECK_INIT(initialized,word);
        prepareDependencies();
   } else if(word=="shareData") {
-       assert(initialized);
+       CHECK_INIT(initialized,word);
        shareData();
   } else if(word=="prepareCalc") {
-       assert(initialized);
+       CHECK_INIT(initialized,word);
        prepareCalc();
   } else if(word=="performCalc") {
-       assert(initialized);
+       CHECK_INIT(initialized,word);
        performCalc();
   } else if(word=="setStep") {
-       assert(initialized);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        step=(*static_cast<int*>(val));
 // words used less frequently:
   } else if(word=="setAtomsNlocal"){
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setAtomsNlocal(*static_cast<int*>(val));
   } else if(word=="setAtomsGatindex"){
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setAtomsGatindex(static_cast<int*>(val));
   } else if(word=="setAtomsContiguous"){
-       assert(initialized);
-       assert(val);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setAtomsContiguous(*static_cast<int*>(val));
   } else if(word=="createFullList"){
-       assert(initialized);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.createFullList(static_cast<int*>(val));
   } else if(word=="getFullList"){
-       assert(initialized);
+       CHECK_INIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.getFullList(static_cast<int**>(val));
   } else if(word=="clearFullList"){
-       assert(initialized);
+       CHECK_INIT(initialized,word);
        atoms.clearFullList();
   } else if(word=="read"){
-       assert(initialized);
+       CHECK_INIT(initialized,word);
        if(val)readInputFile(static_cast<char*>(val));
        else   readInputFile("plumed.dat");
   } else if(word=="clear"){
-       assert(initialized);
+       CHECK_INIT(initialized,word);
        actionSet.clearDelete();
   } else if(word=="getApiVersion"){
+       CHECK_NULL(val,word);
        *(static_cast<int*>(val))=1;
 // commands which can be used only before initialization:
   } else if(word=="init"){
-       assert(!initialized);
+       CHECK_NOTINIT(initialized,word);
        init();
   } else if(word=="setRealPrecision"){
-       assert(!initialized);
-       assert(val);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setRealPrecision(*static_cast<int*>(val));
   } else if(word=="setMDLengthUnits"){
-       assert(!initialized);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        double d;
        atoms.MD2double(val,d);
        atoms.setMDLengthUnits(d);
   } else if(word=="setMDEnergyUnits"){
-       assert(!initialized);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        double d;
        atoms.MD2double(val,d);
        atoms.setMDEnergyUnits(d);
   } else if(word=="setMDTimeUnits"){
-       assert(!initialized);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        double d;
        atoms.MD2double(val,d);
        atoms.setMDTimeUnits(d);
@@ -169,38 +180,40 @@ void PlumedMain::cmd(const std::string & word,void*val){
 // set the boltzman constant for MD in natural units (kb=1)
 // only needed in LJ codes if the MD is passing temperatures to plumed (so, not yet...)
 // use as cmd("setNaturalUnits")
-       assert(!initialized);
-       assert(!val);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setMDNaturalUnits(true);
   } else if(word=="setPlumedDat"){
-       assert(!initialized);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        plumedDat=static_cast<char*>(val);
   } else if(word=="setMPIComm"){
-       assert(!initialized);
+       CHECK_NOTINIT(initialized,word);
        comm.Set_comm(val);
        atoms.setDomainDecomposition(comm);
   } else if(word=="setMPIFComm"){
-       assert(!initialized);
+       CHECK_NOTINIT(initialized,word);
        comm.Set_fcomm(val);
        atoms.setDomainDecomposition(comm);
   } else if(word=="setNatoms"){
-       assert(!initialized);
-       assert(val);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setNatoms(*static_cast<int*>(val));
   } else if(word=="setTimestep"){
-       assert(!initialized);
-       assert(val);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        atoms.setTimeStep(val);
   } else if(word=="setMDEngine"){
-       assert(!initialized);
-       assert(val);
-       assert(MDEngine.length()==0);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        MDEngine=static_cast<char*>(val);
   } else if(word=="setLog"){
-       assert(!initialized);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        log.set(static_cast<FILE*>(val));
   } else if(word=="setLogFile"){
-       assert(!initialized);
+       CHECK_NOTINIT(initialized,word);
+       CHECK_NULL(val,word);
        log.setFile(static_cast<char*>(val));
   } else {
 // multi word commands
@@ -215,17 +228,12 @@ void PlumedMain::cmd(const std::string & word,void*val){
        *(static_cast<int*>(val))=check;
      } else if(nw>1 && words[0]=="GREX"){
        if(!grex) grex=new GREX(*this);
-       assert(grex);
+       plumed_massert(grex,"error allocating grex");
        std::string kk=words[1];
        for(unsigned i=2;i<words.size();i++) kk+=" "+words[i];
        grex->cmd(kk.c_str(),val);
      } else{
-   // error
-       fprintf(stderr,"+++ PLUMED ERROR\n");
-       fprintf(stderr,"+++ CANNOT INTERPRET CALL TO cmd() ROUTINE WITH ARG '%s'\n",word.c_str());
-       fprintf(stderr,"+++ There might be a mistake in the MD code\n");
-       fprintf(stderr,"+++ or you may be using an out-dated plumed version\n");
-       exit(1);
+       plumed_merror("cannot interpret cmd(\"" + word + "\"). check plumed developers manual to see the available commands.");
      };
   };
 }
@@ -263,7 +271,7 @@ void PlumedMain::init(){
 }
 
 void PlumedMain::readInputFile(std::string str){
-  assert(initialized);
+  plumed_assert(initialized);
   log.printf("FILE: %s\n",str.c_str());
   FILE*fp=fopen(str.c_str(),"r");
   std::vector<std::string> words;
@@ -272,11 +280,11 @@ void PlumedMain::readInputFile(std::string str){
     else if(words[0]=="ENDPLUMED") break;
     else if(words[0]=="LOAD") load(words);
     else if(words[0]=="_SET_SUFFIX"){
-      assert(words.size()==2);
+      plumed_assert(words.size()==2);
       setSuffix(words[1]);
     }
     else if(words[0]=="INCLUDE"){
-      assert(words.size()==2);
+      plumed_assert(words.size()==2);
       readInputFile(words[1]);
       continue;
     } else {
@@ -427,7 +435,7 @@ void PlumedMain::justApply(){
 void PlumedMain::load(std::vector<std::string> & words){
   if(DLLoader::installed()){
      string s=words[1];
-     assert(words.size()==2);
+     plumed_assert(words.size()==2);
      size_t n=s.find_last_of(".");
      string extension="";
      string base=s;
@@ -454,7 +462,7 @@ void PlumedMain::load(std::vector<std::string> & words){
      log<<"Loading shared library "<<s.c_str()<<"\n";
      log<<"Here is the new list of available actions\n";
      log<<actionRegister();
-  } else assert(0); // Loading not enabled; please recompile with -D__PLUMED_HAS_DLOPEN
+  } else plumed_merror("loading not enabled, please recompile with -D__PLUMED_HAS_DLOPEN");
 }
 
 double PlumedMain::getBias() const{
@@ -468,7 +476,7 @@ FILE* PlumedMain::fopen(const char *path, const char *mode){
   std::string ppathsuf=ppath+suffix;
   FILE*fp=std::fopen(const_cast<char*>(ppathsuf.c_str()),const_cast<char*>(mmode.c_str()));
   if(!fp) fp=std::fopen(const_cast<char*>(ppath.c_str()),const_cast<char*>(mmode.c_str()));
-  assert(fp);
+  plumed_massert(fp,"file " + ppath + "cannot be found");
   return fp;
 }
 
diff --git a/src/PlumedMainInitializer.cpp b/src/PlumedMainInitializer.cpp
index b26857ac5..6c7b79a3d 100644
--- a/src/PlumedMainInitializer.cpp
+++ b/src/PlumedMainInitializer.cpp
@@ -1,5 +1,5 @@
 #include "PlumedMain.h"
-#include <cassert>
+#include "PlumedException.h"
 #include <cstdlib>
 
 using namespace PLMD;
@@ -26,12 +26,12 @@ extern "C" void*plumedmain_create(){
 }
 
 extern "C" void plumedmain_cmd(void*plumed,const char*key,const void*val){
-  assert(plumed); // ERROR: sending a cmd to an uninitialized plumed object
+  plumed_massert(plumed,"trying to use a plumed object which is not initialized");
   static_cast<PlumedMain*>(plumed)->cmd(key,val);
 }
 
 extern "C" void plumedmain_finalize(void*plumed){
-  assert(plumed); // ERROR: destructing an uninitialized plumed object
+  plumed_massert(plumed,"trying to deallocate a plumed object which is not initialized");
   delete static_cast<PlumedMain*>(plumed);
 }
 
diff --git a/src/SetupUnits.cpp b/src/SetupUnits.cpp
index 450b95e5e..aecfba1bf 100644
--- a/src/SetupUnits.cpp
+++ b/src/SetupUnits.cpp
@@ -1,6 +1,7 @@
 #include "ActionSetup.h"
 #include "ActionRegister.h"
 #include "PlumedMain.h"
+#include <cassert>
 
 using namespace std;
 
diff --git a/src/SwitchingFunction.h b/src/SwitchingFunction.h
index c6955facc..e0fdd8d9b 100644
--- a/src/SwitchingFunction.h
+++ b/src/SwitchingFunction.h
@@ -1,8 +1,8 @@
 #ifndef __PLUMED_SwitchingFunction_h
 #define __PLUMED_SwitchingFunction_h
 
-#include <cassert>
 #include <cmath>
+#include "PlumedException.h"
 
 namespace PLMD {
 
@@ -42,7 +42,7 @@ void SwitchingFunction::set(int nn,int mm,double r_0,double d_0){
 
 inline
 double SwitchingFunction::calculate(double distance,double&dfunc)const{
-  assert(init);
+  plumed_massert(init,"you are trying to use an unset SwitchingFunction");
   const double rdist = (distance-d_0)/r_0;
   double result=0.;
   if(rdist<=0.){
diff --git a/src/Tools.cpp b/src/Tools.cpp
index 110fda1e8..0efeb9997 100644
--- a/src/Tools.cpp
+++ b/src/Tools.cpp
@@ -1,6 +1,6 @@
 #include "Tools.h"
 #include "AtomNumber.h"
-#include <cassert>
+#include "PlumedException.h"
 #include <sstream>
 #include <cstring>
 
@@ -86,8 +86,8 @@ bool Tools::getParsedLine(FILE* fp,vector<string> & words){
     if(w.size()==0) continue;
     if(inside && *(w.begin())=="..."){
       inside=false;
-      if(w.size()==2) assert(w[1]==words[0]);
-      assert(w.size()<=2);
+      if(w.size()==2) plumed_massert(w[1]==words[0],"second word in terminating \"...\" lines, if present, should be equal to first word of directive");
+      plumed_massert(w.size()<=2,"terminating \"...\" lines cannot consist of more than two words");
       w.clear();
     }else if(*(w.end()-1)=="..."){
       inside=true;
@@ -153,7 +153,7 @@ void Tools::interpretRanges(std::vector<std::string>&s){
     words=getWords(*p,"-");
     int a,b;
     if(words.size()==2 && convert(words[0],a) && convert(words[1],b)){
-      assert(b>=a);
+      plumed_massert(b>=a,"interpreting range \"" + words[0] + "-" + words[1] +"\", second atom should have higher index than first atom");
       for(int i=a;i<=b;i++){
         string ss;
         convert(i,ss);
diff --git a/src/Value.cpp b/src/Value.cpp
index 159661ac3..bddc49e1a 100644
--- a/src/Value.cpp
+++ b/src/Value.cpp
@@ -1,5 +1,6 @@
 #include "Value.h"
 #include "ActionWithValue.h"
+#include "PlumedException.h"
 
 using namespace PLMD;
 
@@ -16,7 +17,7 @@ Value::Value(ActionWithValue&action,const std::string& name):
 {}
 
 bool Value::isPeriodic()const{
-  assert(periodicity!=unset);
+  plumed_massert(periodicity!=unset,"periodicity should be set");
   return periodicity==periodic;
 }
 
@@ -48,7 +49,7 @@ void Value::enableDerivatives()
 }
 
 double Value::difference(double d1,double d2)const{
-  assert(periodicity!=unset);
+  plumed_massert(periodicity!=unset,"periodicity should be set to compute differences");
   if(periodicity==periodic){
     double s=(d2-d1)*inv_max_minus_min;
     s=Tools::pbc(s);
diff --git a/src/Value.h b/src/Value.h
index 9e9405cc9..13ab43983 100644
--- a/src/Value.h
+++ b/src/Value.h
@@ -3,8 +3,7 @@
 
 #include <vector>
 #include <string>
-#include <cassert>
-
+#include "PlumedException.h"
 
 namespace PLMD{
 
@@ -124,7 +123,7 @@ bool Value::checkForced()const{
 
 inline
 void Value::addForce(double f){
-  assert(hasDerivatives());
+  plumed_massert(hasDerivatives(),"forces can only be added to values with derivatives");
   forced=true;
   inputForce+=f;
 }
-- 
GitLab