renamed GMX_THREADS to GMX_THREAD_MPI
[alexxy/gromacs.git] / src / kernel / fflibutil.c
1 /*  -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
3  * 
4  *                This source code is part of
5  * 
6  *                 G   R   O   M   A   C   S
7  * 
8  *          GROningen MAchine for Chemical Simulations
9  * 
10  *                        VERSION 3.2.0
11  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13  * Copyright (c) 2001-2004, The GROMACS development team,
14  * check out http://www.gromacs.org for more information.
15
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  * 
21  * If you want to redistribute modifications, please consider that
22  * scientific software is very special. Version control is crucial -
23  * bugs must be traceable. We will be happy to consider code for
24  * inclusion in the official distribution, but derived work must not
25  * be called official GROMACS. Details are found in the README & COPYING
26  * files - if they are missing, get the official version at www.gromacs.org.
27  * 
28  * To help us fund GROMACS development, we humbly ask that you cite
29  * the papers on the package - you can find them in the top README file.
30  * 
31  * For more info, check our website at http://www.gromacs.org
32  * 
33  * And Hey:
34  * GROningen Mixture of Alchemy and Childrens' Stories
35  */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 #include "sysstuff.h"
47 #include "string2.h"
48 #include "futil.h"
49 #include "network.h"
50 #include "gmx_fatal.h"
51 #include "smalloc.h"
52 #include "statutil.h"
53
54 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
55 #include <direct.h>
56 #include <io.h>
57 #endif
58
59 #ifdef HAVE_UNISTD_H
60 #include <unistd.h>
61 #endif
62
63 #ifdef GMX_THREAD_MPI
64 #include "thread_mpi.h"
65 #endif
66
67 #include "fflibutil.h"
68
69 const char *fflib_forcefield_dir_ext()
70 {
71     return ".ff";
72 }
73
74 const char *fflib_forcefield_itp()
75 {
76     return "forcefield.itp";
77 }
78
79 const char *fflib_forcefield_doc()
80 {
81     return "forcefield.doc";
82 }
83
84 void fflib_filename_base(const char *filename,char *filebase,int maxlen)
85 {
86     const char *cptr;
87     char *ptr;
88
89     cptr = strrchr(filename,DIR_SEPARATOR);
90     if (cptr != NULL)
91     {
92         /* Skip the separator */
93         cptr += 1;
94     }
95     else
96     {
97         cptr = filename;
98     }
99     if (strlen(filename) >= (size_t)maxlen)
100     {
101         gmx_fatal(FARGS,"filename is longer (%d) than maxlen (%d)",
102                   strlen(filename),maxlen);
103     }
104     strcpy(filebase,cptr);
105     /* Remove the extension */
106     ptr = strrchr(filebase,'.');
107     if (ptr != NULL)
108     {
109         ptr[0] = '\0';
110     }
111 }
112
113 static void sort_filenames(int n,char **name,char **name2)
114 {
115     /* Slow sort, but we usually have tens of names */
116     int  i,j,f;
117     char *tmp;
118
119     for(i=0; i<n-1; i++)
120     {
121         f = i;
122         for(j=i+1; j<n; j++)
123         {
124             if (strcmp(name[j],name[f]) < 0)
125             {
126                 f = j;
127             }
128         }
129         if (f > i)
130         {
131             tmp     = name[i];
132             name[i] = name[f];
133             name[f] = tmp;
134             if (name2 != NULL)
135             {
136                 tmp      = name2[i];
137                 name2[i] = name2[f];
138                 name2[f] = tmp;
139             }
140         }
141     }
142 }
143
144 static int low_fflib_search_file_end(const char *ffdir,
145                                      gmx_bool bAddCWD,
146                                      const char *file_end,
147                                      gmx_bool bFatalError,
148                                      char ***filenames,
149                                      char ***filenames_short)
150 {
151     char *ret=NULL;
152     char *lib,*dir;
153     char buf[1024];
154     char *libpath;
155     gmx_bool env_is_set;
156     int  len_fe,len_name;
157     char **fns,**fns_short;
158     char dir_print[GMX_PATH_MAX];
159     char *pdum;
160     char *s,fn_dir[GMX_PATH_MAX];
161     gmx_directory_t dirhandle;
162     char nextname[STRLEN];
163     int  n,n_thisdir,rc;
164
165     len_fe = strlen(file_end);
166
167     env_is_set = FALSE;
168     if (ffdir != NULL)
169     {
170         /* Search in current dir and ffdir */
171         libpath = gmxlibfn(ffdir);
172     }
173     else
174     {
175         /* GMXLIB can be a path now */
176         lib = getenv("GMXLIB");
177         snew(libpath,GMX_PATH_MAX);
178         if (bAddCWD)
179         {
180             sprintf(libpath,"%s%s",".",PATH_SEPARATOR);
181         }
182         if (lib != NULL)
183         {
184             env_is_set = TRUE;
185             strncat(libpath,lib,GMX_PATH_MAX);
186         } 
187         else if (!get_libdir(libpath+strlen(libpath)))
188         {
189             strncat(libpath,GMXLIBDIR,GMX_PATH_MAX);
190         }
191     }
192     s = libpath;
193     n = 0;
194     fns       = NULL;
195     fns_short = NULL;
196     /* Loop over all the entries in libpath */
197     while ((dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
198     {
199         rc = gmx_directory_open(&dirhandle,dir);
200         if (rc==0)
201         {
202             strcpy(dir_print,dir);
203
204             n_thisdir = 0;
205             while (gmx_directory_nextfile(dirhandle,nextname,STRLEN-1)==0)
206             {
207                 nextname[STRLEN-1]=0;
208                 if (debug)
209                 {
210                     fprintf(debug,"dir '%s' %d file '%s'\n",
211                             dir,n_thisdir,nextname);
212                 }
213                 len_name = strlen(nextname);
214                 /* What about case sensitivity? */
215                 if (len_name >= len_fe &&
216                     strcmp(nextname+len_name-len_fe,file_end) == 0)
217                 {
218                     /* We have a match */
219                     srenew(fns,n+1);
220                     sprintf(fn_dir,"%s%c%s",
221                             dir_print,DIR_SEPARATOR,nextname);
222
223                     /* Copy the file name, possibly including the path. */
224                     fns[n] = strdup(fn_dir);
225
226                     if (ffdir == NULL)
227                     {
228                         /* We are searching in a path.
229                          * Use the relative path when we use share/top
230                          * from the installation.
231                          * Add the full path when we use the current
232                          * working directory of GMXLIB.
233                          */
234                         srenew(fns_short,n+1);
235                         if (strcmp(dir,".") == 0 || env_is_set)
236                         {
237                             fns_short[n] = strdup(fn_dir);
238                         }
239                         else
240                         {
241                             fns_short[n] = strdup(nextname);
242                         }
243                     }
244                     n++;
245                     n_thisdir++;
246                 }
247             }
248             gmx_directory_close(dirhandle);
249
250             sort_filenames(n_thisdir,
251                            fns+n-n_thisdir,
252                            fns_short==NULL ? NULL : fns_short+n-n_thisdir);
253         }
254     }
255
256     sfree(libpath);
257
258     if (n == 0 && bFatalError)
259     {
260         if (ffdir != NULL)
261         {
262             gmx_fatal(FARGS,"Could not find any files ending on '%s' in the force field directory '%s'",file_end,ffdir);
263         }
264         else
265         {
266             gmx_fatal(FARGS,"Could not find any files ending on '%s' in the current directory or the GROMACS library search path",file_end);
267         }
268     }
269
270     *filenames = fns;
271     if (ffdir == NULL)
272     {
273         *filenames_short = fns_short;
274     }
275
276     return n;
277 }
278
279 int fflib_search_file_end(const char *ffdir,
280                           const char *file_end,
281                           gmx_bool bFatalError,
282                           char ***filenames)
283 {
284     return low_fflib_search_file_end(ffdir,FALSE,file_end,bFatalError,
285                                      filenames,NULL);
286 }
287
288 int fflib_search_file_in_dirend(const char *filename,const char *dirend,
289                                 char ***dirnames)
290 {
291     int  nf,i;
292     char **f,**f_short;
293     int  n;
294     char **dns;
295     gmx_directory_t dirhandle;
296     char nextname[STRLEN];
297     int  rc;
298     
299     /* Find all files (not only dir's) ending on dirend */
300     nf = low_fflib_search_file_end(NULL,TRUE,dirend,FALSE,&f,&f_short);
301
302     n = 0;
303     dns = NULL;
304     for(i=0; i<nf; i++)
305     {
306         rc = gmx_directory_open(&dirhandle,f[i]);
307
308         if (rc==0)
309         {
310             while (gmx_directory_nextfile(dirhandle,nextname,STRLEN-1)==0)
311             {
312                 nextname[STRLEN-1]=0;
313                 if (strcmp(nextname,filename) == 0)
314                 {
315                     /* We have a match */
316                     srenew(dns,n+1);
317                     dns[n] = strdup(f_short[i]);
318                     n++;
319                 }
320             }
321             gmx_directory_close(dirhandle);
322         }
323         sfree(f[i]);
324         sfree(f_short[i]);
325     }
326     sfree(f);
327     sfree(f_short);
328
329     *dirnames = dns;
330
331     return n;
332 }
333
334 gmx_bool fflib_fexist(const char *file)
335 {
336     char *file_fullpath;
337
338     file_fullpath = low_gmxlibfn(file,TRUE,FALSE);
339     
340     if (file_fullpath == NULL)
341     {
342         return FALSE;
343     }
344     else
345     {
346         sfree(file_fullpath);
347
348         return TRUE;
349     }
350 }
351
352
353 FILE *fflib_open(const char *file)
354 {
355     char *file_fullpath;
356     FILE *fp;
357
358     file_fullpath = gmxlibfn(file);
359     fprintf(stderr,"Opening force field file %s\n",file_fullpath);
360     fp = ffopen(file_fullpath,"r");
361     sfree(file_fullpath);
362
363     return fp;
364 }