LCOV - code coverage report
Current view: top level - tools - Keywords.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 272 464 58.6 %
Date: 2019-08-13 10:39:37 Functions: 30 35 85.7 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-2019 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 "Keywords.h"
      23             : #include "Log.h"
      24             : #include "Tools.h"
      25             : #include <iostream>
      26             : 
      27             : namespace PLMD {
      28             : 
      29      384604 : Keywords::KeyType::KeyType( const std::string& type ) {
      30      384604 :   if( type=="compulsory" ) {
      31      105243 :     style=compulsory;
      32      279361 :   } else if( type=="flag" ) {
      33       65314 :     style=flag;
      34      214047 :   } else if( type=="optional" ) {
      35      110221 :     style=optional;
      36      103826 :   } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) {
      37       51450 :     style=atoms;
      38       52376 :   } else if( type=="hidden" ) {
      39       25057 :     style=hidden;
      40       27319 :   } else if( type=="vessel" ) {
      41       27319 :     style=vessel;
      42             :   } else {
      43           0 :     plumed_massert(false,"invalid keyword specifier " + type);
      44             :   }
      45      384604 : }
      46             : 
      47        1826 : void Keywords::KeyType::setStyle( const std::string& type ) {
      48        1826 :   if( type=="compulsory" ) {
      49          35 :     style=compulsory;
      50        1791 :   } else if( type=="flag" ) {
      51           0 :     style=flag;
      52        1791 :   } else if( type=="optional" ) {
      53           7 :     style=optional;
      54        1784 :   } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) {
      55         177 :     style=atoms;
      56        1607 :   } else if( type=="hidden" ) {
      57           0 :     style=hidden;
      58        1607 :   } else if( type=="vessel" ) {
      59        1607 :     style=vessel;
      60             :   } else {
      61           0 :     plumed_massert(false,"invalid keyword specifier " + type);
      62             :   }
      63        1826 : }
      64             : 
      65         509 : void Keywords::add( const Keywords& newkeys ) {
      66         509 :   newkeys.copyData( keys, reserved_keys, types, allowmultiple, documentation, booldefs, numdefs, atomtags, cnames, ckey, cdocs  );
      67         509 : }
      68             : 
      69         509 : void Keywords::copyData( std::vector<std::string>& kk, std::vector<std::string>& rk, std::map<std::string,KeyType>& tt, std::map<std::string,bool>& am,
      70             :                          std::map<std::string,std::string>& docs, std::map<std::string,bool>& bools, std::map<std::string,std::string>& nums,
      71             :                          std::map<std::string,std::string>& atags, std::vector<std::string>& cnam, std::map<std::string,std::string>& ck,
      72             :                          std::map<std::string,std::string>& cd ) const {
      73         509 :   for(unsigned i=0; i<keys.size(); ++i) {
      74           0 :     std::string thiskey=keys[i];
      75           0 :     for(unsigned j=0; j<kk.size(); ++j) plumed_massert( thiskey!=kk[j], "keyword " + thiskey + " is in twice" );
      76           0 :     for(unsigned j=0; j<rk.size(); ++j) plumed_massert( thiskey!=rk[j], "keyword " + thiskey + " is in twice" );
      77           0 :     kk.push_back( thiskey );
      78           0 :     plumed_massert( types.count( thiskey ), "no type data on keyword " + thiskey + " to copy" );
      79           0 :     tt.insert( std::pair<std::string,KeyType>( thiskey,types.find(thiskey)->second) );
      80           0 :     if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair<std::string,std::string>( thiskey,atomtags.find(thiskey)->second) );
      81           0 :     plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" );
      82           0 :     am.insert( std::pair<std::string,bool>(thiskey,allowmultiple.find(thiskey)->second) );
      83           0 :     plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" );
      84           0 :     docs.insert( std::pair<std::string,std::string>(thiskey,documentation.find(thiskey)->second) );
      85           0 :     if( booldefs.count( thiskey ) ) bools.insert( std::pair<std::string,bool>( thiskey,booldefs.find(thiskey)->second) );
      86           0 :     if( numdefs.count( thiskey ) ) nums.insert( std::pair<std::string,std::string>( thiskey,numdefs.find(thiskey)->second) );
      87           0 :   }
      88        9671 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
      89        9162 :     std::string thiskey=reserved_keys[i];
      90        9162 :     for(unsigned j=0; j<kk.size(); ++j) plumed_massert( thiskey!=kk[j], "keyword " + thiskey + " is in twice" );
      91        9162 :     for(unsigned j=0; j<rk.size(); ++j) plumed_massert( thiskey!=rk[j], "keyword " + thiskey + " is in twice" );
      92        9162 :     rk.push_back( thiskey );
      93        9162 :     plumed_massert( types.count( thiskey ), "no type data on keyword " + thiskey + " to copy" );
      94        9162 :     tt.insert( std::pair<std::string,KeyType>( thiskey,types.find(thiskey)->second) );
      95        9162 :     if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair<std::string,std::string>( thiskey,atomtags.find(thiskey)->second) );
      96        9162 :     plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" );
      97        9162 :     am.insert( std::pair<std::string,bool>(thiskey,allowmultiple.find(thiskey)->second) );
      98        9162 :     plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" );
      99        9162 :     docs.insert( std::pair<std::string,std::string>(thiskey,documentation.find(thiskey)->second) );
     100        9162 :     if( booldefs.count( thiskey ) ) bools.insert( std::pair<std::string,bool>( thiskey,booldefs.find(thiskey)->second) );
     101        9162 :     if( numdefs.count( thiskey ) ) nums.insert( std::pair<std::string,std::string>( thiskey,numdefs.find(thiskey)->second) );
     102        9162 :   }
     103        9671 :   for(unsigned i=0; i<cnames.size(); ++i) {
     104        9162 :     std::string thisnam=cnames[i];
     105        9162 :     for(unsigned j=0; j<cnam.size(); ++j) plumed_massert( thisnam!=cnam[j], "component " + thisnam + " is in twice" );
     106        9162 :     cnam.push_back( thisnam );
     107        9162 :     plumed_massert( ckey.count( thisnam ), "no keyword data on component " + thisnam + " to copy" );
     108        9162 :     ck.insert( std::pair<std::string,std::string>( thisnam, ckey.find(thisnam)->second) );
     109        9162 :     plumed_massert( cdocs.count( thisnam ), "no documentation on component " + thisnam + " to copy" );
     110        9162 :     cd.insert( std::pair<std::string,std::string>( thisnam, cdocs.find(thisnam)->second) );
     111        9162 :   }
     112         509 : }
     113             : 
     114       51070 : void Keywords::reserve( const std::string & t, const std::string & k, const std::string & d ) {
     115       51070 :   plumed_assert( !exists(k) && !reserved(k) );
     116      102140 :   std::string fd, lowkey=k;
     117             :   // Convert to lower case
     118       51070 :   std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
     119             : // Remove any underscore characters
     120       69273 :   for(unsigned i=0;; ++i) {
     121       69273 :     std::size_t num=lowkey.find_first_of("_");
     122       69273 :     if( num==std::string::npos ) break;
     123       18203 :     lowkey.erase( lowkey.begin() + num, lowkey.begin() + num + 1 );
     124       18203 :   }
     125       51070 :   if( t=="vessel" ) {
     126       27319 :     fd = d + " The final value can be referenced using <em>label</em>." + lowkey;
     127       51424 :     if(d.find("flag")==std::string::npos) fd += ".  You can use multiple instances of this keyword i.e. " +
     128       48210 :           k +"1, " + k + "2, " + k + "3...  The corresponding values are then "
     129       48210 :           "referenced using <em>label</em>."+ lowkey +"-1,  <em>label</em>." + lowkey +
     130       24105 :           "-2,  <em>label</em>." + lowkey + "-3...";
     131       27319 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     132       27319 :     types.insert( std::pair<std::string,KeyType>(k,KeyType("vessel")) );
     133       23751 :   } else if( t=="numbered" ) {
     134        2088 :     fd = d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3...";
     135        2088 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     136        2088 :     types.insert( std::pair<std::string,KeyType>(k,KeyType("optional")) );
     137             :   } else {
     138       21663 :     fd = d;
     139       21663 :     if( t=="atoms" && isaction ) fd = d + ".  For more information on how to specify lists of atoms see \\ref Group";
     140       21663 :     allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     141       21663 :     types.insert( std::pair<std::string,KeyType>(k,KeyType(t)) );
     142       21663 :     if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,t) );
     143             :   }
     144       51070 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     145      102140 :   reserved_keys.push_back(k);
     146       51070 : }
     147             : 
     148        1591 : void Keywords::reserveFlag( const std::string & k, const bool def, const std::string & d ) {
     149        1591 :   plumed_assert( !exists(k) && !reserved(k) );
     150        1591 :   std::string defstr;
     151        1591 :   if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; }
     152        1591 :   types.insert( std::pair<std::string,KeyType>(k,KeyType("flag")) );
     153        3182 :   std::string fd,lowkey=k; std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
     154        1591 :   fd=defstr + d;
     155        1591 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     156        1591 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     157        1591 :   booldefs.insert( std::pair<std::string,bool>(k,def) );
     158        3182 :   reserved_keys.push_back(k);
     159        1591 : }
     160             : 
     161       11514 : void Keywords::use( const std::string & k ) {
     162       11514 :   plumed_massert( reserved(k), "the " + k + " keyword is not reserved");
     163      154138 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
     164      142624 :     if(reserved_keys[i]==k) keys.push_back( reserved_keys[i] );
     165             :   }
     166       11514 : }
     167             : 
     168        1826 : void Keywords::reset_style( const std::string & k, const std::string & style ) {
     169        1826 :   plumed_assert( exists(k) || reserved(k) );
     170        1826 :   (types.find(k)->second).setStyle(style);
     171        1826 :   if( (types.find(k)->second).isVessel() ) allowmultiple[k]=true;
     172        1826 :   if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,style) );
     173        1826 : }
     174             : 
     175      186259 : void Keywords::add( const std::string & t, const std::string & k, const std::string & d ) {
     176      186259 :   plumed_massert( !exists(k) && t!="flag" && !reserved(k) && t!="vessel", "keyword " + k + " has already been registered");
     177      186259 :   std::string fd;
     178      186259 :   if( t=="numbered" ) {
     179        1071 :     fd=d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3...";
     180        1071 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     181        1071 :     types.insert( std::pair<std::string,KeyType>(k, KeyType("optional")) );
     182             :   } else {
     183      185188 :     fd=d;
     184      185188 :     allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     185      185188 :     types.insert( std::pair<std::string,KeyType>(k,KeyType(t)) );
     186      185188 :     if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,t) );
     187             :   }
     188      186259 :   if( t=="atoms" && isaction ) fd = d + ".  For more information on how to specify lists of atoms see \\ref Group";
     189      186259 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     190      186259 :   keys.push_back(k);
     191      186259 : }
     192             : 
     193       81961 : void Keywords::add( const std::string & t, const std::string & k, const std::string &  def, const std::string & d ) {
     194       81961 :   plumed_assert( !exists(k) && !reserved(k) &&  (t=="compulsory" || t=="hidden" )); // An optional keyword can't have a default
     195       81961 :   types.insert(  std::pair<std::string,KeyType>(k, KeyType(t)) );
     196       81961 :   documentation.insert( std::pair<std::string,std::string>(k,"( default=" + def + " ) " + d) );
     197       81961 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     198       81961 :   numdefs.insert( std::pair<std::string,std::string>(k,def) );
     199       81961 :   keys.push_back(k);
     200       81961 : }
     201             : 
     202       63723 : void Keywords::addFlag( const std::string & k, const bool def, const std::string & d ) {
     203       63723 :   plumed_massert( !exists(k) && !reserved(k), "keyword " + k + " has already been registered");
     204       63723 :   std::string defstr;
     205       63723 :   if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; }
     206       63723 :   types.insert( std::pair<std::string,KeyType>(k,KeyType("flag")) );
     207       63723 :   documentation.insert( std::pair<std::string,std::string>(k,defstr + d) );
     208       63723 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     209       63723 :   booldefs.insert( std::pair<std::string,bool>(k,def) );
     210       63723 :   keys.push_back(k);
     211       63723 : }
     212             : 
     213         861 : void Keywords::remove( const std::string & k ) {
     214         861 :   bool found=false; unsigned j=0, n=0;
     215             : 
     216             :   while(true) {
     217        1722 :     for(j=0; j<keys.size(); j++) if(keys[j]==k)break;
     218        1722 :     for(n=0; n<reserved_keys.size(); n++) if(reserved_keys[n]==k)break;
     219        1722 :     if(j<keys.size()) {
     220         857 :       keys.erase(keys.begin()+j);
     221         857 :       found=true;
     222         865 :     } else if(n<reserved_keys.size()) {
     223           4 :       reserved_keys.erase(reserved_keys.begin()+n);
     224           4 :       found=true;
     225         861 :     } else break;
     226             :   }
     227             :   // Delete documentation, type and so on from the description
     228         861 :   types.erase(k); documentation.erase(k); allowmultiple.erase(k); booldefs.erase(k); numdefs.erase(k);
     229        1722 :   plumed_massert(found,"You are trying to forbid " + k + " a keyword that isn't there"); // You have tried to forbid a keyword that isn't there
     230         861 : }
     231             : 
     232        6310 : bool Keywords::numbered( const std::string & k ) const {
     233        6310 :   if( style( k,"atoms") ) return true;
     234        4715 :   plumed_massert( allowmultiple.count(k), "Did not find keyword " + k );
     235        4715 :   return allowmultiple.find(k)->second;
     236             : }
     237             : 
     238      405423 : bool Keywords::style( const std::string & k, const std::string & t ) const {
     239      405423 :   plumed_massert( types.count(k), "Did not find keyword " + k );
     240             : 
     241      405423 :   if( (types.find(k)->second).toString()==t ) return true;
     242      321394 :   return false;
     243             : }
     244             : 
     245      521001 : unsigned Keywords::size() const {
     246      521001 :   return keys.size();
     247             : }
     248             : 
     249        8229 : std::string Keywords::getKeyword( const unsigned i ) const {
     250        8229 :   plumed_assert( i<size() );
     251        8229 :   return keys[i];
     252             : }
     253             : 
     254      507673 : bool Keywords::exists( const std::string & k ) const {
     255     5488059 :   for(unsigned i=0; i<keys.size(); ++i) {
     256     5084822 :     if( keys[i]==k ) return true;
     257             :   }
     258      403237 :   return false;
     259             : }
     260             : 
     261      397846 : bool Keywords::reserved( const std::string & k ) const {
     262     1062649 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
     263      678045 :     if( reserved_keys[i]==k ) return true;
     264             :   }
     265      384604 :   return false;
     266             : }
     267             : 
     268           0 : void Keywords::print_template(const std::string& actionname, bool include_optional) const {
     269           0 :   unsigned nkeys=0;
     270           0 :   printf("%s",actionname.c_str());
     271           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     272           0 :     if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
     273             :   }
     274           0 :   if( nkeys>0 ) {
     275           0 :     std::string prevtag="start";
     276           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     277           0 :       if( (types.find(keys[i])->second).isAtomList() ) {
     278           0 :         plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello");
     279           0 :         if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second ) break;
     280           0 :         if( (atomtags.find(keys[i])->second).find("residues")!=std::string::npos) printf(" %s=<residue selection>", keys[i].c_str() );
     281           0 :         else printf(" %s=<atom selection>", keys[i].c_str() );
     282           0 :         prevtag=atomtags.find(keys[i])->second;
     283             :       }
     284           0 :     }
     285             :   }
     286           0 :   nkeys=0;
     287           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     288           0 :     if ( include_optional || \
     289           0 :          (types.find(keys[i])->second).isCompulsory() ) nkeys++;
     290             :   }
     291           0 :   if( nkeys>0 ) {
     292           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     293           0 :       if ( (types.find(keys[i])->second).isCompulsory() ) {
     294           0 :         std::string def;
     295           0 :         if( getDefaultValue( keys[i], def) ) {
     296           0 :           printf(" %s=%s ", keys[i].c_str(), def.c_str() );
     297             :         } else {
     298           0 :           printf(" %s=    ", keys[i].c_str() );
     299           0 :         }
     300           0 :       } else if (include_optional) {
     301             :         // TG no defaults for optional keywords?
     302           0 :         printf(" [%s]", keys[i].c_str() );
     303             :       }
     304             :     }
     305             :   }
     306           0 :   printf("\n");
     307           0 : }
     308             : 
     309         223 : void Keywords::print_vim() const {
     310        3381 :   for(unsigned i=0; i<keys.size(); ++i) {
     311        3158 :     if( (types.find(keys[i])->second).isFlag() ) {
     312         717 :       printf( ",flag:%s", keys[i].c_str() );
     313             :     } else {
     314        2441 :       if( allowmultiple.find(keys[i])->second ) printf(",numbered:%s",keys[i].c_str() );
     315        1830 :       else printf(",option:%s",keys[i].c_str() );
     316             :     }
     317             :   }
     318         223 :   fprintf(stdout,"\n");
     319         223 :   print(stdout);
     320         223 : }
     321             : 
     322           0 : void Keywords::print_html() const {
     323             : 
     324             : // This is the part that outputs the details of the components
     325           0 :   if( cnames.size()>0 ) {
     326           0 :     unsigned ndef=0;
     327           0 :     for(unsigned i=0; i<cnames.size(); ++i) {
     328           0 :       if(ckey.find(cnames[i])->second=="default") ndef++;
     329             :     }
     330             : 
     331           0 :     if( ndef>0 ) {
     332           0 :       std::cout<<"\\par Description of components\n\n";
     333           0 :       std::cout<<cstring<<"\n\n";
     334           0 :       std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     335           0 :       printf("<tr> <td width=5%%> <b> Quantity </b> </td> <td> <b> Description </b> </td> </tr>\n");
     336           0 :       unsigned nndef=0;
     337           0 :       for(unsigned i=0; i<cnames.size(); ++i) {
     338             :         //plumed_assert( ckey.find(cnames[i])->second=="default" );
     339           0 :         if( ckey.find(cnames[i])->second!="default" ) { nndef++; continue; }
     340           0 :         printf("<tr>\n");
     341           0 :         printf("<td width=15%%> <b> %s </b></td>\n",cnames[i].c_str() );
     342           0 :         printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
     343           0 :         printf("</tr>\n");
     344             :       }
     345           0 :       std::cout<<"</table>\n\n";
     346           0 :       if( nndef>0 ) {
     347           0 :         std::cout<<"In addition the following quantities can be calculated by employing the keywords listed below"<<std::endl;
     348           0 :         std::cout<<"\n\n";
     349           0 :         std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     350           0 :         printf("<tr> <td width=5%%> <b> Quantity </b> </td> <td> <b> Keyword </b> </td> <td> <b> Description </b> </td> </tr>\n");
     351           0 :         for(unsigned i=0; i<cnames.size(); ++i) {
     352           0 :           if( ckey.find(cnames[i])->second!="default") {
     353           0 :             printf("<tr>\n");
     354             :             printf("<td width=5%%> <b> %s </b></td> <td width=10%%> <b> %s </b> </td> \n",
     355           0 :                    cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() );
     356           0 :             printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
     357           0 :             printf("</tr>\n");
     358             :           }
     359             :         }
     360           0 :         std::cout<<"</table>\n\n";
     361             :       }
     362             :     } else {
     363           0 :       unsigned nregs=0;
     364           0 :       for(unsigned i=0; i<cnames.size(); ++i) {
     365           0 :         if( exists(ckey.find(cnames[i])->second) ) nregs++;
     366             :       }
     367           0 :       if( nregs>0 ) {
     368           0 :         std::cout<<"\\par Description of components\n\n";
     369           0 :         std::cout<<cstring<<"\n\n";
     370           0 :         std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     371           0 :         printf("<tr> <td width=5%%> <b> Quantity </b> </td> <td> <b> Keyword </b> </td> <td> <b> Description </b> </td> </tr>\n");
     372           0 :         for(unsigned i=0; i<cnames.size(); ++i) {
     373           0 :           if( exists(ckey.find(cnames[i])->second) ) {
     374           0 :             printf("<tr>\n");
     375             :             printf("<td width=5%%> <b> %s </b></td> <td width=10%%> <b> %s </b> </td> \n",
     376           0 :                    cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() );
     377           0 :             printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
     378           0 :             printf("</tr>\n");
     379             :           }
     380             :         }
     381           0 :         std::cout<<"</table>\n\n";
     382             :       }
     383             :     }
     384             :   }
     385             : 
     386           0 :   unsigned nkeys=0;
     387           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     388           0 :     if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
     389             :   }
     390           0 :   if( nkeys>0 ) {
     391           0 :     if(isaction) std::cout<<"\\par The atoms involved can be specified using\n\n";
     392           0 :     else std::cout<<"\\par The input trajectory is specified using one of the following\n\n";
     393           0 :     std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     394           0 :     std::string prevtag="start";
     395           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     396           0 :       if ( (types.find(keys[i])->second).isAtomList() ) {
     397           0 :         plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello");
     398           0 :         if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second && isaction ) {
     399           0 :           std::cout<<"</table>\n\n";
     400           0 :           std::cout<<"\\par Or alternatively by using\n\n";
     401           0 :           std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     402             :         }
     403           0 :         print_html_item( keys[i] );
     404           0 :         prevtag=atomtags.find(keys[i])->second;
     405             :       }
     406             :     }
     407           0 :     std::cout<<"</table>\n\n";
     408             :   }
     409           0 :   nkeys=0;
     410           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     411           0 :     if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
     412             :   }
     413           0 :   if( nkeys>0 ) {
     414           0 :     if(isaction) std::cout<< "\\par Compulsory keywords\n\n";
     415           0 :     else std::cout<<"\\par The following must be present\n\n";
     416           0 :     std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     417           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     418           0 :       if ( (types.find(keys[i])->second).isCompulsory() ) print_html_item( keys[i] );
     419             :     }
     420           0 :     std::cout<<"</table>\n\n";
     421             :   }
     422           0 :   nkeys=0;
     423           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     424           0 :     if ( (types.find(keys[i])->second).isFlag() || (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++;
     425             :   }
     426           0 :   if( nkeys>0 ) {
     427           0 :     if(isaction) std::cout<<"\\par Options\n\n";
     428           0 :     else std::cout<<"\\par The following options are available\n\n";
     429           0 :     std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     430           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     431           0 :       if ( (types.find(keys[i])->second).isFlag() ) print_html_item( keys[i] );
     432             :     }
     433           0 :     std::cout<<"\n";
     434             :   }
     435           0 :   nkeys=0;
     436           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     437           0 :     if ( (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++;
     438             :   }
     439           0 :   if( nkeys>0 ) {
     440           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     441           0 :       if ( (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) print_html_item( keys[i] );
     442             :     }
     443           0 :     std::cout<<"\n";
     444             :   }
     445           0 :   std::cout<<"</table>\n\n";
     446           0 : }
     447             : 
     448         223 : void Keywords::print( FILE* out ) const {
     449         223 :   unsigned nkeys=0;
     450        3381 :   for(unsigned i=0; i<keys.size(); ++i) {
     451        3158 :     if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
     452             :   }
     453         223 :   if( nkeys>0 ) {
     454          95 :     fprintf(out,"The input trajectory can be in any of the following formats: \n\n");
     455        1904 :     for(unsigned i=0; i<keys.size(); ++i) {
     456        1809 :       if ( (types.find(keys[i])->second).isAtomList() ) printKeyword( keys[i], out );
     457             :     }
     458             :   }
     459         223 :   nkeys=0;
     460        3381 :   for(unsigned i=0; i<keys.size(); ++i) {
     461        3158 :     if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
     462             :   }
     463         223 :   unsigned ncompulsory=nkeys;
     464         223 :   if( nkeys>0 ) {
     465         166 :     fprintf(out,"\nThe following arguments are compulsory: \n\n");
     466        2620 :     for(unsigned i=0; i<keys.size(); ++i) {
     467        2454 :       if ( (types.find(keys[i])->second).isCompulsory() ) printKeyword( keys[i], out );   //log.printKeyword( keys[i], documentation[i] );
     468             :     }
     469             :   }
     470         223 :   nkeys=0;
     471        3381 :   for(unsigned i=0; i<keys.size(); ++i) {
     472        3158 :     if ( (types.find(keys[i])->second).isFlag() ) nkeys++;
     473             :   }
     474         223 :   if( nkeys>0 ) {
     475         192 :     if(ncompulsory>0) fprintf( out,"\nIn addition you may use the following options: \n\n");
     476          52 :     else fprintf( out,"\nThe following options are available\n\n");
     477        3214 :     for(unsigned i=0; i<keys.size(); ++i) {
     478        3022 :       if ( (types.find(keys[i])->second).isFlag() ) printKeyword( keys[i], out );   //log.printKeyword( keys[i], documentation[i] );
     479             :     }
     480             :   }
     481         223 :   nkeys=0;
     482        3381 :   for(unsigned i=0; i<keys.size(); ++i) {
     483        3158 :     if ( (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++;
     484             :   }
     485         223 :   if( nkeys>0 ) {
     486        2960 :     for(unsigned i=0; i<keys.size(); ++i) {
     487        2795 :       if ( (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) printKeyword( keys[i], out );   //log.printKeyword( keys[i], documentation[i] );
     488             :     }
     489         165 :     fprintf(out,"\n");
     490             :   }
     491         223 : }
     492             : 
     493        2638 : void Keywords::printKeyword( const std::string& key, FILE* out ) const {
     494        2638 :   bool killdot=( (documentation.find(key)->second).find("\\f$")!=std::string::npos ); // Check for latex
     495        2638 :   std::vector<std::string> w=Tools::getWords( documentation.find(key)->second );
     496        2638 :   fprintf(out,"%23s - ", key.c_str() );
     497        5276 :   unsigned nl=0; std::string blank=" ";
     498       57417 :   for(unsigned i=0; i<w.size(); ++i) {
     499       55035 :     nl+=w[i].length() + 1;
     500       55035 :     if( nl>60 ) {
     501        4350 :       fprintf(out,"\n%23s   %s ", blank.c_str(), w[i].c_str() ); nl=0;
     502             :     } else {
     503       50685 :       fprintf(out,"%s ", w[i].c_str() );
     504             :     }
     505       55035 :     if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot
     506             :   }
     507        5276 :   fprintf(out,"\n");
     508        2638 : }
     509             : 
     510           0 : void Keywords::print( Log& log ) const {
     511           0 :   unsigned nkeys=0;
     512           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     513           0 :     if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
     514             :   }
     515           0 :   if (nkeys>0 ) {
     516           0 :     log.printf( "The input for this keyword can be specified using one of the following \n\n");
     517           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     518           0 :       if ( (types.find(keys[i])->second).isAtomList() ) printKeyword( keys[i], log );   //log.printKeyword( keys[i], documentation[i] );
     519             :     }
     520             :   }
     521           0 :   nkeys=0;
     522           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     523           0 :     if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
     524             :   }
     525           0 :   if( nkeys>0 ) {
     526           0 :     log.printf( "\n The compulsory keywords for this action are: \n\n");
     527           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     528           0 :       if ( (types.find(keys[i])->second).isCompulsory() ) printKeyword( keys[i], log );   //log.printKeyword( keys[i], documentation[i] );
     529             :     }
     530             :   }
     531           0 :   nkeys=0;
     532           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     533           0 :     if ( (types.find(keys[i])->second).isFlag() ) nkeys++;
     534             :   }
     535           0 :   if( nkeys>0 ) {
     536           0 :     log.printf( "\n The following options are available: \n\n");
     537           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     538           0 :       if ( (types.find(keys[i])->second).isFlag() ) printKeyword( keys[i], log );   //log.printKeyword( keys[i], documentation[i] );
     539             :     }
     540           0 :     log.printf("\n");
     541             :   }
     542           0 :   nkeys=0;
     543           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     544           0 :     if ( (types.find(keys[i])->second).isOptional() ) nkeys++;
     545             :   }
     546           0 :   if( nkeys>0 ) {
     547           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     548           0 :       if ( (types.find(keys[i])->second).isOptional() ) printKeyword( keys[i], log );   //log.printKeyword( keys[i], documentation[i] );
     549             :     }
     550           0 :     log.printf("\n");
     551             :   }
     552           0 : }
     553             : 
     554           0 : void Keywords::printKeyword( const std::string& key, Log& log ) const {
     555           0 :   bool killdot=( (documentation.find(key)->second).find("\\f$")!=std::string::npos ); // Check for latex
     556           0 :   std::vector<std::string> w=Tools::getWords( documentation.find(key)->second );
     557           0 :   log.printf("%23s - ", key.c_str() );
     558           0 :   unsigned nl=0; std::string blank=" ";
     559           0 :   for(unsigned i=0; i<w.size(); ++i) {
     560           0 :     nl+=w[i].length() + 1;
     561           0 :     if( nl>60 ) {
     562           0 :       log.printf("\n%23s   %s ", blank.c_str(), w[i].c_str() ); nl=0;
     563             :     } else {
     564           0 :       log.printf("%s ", w[i].c_str() );
     565             :     }
     566           0 :     if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot
     567             :   }
     568           0 :   log.printf("\n");
     569           0 : }
     570             : 
     571           0 : void Keywords::print_html_item( const std::string& key ) const {
     572           0 :   printf("<tr>\n");
     573           0 :   printf("<td width=15%%> <b> %s </b></td>\n",key.c_str() );
     574           0 :   printf("<td> %s </td>\n",(documentation.find(key)->second).c_str() );
     575           0 :   printf("</tr>\n");
     576           0 : }
     577             : 
     578      244663 : std::string Keywords::get( const unsigned k ) const {
     579      244663 :   plumed_assert( k<size() );
     580      244663 :   return keys[k];
     581             : }
     582             : 
     583       10796 : bool Keywords::getLogicalDefault( std::string key, bool& def ) const {
     584       10796 :   if( booldefs.find(key)!=booldefs.end() ) {
     585       10796 :     def=booldefs.find(key)->second;
     586       10796 :     return true;
     587             :   } else {
     588           0 :     return false;
     589             :   }
     590             : }
     591             : 
     592        7370 : bool Keywords::getDefaultValue( std::string key, std::string& def ) const {
     593        7370 :   plumed_assert( style(key,"compulsory") || style(key,"hidden") );
     594             : 
     595        7370 :   if( numdefs.find(key)!=numdefs.end() ) {
     596        3466 :     def=numdefs.find(key)->second;
     597        3466 :     return true;
     598             :   } else {
     599        3904 :     return false;
     600             :   }
     601             : }
     602             : 
     603        5772 : void Keywords::destroyData() {
     604        5772 :   keys.clear(); reserved_keys.clear(); types.clear();
     605        5772 :   allowmultiple.clear(); documentation.clear();
     606        5772 :   booldefs.clear(); numdefs.clear(); atomtags.clear();
     607        5772 :   ckey.clear(); cdocs.clear(); ckey.clear();
     608        5772 : }
     609             : 
     610        4906 : void Keywords::setComponentsIntroduction( const std::string& instr ) {
     611        4906 :   cstring = instr;
     612        4906 : }
     613             : 
     614       35963 : void Keywords::addOutputComponent( const std::string& name, const std::string& key, const std::string& descr ) {
     615       35963 :   plumed_assert( !outputComponentExists( name, false ) );
     616       35963 :   plumed_massert( name.find("-")==std::string::npos,"dash is reseved character in component names" );
     617             : 
     618       35963 :   std::size_t num2=name.find_first_of("_");
     619       35963 :   if( num2!=std::string::npos ) plumed_massert( num2==0, "underscore is reserved character in component names that has special meaning");
     620             : 
     621       35963 :   ckey.insert( std::pair<std::string,std::string>(name,key) );
     622       35963 :   cdocs.insert( std::pair<std::string,std::string>(name,descr) );
     623       35963 :   cnames.push_back(name);
     624       35963 : }
     625             : 
     626       68723 : bool Keywords::outputComponentExists( const std::string& name, const bool& custom ) const {
     627       68723 :   if( custom && cstring.find("customizable")!=std::string::npos ) return true;
     628             : 
     629       39489 :   std::string sname; std::size_t num=name.find_first_of("-");
     630       39489 :   if( num!=std::string::npos ) sname=name.substr(0,num);
     631             :   else {
     632       39427 :     std::size_t num2=name.find_first_of("_");
     633       39427 :     if( num2!=std::string::npos ) sname=name.substr(num2);
     634       37693 :     else sname=name;
     635             :   }
     636             : 
     637      319304 :   for(unsigned i=0; i<cnames.size(); ++i) {
     638      283196 :     if( sname==cnames[i] ) return true;
     639             :   }
     640       36108 :   return false;
     641             : }
     642             : 
     643        4821 : }

Generated by: LCOV version 1.13