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: 2018-12-19 07:49:13 Functions: 30 35 85.7 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-2018 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      150805 : Keywords::KeyType::KeyType( const std::string& type ) {
      30      150805 :   if( type=="compulsory" ) {
      31       27176 :     style=compulsory;
      32      123629 :   } else if( type=="flag" ) {
      33       29604 :     style=flag;
      34       94025 :   } else if( type=="optional" ) {
      35       43410 :     style=optional;
      36       50615 :   } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) {
      37       24460 :     style=atoms;
      38       26155 :   } else if( type=="hidden" ) {
      39       12699 :     style=hidden;
      40       13456 :   } else if( type=="vessel" ) {
      41       13456 :     style=vessel;
      42             :   } else {
      43           0 :     plumed_massert(false,"invalid keyword specifier " + type);
      44             :   }
      45      150805 : }
      46             : 
      47        1057 : void Keywords::KeyType::setStyle( const std::string& type ) {
      48        1057 :   if( type=="compulsory" ) {
      49          33 :     style=compulsory;
      50        1024 :   } else if( type=="flag" ) {
      51           0 :     style=flag;
      52        1024 :   } else if( type=="optional" ) {
      53           7 :     style=optional;
      54        1017 :   } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) {
      55         176 :     style=atoms;
      56         841 :   } else if( type=="hidden" ) {
      57           0 :     style=hidden;
      58         841 :   } else if( type=="vessel" ) {
      59         841 :     style=vessel;
      60             :   } else {
      61           0 :     plumed_massert(false,"invalid keyword specifier " + type);
      62             :   }
      63        1057 : }
      64             : 
      65         414 : void Keywords::add( const Keywords& newkeys ) {
      66         414 :   newkeys.copyData( keys, reserved_keys, types, allowmultiple, documentation, booldefs, numdefs, atomtags, cnames, ckey, cdocs  );
      67         414 : }
      68             : 
      69         414 : 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         414 :   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        7452 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
      89        7038 :     std::string thiskey=reserved_keys[i];
      90        7038 :     for(unsigned j=0; j<kk.size(); ++j) plumed_massert( thiskey!=kk[j], "keyword " + thiskey + " is in twice" );
      91        7038 :     for(unsigned j=0; j<rk.size(); ++j) plumed_massert( thiskey!=rk[j], "keyword " + thiskey + " is in twice" );
      92        7038 :     rk.push_back( thiskey );
      93        7038 :     plumed_massert( types.count( thiskey ), "no type data on keyword " + thiskey + " to copy" );
      94        7038 :     tt.insert( std::pair<std::string,KeyType>( thiskey,types.find(thiskey)->second) );
      95        7038 :     if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair<std::string,std::string>( thiskey,atomtags.find(thiskey)->second) );
      96        7038 :     plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" );
      97        7038 :     am.insert( std::pair<std::string,bool>(thiskey,allowmultiple.find(thiskey)->second) );
      98        7038 :     plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" );
      99        7038 :     docs.insert( std::pair<std::string,std::string>(thiskey,documentation.find(thiskey)->second) );
     100        7038 :     if( booldefs.count( thiskey ) ) bools.insert( std::pair<std::string,bool>( thiskey,booldefs.find(thiskey)->second) );
     101        7038 :     if( numdefs.count( thiskey ) ) nums.insert( std::pair<std::string,std::string>( thiskey,numdefs.find(thiskey)->second) );
     102        7038 :   }
     103        7038 :   for(unsigned i=0; i<cnames.size(); ++i) {
     104        6624 :     std::string thisnam=cnames[i];
     105        6624 :     for(unsigned j=0; j<cnam.size(); ++j) plumed_massert( thisnam!=cnam[j], "component " + thisnam + " is in twice" );
     106        6624 :     cnam.push_back( thisnam );
     107        6624 :     plumed_massert( ckey.count( thisnam ), "no keyword data on component " + thisnam + " to copy" );
     108        6624 :     ck.insert( std::pair<std::string,std::string>( thisnam, ckey.find(thisnam)->second) );
     109        6624 :     plumed_massert( cdocs.count( thisnam ), "no documentation on component " + thisnam + " to copy" );
     110        6624 :     cd.insert( std::pair<std::string,std::string>( thisnam, cdocs.find(thisnam)->second) );
     111        6624 :   }
     112         414 : }
     113             : 
     114       24110 : void Keywords::reserve( const std::string & t, const std::string & k, const std::string & d ) {
     115       24110 :   plumed_assert( !exists(k) && !reserved(k) );
     116       48220 :   std::string fd, lowkey=k;
     117             :   // Convert to lower case
     118       24110 :   std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
     119             : // Remove any underscore characters
     120       31675 :   for(unsigned i=0;; ++i) {
     121       31675 :     std::size_t num=lowkey.find_first_of("_");
     122       31675 :     if( num==std::string::npos ) break;
     123        7565 :     lowkey.erase( lowkey.begin() + num, lowkey.begin() + num + 1 );
     124        7565 :   }
     125       24110 :   if( t=="vessel" ) {
     126       13456 :     fd = d + " The final value can be referenced using <em>label</em>." + lowkey;
     127       25230 :     if(d.find("flag")==std::string::npos) fd += ".  You can use multiple instances of this keyword i.e. " +
     128       23548 :           k +"1, " + k + "2, " + k + "3...  The corresponding values are then "
     129       23548 :           "referenced using <em>label</em>."+ lowkey +"-1,  <em>label</em>." + lowkey +
     130       11774 :           "-2,  <em>label</em>." + lowkey + "-3...";
     131       13456 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     132       13456 :     types.insert( std::pair<std::string,KeyType>(k,KeyType("vessel")) );
     133       10654 :   } else if( t=="numbered" ) {
     134        1108 :     fd = d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3...";
     135        1108 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     136        1108 :     types.insert( std::pair<std::string,KeyType>(k,KeyType("optional")) );
     137             :   } else {
     138        9546 :     fd = d;
     139        9546 :     if( t=="atoms" && isaction ) fd = d + ".  For more information on how to specify lists of atoms see \\ref Group";
     140        9546 :     allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     141        9546 :     types.insert( std::pair<std::string,KeyType>(k,KeyType(t)) );
     142        9546 :     if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,t) );
     143             :   }
     144       24110 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     145       48220 :   reserved_keys.push_back(k);
     146       24110 : }
     147             : 
     148         414 : void Keywords::reserveFlag( const std::string & k, const bool def, const std::string & d ) {
     149         414 :   plumed_assert( !exists(k) && !reserved(k) );
     150         414 :   std::string defstr;
     151         414 :   if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; }
     152         414 :   types.insert( std::pair<std::string,KeyType>(k,KeyType("flag")) );
     153         828 :   std::string fd,lowkey=k; std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
     154         414 :   fd=defstr + d;
     155         414 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     156         414 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     157         414 :   booldefs.insert( std::pair<std::string,bool>(k,def) );
     158         828 :   reserved_keys.push_back(k);
     159         414 : }
     160             : 
     161        5919 : void Keywords::use( const std::string & k ) {
     162        5919 :   plumed_massert( reserved(k), "the " + k + " keyword is not reserved");
     163       88640 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
     164       82721 :     if(reserved_keys[i]==k) keys.push_back( reserved_keys[i] );
     165             :   }
     166        5919 : }
     167             : 
     168        1057 : void Keywords::reset_style( const std::string & k, const std::string & style ) {
     169        1057 :   plumed_assert( exists(k) || reserved(k) );
     170        1057 :   (types.find(k)->second).setStyle(style);
     171        1057 :   if( (types.find(k)->second).isVessel() ) allowmultiple[k]=true;
     172        1057 :   if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,style) );
     173        1057 : }
     174             : 
     175       76688 : void Keywords::add( const std::string & t, const std::string & k, const std::string & d ) {
     176       76688 :   plumed_massert( !exists(k) && t!="flag" && !reserved(k) && t!="vessel", "keyword " + k + " has already been registered");
     177       76688 :   std::string fd;
     178       76688 :   if( t=="numbered" ) {
     179         166 :     fd=d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3...";
     180         166 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     181         166 :     types.insert( std::pair<std::string,KeyType>(k, KeyType("optional")) );
     182             :   } else {
     183       76522 :     fd=d;
     184       76522 :     allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     185       76522 :     types.insert( std::pair<std::string,KeyType>(k,KeyType(t)) );
     186       76522 :     if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,t) );
     187             :   }
     188       76688 :   if( t=="atoms" && isaction ) fd = d + ".  For more information on how to specify lists of atoms see \\ref Group";
     189       76688 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     190       76688 :   keys.push_back(k);
     191       76688 : }
     192             : 
     193       20403 : void Keywords::add( const std::string & t, const std::string & k, const std::string &  def, const std::string & d ) {
     194       20403 :   plumed_assert( !exists(k) && !reserved(k) &&  (t=="compulsory" || t=="hidden" )); // An optional keyword can't have a default
     195       20403 :   types.insert(  std::pair<std::string,KeyType>(k, KeyType(t)) );
     196       20403 :   documentation.insert( std::pair<std::string,std::string>(k,"( default=" + def + " ) " + d) );
     197       20403 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     198       20403 :   numdefs.insert( std::pair<std::string,std::string>(k,def) );
     199       20403 :   keys.push_back(k);
     200       20403 : }
     201             : 
     202       29190 : void Keywords::addFlag( const std::string & k, const bool def, const std::string & d ) {
     203       29190 :   plumed_massert( !exists(k) && !reserved(k), "keyword " + k + " has already been registered");
     204       29190 :   std::string defstr;
     205       29190 :   if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; }
     206       29190 :   types.insert( std::pair<std::string,KeyType>(k,KeyType("flag")) );
     207       29190 :   documentation.insert( std::pair<std::string,std::string>(k,defstr + d) );
     208       29190 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     209       29190 :   booldefs.insert( std::pair<std::string,bool>(k,def) );
     210       29190 :   keys.push_back(k);
     211       29190 : }
     212             : 
     213         545 : void Keywords::remove( const std::string & k ) {
     214         545 :   bool found=false; unsigned j=0, n=0;
     215             : 
     216             :   while(true) {
     217        1090 :     for(j=0; j<keys.size(); j++) if(keys[j]==k)break;
     218        1090 :     for(n=0; n<reserved_keys.size(); n++) if(reserved_keys[n]==k)break;
     219        1090 :     if(j<keys.size()) {
     220         541 :       keys.erase(keys.begin()+j);
     221         541 :       found=true;
     222         549 :     } else if(n<reserved_keys.size()) {
     223           4 :       reserved_keys.erase(reserved_keys.begin()+n);
     224           4 :       found=true;
     225         545 :     } else break;
     226             :   }
     227             :   // Delete documentation, type and so on from the description
     228         545 :   types.erase(k); documentation.erase(k); allowmultiple.erase(k); booldefs.erase(k); numdefs.erase(k);
     229        1090 :   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         545 : }
     231             : 
     232        4140 : bool Keywords::numbered( const std::string & k ) const {
     233        4140 :   if( style( k,"atoms") ) return true;
     234        2712 :   plumed_massert( allowmultiple.count(k), "Did not find keyword " + k );
     235        2712 :   return allowmultiple.find(k)->second;
     236             : }
     237             : 
     238      217123 : bool Keywords::style( const std::string & k, const std::string & t ) const {
     239      217123 :   plumed_massert( types.count(k), "Did not find keyword " + k );
     240             : 
     241      217123 :   if( (types.find(k)->second).toString()==t ) return true;
     242      168692 :   return false;
     243             : }
     244             : 
     245      275146 : unsigned Keywords::size() const {
     246      275146 :   return keys.size();
     247             : }
     248             : 
     249        6798 : std::string Keywords::getKeyword( const unsigned i ) const {
     250        6798 :   plumed_assert( i<size() );
     251        6798 :   return keys[i];
     252             : }
     253             : 
     254      211079 : bool Keywords::exists( const std::string & k ) const {
     255     2265339 :   for(unsigned i=0; i<keys.size(); ++i) {
     256     2106299 :     if( keys[i]==k ) return true;
     257             :   }
     258      159040 :   return false;
     259             : }
     260             : 
     261      157786 : bool Keywords::reserved( const std::string & k ) const {
     262      489603 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
     263      338798 :     if( reserved_keys[i]==k ) return true;
     264             :   }
     265      150805 :   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         160 : void Keywords::print_vim() const {
     310        2190 :   for(unsigned i=0; i<keys.size(); ++i) {
     311        2030 :     if( (types.find(keys[i])->second).isFlag() ) {
     312         493 :       printf( ",flag:%s", keys[i].c_str() );
     313             :     } else {
     314        1537 :       if( allowmultiple.find(keys[i])->second ) printf(",numbered:%s",keys[i].c_str() );
     315        1105 :       else printf(",option:%s",keys[i].c_str() );
     316             :     }
     317             :   }
     318         160 :   fprintf(stdout,"\n");
     319         160 :   print(stdout);
     320         160 : }
     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         160 : void Keywords::print( FILE* out ) const {
     449         160 :   unsigned nkeys=0;
     450        2190 :   for(unsigned i=0; i<keys.size(); ++i) {
     451        2030 :     if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
     452             :   }
     453         160 :   if( nkeys>0 ) {
     454          78 :     fprintf(out,"The input trajectory can be in any of the following formats: \n\n");
     455        1287 :     for(unsigned i=0; i<keys.size(); ++i) {
     456        1209 :       if ( (types.find(keys[i])->second).isAtomList() ) printKeyword( keys[i], out );
     457             :     }
     458             :   }
     459         160 :   nkeys=0;
     460        2190 :   for(unsigned i=0; i<keys.size(); ++i) {
     461        2030 :     if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
     462             :   }
     463         160 :   unsigned ncompulsory=nkeys;
     464         160 :   if( nkeys>0 ) {
     465         118 :     fprintf(out,"\nThe following arguments are compulsory: \n\n");
     466        1690 :     for(unsigned i=0; i<keys.size(); ++i) {
     467        1572 :       if ( (types.find(keys[i])->second).isCompulsory() ) printKeyword( keys[i], out );   //log.printKeyword( keys[i], documentation[i] );
     468             :     }
     469             :   }
     470         160 :   nkeys=0;
     471        2190 :   for(unsigned i=0; i<keys.size(); ++i) {
     472        2030 :     if ( (types.find(keys[i])->second).isFlag() ) nkeys++;
     473             :   }
     474         160 :   if( nkeys>0 ) {
     475         135 :     if(ncompulsory>0) fprintf( out,"\nIn addition you may use the following options: \n\n");
     476          39 :     else fprintf( out,"\nThe following options are available\n\n");
     477        2050 :     for(unsigned i=0; i<keys.size(); ++i) {
     478        1915 :       if ( (types.find(keys[i])->second).isFlag() ) printKeyword( keys[i], out );   //log.printKeyword( keys[i], documentation[i] );
     479             :     }
     480             :   }
     481         160 :   nkeys=0;
     482        2190 :   for(unsigned i=0; i<keys.size(); ++i) {
     483        2030 :     if ( (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++;
     484             :   }
     485         160 :   if( nkeys>0 ) {
     486        1854 :     for(unsigned i=0; i<keys.size(); ++i) {
     487        1740 :       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         114 :     fprintf(out,"\n");
     490             :   }
     491         160 : }
     492             : 
     493        1654 : void Keywords::printKeyword( const std::string& key, FILE* out ) const {
     494        1654 :   bool killdot=( (documentation.find(key)->second).find("\\f$")!=std::string::npos ); // Check for latex
     495        1654 :   std::vector<std::string> w=Tools::getWords( documentation.find(key)->second );
     496        1654 :   fprintf(out,"%23s - ", key.c_str() );
     497        3308 :   unsigned nl=0; std::string blank=" ";
     498       37719 :   for(unsigned i=0; i<w.size(); ++i) {
     499       36240 :     nl+=w[i].length() + 1;
     500       36240 :     if( nl>60 ) {
     501        2914 :       fprintf(out,"\n%23s   %s ", blank.c_str(), w[i].c_str() ); nl=0;
     502             :     } else {
     503       33326 :       fprintf(out,"%s ", w[i].c_str() );
     504             :     }
     505       36240 :     if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot
     506             :   }
     507        3308 :   fprintf(out,"\n");
     508        1654 : }
     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      126710 : std::string Keywords::get( const unsigned k ) const {
     579      126710 :   plumed_assert( k<size() );
     580      126710 :   return keys[k];
     581             : }
     582             : 
     583        5322 : bool Keywords::getLogicalDefault( std::string key, bool& def ) const {
     584        5322 :   if( booldefs.find(key)!=booldefs.end() ) {
     585        5322 :     def=booldefs.find(key)->second;
     586        5322 :     return true;
     587             :   } else {
     588           0 :     return false;
     589             :   }
     590             : }
     591             : 
     592        3913 : bool Keywords::getDefaultValue( std::string key, std::string& def ) const {
     593        3913 :   plumed_assert( style(key,"compulsory") || style(key,"hidden") );
     594             : 
     595        3913 :   if( numdefs.find(key)!=numdefs.end() ) {
     596        1903 :     def=numdefs.find(key)->second;
     597        1903 :     return true;
     598             :   } else {
     599        2010 :     return false;
     600             :   }
     601             : }
     602             : 
     603        2808 : void Keywords::destroyData() {
     604        2808 :   keys.clear(); reserved_keys.clear(); types.clear();
     605        2808 :   allowmultiple.clear(); documentation.clear();
     606        2808 :   booldefs.clear(); numdefs.clear(); atomtags.clear();
     607        2808 :   ckey.clear(); cdocs.clear(); ckey.clear();
     608        2808 : }
     609             : 
     610        2438 : void Keywords::setComponentsIntroduction( const std::string& instr ) {
     611        2438 :   cstring = instr;
     612        2438 : }
     613             : 
     614       16521 : void Keywords::addOutputComponent( const std::string& name, const std::string& key, const std::string& descr ) {
     615       16521 :   plumed_assert( !outputComponentExists( name, false ) );
     616       16521 :   plumed_massert( name.find("-")==std::string::npos,"dash is reseved character in component names" );
     617             : 
     618       16521 :   std::size_t num2=name.find_first_of("_");
     619       16521 :   if( num2!=std::string::npos ) plumed_massert( num2==0, "underscore is reserved character in component names that has special meaning");
     620             : 
     621       16521 :   ckey.insert( std::pair<std::string,std::string>(name,key) );
     622       16521 :   cdocs.insert( std::pair<std::string,std::string>(name,descr) );
     623       16521 :   cnames.push_back(name);
     624       16521 : }
     625             : 
     626       27104 : bool Keywords::outputComponentExists( const std::string& name, const bool& custom ) const {
     627       27104 :   if( custom && cstring.find("customizable")!=std::string::npos ) return true;
     628             : 
     629       17664 :   std::string sname; std::size_t num=name.find_first_of("-");
     630       17664 :   if( num!=std::string::npos ) sname=name.substr(0,num);
     631             :   else {
     632       17602 :     std::size_t num2=name.find_first_of("_");
     633       17602 :     if( num2!=std::string::npos ) sname=name.substr(num2);
     634       17544 :     else sname=name;
     635             :   }
     636             : 
     637      129728 :   for(unsigned i=0; i<cnames.size(); ++i) {
     638      113206 :     if( sname==cnames[i] ) return true;
     639             :   }
     640       16522 :   return false;
     641             : }
     642             : 
     643        2523 : }

Generated by: LCOV version 1.13