Merge 'release-4-6' into master
[alexxy/gromacs.git] / src / gromacs / gmxlib / nonbonded / nb_kernel.c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
3  * This file is part of GROMACS.
4  * Copyright (c) 2012-
5  *
6  * Written by the Gromacs development team under coordination of
7  * David van der Spoel, Berk Hess, and Erik Lindahl.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * To help us fund GROMACS development, we humbly ask that you cite
15  * the research papers on the package. Check out http://www.gromacs.org
16  *
17  * And Hey:
18  * Gnomes, ROck Monsters And Chili Sauce
19  */
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "nb_kernel.h"
29 #include "smalloc.h"
30 #include "string2.h"
31
32
33 /* Static data structures to find kernels */
34 static nb_kernel_info_t *   kernel_list           = NULL;
35 static unsigned int         kernel_list_size      = 0;
36 static int *                kernel_list_hash      = NULL;
37 static unsigned int         kernel_list_hash_size = 0;
38
39 static unsigned int
40 nb_kernel_hash_func(const char *   arch,
41                     const char *   elec,
42                     const char *   elec_mod,
43                     const char *   vdw,
44                     const char *   vdw_mod,
45                     const char *   geom,
46                     const char *   other,
47                     const char *   vf)
48 {
49     unsigned int hash;
50
51     hash = gmx_string_hash_func(arch,gmx_string_hash_init);
52     hash = gmx_string_hash_func(elec,hash);
53     hash = gmx_string_hash_func(elec_mod,hash);
54     hash = gmx_string_hash_func(vdw,hash);
55     hash = gmx_string_hash_func(vdw_mod,hash);
56     hash = gmx_string_hash_func(geom,hash);
57     hash = gmx_string_hash_func(other,hash);
58     hash = gmx_string_hash_func(vf,hash);
59
60     return hash;
61 }
62
63 void
64 nb_kernel_list_add_kernels(nb_kernel_info_t *   new_kernel_list,
65                            int                  new_kernel_list_size)
66 {
67     srenew(kernel_list,kernel_list_size+new_kernel_list_size);
68     memcpy(kernel_list+kernel_list_size,new_kernel_list,new_kernel_list_size*sizeof(nb_kernel_info_t));
69     kernel_list_size += new_kernel_list_size;
70 }
71
72
73 int
74 nb_kernel_list_hash_init(void)
75 {
76     unsigned int            i;
77     unsigned int            index;
78
79     kernel_list_hash_size   = kernel_list_size*5;
80     snew(kernel_list_hash,kernel_list_hash_size);
81
82     for(i=0;i<kernel_list_hash_size;i++)
83     {
84         kernel_list_hash[i] = -1;
85     }
86     for(i=0;i<kernel_list_size;i++)
87     {
88         index=nb_kernel_hash_func(kernel_list[i].architecture,
89                                   kernel_list[i].electrostatics,
90                                   kernel_list[i].electrostatics_modifier,
91                                   kernel_list[i].vdw,
92                                   kernel_list[i].vdw_modifier,
93                                   kernel_list[i].geometry,
94                                   kernel_list[i].other,
95                                   kernel_list[i].vf) % kernel_list_hash_size;
96
97         /* Check for collisions and advance if necessary */
98         while( kernel_list_hash[index] != -1 )
99         {
100             index = (index+1) % kernel_list_hash_size;
101         }
102
103         kernel_list_hash[index] = i;
104     }
105     return 0;
106 }
107
108 void
109 nb_kernel_list_hash_destroy()
110 {
111     sfree(kernel_list_hash);
112     kernel_list_hash = NULL;
113     kernel_list_hash_size = 0;
114 }
115
116
117 nb_kernel_t *
118 nb_kernel_list_findkernel(FILE *              log,
119                           const char *        arch,
120                           const char *        electrostatics,
121                           const char *        electrostatics_modifier,
122                           const char *        vdw,
123                           const char *        vdw_modifier,
124                           const char *        geometry,
125                           const char *        other,
126                           const char *        vf)
127 {
128     int                 i;
129     unsigned int        index;
130     nb_kernel_info_t *  kernelinfo_ptr;
131
132     if(kernel_list_hash_size==0)
133     {
134         return NULL;
135     }
136
137     index=nb_kernel_hash_func(arch,
138                               electrostatics,
139                               electrostatics_modifier,
140                               vdw,
141                               vdw_modifier,
142                               geometry,
143                               other,
144                               vf) % kernel_list_hash_size;
145
146     kernelinfo_ptr = NULL;
147     while( (i=kernel_list_hash[index]) != -1)
148     {
149         if(!gmx_strcasecmp_min(kernel_list[i].architecture,arch) &&
150            !gmx_strcasecmp_min(kernel_list[i].electrostatics,electrostatics) &&
151            !gmx_strcasecmp_min(kernel_list[i].electrostatics_modifier,electrostatics_modifier) &&
152            !gmx_strcasecmp_min(kernel_list[i].vdw,vdw) &&
153            !gmx_strcasecmp_min(kernel_list[i].vdw_modifier,vdw_modifier) &&
154            !gmx_strcasecmp_min(kernel_list[i].geometry,geometry) &&
155            !gmx_strcasecmp_min(kernel_list[i].other,other) &&
156            !gmx_strcasecmp_min(kernel_list[i].vf,vf))
157         {
158             kernelinfo_ptr = kernel_list+i;
159             break;
160         }
161         index = (index+1) % kernel_list_hash_size;
162     }
163
164     if(log && kernelinfo_ptr!=NULL)
165     {
166         fprintf(log,
167                 "NB kernel %s() with architecture '%s' used for neighborlist with\n"
168                 "    Elec: '%s', Modifier: '%s'\n"
169                 "    Vdw:  '%s', Modifier: '%s'\n"
170                 "    Geom: '%s', Other: '%s', Calc: '%s'\n\n",
171                 kernelinfo_ptr->kernelname,arch,electrostatics,electrostatics_modifier,
172                 vdw,vdw_modifier,geometry,other,vf);
173     }
174
175     /* If we did not find any kernel the pointer will still be NULL */
176     return (kernelinfo_ptr !=NULL) ? kernelinfo_ptr->kernelptr : NULL;
177 }