Merge branch release-4-6
[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 #include "gmx_fatal.h"
32
33
34 /* Static data structures to find kernels */
35 static nb_kernel_info_t *   kernel_list           = NULL;
36 static unsigned int         kernel_list_size      = 0;
37 static int *                kernel_list_hash      = NULL;
38 static unsigned int         kernel_list_hash_size = 0;
39
40 static unsigned int
41 nb_kernel_hash_func(const char *   arch,
42                     const char *   elec,
43                     const char *   elec_mod,
44                     const char *   vdw,
45                     const char *   vdw_mod,
46                     const char *   geom,
47                     const char *   other,
48                     const char *   vf)
49 {
50     unsigned int hash;
51
52     hash = gmx_string_hash_func(arch, gmx_string_hash_init);
53     hash = gmx_string_hash_func(elec, hash);
54     hash = gmx_string_hash_func(elec_mod, hash);
55     hash = gmx_string_hash_func(vdw, hash);
56     hash = gmx_string_hash_func(vdw_mod, hash);
57     hash = gmx_string_hash_func(geom, hash);
58     hash = gmx_string_hash_func(other, hash);
59     hash = gmx_string_hash_func(vf, hash);
60
61     return hash;
62 }
63
64 void
65 nb_kernel_list_add_kernels(nb_kernel_info_t *   new_kernel_list,
66                            int                  new_kernel_list_size)
67 {
68     srenew(kernel_list, kernel_list_size+new_kernel_list_size);
69     memcpy(kernel_list+kernel_list_size, new_kernel_list, new_kernel_list_size*sizeof(nb_kernel_info_t));
70     kernel_list_size += new_kernel_list_size;
71 }
72
73
74 int
75 nb_kernel_list_hash_init(void)
76 {
77     unsigned int            i;
78     unsigned int            index;
79
80     kernel_list_hash_size   = kernel_list_size*5;
81     snew(kernel_list_hash, kernel_list_hash_size);
82
83     for (i = 0; i < kernel_list_hash_size; i++)
84     {
85         kernel_list_hash[i] = -1;
86     }
87     for (i = 0; i < kernel_list_size; i++)
88     {
89         index = nb_kernel_hash_func(kernel_list[i].architecture,
90                                     kernel_list[i].electrostatics,
91                                     kernel_list[i].electrostatics_modifier,
92                                     kernel_list[i].vdw,
93                                     kernel_list[i].vdw_modifier,
94                                     kernel_list[i].geometry,
95                                     kernel_list[i].other,
96                                     kernel_list[i].vf) % kernel_list_hash_size;
97
98         /* Check for collisions and advance if necessary */
99         while (kernel_list_hash[index] != -1)
100         {
101             index = (index+1) % kernel_list_hash_size;
102         }
103
104         kernel_list_hash[index] = i;
105     }
106     return 0;
107 }
108
109 void
110 nb_kernel_list_hash_destroy()
111 {
112     sfree(kernel_list_hash);
113     kernel_list_hash      = NULL;
114     kernel_list_hash_size = 0;
115 }
116
117
118 nb_kernel_t *
119 nb_kernel_list_findkernel(FILE gmx_unused *   log,
120                           const char *        arch,
121                           const char *        electrostatics,
122                           const char *        electrostatics_modifier,
123                           const char *        vdw,
124                           const char *        vdw_modifier,
125                           const char *        geometry,
126                           const char *        other,
127                           const char *        vf)
128 {
129     int                 i;
130     unsigned int        index;
131     nb_kernel_info_t *  kernelinfo_ptr;
132
133     if (kernel_list_hash_size == 0)
134     {
135         return NULL;
136     }
137
138     index = nb_kernel_hash_func(arch,
139                                 electrostatics,
140                                 electrostatics_modifier,
141                                 vdw,
142                                 vdw_modifier,
143                                 geometry,
144                                 other,
145                                 vf) % kernel_list_hash_size;
146
147     kernelinfo_ptr = NULL;
148     while ( (i = kernel_list_hash[index]) != -1)
149     {
150         if (!gmx_strcasecmp_min(kernel_list[i].architecture, arch) &&
151             !gmx_strcasecmp_min(kernel_list[i].electrostatics, electrostatics) &&
152             !gmx_strcasecmp_min(kernel_list[i].electrostatics_modifier, electrostatics_modifier) &&
153             !gmx_strcasecmp_min(kernel_list[i].vdw, vdw) &&
154             !gmx_strcasecmp_min(kernel_list[i].vdw_modifier, vdw_modifier) &&
155             !gmx_strcasecmp_min(kernel_list[i].geometry, geometry) &&
156             !gmx_strcasecmp_min(kernel_list[i].other, other) &&
157             !gmx_strcasecmp_min(kernel_list[i].vf, vf))
158         {
159             kernelinfo_ptr = kernel_list+i;
160             break;
161         }
162         index = (index+1) % kernel_list_hash_size;
163     }
164
165     if (debug && kernelinfo_ptr != NULL)
166     {
167         fprintf(debug,
168                 "NB kernel %s() with architecture '%s' used for neighborlist with\n"
169                 "    Elec: '%s', Modifier: '%s'\n"
170                 "    Vdw:  '%s', Modifier: '%s'\n"
171                 "    Geom: '%s', Other: '%s', Calc: '%s'\n\n",
172                 kernelinfo_ptr->kernelname, arch, electrostatics, electrostatics_modifier,
173                 vdw, vdw_modifier, geometry, other, vf);
174     }
175
176     /* If we did not find any kernel the pointer will still be NULL */
177     return (kernelinfo_ptr != NULL) ? kernelinfo_ptr->kernelptr : NULL;
178 }