LCOV - code coverage report
Current view: top level - tools - Keywords.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 219 375 58.4 %
Date: 2020-11-18 11:20:57 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      386081 : Keywords::KeyType::KeyType( const std::string& type ) {
      30      386081 :   if( type=="compulsory" ) {
      31      105674 :     style=compulsory;
      32      280407 :   } else if( type=="flag" ) {
      33       65553 :     style=flag;
      34      214854 :   } else if( type=="optional" ) {
      35      110634 :     style=optional;
      36      156844 :   } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) {
      37       51640 :     style=atoms;
      38       52580 :   } else if( type=="hidden" ) {
      39       25159 :     style=hidden;
      40       27421 :   } else if( type=="vessel" ) {
      41       27421 :     style=vessel;
      42             :   } else {
      43           0 :     plumed_massert(false,"invalid keyword specifier " + type);
      44             :   }
      45      386081 : }
      46             : 
      47        1832 : void Keywords::KeyType::setStyle( const std::string& type ) {
      48        1832 :   if( type=="compulsory" ) {
      49          35 :     style=compulsory;
      50        1797 :   } else if( type=="flag" ) {
      51           0 :     style=flag;
      52        1797 :   } else if( type=="optional" ) {
      53           7 :     style=optional;
      54        3403 :   } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) {
      55         177 :     style=atoms;
      56        1613 :   } else if( type=="hidden" ) {
      57           0 :     style=hidden;
      58        1613 :   } else if( type=="vessel" ) {
      59        1613 :     style=vessel;
      60             :   } else {
      61           0 :     plumed_massert(false,"invalid keyword specifier " + type);
      62             :   }
      63        1832 : }
      64             : 
      65         513 : void Keywords::add( const Keywords& newkeys ) {
      66         513 :   newkeys.copyData( keys, reserved_keys, types, allowmultiple, documentation, booldefs, numdefs, atomtags, cnames, ckey, cdocs  );
      67         513 : }
      68             : 
      69         513 : 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        1026 :   for(unsigned i=0; i<keys.size(); ++i) {
      74             :     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             :   }
      88       28728 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
      89             :     std::string thiskey=reserved_keys[i];
      90      246024 :     for(unsigned j=0; j<kk.size(); ++j) plumed_massert( thiskey!=kk[j], "keyword " + thiskey + " is in twice" );
      91      370683 :     for(unsigned j=0; j<rk.size(); ++j) plumed_massert( thiskey!=rk[j], "keyword " + thiskey + " is in twice" );
      92        9234 :     rk.push_back( thiskey );
      93           0 :     plumed_massert( types.count( thiskey ), "no type data on keyword " + thiskey + " to copy" );
      94        9234 :     tt.insert( std::pair<std::string,KeyType>( thiskey,types.find(thiskey)->second) );
      95        9234 :     if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair<std::string,std::string>( thiskey,atomtags.find(thiskey)->second) );
      96           0 :     plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" );
      97        9234 :     am.insert( std::pair<std::string,bool>(thiskey,allowmultiple.find(thiskey)->second) );
      98           0 :     plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" );
      99       18468 :     docs.insert( std::pair<std::string,std::string>(thiskey,documentation.find(thiskey)->second) );
     100           0 :     if( booldefs.count( thiskey ) ) bools.insert( std::pair<std::string,bool>( thiskey,booldefs.find(thiskey)->second) );
     101           0 :     if( numdefs.count( thiskey ) ) nums.insert( std::pair<std::string,std::string>( thiskey,numdefs.find(thiskey)->second) );
     102             :   }
     103       28728 :   for(unsigned i=0; i<cnames.size(); ++i) {
     104             :     std::string thisnam=cnames[i];
     105      253935 :     for(unsigned j=0; j<cnam.size(); ++j) plumed_massert( thisnam!=cnam[j], "component " + thisnam + " is in twice" );
     106        9234 :     cnam.push_back( thisnam );
     107           0 :     plumed_massert( ckey.count( thisnam ), "no keyword data on component " + thisnam + " to copy" );
     108       18468 :     ck.insert( std::pair<std::string,std::string>( thisnam, ckey.find(thisnam)->second) );
     109           0 :     plumed_massert( cdocs.count( thisnam ), "no documentation on component " + thisnam + " to copy" );
     110       18468 :     cd.insert( std::pair<std::string,std::string>( thisnam, cdocs.find(thisnam)->second) );
     111             :   }
     112         513 : }
     113             : 
     114       51266 : void Keywords::reserve( const std::string & t, const std::string & k, const std::string & d ) {
     115       51266 :   plumed_assert( !exists(k) && !reserved(k) );
     116             :   std::string fd, lowkey=k;
     117             :   // Convert to lower case
     118       51266 :   std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
     119             : // Remove any underscore characters
     120             :   for(unsigned i=0;; ++i) {
     121             :     std::size_t num=lowkey.find_first_of("_");
     122       69555 :     if( num==std::string::npos ) break;
     123       18289 :     lowkey.erase( lowkey.begin() + num, lowkey.begin() + num + 1 );
     124       18289 :   }
     125       51266 :   if( t=="vessel" ) {
     126       82263 :     fd = d + " The final value can be referenced using <em>label</em>." + lowkey;
     127       51616 :     if(d.find("flag")==std::string::npos) fd += ".  You can use multiple instances of this keyword i.e. " +
     128      145170 :           k +"1, " + k + "2, " + k + "3...  The corresponding values are then "
     129      120975 :           "referenced using <em>label</em>."+ lowkey +"-1,  <em>label</em>." + lowkey +
     130       72585 :           "-2,  <em>label</em>." + lowkey + "-3...";
     131       27421 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     132       82263 :     types.insert( std::pair<std::string,KeyType>(k,KeyType("vessel")) );
     133       23845 :   } else if( t=="numbered" ) {
     134       16760 :     fd = d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3...";
     135        2095 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     136        6285 :     types.insert( std::pair<std::string,KeyType>(k,KeyType("optional")) );
     137             :   } else {
     138             :     fd = d;
     139       21750 :     if( t=="atoms" && isaction ) fd = d + ".  For more information on how to specify lists of atoms see \\ref Group";
     140       21750 :     allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     141       43500 :     types.insert( std::pair<std::string,KeyType>(k,KeyType(t)) );
     142       22947 :     if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,t) );
     143             :   }
     144      102532 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     145       51266 :   reserved_keys.push_back(k);
     146       51266 : }
     147             : 
     148        1602 : void Keywords::reserveFlag( const std::string & k, const bool def, const std::string & d ) {
     149        1602 :   plumed_assert( !exists(k) && !reserved(k) );
     150             :   std::string defstr;
     151        1602 :   if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; }
     152        4806 :   types.insert( std::pair<std::string,KeyType>(k,KeyType("flag")) );
     153        1602 :   std::string fd,lowkey=k; std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
     154        3204 :   fd=defstr + d;
     155        3204 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     156        1602 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     157        1602 :   booldefs.insert( std::pair<std::string,bool>(k,def) );
     158        1602 :   reserved_keys.push_back(k);
     159        1602 : }
     160             : 
     161       11547 : void Keywords::use( const std::string & k ) {
     162       11547 :   plumed_massert( reserved(k), "the " + k + " keyword is not reserved");
     163      452634 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
     164      143180 :     if(reserved_keys[i]==k) keys.push_back( reserved_keys[i] );
     165             :   }
     166       11547 : }
     167             : 
     168        1832 : void Keywords::reset_style( const std::string & k, const std::string & style ) {
     169        1832 :   plumed_assert( exists(k) || reserved(k) );
     170        1832 :   (types.find(k)->second).setStyle(style);
     171        3445 :   if( (types.find(k)->second).isVessel() ) allowmultiple[k]=true;
     172        2009 :   if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,style) );
     173        1832 : }
     174             : 
     175      186986 : void Keywords::add( const std::string & t, const std::string & k, const std::string & d ) {
     176      560958 :   plumed_massert( !exists(k) && t!="flag" && !reserved(k) && t!="vessel", "keyword " + k + " has already been registered");
     177             :   std::string fd;
     178      186986 :   if( t=="numbered" ) {
     179        8568 :     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        3213 :     types.insert( std::pair<std::string,KeyType>(k, KeyType("optional")) );
     182             :   } else {
     183             :     fd=d;
     184      185915 :     allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     185      371830 :     types.insert( std::pair<std::string,KeyType>(k,KeyType(t)) );
     186      236358 :     if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,t) );
     187             :   }
     188      191767 :   if( t=="atoms" && isaction ) fd = d + ".  For more information on how to specify lists of atoms see \\ref Group";
     189      373972 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     190      186986 :   keys.push_back(k);
     191      186986 : }
     192             : 
     193       82276 : void Keywords::add( const std::string & t, const std::string & k, const std::string &  def, const std::string & d ) {
     194      164552 :   plumed_assert( !exists(k) && !reserved(k) &&  (t=="compulsory" || t=="hidden" )); // An optional keyword can't have a default
     195      164552 :   types.insert(  std::pair<std::string,KeyType>(k, KeyType(t)) );
     196      411380 :   documentation.insert( std::pair<std::string,std::string>(k,"( default=" + def + " ) " + d) );
     197       82276 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     198      164552 :   numdefs.insert( std::pair<std::string,std::string>(k,def) );
     199       82276 :   keys.push_back(k);
     200       82276 : }
     201             : 
     202       63951 : void Keywords::addFlag( const std::string & k, const bool def, const std::string & d ) {
     203       63951 :   plumed_massert( !exists(k) && !reserved(k), "keyword " + k + " has already been registered");
     204             :   std::string defstr;
     205       63951 :   if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; }
     206      191853 :   types.insert( std::pair<std::string,KeyType>(k,KeyType("flag")) );
     207      191853 :   documentation.insert( std::pair<std::string,std::string>(k,defstr + d) );
     208       63951 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     209       63951 :   booldefs.insert( std::pair<std::string,bool>(k,def) );
     210       63951 :   keys.push_back(k);
     211       63951 : }
     212             : 
     213         881 : void Keywords::remove( const std::string & k ) {
     214             :   bool found=false; unsigned j=0, n=0;
     215             : 
     216             :   while(true) {
     217       25014 :     for(j=0; j<keys.size(); j++) if(keys[j]==k)break;
     218       49740 :     for(n=0; n<reserved_keys.size(); n++) if(reserved_keys[n]==k)break;
     219        1762 :     if(j<keys.size()) {
     220         877 :       keys.erase(keys.begin()+j);
     221             :       found=true;
     222         885 :     } else if(n<reserved_keys.size()) {
     223           4 :       reserved_keys.erase(reserved_keys.begin()+n);
     224             :       found=true;
     225             :     } else break;
     226             :   }
     227             :   // Delete documentation, type and so on from the description
     228             :   types.erase(k); documentation.erase(k); allowmultiple.erase(k); booldefs.erase(k); numdefs.erase(k);
     229         881 :   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         881 : }
     231             : 
     232        6313 : bool Keywords::numbered( const std::string & k ) const {
     233       12626 :   if( style( k,"atoms") ) return true;
     234           0 :   plumed_massert( allowmultiple.count(k), "Did not find keyword " + k );
     235        4718 :   return allowmultiple.find(k)->second;
     236             : }
     237             : 
     238      406814 : bool Keywords::style( const std::string & k, const std::string & t ) const {
     239           0 :   plumed_massert( types.count(k), "Did not find keyword " + k );
     240             : 
     241      813628 :   if( (types.find(k)->second).toString()==t ) return true;
     242      322490 :   return false;
     243             : }
     244             : 
     245      522611 : unsigned Keywords::size() const {
     246      522611 :   return keys.size();
     247             : }
     248             : 
     249        8229 : std::string Keywords::getKeyword( const unsigned i ) const {
     250        8229 :   plumed_assert( i<size() );
     251       16458 :   return keys[i];
     252             : }
     253             : 
     254      509669 : bool Keywords::exists( const std::string & k ) const {
     255    16016545 :   for(unsigned i=0; i<keys.size(); ++i) {
     256     5103926 :     if( keys[i]==k ) return true;
     257             :   }
     258             :   return false;
     259             : }
     260             : 
     261      399362 : bool Keywords::reserved( const std::string & k ) const {
     262     2802943 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
     263      681354 :     if( reserved_keys[i]==k ) return true;
     264             :   }
     265             :   return false;
     266             : }
     267             : 
     268           0 : void Keywords::print_template(const std::string& actionname, bool include_optional) const {
     269             :   unsigned nkeys=0;
     270             :   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             :         else printf(" %s=<atom selection>", keys[i].c_str() );
     282           0 :         prevtag=atomtags.find(keys[i])->second;
     283             :       }
     284             :     }
     285             :   }
     286             :   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             :         std::string def;
     295           0 :         if( getDefaultValue( keys[i], def) ) {
     296             :           printf(" %s=%s ", keys[i].c_str(), def.c_str() );
     297             :         } else {
     298             :           printf(" %s=    ", keys[i].c_str() );
     299             :         }
     300           0 :       } else if (include_optional) {
     301             :         // TG no defaults for optional keywords?
     302             :         printf(" [%s]", keys[i].c_str() );
     303             :       }
     304             :     }
     305             :   }
     306             :   printf("\n");
     307           0 : }
     308             : 
     309         223 : void Keywords::print_vim() const {
     310        9920 :   for(unsigned i=0; i<keys.size(); ++i) {
     311        3158 :     if( (types.find(keys[i])->second).isFlag() ) {
     312             :       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             :       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             :     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             :       printf("<tr> <td width=5%%> <b> Quantity </b> </td> <td> <b> Description </b> </td> </tr>\n");
     336             :       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             :         printf("<tr>\n");
     341             :         printf("<td width=15%%> <b> %s </b></td>\n",cnames[i].c_str() );
     342             :         printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
     343             :         printf("</tr>\n");
     344             :       }
     345           0 :       std::cout<<"</table>\n\n";
     346           0 :       if( nndef>0 ) {
     347             :         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             :         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             :             printf("<tr>\n");
     354             :             printf("<td width=5%%> <b> %s </b></td> <td width=10%%> <b> %s </b> </td> \n",
     355             :                    cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() );
     356             :             printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
     357             :             printf("</tr>\n");
     358             :           }
     359             :         }
     360           0 :         std::cout<<"</table>\n\n";
     361             :       }
     362             :     } else {
     363             :       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             :         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             :             printf("<tr>\n");
     375             :             printf("<td width=5%%> <b> %s </b></td> <td width=10%%> <b> %s </b> </td> \n",
     376             :                    cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() );
     377             :             printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
     378             :             printf("</tr>\n");
     379             :           }
     380             :         }
     381           0 :         std::cout<<"</table>\n\n";
     382             :       }
     383             :     }
     384             :   }
     385             : 
     386             :   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             :   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             :   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             :   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             :   unsigned nkeys=0;
     450        9920 :   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             :     fprintf(out,"The input trajectory can be in any of the following formats: \n\n");
     455        5617 :     for(unsigned i=0; i<keys.size(); ++i) {
     456        2013 :       if ( (types.find(keys[i])->second).isAtomList() ) printKeyword( keys[i], out );
     457             :     }
     458             :   }
     459             :   nkeys=0;
     460        9920 :   for(unsigned i=0; i<keys.size(); ++i) {
     461        3158 :     if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
     462             :   }
     463             :   unsigned ncompulsory=nkeys;
     464         223 :   if( nkeys>0 ) {
     465             :     fprintf(out,"\nThe following arguments are compulsory: \n\n");
     466        7694 :     for(unsigned i=0; i<keys.size(); ++i) {
     467        3079 :       if ( (types.find(keys[i])->second).isCompulsory() ) printKeyword( keys[i], out );   //log.printKeyword( keys[i], documentation[i] );
     468             :     }
     469             :   }
     470             :   nkeys=0;
     471        9920 :   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             :     else fprintf( out,"\nThe following options are available\n\n");
     477        9450 :     for(unsigned i=0; i<keys.size(); ++i) {
     478        3739 :       if ( (types.find(keys[i])->second).isFlag() ) printKeyword( keys[i], out );   //log.printKeyword( keys[i], documentation[i] );
     479             :     }
     480             :   }
     481             :   nkeys=0;
     482        9920 :   for(unsigned i=0; i<keys.size(); ++i) {
     483        5714 :     if ( (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++;
     484             :   }
     485         223 :   if( nkeys>0 ) {
     486        8715 :     for(unsigned i=0; i<keys.size(); ++i) {
     487        6080 :       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             :     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        5276 :   std::vector<std::string> w=Tools::getWords( documentation.find(key)->second );
     496             :   fprintf(out,"%23s - ", key.c_str() );
     497        2638 :   unsigned nl=0; std::string blank=" ";
     498      169613 :   for(unsigned i=0; i<w.size(); ++i) {
     499       55035 :     nl+=w[i].length() + 1;
     500       55035 :     if( nl>60 ) {
     501             :       fprintf(out,"\n%23s   %s ", blank.c_str(), w[i].c_str() ); nl=0;
     502             :     } else {
     503             :       fprintf(out,"%s ", w[i].c_str() );
     504             :     }
     505       57092 :     if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot
     506             :   }
     507             :   fprintf(out,"\n");
     508        2638 : }
     509             : 
     510           0 : void Keywords::print( Log& log ) const {
     511             :   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             :   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             :   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             :   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             :   printf("<tr>\n");
     573             :   printf("<td width=15%%> <b> %s </b></td>\n",key.c_str() );
     574             :   printf("<td> %s </td>\n",(documentation.find(key)->second).c_str() );
     575             :   printf("</tr>\n");
     576           0 : }
     577             : 
     578      245442 : std::string Keywords::get( const unsigned k ) const {
     579      245442 :   plumed_assert( k<size() );
     580      490884 :   return keys[k];
     581             : }
     582             : 
     583       10826 : bool Keywords::getLogicalDefault( std::string key, bool& def ) const {
     584       10826 :   if( booldefs.find(key)!=booldefs.end() ) {
     585       10826 :     def=booldefs.find(key)->second;
     586       10826 :     return true;
     587             :   } else {
     588             :     return false;
     589             :   }
     590             : }
     591             : 
     592        7415 : bool Keywords::getDefaultValue( std::string key, std::string& def ) const {
     593       22245 :   plumed_assert( style(key,"compulsory") || style(key,"hidden") );
     594             : 
     595        7415 :   if( numdefs.find(key)!=numdefs.end() ) {
     596        3484 :     def=numdefs.find(key)->second;
     597             :     return true;
     598             :   } else {
     599             :     return false;
     600             :   }
     601             : }
     602             : 
     603        5792 : void Keywords::destroyData() {
     604        5792 :   keys.clear(); reserved_keys.clear(); types.clear();
     605             :   allowmultiple.clear(); documentation.clear();
     606             :   booldefs.clear(); numdefs.clear(); atomtags.clear();
     607             :   ckey.clear(); cdocs.clear(); ckey.clear();
     608        5792 : }
     609             : 
     610        4918 : void Keywords::setComponentsIntroduction( const std::string& instr ) {
     611        4918 :   cstring = instr;
     612        4918 : }
     613             : 
     614       36077 : void Keywords::addOutputComponent( const std::string& name, const std::string& key, const std::string& descr ) {
     615       36077 :   plumed_assert( !outputComponentExists( name, false ) );
     616       36077 :   plumed_massert( name.find("-")==std::string::npos,"dash is reseved character in component names" );
     617             : 
     618             :   std::size_t num2=name.find_first_of("_");
     619       36077 :   if( num2!=std::string::npos ) plumed_massert( num2==0, "underscore is reserved character in component names that has special meaning");
     620             : 
     621       72154 :   ckey.insert( std::pair<std::string,std::string>(name,key) );
     622       72154 :   cdocs.insert( std::pair<std::string,std::string>(name,descr) );
     623       36077 :   cnames.push_back(name);
     624       36077 : }
     625             : 
     626       68839 : bool Keywords::outputComponentExists( const std::string& name, const bool& custom ) const {
     627      101298 :   if( custom && cstring.find("customizable")!=std::string::npos ) return true;
     628             : 
     629             :   std::string sname; std::size_t num=name.find_first_of("-");
     630       39667 :   if( num!=std::string::npos ) sname=name.substr(0,num);
     631             :   else {
     632             :     std::size_t num2=name.find_first_of("_");
     633       41277 :     if( num2!=std::string::npos ) sname=name.substr(num2);
     634             :     else sname=name;
     635             :   }
     636             : 
     637      921433 :   for(unsigned i=0; i<cnames.size(); ++i) {
     638      284124 :     if( sname==cnames[i] ) return true;
     639             :   }
     640             :   return false;
     641             : }
     642             : 
     643        4839 : }

Generated by: LCOV version 1.13