+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-
-/* This program is NOT threadsafe, but it is only used to create
- * the nonbonded functions during the build process, so it will never be
- * executed by multiple threads.
- */
-
-#include <mknb_common.h>
-#include <mknb_declarations.h>
-#include <mknb_outerloop.h>
-#include <mknb_metacode.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* This program generates nonbonded interaction source code for the GROMACS
- * Molecular Dynamics package. The functions are nearly optimal, i.e.
- * there are no superfluous declarations or statements in the code.
- * The functions are generated in either C or Fortran 77. Note that some
- * special functions (free energy, generalized-born interactions) are
- * written outside this generator.
- *
- * C is somewhat more portable, but Fortran is faster on some machines.
- * There are also a lot of special options like prefetching, the software
- * version of 1/sqrt(x), thread synchronization, etc. In C we could handle
- * some of this with a lot of defines, but not all Fortran compilers
- * support preprocessing. It is also very error-prone to have 200-300
- * different functions to check - by generating them automatically any error
- * will probably show up in all functions and be fixed immediately.
- *
- */
-
-
-
-void
-mknb_write_function(void)
-{
- char funcname[255];
-
- /* Give the routines names like nb_kernel123nf */
-
-#ifdef IBM_FORTRAN_CPP
- sprintf(funcname,"pwr6kernel%d%d%d%s",
- mknb_func.coul,mknb_func.vdw,mknb_func.water,
- mknb_func.do_force ? "" : "nf");
-#else
- sprintf(funcname,"nb_kernel%d%d%d%s",
- mknb_func.coul,mknb_func.vdw,mknb_func.water,
- mknb_func.do_force ? "" : "nf");
-#endif
-
- /* Set variables we need when writing the code */
-
- /* ni is the number of atoms we work with in each
- * iteration of the outer loop.
- */
- if(mknb_func.water==MKNB_WATER_SPC_SINGLE ||
- mknb_func.water==MKNB_WATER_SPC_PAIR) {
- /* For all SPC/TIP3P loops we have 3 atoms in outer loop */
- mknb_func.ni=3;
- }
- else if(mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR) {
- /* For all TIP4P loops there are 4 atoms in outer loop */
- mknb_func.ni=4;
- }
- else {
- /* No water optimization */
- mknb_func.ni=1;
- }
-
- /* nj is the number of atoms we work with in each
- * iteration of the inner loop.
- */
- if(mknb_func.water==MKNB_WATER_SPC_PAIR) {
- /* Water-water optimization for SPC/TIP3P */
- mknb_func.nj=3;
- }
- else if(mknb_func.water==MKNB_WATER_TIP4P_PAIR) {
- /* Water-water optimization for TIP4P */
- mknb_func.nj=4;
- }
- else {
- /* No water-water optimization.
- * (i.e. non-water or water-other atoms kernel).
- */
- mknb_func.nj=1;
- }
-
- /* LJ uses 2 parameters, Buckingham 3 */
- if(mknb_func.vdw==MKNB_VDW_BHAM)
- mknb_func.nvdw_parameters=3;
- else
- mknb_func.nvdw_parameters=2;
-
- /* Each table point needs 4 floats per interaction.
- * Since the repulsive and dispersive parts of LJ are separate,
- * this means we need 4 floats for coulomb-only, 8 for lj-only
- * and 12 for LJ+coulomb tabulated interactions.
- */
- mknb_func.table_element_size=0;
-
- if(mknb_func.coul==MKNB_COUL_TAB)
- mknb_func.table_element_size += 4;
-
- if(mknb_func.vdw==MKNB_VDW_TAB)
- mknb_func.table_element_size += 8;
-
-
- /* Cosmetics for C, important for Fortran */
- mknb_indent_level = 0;
-
- /* Write info about this particular kernel */
- if(!mknb_fortran)
- fprintf(mknb_output,"\n\n\n/*\n"
- " * Gromacs nonbonded kernel %s\n"
- " * Coulomb interaction: %s\n"
- " * VdW interaction: %s\n"
- " * water optimization: %s\n"
- " * Calculate forces: %s\n"
- " */\n",funcname,
- mknb_coul_names[mknb_func.coul],
- mknb_vdw_names[mknb_func.vdw],
- mknb_water_names[mknb_func.water],
- mknb_func.do_force ? "yes" : "no");
- else
- fprintf(mknb_output,"\n\n\nC\n"
- "C Gromacs nonbonded kernel %s\n"
- "C Coulomb interaction: %s\n"
- "C VdW interaction: %s\n"
- "C water optimization: %s\n"
- "C Calculate forces: %s\n"
- "C\n",funcname,
- mknb_coul_names[mknb_func.coul],
- mknb_vdw_names[mknb_func.vdw],
- mknb_water_names[mknb_func.water],
- mknb_func.do_force ? "yes" : "no");
-
- /* Write the function header and call parameters */
- mknb_function_header(funcname);
-
- /* Local variables */
- mknb_declare_variables();
-
- /* Initialize local data; e.g. charges for water-water */
- mknb_initialize_data();
-
- /* Start the loops over outer and inner atoms/groups */
- mknb_outerloop();
-
- mknb_finish_function();
-}
-
-
-void
-mknb_write_file_header(void)
-{
-
- /* Write info about an entire file
- * (usually two kernels, with and without forces).
- */
- if(!mknb_fortran) {
- fprintf(mknb_output,"/*\n"
- " * Copyright (c) Erik Lindahl, David van der Spoel 2003\n"
- " * \n"
- " * This file is generated automatically at compile time\n"
- " * by the program mknb in the Gromacs distribution.\n"
- " *\n"
- " * Options used when generation this file:\n"
- " * Language: c\n"
- " * Precision: %s\n"
- " * Threads: %s\n"
- " * Software invsqrt: %s\n"
- " * PowerPC invsqrt: %s\n"
- " * Prefetch forces: %s\n"
- " * Comments: %s\n */\n",
- mknb_double ? "double" : "single",
- mknb_options.threads ? "yes" : "no",
- mknb_options.software_invsqrt ? "yes" : "no",
- mknb_options.ppc_invsqrt ? "yes" : "no",
- mknb_options.prefetch_forces ? "yes" : "no",
- mknb_keep_comments ? "yes" : "no");
-
- fprintf(mknb_output,"#ifdef HAVE_CONFIG_H\n#include<config.h>\n#endif\n");
-
- if(mknb_options.threads)
- {
- /* thread_mpi.h must come before all other includes
- (except config.h) */
- fprintf(mknb_output,"#ifdef GMX_THREAD_SHM_FDECOMP\n");
- fprintf(mknb_output,"#include<thread_mpi.h>\n");
- fprintf(mknb_output,"#endif\n");
- }
-
- fprintf(mknb_output,"#include<math.h>\n");
-
- if(mknb_options.software_invsqrt)
- fprintf(mknb_output,"#include<vec.h>\n");
-
- } else {
- fprintf(mknb_output,
- "C\n"
- "C This source code is part of\n"
- "C\n"
- "C G R O M A C S\n"
- "C\n"
- "C Copyright (c) 1991-2000, University of Groningen, The Netherlands.\n"
- "C Copyright (c) 2001-2009, The GROMACS Development Team\n"
- "C\n"
- "C Gromacs is a library for molecular simulation and trajectory analysis,\n"
- "C written by Erik Lindahl, David van der Spoel, Berk Hess, and others - for\n"
- "C a full list of developers and information, check out http://www.gromacs.org\n"
- "C\n"
- "C This program is free software; you can redistribute it and/or modify it under\n"
- "C the terms of the GNU Lesser General Public License as published by the Free\n"
- "C Software Foundation; either version 2 of the License, or (at your option) any\n"
- "C later version.\n"
- "C As a special exception, you may use this file as part of a free software\n"
- "C library without restriction. Specifically, if other files instantiate\n"
- "C templates or use macros or inline functions from this file, or you compile\n"
- "C this file and link it with other files to produce an executable, this\n"
- "C file does not by itself cause the resulting executable to be covered by\n"
- "C the GNU Lesser General Public License.\n"
- "C\n"
- "C In plain-speak: do not worry about classes/macros/templates either - only\n"
- "C changes to the library have to be LGPL, not an application linking with it.\n"
- "C\n"
- "C To help fund GROMACS development, we humbly ask that you cite\n"
- "C the papers people have written on it - you can find them on the website!\n"
- "C\n\n");
-#ifdef IBM_FORTRAN_CPP
- fprintf(mknb_output,"#ifdef HAVE_CONFIG_H\n# include<config.h>\n#endif\n\n");
- fprintf(mknb_output,"#ifdef GMX_DOUBLE\n");
- fprintf(mknb_output,"# define gmxreal real*8\n");
- fprintf(mknb_output,"#else\n");
- fprintf(mknb_output,"# define gmxreal real*4\n");
- fprintf(mknb_output,"#endif\n");
-
-#endif
- }
-}
-
-
-int
-main(int argc,char *argv[])
-{
- char filename[255];
- int i,nfiles;
- FILE *fp;
- char *ch;
-
- /* First set options to default values */
- mknb_fortran = 0; /* global variable in mknb_metacode.c */
- mknb_double = 0; /* global variable in mknb_metacode.c */
- mknb_keep_comments = 0; /* global variable in mknb_metacode.c */
- mknb_options.threads = 0; /* global variable in mknb.c */
- mknb_options.software_invsqrt = 0; /* global variable in mknb.c */
- mknb_options.ppc_invsqrt = 0; /* global variable in mknb.c */
- mknb_options.prefetch_forces = 0; /* global variable in mknb.c */
-
- fprintf(stderr,">>> Gromacs nonbonded kernel generator (-h for help)\n");
-
- /* Change options from command line arguments */
- for(i=1;i<argc;i++) {
- if(argv[i][0]!='-')
- fprintf(stderr,"Unknown option: %s\n",argv[i]);
- else if(argv[i][1]=='f') /* f as in fortran */
- mknb_fortran = 1;
- else if(argv[i][1]=='d') /* d as in double */
- mknb_double = 1;
- else if(argv[i][1]=='t') /* t as in threads */
- mknb_options.threads = 1;
- else if(argv[i][1]=='s') /* s as in software_invsqrt */
- mknb_options.software_invsqrt = 1;
- else if(argv[i][1]=='p' && argv[i][2]=='p') /* pp as in ppc_invsqrt */
- {
- /* Check if it says -ppc_invsqrt=1 , otherwise assume 2 */
- if( (ch=strchr(argv[i],'=')) != NULL && *(++ch)=='1')
- {
- mknb_options.ppc_invsqrt = 1;
- }
- else
- {
- mknb_options.ppc_invsqrt = 2;
- }
- }
- else if(argv[i][1]=='p') /* p as in prefetch_forces (but not pp) */
- mknb_options.prefetch_forces = 1;
- else if(argv[i][1]=='c') /* c as in comments */
- mknb_keep_comments = 1;
- else if(argv[i][1]=='h') { /* h as in help */
- fprintf(stderr,
- "Available options:\n"
- " -fortran Write Fortran77 code instead of C\n"
- " -double Use double precision iso. single\n"
- " -threads Write kernels with thread support\n"
- " -software_invsqrt Use Gromacs software for 1/sqrt(x)\n"
- " -ppc_invsqrt Use PowerPC intrinsics for 1/sqrt(x)\n"
- " (even better: -ppc_invsqrt=1 for pwr4/ppc440/450)\n"
- " -prefetch_forces Prefetch force memory in loops\n"
- " -comments Write comments in output files\n\n");
- exit(0);
- }
- }
-
-
- fprintf(stderr,">>> Generating %s%s precision functions in %s.\n",
- (mknb_options.threads==1) ? "multithreaded " : "",
- (mknb_double) ? "double" : "single",
- (mknb_fortran) ? "Fortran77" : "C");
- if(mknb_options.software_invsqrt)
- fprintf(stderr,">>> Using Gromacs software version of 1/sqrt(x).\n");
-
- if(mknb_options.ppc_invsqrt>0)
- fprintf(stderr,">>> Using PowerPC intrinsics for 1/sqrt(x) table (%d iterations for %s precision).\n",
- mknb_double ? mknb_options.ppc_invsqrt+1 : mknb_options.ppc_invsqrt,
- mknb_double ? "double" : "single");
-
- if(mknb_options.prefetch_forces)
- fprintf(stderr,">>> Prefetching forces in loops.\n");
-
-
- /* Start to write the nonbonded functions.
- *
- * To speed up the compile on SMP machines we
- * use one file for each combination of Coulomb & VdW
- * interactions. Every file then contains the standard
- * version of the function, and functions otimized for water.
- * Finally, we also write versions of the functions without forces,
- * which can be significantly faster for MC simulations.
- */
-
- nfiles=0;
- /* Loop over all combinations to construct nonbonded functions.
- * mknb_func is a global variable structure in mknb.c.
- */
-
- /* Coulomb interaction alteratives */
- for(mknb_func.coul=MKNB_COUL_NO;
- mknb_func.coul<MKNB_COUL_NR;
- mknb_func.coul = (enum mknb_coul)(mknb_func.coul + 1)) {
-
- /* VdW interaction alternatives */
- for(mknb_func.vdw=MKNB_VDW_NO;
- mknb_func.vdw<MKNB_VDW_NR;
- mknb_func.vdw = (enum mknb_vdw)(mknb_func.vdw + 1)) {
-
- /* Skip the case when we dont have any interaction at all */
- if(mknb_func.coul==MKNB_COUL_NO && mknb_func.vdw==MKNB_VDW_NO)
- continue;
-
- /* Water optimization alternatives */
- for(mknb_func.water=MKNB_WATER_NO;
- mknb_func.water<MKNB_WATER_NR;
- mknb_func.water = (enum mknb_water)(mknb_func.water + 1)) {
-
- /* Water optimization is useless without coulomb */
- if(mknb_func.coul==MKNB_COUL_NO &&
- mknb_func.water!=MKNB_WATER_NO)
- continue;
-
- /* Only do Generalized-Born for non-water loops */
- if(mknb_func.coul==MKNB_COUL_GB &&
- mknb_func.water!=MKNB_WATER_NO)
- continue;
-
- /* Open a new file for this function type */
-#ifdef IBM_FORTRAN_CPP
- sprintf(filename,"pwr6kernel%d%d%d.F",
- mknb_func.coul,mknb_func.vdw,mknb_func.water);
-#else
- sprintf(filename,"nb_kernel%d%d%d_%s.%s",
- mknb_func.coul,mknb_func.vdw,mknb_func.water,
- (mknb_fortran) ? "f" : "c",
- (mknb_fortran) ? "f" : "c");
-#endif
-
- /* Make sure that we can open it */
- if( (mknb_output = fopen(filename,"w")) == NULL ) {
- fprintf(stderr,"Error: Cannot open %s for writing.\n",
- filename);
- exit(1);
- }
-
- /* Write a header for the entire file */
- mknb_write_file_header();
-
- /* Write two kernels. First one with force, then without. */
- for(i=0;i<=1;i++) {
- mknb_func.do_force=(i==0);
-
- mknb_write_function();
- }
-
- /* Close the file */
- fclose(mknb_output);
-
- /* Wrote one more without crashing - be happy! */
- nfiles++;
-
- /* Apparently we have 67 files in total now... */
- fprintf(stderr,"\rProgress: %2d%%",100*nfiles/67);
- }
- }
- }
- fprintf(stderr,"\n");
-
- /* Touch a stamp-file to show that kernels have been updated */
- fp = fopen("kernel-stamp","w");
- /* Just write something so the file is not empty, otherwise the
- * time-stamping will not work e.g. on AFS.
- */
- fprintf(fp,"kernel-stamp\n");
- fclose(fp);
-
- return 0;
-}
-
-
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-
-#include <mknb_common.h>
-
-/* This file just contains the global variables for make_nb_kernels,
- * as defined in mknb_common.h. Global variables are B*A*D, but all the
- * function calls in the generator would be much more complicated
- * without them, and that feels a bit unnecessary...
- *
- * It's only executed at compile-time anyway :-)
- */
-
-
-
-
-/* Coulomb interaction alternatives */
-const char *
-mknb_coul_names[MKNB_COUL_NR] = {
- "Not calculated",
- "Normal Coulomb",
- "Reaction field",
- "Tabulated",
- "Generalized-Born"
-};
-
-
-/* VdW interaction alternatives */
-const char *
-mknb_vdw_names[MKNB_VDW_NR] = {
- "Not calculated",
- "Lennard-Jones",
- "Buckingham",
- "Tabulated"
-};
-
-
-/* Water optimization alternatives */
-const char *
-mknb_water_names[MKNB_WATER_NR] = {
- "No",
- "SPC/TIP3P - other atoms",
- "pairs of SPC/TIP3P interactions",
- "TIP4P - other atoms",
- "pairs of TIP4P interactions"
-};
-
-
-
-/* General program options, see mknb_common.h for definition of type.
- */
-struct mknb_options
-mknb_options;
-
-
-
-/* Options for the kernel currently being generated. Definition in mknb_common.h.
- */
-struct mknb_func
-mknb_func;
-
-
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-#ifndef _MKNB_H_
-#define _MKNB_H_
-
-
-
-/*! \file mknb_common.h
- * \brief Kernel generator (only for compile): Typedefs/variables
- *
- * \internal
- *
- * \note This file is only used to generate the inner loop kernels
- * at compile time, which in turn are included in Gromacs.
- * This code itself is NOT linked into the Gromacs library, so
- * it does not need to be threadsafe.
- *
- * mknb_common.h contains definitions of enumerated types and structures
- * used in the nonbonded kernel generator itself, i.e. not in
- * the generated code. Declarations for the generated code are
- * in the file mknb_declarations.c
- */
-
-
-
-/*! \brief Kernel generator (only for compile): Options from command line.
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * The options in this structure control the overall behavior of
- * the kernel generator, for instance whether threads and/or software
- * inverse square root is used.
- *
- * For each alternative, 1 means enabled, and 0 disabled.
- */
-struct mknb_options
-{
- int threads; /*!< Create kernels with thread support */
- int software_invsqrt; /*!< Use software optimization of 1/sqrt */
- int ppc_invsqrt; /*!< Use IBM PowerPC intrinsics of 1/sqrt */
- int prefetch_forces; /*!< Prefetch forces in innermost loop */
-};
-
-
-
-
-/*! \brief Kernel generator (only for compile): Coulomb interaction alternatives
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Type of Coulomb interaction to generate in a
- * nonbonded kernel. There are different kernels for different
- * alternatives, so the generator code will be looping over these.
- *
- * Make sure you update the text descriptions in mknb_coul_names
- * if you change this.
- */
-enum mknb_coul {
- MKNB_COUL_NO, /*!< No Coulomb interaction */
- MKNB_COUL_NORMAL, /*!< Standard 1/r Coulomb interaction */
- MKNB_COUL_RF, /*!< Reaction-Field Coulomb */
- MKNB_COUL_TAB, /*!< Tabulated Coulomb */
- MKNB_COUL_GB, /*!< Generalized Born Coulomb */
- MKNB_COUL_NR /*!< Number of choices for Coulomb */
-};
-
-
-
-
-/*! \brief Kernel generator (only for compile): Van der Waals interaction alternatives
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Type of Van der Waals interaction to generate in a
- * nonbonded kernel. There are different kernels for different
- * alternatives, so the generator code will be looping over these.
- *
- * Make sure you update the text descriptions in mknb_vdw_names
- * if you change this.
- */
-enum mknb_vdw {
- MKNB_VDW_NO, /*!< No Van der Waals interaction */
- MKNB_VDW_LJ, /*!< Lennard-Jones 6-12 interactions */
- MKNB_VDW_BHAM, /*!< Buckingham 6-exp interactions */
- MKNB_VDW_TAB, /*!< Tabulated VdW interactions */
- MKNB_VDW_NR /*!< Number of choices for Vdw */
-};
-
-
-
-/*! \brief Kernel generator (only for compile): Water optimization alternatives
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Since water is extremely common in biological systems, Gromacs
- * includes special nonbonded kernels optimized for interactions between
- * water molecules and other atoms, as well as interactions between
- * pairs of water molecules to improve performance.
- *
- * Make sure you update the text descriptions in mknb_water_names
- * if you change this.
- */
-enum mknb_water {
- MKNB_WATER_NO, /*!< No water optimization */
- MKNB_WATER_SPC_SINGLE, /*!< 3-atom water - other atom (SPC,TIP3P) */
- MKNB_WATER_SPC_PAIR, /*!< 3-atom water - 3-atom water (SPC,TIP3P) */
- MKNB_WATER_TIP4P_SINGLE, /*!< 4-atom water - other atom (TIP4P) */
- MKNB_WATER_TIP4P_PAIR, /*!< 4-atom water - 4-atom water (TIP4P) */
- MKNB_WATER_NR /*!< Number of choices for water optimization */
-};
-
-
-
-
-/*! \brief Kernel generator (only for compile): Text for enum mknb_coul
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Make sure you update these when you change the enumerated
- * alternatives in enum mknb_coul.
- */
-extern const char *
-mknb_coul_names[MKNB_COUL_NR];
-
-
-
-
-/*! \brief Kernel generator (only for compile): Text for enum mknb_vdw
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Make sure you update these when you change the enumerated
- * alternatives in enum mknb_vdw.
- */
-extern const char *
-mknb_vdw_names[MKNB_VDW_NR];
-
-
-
-
-/*! \brief Kernel generator (only for compile): Text for enum mknb_water
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Make sure you update these when you change the enumerated
- * alternatives in enum mknb_water.
- */
-extern const char *
-mknb_water_names[MKNB_WATER_NR];
-
-
-
-
-/*! \brief Kernel generator (only for compile): Options for a nonbonded kernel
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Some fields deserve a comment:
- *
- * ni,nj: * For a normal (non-water) kernel we treat one atom
- * per iteration in both the outer and inner loop. Then ni=nj=1.
- * In water-optimized kernels we use 3 (SPC/TIP3P) or 4 (TIP4P)
- * atoms in the outer loop (ni=3/4, nj=1). Finally, in kernels
- * optimized for water-water interactions you have multiple
- * atoms in the inner loop too, i.e. ni=nj=3 (or 4).
- *
- * table_element_size: Each interaction uses four floating-point
- * variables per table point. To optimize, we merge the Coulomb
- * and VdW tables into a single structure if both are tabulated,
- * i.e. depending on the type of interaction the kernel is called
- * either with a table containing only Coulomb, only VdW, or both.
- * I.e., table_element_size is 4 if only Coulomb is tabulated,
- * 8 if only VdW is tabulated, and 12 if both are tabulated.
- *
- * nvdw_parameters: Lennard-Jones interactions use 2 (c6 & c12),
- * while Buckingham interactions need 3 (c6 & a & b).
- */
-struct mknb_func {
- char name[32]; /*!< Name for this kernel */
- enum mknb_coul coul; /*!< Type of Coulomb interaction */
- enum mknb_vdw vdw; /*!< Type of VdW interaction */
- enum mknb_water water; /*!< Water optimization type */
- int ni; /*!< Number of atoms in outerloop */
- int nj; /*!< Number of atoms in innerloop */
- int do_force; /*!< Calculate Forces in loop? */
- int table_element_size;/*!< Number of floats/table point */
- int nvdw_parameters; /*!< LJ needs 2, Buckingham 3 */
-};
-
-
-
-
-/*! \brief Kernel generator (only for compile): Global variable for general mknb options.
- *
- * \internal
- *
- * Variable is defined in mknb_common.c
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * The fields in this structure are set when the program is
- * started, and specifies general options like thread support, software
- * inverse square root, force prefetching.
- */
-extern struct mknb_options
-mknb_options;
-
-
-
-
-/*! \brief Kernel generator (only for compile): Global variable for current kernel options.
- *
- * \internal
- *
- * Variable is defined in mknb_common.c
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * The fields in this structure are updated before each new kernel is
- * generated, and determine the type of interactions, water optimization,
- * etc.
- */
-extern struct mknb_func
-mknb_func;
-
-
-
-
-
-
-#endif /* _MKNB_H_ */
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-
-/* This file is NOT threadsafe, but it is only used to create
- * the nonbonded functions during the build process, so it will never be
- * executed by multiple threads.
- */
-
-#include <string.h>
-#include <stdlib.h>
-
-
-#include <mknb_common.h>
-#include <mknb_declarations.h>
-#include <mknb_metacode.h>
-
-
-void
-mknb_function_header(char *funcname)
-{
-
- /* Important - make sure the C and Fortran declarations match...
- * The rest here is just pretty formatting that we could live without.
- */
- if(!mknb_fortran) {
-
-#define C_REAL (mknb_double ? "double *" : "float *")
-
- fprintf(mknb_output,"void %s(\n",funcname);
- fprintf(mknb_output,"%19s %-8s %6s p_nri,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s iinr,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s jindex,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s jjnr,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s shift,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s shiftvec,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s fshift,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s gid,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s pos,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s faction,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s charge,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s p_facel,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s p_krf,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s p_crf,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s Vc,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s type,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s p_ntype,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s vdwparam,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s Vvdw,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s p_tabscale,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s VFtab,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s invsqrta,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s dvda,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s p_gbtabscale,\n","", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s GBtab,\n", "", C_REAL, "");
- fprintf(mknb_output,"%19s %-8s %6s p_nthreads,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s count,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s mtx,\n", "", "void *", "");
- fprintf(mknb_output,"%19s %-8s %6s outeriter,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s inneriter,\n", "", "int *", "");
- fprintf(mknb_output,"%19s %-8s %6s work)\n{", "", C_REAL, "");
-
-#undef C_REAL
-
- } else {
-
- /* Fortran */
-
- fprintf(mknb_output," subroutine %s(\n",funcname);
- fprintf(mknb_output," & nri,\n");
- fprintf(mknb_output," & iinr,\n");
- fprintf(mknb_output," & jindex,\n");
- fprintf(mknb_output," & jjnr,\n");
- fprintf(mknb_output," & shift,\n");
- fprintf(mknb_output," & shiftvec,\n");
- fprintf(mknb_output," & fshift,\n");
- fprintf(mknb_output," & gid,\n");
- fprintf(mknb_output," & pos,\n");
- fprintf(mknb_output," & faction,\n");
- fprintf(mknb_output," & charge,\n");
- fprintf(mknb_output," & facel,\n");
- fprintf(mknb_output," & krf,\n");
- fprintf(mknb_output," & crf,\n");
- fprintf(mknb_output," & Vc,\n");
- fprintf(mknb_output," & type,\n");
- fprintf(mknb_output," & ntype,\n");
- fprintf(mknb_output," & vdwparam,\n");
- fprintf(mknb_output," & Vvdw,\n");
- fprintf(mknb_output," & tabscale,\n");
- fprintf(mknb_output," & VFtab,\n");
- fprintf(mknb_output," & invsqrta,\n");
- fprintf(mknb_output," & dvda,\n");
- fprintf(mknb_output," & gbtabscale,\n");
- fprintf(mknb_output," & GBtab,\n");
- fprintf(mknb_output," & nthreads,\n");
- fprintf(mknb_output," & count,\n");
- fprintf(mknb_output," & mtx,\n");
- fprintf(mknb_output," & outeriter,\n");
- fprintf(mknb_output," & inneriter,\n");
- fprintf(mknb_output," & work)\n");
-
- /* Declare fortran call arguments after header */
-
- mknb_declare_other("implicit","none");
- mknb_declare_int("nri,iinr(*),jindex(*),jjnr(*),shift(*)");
- mknb_declare_real("shiftvec(*),fshift(*),pos(*),faction(*)");
- mknb_declare_int("gid(*),type(*),ntype");
- mknb_declare_real("charge(*),facel,krf,crf,Vc(*),vdwparam(*)");
- mknb_declare_real("Vvdw(*),tabscale,VFtab(*)");
- mknb_declare_real("invsqrta(*),dvda(*),gbtabscale,GBtab(*)");
-
- /*
- * mask the mutex pointer as an integer passed by
- * reference when using fortran, or as placeholder
- */
- mknb_declare_int("nthreads,count,mtx,outeriter,inneriter");
-
- /* Workspace */
- mknb_declare_real("work(*)");
-
- }
- fprintf(mknb_output,"\n");
-}
-
-
-void
-mknb_finish_function()
-{
-
- mknb_comment("Write outer/inner iteration count to pointers");
- mknb_assign( mknb_fortran ? "outeriter" : "*outeriter" ,
- mknb_options.threads ? "nouter" : "nri");
- mknb_assign( mknb_fortran ? "inneriter" : "*inneriter" ,
- mknb_options.threads ? "ninner" : "nj1");
-
- if(mknb_fortran) {
- mknb_code("return");
- mknb_code("end");
- } else {
- fprintf(mknb_output,"}");
- }
- fprintf(mknb_output,"\n\n\n");
-}
-
-
-void
-mknb_declare_variables()
-{
- int i,j,firsti,firstj;
- char buf[255],buf2[255];
-
- /* Never mind the if-statements when you are developing -
- * they are just there to avoid tons of warnings about
- * unused variables in the shipping code.
- * The for-statements have the same function - we only
- * declare what we need to make the generated code prettier.
- */
-
- /* Scalar versions of arguments passed by reference */
- if(!mknb_fortran) {
- mknb_declare_int("nri,ntype,nthreads");
- mknb_declare_real("facel,krf,crf,tabscale,gbtabscale");
- }
-
- /* loop indices and group id*/
- mknb_declare_int("n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid");
- if(mknb_options.threads)
- mknb_declare_int("nn0,nn1,nouter,ninner");
- mknb_declare_real("shX,shY,shZ"); /* shift vectors */
- /* scalar force and vectorial force */
- if(mknb_func.do_force)
- mknb_declare_real("fscal,tx,ty,tz");
-
- if((mknb_func.do_force &&
- (mknb_func.coul==MKNB_COUL_NORMAL || mknb_func.coul==MKNB_COUL_RF)) ||
- mknb_func.vdw==MKNB_VDW_LJ || mknb_func.vdw==MKNB_VDW_BHAM)
- mknb_declare_real("rinvsq");
-
- if(mknb_func.coul) {
- if(mknb_func.water==MKNB_WATER_NO)
- mknb_declare_real("iq");
- else if(mknb_func.water==MKNB_WATER_SPC_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_SINGLE)
- mknb_declare_real("jq");
- mknb_declare_real("qq,vcoul,vctot");
- }
-
- if(mknb_func.vdw) {
- if(mknb_func.water!=MKNB_WATER_SPC_PAIR &&
- mknb_func.water!=MKNB_WATER_TIP4P_PAIR)
- mknb_declare_int("nti");
- mknb_declare_int("tj");
- if(mknb_func.vdw!=MKNB_VDW_TAB)
- mknb_declare_real("rinvsix");
- mknb_declare_real("Vvdw6,Vvdwtot");
- if(mknb_func.vdw!=MKNB_VDW_BHAM)
- mknb_declare_real("Vvdw12");
- }
-
- if(mknb_func.coul==MKNB_COUL_TAB || mknb_func.coul==MKNB_COUL_GB ||
- mknb_func.vdw==MKNB_VDW_TAB) {
- mknb_declare_real("r,rt,eps,eps2");
- mknb_declare_int("n0,nnn");
- mknb_declare_real("Y,F,Geps,Heps2,Fp,VV");
- if(mknb_func.do_force) {
- mknb_declare_real("FF");
- if(mknb_func.coul==MKNB_COUL_TAB || mknb_func.coul==MKNB_COUL_GB)
- mknb_declare_real("fijC");
- if(mknb_func.vdw==MKNB_VDW_TAB)
- mknb_declare_real("fijD,fijR");
- }
- }
- if(mknb_func.coul==MKNB_COUL_RF)
- mknb_declare_real("krsq");
- if(mknb_func.coul==MKNB_COUL_GB) {
- mknb_declare_real("isai,isaj,isaprod,gbscale,vgb");
- if(mknb_func.do_force)
- mknb_declare_real("dvdasum,dvdatmp,dvdaj,fgb");
- }
-
- if(mknb_func.vdw==MKNB_VDW_BHAM)
- mknb_declare_real("Vvdwexp,br");
-
- /* TIP4P water doesnt have any coulomb interaction
- * on atom 1, so we skip it if we dont do LJ
- */
- /* check for outer/i atom */
- firsti = ((mknb_func.vdw==MKNB_VDW_NO) &&
- (mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR)) ? 2 : 1;
-
- /* inner/j atom */
- firstj = ((mknb_func.vdw==MKNB_VDW_NO) &&
- (mknb_func.water==MKNB_WATER_TIP4P_PAIR)) ? 2 : 1;
-
- /* i coordinates and forces */
- for(i=firsti;i<=mknb_func.ni;i++) {
- sprintf(buf,"ix%d,iy%d,iz%d",i,i,i);
- if(mknb_func.do_force) {
- sprintf(buf2,",fix%d,fiy%d,fiz%d",i,i,i);
- strcat(buf,buf2);
- }
- mknb_declare_real(buf);
- }
- /* j coordinates and forces */
- for(j=firstj;j<=mknb_func.nj;j++) {
- sprintf(buf,"jx%d,jy%d,jz%d",j,j,j);
- if(mknb_func.do_force &&
- (mknb_func.water || mknb_options.prefetch_forces)) {
- if(!(mknb_func.water==MKNB_WATER_TIP4P_PAIR && j==1) ||
- mknb_options.prefetch_forces) {
- sprintf(buf2,",fjx%d,fjy%d,fjz%d",j,j,j);
- strcat(buf,buf2);
- }
- }
- mknb_declare_real(buf);
- }
- /* i-j vectorial distance, rsq and rinv. */
- for(i=firsti;i<=mknb_func.ni;i++) {
- for(j=firstj;j<=mknb_func.nj;j++) {
- /* For TIP4p, site 1 never interacts with site 2,3,4 */
- if(mknb_func.water==MKNB_WATER_TIP4P_PAIR &&
- ((i==1 && j>1) || (j==1 && i>1)))
- continue;
- sprintf(buf,"dx%d%d,dy%d%d,dz%d%d,rsq%d%d",
- i,j,i,j,i,j,i,j);
- if(mknb_func.coul || mknb_func.vdw!=MKNB_VDW_LJ) {
- if(!((mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR) &&
- i==1 && j==1 && mknb_func.vdw==MKNB_VDW_LJ)) {
- sprintf(buf2,",rinv%d%d",i,j);
- strcat(buf,buf2);
- }
- }
- mknb_declare_real(buf);
- }
- }
-
- /* The water charges and VdW parameters dont change,
- * so we can determine them outside the mknb_func.
- */
- if(mknb_func.water==MKNB_WATER_SPC_SINGLE)
- mknb_declare_real("qO,qH");
- else if(mknb_func.water==MKNB_WATER_TIP4P_SINGLE)
- mknb_declare_real("qH,qM");
-
- if(mknb_func.water==MKNB_WATER_SPC_PAIR)
- mknb_declare_real("qO,qH,qqOO,qqOH,qqHH");
- if(mknb_func.water==MKNB_WATER_TIP4P_PAIR)
- mknb_declare_real("qH,qM,qqMM,qqMH,qqHH");
-
- if(mknb_func.vdw==MKNB_VDW_BHAM)
- mknb_declare_real("c6,cexp1,cexp2");
- else if(mknb_func.vdw!=MKNB_VDW_NO)
- mknb_declare_real("c6,c12");
-
- /* Variables needed for the inlined software inverse square root */
- if(mknb_options.software_invsqrt &&
- (mknb_func.coul || mknb_func.vdw==MKNB_VDW_BHAM ||
- mknb_func.vdw==MKNB_VDW_TAB)) {
- mknb_declare_const_int("fractshift",12);
- mknb_declare_const_int("fractmask",8388607);
- mknb_declare_const_int("expshift",23);
- mknb_declare_const_int("expmask",2139095040);
- mknb_declare_const_int("explsb",8388608);
- mknb_declare_real4("lu");
- mknb_declare_int4("iexp,addr");
- /* To do bitwise manipulation of a FP number we need to move
- * it back and forth between floating point and integer registers,
- * without converting the actual data.
- */
- if(mknb_fortran) {
- mknb_declare_int4("bval,result");
- mknb_declare_real4("fval");
- mknb_code("equivalence(bval,fval)");
- mknb_code("equivalence(result,lu)");
- mknb_declare_int4("invsqrtexptab,invsqrtfracttab");
- mknb_code("common /gmxinvsqrtdata/ invsqrtexptab(256),invsqrtfracttab(4096)");
- } else {
- mknb_declare_other("union { unsigned int bval; float fval; }",
- "bitpattern,result");
- }
- }
- fprintf(mknb_output,"\n");
-}
-
-void
-mknb_initialize_data(void)
-{
- char buf[255];
-
- /* move arguments passed by reference to local scalars */
- if(!mknb_fortran) {
- mknb_assign("nri", "*p_nri");
- mknb_assign("ntype", "*p_ntype");
- mknb_assign("nthreads", "*p_nthreads");
- mknb_assign("facel", "*p_facel");
- mknb_assign("krf", "*p_krf");
- mknb_assign("crf", "*p_crf");
- mknb_assign("tabscale", "*p_tabscale");
- if(mknb_func.coul==MKNB_COUL_GB)
- {
- mknb_assign("gbtabscale", "*p_gbtabscale");
- }
- }
-
- /* assign the charge combinations for OO,OH and HH,
- * or HH/HL/LL for TIP4P/TIP5P
- */
- /* we're always doing coulomb */
- if(mknb_func.water) {
- mknb_comment("Initialize water data");
-
- mknb_assign("ii", "%s%s",
- mknb_array("iinr",(mknb_fortran) ? "1" : "0"),
- (mknb_fortran) ? "+1" : "");
- switch(mknb_func.water) {
- case MKNB_WATER_SPC_SINGLE:
- mknb_assign("qO", "facel*%s", mknb_array("charge","ii"));
- mknb_assign("qH", "facel*%s", mknb_array("charge","ii+1"));
- break;
- case MKNB_WATER_TIP4P_SINGLE:
- mknb_assign("qH", "facel*%s", mknb_array("charge","ii+1"));
- mknb_assign("qM", "facel*%s", mknb_array("charge","ii+3"));
- break;
- case MKNB_WATER_SPC_PAIR:
- mknb_assign("qO", mknb_array("charge","ii"));
- mknb_assign("qH", mknb_array("charge","ii+1"));
- mknb_assign("qqOO","facel*qO*qO");
- mknb_assign("qqOH","facel*qO*qH");
- mknb_assign("qqHH","facel*qH*qH");
- break;
- case MKNB_WATER_TIP4P_PAIR:
- mknb_assign("qH", mknb_array("charge","ii+1"));
- mknb_assign("qM", mknb_array("charge","ii+3"));
- mknb_assign("qqMM","facel*qM*qM");
- mknb_assign("qqMH","facel*qM*qH");
- mknb_assign("qqHH","facel*qH*qH");
- break;
- default:
- printf("Error, unidentified water model (mknb_declarations.c)\n");
- exit(0);
- }
-
- if((mknb_func.water==MKNB_WATER_SPC_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_SINGLE) && mknb_func.vdw)
- {
- mknb_assign("nti","%d*ntype*%s",
- mknb_func.nvdw_parameters,
- mknb_array("type","ii"));
- }
-
- /* assign the nonbonded combination for the
- * Oxygen-oxygen interactions
- */
- if((mknb_func.water==MKNB_WATER_SPC_PAIR ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR) && mknb_func.vdw) {
- sprintf(buf,"%d*(ntype+1)*%s%s",mknb_func.nvdw_parameters,
- mknb_array("type","ii"), (mknb_fortran) ? "+1" : "");
- mknb_assign("tj",buf);
- mknb_assign("c6",mknb_array("vdwparam","tj"));
- if(mknb_func.vdw==MKNB_VDW_BHAM) {
- mknb_assign("cexp1",mknb_array("vdwparam","tj+1"));
- mknb_assign("cexp2",mknb_array("vdwparam","tj+2"));
- } else
- mknb_assign("c12",mknb_array("vdwparam","tj+1"));
- }
- fprintf(mknb_output,"\n");
- }
-
- mknb_comment("Reset outer and inner iteration counters");
-
- if(mknb_options.threads)
- {
- mknb_assign("nouter","0");
- mknb_assign("ninner","0");
- }
- else
- {
- mknb_comment("Avoid compiler warning about unassigned variable");
- mknb_assign("nj1","0");
- }
-}
-
-
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-#ifndef _MKNB_DECLARATIONS_H_
-#define _MKNB_DECLARATIONS_H_
-
-
-/*! \file mknb_declarations.h
- * \brief Kernel generator (only for compile): Function declarations
- *
- * \internal
- *
- * \note This file is only used to generate the inner loop kernels
- * at compile time, which in turn are included in Gromacs.
- * This code itself is NOT linked into the Gromacs library, so
- * it does not need to be threadsafe.
- *
- * This file is only used to generate the inner loop kernels
- * at compile time, which in turn are included in Gromacs.
- * This code itself is NOT linked into the Gromacs library, so
- * it does not need to be threadsafe.
- *
- * mknb_declarations.h provides routines to generate function
- * headers for nonbonded interaction kernels in either C or
- * Fortran, routines to declare local variables and local data
- * initialization before the actual loop starts.
- *
- * Definitions and structures used in the nonbonded kernel
- * generator itself (i.e. not in the generated code) are in
- * the file mknb_common.h.
- */
-
-
-
-/*! \brief Kernel generator (only for compile): Function definition and header
- *
- * \internal
- *
- * \note Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.
- *
- * All level1/level2 Gromacs nonbonded kernels use the same
- * parameters, so the only difference here is the function
- * name and the language used.
- *
- * \param funcname Name of the nonbonded kernel to write
- */
-void
-mknb_function_header (char * funcname);
-
-
-
-/*! \brief Kernel generator (only for compile): Local function variables
- *
- * \internal
- *
- * \note Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.
- *
- * This routine tries to determine which variables will
- * be needed based on the current values in the global
- * variable 'func', which containts the current settings
- * for Coulomb/L-J interactions, water optimization, etc.
- */
-void
-mknb_declare_variables (void);
-
-
-
-/*! \brief Kernel generator (only for compile): Init code before loop
- *
- * \internal
- *
- * \note Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.
- *
- * Some nonbonded kernels (mainly water optimized ones)
- * extracts parameters or similar things outside the
- * outer loop for better performance. This code should
- * be run after mknb_declare_variables(), but before
- * the outer loop is started.
- */
-void
-mknb_initialize_data (void);
-
-
-
-/*! \brief Kernel generator (only for compile): Close a function body.
- *
- * \internal
- *
- * \note Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.
- *
- * This finishes a function previously started with
- * mknb_function_header().
- *
- */
-void
-mknb_finish_function (void);
-
-
-
-
-#endif /* _MKNB_DECLARATIONS_H_ */
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-
-/* This file is NOT threadsafe, but it is only used to create
- * the nonbonded functions during the build process, so it will never be
- * executed by multiple threads.
- */
-#include <mknb_common.h>
-#include <mknb_interactions.h>
-#include <mknb_metacode.h>
-
-int
-ppc_invsqrt(char *rsq, char *rinv)
-{
- int nflops = 1;
-
- mknb_comment("PowerPC intrinsics 1/sqrt lookup table");
-
- /* fsqrte step */
-
- if (mknb_double) {
- if (mknb_fortran) {
- mknb_assign (rinv,"frsqrte(%s)",rsq);
- } else {
- mknb_assign (rinv,"__frsqrte(%s)",rsq);
- }
- } else {
- /* Frsqrtes is only supported on Power5 and higher, but no use in optimizing old HW! */
- if (mknb_fortran) {
- mknb_assign (rinv,"frsqrtes(%s)",rsq);
- } else {
- mknb_assign (rinv,"__frsqrtes(%s)",rsq);
- }
- }
-
- /* Newton-Rhapson iteration step */
- mknb_assign(rinv,"(0.5*%s*(3.0-((%s*%s)*%s)))",rinv,rsq,rinv,rinv);
- nflops += 5; /* 4 mult and one sub on the last line */
-
- if(mknb_options.ppc_invsqrt==2)
- {
- /* Older powerpc architectures need two iterations for single, 3 for double */
- mknb_assign(rinv,"(0.5*%s*(3.0-((%s*%s)*%s)))",rinv,rsq,rinv,rinv);
- nflops += 5;
- }
-
- if(mknb_double) {
- mknb_assign(rinv,"(0.5*%s*(3.0-((%s*%s)*%s)))",rinv,rsq,rinv,rinv);
- nflops += 5; /* 4 mult and one sub on the last line */
- }
-#ifdef IBM_FORTRAN_CPP
- fprintf(mknb_output,"#ifdef GMX_DOUBLE\n");
- mknb_assign(rinv,"(0.5*%s*(3.0-((%s*%s)*%s)))",rinv,rsq,rinv,rinv);
- fprintf(mknb_output,"#endif\n");
-#endif
- return nflops;
-}
-
-
-int
-software_invsqrt(char *rsq, char *rinv)
-{
- int nflops = 0;
-
- mknb_comment("Gromacs software 1/sqrt");
- /* table lookup step */
- mknb_assign ( (mknb_fortran) ? "fval" : "bitpattern.fval", rsq);
-
- if(mknb_fortran) {
- mknb_assign("iexp","rshift(and(bval,expmask),expshift)");
- mknb_assign("addr","rshift(and(bval,or(fractmask,explsb)),fractshift)");
- mknb_assign("result","or(invsqrtexptab(iexp+1),invsqrtfracttab(addr+1))");
- } else {
- mknb_assign("iexp","(((bitpattern.bval)&expmask)>>expshift)");
- mknb_assign("addr","(((bitpattern.bval)&(fractmask|explsb))>>fractshift)");
-
- mknb_assign("result.bval",
- "gmx_invsqrt_exptab[iexp] | gmx_invsqrt_fracttab[addr]");
- mknb_assign("lu", "result.fval");
- }
-
- /* Newton-Rhapson iteration step */
- mknb_assign(rinv,"(0.5*lu*(3.0-((%s*lu)*lu)))",rsq);
- nflops += 5; /* 4 mult and one sub on the last line */
- if(mknb_double) {
- mknb_assign(rinv,"(0.5*%s*(3.0-((%s*%s)*%s)))",rinv,rsq,rinv,rinv);
- nflops += 5; /* 4 mult and one sub on the last line */
- }
- return nflops;
-}
-
-
-int
-mknb_load_inner_coordinates()
-{
- int j,firstj;
- char tmp[255];
-
- /* TIP4P water doesnt have any coulomb interaction
- * on atom 1, so we skip it if we dont do LJ
- */
- firstj = ((mknb_func.vdw==MKNB_VDW_NO) &&
- (mknb_func.water==MKNB_WATER_TIP4P_PAIR)) ? 2 : 1;
-
- mknb_comment("load j atom coordinates");
- for(j=firstj;j<=mknb_func.nj;j++) {
- sprintf(tmp,"j3+%d",3*(j-1));
- mknb_assign("jx%d","%s",j,mknb_array("pos",tmp));
- sprintf(tmp,"j3+%d",3*(j-1)+1);
- mknb_assign("jy%d","%s",j,mknb_array("pos",tmp));
- sprintf(tmp,"j3+%d",3*(j-1)+2);
- mknb_assign("jz%d","%s",j,mknb_array("pos",tmp));
- }
- /* Only assignment, no flops */
- return 0;
-}
-
-int
-mknb_calc_distance()
-{
- int i,j,firsti,firstj,nflops=0;
-
- /* TIP4P water doesnt have any coulomb interaction
- * on atom 1, so we skip it if we dont do LJ
- */
- if(mknb_func.vdw==MKNB_VDW_NO) {
- firsti = (mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR) ? 2 : 1;
- firstj = (mknb_func.water==MKNB_WATER_TIP4P_PAIR) ? 2 : 1;
- } else {
- firsti = 1;
- firstj = 1;
- }
-
- mknb_comment("Calculate distance");
- for(i=firsti;i<=mknb_func.ni;i++)
- for(j=firstj;j<=mknb_func.nj;j++) {
- /* For TIP4p, site 1 never interacts with site 2,3,4 */
- if(mknb_func.water==MKNB_WATER_TIP4P_PAIR &&
- ((i==1 && j>1) || (j==1 && i>1)))
- continue;
- mknb_assign("dx%d%d","ix%d - jx%d",i,j,i,j);
- mknb_assign("dy%d%d","iy%d - jy%d",i,j,i,j);
- mknb_assign("dz%d%d","iz%d - jz%d",i,j,i,j);
- mknb_assign("rsq%d%d","dx%d%d*dx%d%d+dy%d%d*dy%d%d+dz%d%d*dz%d%d",
- i,j,i,j,i,j,i,j,i,j,i,j,i,j);
-
- /* three subtractions, two adds and three multiplications */
- nflops += 8;
- }
- return nflops;
-}
-
-
-int
-mknb_prefetch_inner_forces()
-{
- int j,firstj,nflops=0;
- char tmp[255];
-
- /* TIP4P water doesnt have any coulomb interaction
- * on atom 1, so we skip it if we dont do LJ
- */
- firstj = ((mknb_func.vdw==MKNB_VDW_NO) &&
- (mknb_func.water==MKNB_WATER_TIP4P_PAIR)) ? 2 : 1;
-
- if(mknb_func.do_force) {
- mknb_comment("prefetch forces");
-
- for(j=firstj;j<=mknb_func.nj;j++) {
- sprintf(tmp,"j3+%d",3*(j-1));
- mknb_assign("fjx%d","%s",j,mknb_array("faction",tmp));
- sprintf(tmp,"j3+%d",3*(j-1)+1);
- mknb_assign("fjy%d","%s",j,mknb_array("faction",tmp));
- sprintf(tmp,"j3+%d",3*(j-1)+2);
- mknb_assign("fjz%d","%s",j,mknb_array("faction",tmp));
- }
- }
- return nflops;
-}
-
-
-int
-mknb_load_inner_parameters(int i,int j)
-{
- int nflops=0;
- char idx[255];
-
- /* For water-water functions all parameters are constant,
- * so we only assign them to the right variable. In
- * the other cases we also have to load the data.
- */
- mknb_comment("Load parameters for j atom");
-
- /* Coulomb parameters */
- if(mknb_func.coul) {
- if(mknb_func.water==MKNB_WATER_NO) {
- if(mknb_func.coul==MKNB_COUL_GB) {
- /* Generalized born: load 1/sqrt(a) */
- mknb_assign("isaj",mknb_array("invsqrta","jnr"));
- mknb_assign("isaprod","isai*isaj");
-
- /* GB-PL */
- mknb_assign("qq","iq*%s",mknb_array("charge","jnr"));
- mknb_assign("vcoul","qq*rinv%d%d",i,j);
-
- if(mknb_func.do_force)
- mknb_assign("fscal","vcoul*rinv%d%d",i,j);
-
- /* Save a flop by multiplying qq with isa1*isa2 already here */
- mknb_assign("qq","isaprod*(-qq)");
- mknb_assign("gbscale","isaprod*gbtabscale");
- nflops+=4;
- } else {
- /* Load normal (non-GB) charges */
- mknb_assign("qq","iq*%s",mknb_array("charge","jnr"));
- nflops++;
- }
- } else if(mknb_func.water==MKNB_WATER_SPC_SINGLE) {
- sprintf(idx,"jnr+%d",j-1);
- if(i==1)
- mknb_assign("jq", mknb_array("charge",idx));
- if(i==1 || i==2) {
- mknb_assign("qq","%s*jq", (i==1) ? "qO" : "qH");
- nflops++;
- }
- } else if(mknb_func.water==MKNB_WATER_TIP4P_SINGLE) {
- sprintf(idx,"jnr+%d",j-1);
- if(i==2)
- mknb_assign("jq", mknb_array("charge",idx));
- if(i==2 || i==4) {
- mknb_assign("qq","%s*jq", (i==4) ? "qM" : "qH");
- nflops++;
- }
- } else if(mknb_func.water==MKNB_WATER_SPC_PAIR) {
- if(i==1 && j==1)
- mknb_assign("qq","qqOO");
- else if(i>1 && j>1)
- mknb_assign("qq","qqHH");
- else
- mknb_assign("qq","qqOH");
- } else if(mknb_func.water==MKNB_WATER_TIP4P_PAIR) {
- if(i==1 || j==1) {
- /* Do nothing - site 1 is LJ-only in TIP4P */
- } else if(i==4 && j==4)
- mknb_assign("qq","qqMM");
- else if(i<4 && j<4)
- mknb_assign("qq","qqHH");
- else
- mknb_assign("qq","qqMH");
- }
- }
-
- /* VdW parameters */
- if(mknb_func.vdw) {
- if(mknb_func.water==MKNB_WATER_NO ||
- ((mknb_func.water==MKNB_WATER_SPC_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_SINGLE) && (i==1))) {
-
- mknb_assign("tj","nti+%d*%s%s",mknb_func.nvdw_parameters,
- mknb_array("type","jnr"), (mknb_fortran) ? "+1" : "");
-
- mknb_assign("c6",mknb_array("vdwparam","tj"));
-
- if(mknb_func.vdw==MKNB_VDW_BHAM) {
- mknb_assign("cexp1",mknb_array("vdwparam","tj+1"));
- mknb_assign("cexp2",mknb_array("vdwparam","tj+2"));
- } else {
- mknb_assign("c12",mknb_array("vdwparam","tj+1"));
- }
- }
- /* For water-water interactions the LJ parameters are constant
- * and calculate outside the loops.
- */
- }
- return nflops;
-}
-
-
-int
-mknb_calc_square_root()
-{
- int i,j,firsti,firstj,nflops=0;
- char tmp[255],tmp2[255];
-
- /* TIP4P water doesnt have any coulomb interaction
- * on atom 1, so skip it completely if we dont do LJ
- */
- if(mknb_func.vdw==MKNB_VDW_NO) {
- firsti = (mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR) ? 2 : 1;
- firstj = (mknb_func.water==MKNB_WATER_TIP4P_PAIR) ? 2 : 1;
- } else {
- firsti = 1;
- firstj = 1;
- }
-
- mknb_comment("Calculate 1/r and 1/r2");
- for(i=firsti;i<=mknb_func.ni;i++) {
- for(j=firstj;j<=mknb_func.nj;j++) {
- /* For TIP4p, site 1 never interacts with site 2,3,4 */
- if(mknb_func.water==MKNB_WATER_TIP4P_PAIR &&
- ((i==1 && j>1) || (j==1 && i>1)))
- continue;
- /* For LJ-only interactions we only need 1/rsq.
- * This is always true for the LJ-only site in TIP4P.
- */
- if( mknb_func.vdw==MKNB_VDW_LJ &&
- (mknb_func.coul==MKNB_COUL_NO ||
- ((i==1) && (mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR)))) {
- mknb_assign("rinvsq","1.0/rsq%d%d",i,j,i,j);
- nflops+=4; /* Estimate 1/x to 4 flops (SSE value) */
- } else {
- if(mknb_options.software_invsqrt) {
- sprintf(tmp,"rsq%d%d",i,j);
- sprintf(tmp2,"rinv%d%d",i,j);
- nflops += software_invsqrt(tmp,tmp2);
- } else if (mknb_options.ppc_invsqrt) {
- sprintf(tmp,"rsq%d%d",i,j);
- sprintf(tmp2,"rinv%d%d",i,j);
- nflops += ppc_invsqrt(tmp,tmp2);
- } else {
- mknb_assign("rinv%d%d","1.0/sqrt(rsq%d%d)",i,j,i,j);
- /* Estimate 1/sqrt(x) to 5 flops in single, 10 in double */
- nflops += mknb_double ? 10 : 5;
- }
- }
- }
- }
- return nflops;
-}
-
-void mknb_innerloop()
-{
- int i,j,firsti,firstj;
- int nflops = 0;
- int vdwsave,coulsave,read_from_mem,write_to_mem;
- char tmp[255],mem[255],var[255],rsq[255],rinv[255];
-
-
- mknb_start_loop("k", "nj0" ,"nj1");
-
- mknb_comment("Get j neighbor index, and coordinate index");
- mknb_assign("jnr", "%s%s", mknb_array("jjnr","k"),
- (mknb_fortran) ? "+1" : "");
- mknb_assign("j3","3*jnr%s", (mknb_fortran) ? "-2" : "");
-
- /* Load j particle coordinates */
- nflops += mknb_load_inner_coordinates();
-
- nflops += mknb_calc_distance();
-
- /* calculate inverse square root, except when we only do LJ coulomb -
- * in that case we only need 1/rsq and can use a faster division.
- * This also applies to the first atom in TIP4P water, which
- * only has LJ.
- */
- nflops += mknb_calc_square_root();
-
- if(mknb_func.do_force && mknb_options.prefetch_forces)
- nflops += mknb_prefetch_inner_forces();
-
- /* TIP4P water doesnt have any coulomb interaction
- * on atom 1, so skip it completely if we dont do LJ
- */
- if(mknb_func.vdw==MKNB_VDW_NO) {
- firsti = (mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR) ? 2 : 1;
- firstj = (mknb_func.water==MKNB_WATER_TIP4P_PAIR) ? 2 : 1;
- } else {
- firsti = 1;
- firstj = 1;
- }
-
- /* Do each interaction and update forces directly. */
-
- for(i=firsti;i<=mknb_func.ni;i++) {
- for(j=firstj;j<=mknb_func.nj;j++) {
- /* For TIP4P, site 1 never interacts with site 2,3,4 */
- if(mknb_func.water==MKNB_WATER_TIP4P_PAIR &&
- ((i==1 && j>1) || (j==1 && i>1)))
- continue;
-
- coulsave=mknb_func.coul;
- vdwsave=mknb_func.vdw;
-
- /* Do not do VdW for atoms 2,3,(4) in waters */
- if(i>1 || j>1)
- mknb_func.vdw=MKNB_VDW_NO;
-
- /* Do not do coulomb for atom 1 on TIP4P waters */
- if(((mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR) && i==1) ||
- (mknb_func.water==MKNB_WATER_TIP4P_PAIR && j==1))
- mknb_func.coul=MKNB_COUL_NO;
-
- /* load j atom parameters, and calculate charge products, etc. */
- nflops += mknb_load_inner_parameters(i,j);
-
- sprintf(rsq,"rsq%d%d",i,j);
- sprintf(rinv,"rinv%d%d",i,j);
-
- nflops += mknb_calculate_interaction(rsq,rinv);
-
- mknb_func.coul=coulsave;
- mknb_func.vdw=vdwsave;
-
- /* now we have the scalar force - update the forces if necessary */
- if(mknb_func.do_force) {
- mknb_comment("Calculate temporary vectorial force");
- mknb_assign("tx","fscal*dx%d%d",i,j);
- mknb_assign("ty","fscal*dy%d%d",i,j);
- mknb_assign("tz","fscal*dz%d%d",i,j);
- nflops += 3;
- /* increment i force */
- mknb_comment("Increment i atom force");
- mknb_assign("fix%d","fix%d + tx",i,i);
- mknb_assign("fiy%d","fiy%d + ty",i,i);
- mknb_assign("fiz%d","fiz%d + tz",i,i);
- nflops += 3;
- /* decrement j force.
- * The first time we access it we load from memory,
- * unless we already prefetched the forces above.
- * The last time the result is stored to memory.
- */
- mknb_comment("Decrement j atom force");
- /* Read from memory if we did not prefetch, if one of this is true:
- * Non-water
- * SPC_SINGLE, and i==1
- * TIP4P_SINGLE, and i==1, or i==2 if no LJ
- * SPC_PAIR, and i==1
- * TIP4P_PAIR, and i==1, or i==2.
- */
- read_from_mem = !mknb_options.prefetch_forces &&
- ((mknb_func.water==MKNB_WATER_NO) ||
- (mknb_func.water==MKNB_WATER_SPC_SINGLE && i==1) ||
- (mknb_func.water==MKNB_WATER_TIP4P_SINGLE &&
- (i==1 || (i==2 && mknb_func.vdw==MKNB_VDW_NO))) ||
- (mknb_func.water==MKNB_WATER_SPC_PAIR && i==1) ||
- (mknb_func.water==MKNB_WATER_TIP4P_PAIR && (i==1 || i==2)));
-
- /* Write the force directly to memory in these cases:
- * Non-water
- * SPC_SINGLE, and i==3
- * TIP4P_SINGLE, and i==1 or i==4.
- * SPC_PAIR, and i==3
- * TIP4P_PAIR, and i==1, or i==4.
- */
- write_to_mem =
- (mknb_func.water==MKNB_WATER_NO) ||
- (mknb_func.water==MKNB_WATER_SPC_SINGLE && i==3) ||
- (mknb_func.water==MKNB_WATER_TIP4P_SINGLE && i==4) ||
- (mknb_func.water==MKNB_WATER_SPC_PAIR && i==3) ||
- (mknb_func.water==MKNB_WATER_TIP4P_PAIR && (i==1 || i==4));
-
- sprintf(tmp,"j3+%d",3*(j-1));
- sprintf(mem,"%s",mknb_array("faction",tmp));
- sprintf(var,"fjx%d",j);
-
- mknb_assign( write_to_mem ? mem : var, "%s - tx",
- read_from_mem ? mem : var);
-
- sprintf(tmp,"j3+%d",3*(j-1)+1);
- sprintf(mem,"%s",mknb_array("faction",tmp));
- sprintf(var,"fjy%d",j);
-
- mknb_assign( write_to_mem ? mem : var, "%s - ty",
- read_from_mem ? mem : var);
-
- sprintf(tmp,"j3+%d",3*(j-1)+2);
- sprintf(mem,"%s",mknb_array("faction",tmp));
- sprintf(var,"fjz%d",j);
-
- mknb_assign( write_to_mem ? mem : var, "%s - tz",
- read_from_mem ? mem : var);
-
- nflops += 3; /* Decrementing j forces */
- }
- }
- }
- sprintf(tmp,"Inner loop uses %d flops/iteration",nflops);
- mknb_comment(tmp);
-
- mknb_end_loop();
-}
-
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-#ifndef _MKNB_INNERLOOP_H_
-#define _MKNB_INNERLOOP_H_
-
-
-/*! \file mknb_innerloop.h
- * \brief Kernel generator (only for compile): Loop over neighbors in lists
- *
- * \internal
- *
- * \note This file is only used to generate the inner loop kernels
- * at compile time, which in turn are included in Gromacs.
- * This code itself is NOT linked into the Gromacs library, so
- * it does not need to be threadsafe.
- *
- * This file is only used to generate the inner loop kernels
- * at compile time, which in turn are included in Gromacs.
- * This code itself is NOT linked into the Gromacs library, so
- * it does not need to be threadsafe.
- */
-
-
-/*! \brief Kernel generator (only for compile): Inner loop over neighbors.
- *
- * \internal
- *
- * \note Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.
- *
- * This routine will open a loop, load indices, coordinates and
- * parameters for the inner (also known as 'j') particle.
- * The vectorial distance to the outer ('i') particle is
- * calculated, squared, and used to calculate 1/r through an
- * inverse square root (often heavily optimized).
- *
- * The routine mknb_calculate_interaction() is called to
- * calculate the scalar force and potential between the two
- * particles, and when it returns we update the vectorial
- * force, subtract it on the 'j' particle and increment the
- * local force variable for the outer 'i' particle.
- *
- * The parameters to be loaded are determined by the current
- * values in the 'func' structure global to this file.
- */
-void
-mknb_innerloop(void);
-
-
-#endif /* _MKNB_INNERLOOP_H_ */
-
+++ /dev/null
-/*
- *
- * Gromacs 4.0 Copyright (c) 1991-2003
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-
-/* This file is NOT threadsafe, but it is only used to create
- * the nonbonded functions during the build process, so it will never be
- * executed by multiple threads.
- */
-
-#include <mknb_common.h>
-#include <mknb_metacode.h>
-
-#include <string.h>
-#include <stdlib.h>
-
-
-/* fscal terms to be mult. by -tabscale/r */
-static char
-fs_minus_tabscale_rinv[1024];
-
-
-/* fscal terms to be mult. by -1/r */
-static char
-fs_minus_rinv[1024];
-
-
-/* fscal terms to be mult. by 1/(r*r) */
-static char
-fs_rinvsq[1024];
-
-
-
-
-/* UTILITY ROUTINES FOR TABLE INTERACTIONS: */
-
-/* Calculate the table index from rsq and rinv */
-int
-mknb_calc_table_index(char *r)
-{
- int nflops = 0;
-
- mknb_comment("Calculate table index");
- mknb_assign("rt","r*tabscale");
- nflops++;
-
- /* Truncate rt to an integer. */
- mknb_assign("n0","rt");
-
- mknb_assign("eps","rt-n0");
- mknb_assign("eps2","eps*eps");
- nflops += 2;
-
- mknb_assign("nnn","%d*n0%s",mknb_func.table_element_size,
- (mknb_fortran) ? "+1" : "");
-
- return nflops;
-
-}
-
-/* Calculate the table index from rsq and rinv */
-int
-mknb_calc_gbtable_index(char *r)
-{
- int nflops = 0;
-
- mknb_comment("Calculate table index");
- mknb_assign("rt","r*gbscale");
- nflops ++;
-
- /* Truncate rt to an integer. */
- mknb_assign("n0","rt");
-
- mknb_assign("eps","rt-n0");
- mknb_assign("eps2","eps*eps");
- nflops += 2;
-
- mknb_assign("nnn","4*n0%s", (mknb_fortran) ? "+1" : "");
- return nflops;
-
-}
-
-
-/* Perform a table lookup and calculate VV and FF */
-int
-mknb_read_table(char *tabname)
-{
- int nflops = 0;
-
- /* See the Gromacs manual for details on cubic spline table interpolation */
- mknb_assign("Y",mknb_array(tabname,"nnn"));
- mknb_assign("F",mknb_array(tabname,"nnn+1"));
- mknb_assign("Geps","eps*%s",mknb_array(tabname,"nnn+2"));
- mknb_assign("Heps2","eps2*%s",mknb_array(tabname,"nnn+3"));
-
- mknb_assign("Fp","F+Geps+Heps2");
- mknb_assign("VV","Y+eps*Fp");
- nflops += 6;
-
- if(mknb_func.do_force) {
- mknb_assign("FF","Fp+Geps+2.0*Heps2");
- nflops += 3;
- }
- return nflops;
-}
-
-/* COULOMB INTERACTIONS */
-
-int
-mknb_coul_normal(char *rinv)
-{
- mknb_comment("Coulomb interaction");
- /* The Coulomb potential is simply charge/r.
- * vcoul is just a temporary variable defined in mknb_declarations.c */
- mknb_assign("vcoul","qq*%s",rinv);
- /* The Coulomb force is -charge/(r*r) = -vcoul/r.
- * We are going to multiply by the vector r later, and take care of
- * the sign when incrementing/decrementing forces, so the part we
- * want to add to fs is vcoul/(r*r).
- */
- if(mknb_func.do_force)
- sprintf(fs_rinvsq,"vcoul");
-
- /* Update total Coulomb energy */
- mknb_assign("vctot","vctot+vcoul");
- /* Done. 2 flops */
- return 2;
-}
-
-int
-mknb_coul_rf(char *rsq,char *rinv)
-{
- mknb_comment("Coulomb reaction-field interaction");
-
- mknb_assign("krsq","krf*%s",rsq);
- mknb_assign("vcoul","qq*(%s+krsq-crf)",rinv);
-
- if(mknb_func.do_force)
- sprintf(fs_rinvsq,"qq*(%s-2.0*krsq)",rinv);
-
- mknb_assign("vctot","vctot+vcoul");
- /* Done. 8 flops with force, 5 for energy only */
- return mknb_func.do_force ? 8 : 5;
-}
-
-int
-mknb_coul_tab(char *rsq, char *rinv)
-{
- int nflops = 0;
-
- mknb_comment("Tabulated coulomb interaction");
-
- /* We already calculated the table index. Coulomb is always first in table,
- * so we just use it and do the lookup.
- */
- nflops += mknb_read_table("VFtab");
- mknb_assign("vcoul","qq*VV");
- nflops++;
- if(mknb_func.do_force) {
- mknb_assign("fijC","qq*FF");
- nflops++;
- /* fs_minusrinv is empty */
- sprintf(fs_minus_tabscale_rinv,"fijC");
- }
- mknb_assign("vctot","vctot + vcoul");
- nflops++;
-
- return nflops;
-}
-
-
-int
-mknb_coul_gb(char *rsq, char *rinv)
-{
- int nflops = 0;
-
- mknb_comment("Tabulated Generalized-Born interaction");
- if(mknb_func.do_force)
- mknb_assign("dvdaj",mknb_array("dvda","jnr"));
- /* Coulomb is always the first interaction, so we
- * have not calculated the table index yet.
- */
- mknb_assign("r","%s*%s",rsq,rinv);
- nflops++;
- nflops += mknb_calc_gbtable_index("r");
-
- nflops += mknb_read_table("GBtab");
- mknb_assign("vgb","qq*VV");
- nflops++;
- if(mknb_func.do_force) {
- mknb_assign("fijC","qq*FF*gbscale");
- mknb_assign("dvdatmp","-0.5*(vgb+fijC*r)");
- mknb_assign("dvdasum","dvdasum + dvdatmp");
- nflops+=6;
- /* fs_minusrinv is empty */
- sprintf(fs_minus_rinv,"fijC-fscal");
- /* Update j atom dvda */
- mknb_assign(mknb_array("dvda","jnr"),"dvdaj+dvdatmp*isaj*isaj");
- }
- /* This will only give thw Coulomb part back to the total potential */
- mknb_assign("vctot","vctot + vcoul");
- nflops++;
-
- return nflops;
-}
-
-/* MKNB_VDW INTERACTIONS */
-int
-mknb_vdw_lj(char *rsq, char *rinv)
-{
- mknb_comment("Lennard-Jones interaction");
-
- mknb_assign("rinvsix","rinvsq*rinvsq*rinvsq");
- mknb_assign("Vvdw6","c6*rinvsix");
- mknb_assign("Vvdw12","c12*rinvsix*rinvsix");
-
- if(mknb_func.do_force) {
- if(strlen(fs_rinvsq)==0)
- sprintf(fs_rinvsq,"12.0*Vvdw12-6.0*Vvdw6");
- else /* append */
- strcat(fs_rinvsq,"+12.0*Vvdw12-6.0*Vvdw6");
- }
-
- mknb_assign("Vvdwtot","Vvdwtot+Vvdw12-Vvdw6");
- /* Done. 11 flops with force, 7 for energy only */
- return mknb_func.do_force ? 11 : 7;
-}
-
-
-int
-mknb_vdw_bham(char *rsq, char *rinv)
-{
- mknb_comment("Buckingham interaction");
-
- mknb_assign("rinvsix","rinvsq*rinvsq*rinvsq");
- mknb_assign("Vvdw6","c6*rinvsix");
- mknb_assign("br","cexp2*%s*%s",rsq,rinv); /* br=cexp2*r */
- mknb_assign("Vvdwexp","cexp1*exp(-br)");
-
- if(mknb_func.do_force) {
- if(strlen(fs_rinvsq)==0)
- sprintf(fs_rinvsq,"br*Vvdwexp-6.0*Vvdw6");
- else /* append */
- strcat(fs_rinvsq,"+br*Vvdwexp-6.0*Vvdw6");
- }
-
- mknb_assign("Vvdwtot","Vvdwtot+Vvdwexp-Vvdw6");
- /* exp() is expensive, 25 flops is a low estimate.
- * This gives about 37 flops , 34 for energy only
- */
- return mknb_func.do_force ? 37 : 34;
-}
-
-
-int
-mknb_vdw_tab(char *rsq, char *rinv)
-{
- int nflops = 0;
-
- mknb_comment("Tabulated VdW interaction - dispersion");
-
- /* If we just did tabulated coulomb we already
- * have the lookup seed. Just add the offset (4)
- * to use the LJ instead of the coulomb table.
- */
- if(mknb_func.table_element_size==12)
- {
- mknb_assign("nnn","nnn+4");
- }
- /* Without coulomb, dispersion is first element - nothing to do */
-
- nflops += mknb_read_table("VFtab");
- mknb_assign("Vvdw6","c6*VV");
-
- nflops++;
- if(mknb_func.do_force)
- {
- mknb_assign("fijD","c6*FF");
- nflops++;
- if(strlen(fs_minus_tabscale_rinv)==0)
- sprintf(fs_minus_tabscale_rinv,"fijD");
- else
- {
- strcat(fs_minus_tabscale_rinv,"+fijD");
- nflops++;
- }
- }
-
- mknb_comment("Tabulated VdW interaction - repulsion");
- mknb_assign("nnn", "nnn+4");
- nflops += mknb_read_table("VFtab");
- mknb_assign("Vvdw12","c12*VV");
-
- nflops++;
- if(mknb_func.do_force)
- {
- mknb_assign("fijR","c12*FF");
- nflops++;
- /* string is never empty here */
- strcat(fs_minus_tabscale_rinv,"+fijR");
- nflops++;
- }
- mknb_assign("Vvdwtot","Vvdwtot+ Vvdw6 + Vvdw12");
- nflops += 2;
-
- return nflops;
-}
-
-
-int
-mknb_calculate_interaction(char *rsq, char *rinv)
-{
- int nflops = 0;
- char tmp[512];
-
- /* Time to do the actual work. All the extra code in the function
- * generation program only comes down to one thing: to make it
- * possible to execute these switch statements at compile time
- * instead of when running the code (as we do in the unoptimized
- * routine for nonbonded forces).
- */
-
- /* Available variables:
- * rsq: a textstring with the variable holding r*r
- * rinv: textstring with the variable for 1/r
- *
- * The only exception is LJ-only functions, where we only need 1/(r*r)
- * and calculated it directly as 1/(rsq). This value can
- * be accessed directly as "rinvsq".
- */
-
- /* Add your potential to vctot or Vvdwtot.
- * The force is a bit special:
- *
- * First - skip all force calculations when mknb_func.do_force is false!
- *
- * To calculate the vectorial force we need to divide by the scalar r
- * and then multiply by the vector r. To avoid a stupid division, we
- * calculate (f/r) directly and add it to the variable "fs" with the
- * same sign as the potential (i.e. fs=grad(V)*r).
- *
- * To avoid duplicate calculations, we use two intermediary strings:
- * "fs_rinv" and "fs_rinvsq".
- *
- * The contents of these strings will be
- * multiplied by by rinv and rinvsq respectively, and added to get fs.
- *
- * So, if your coulomb interaction writes "A" to fs_rinv, "B" to
- * fs_rinvsq, and the VdW routine adds "-C" to the end of fs_rinv,
- * the fs variable will be
- *
- * fs = (A-C)*rinv + (B)*rinvsq
- */
-
- /* A lot of routines need 1/(r*r). To avoid duplicating operations
- * we calculate it before calling the interactions, when necessary.
- *
- * For LJ-only calculation it has already been computed.
- * All coulomb calculations except tabulated ones need rinvsq for force.
- * All vdw calculations except tabulated ones need it (even for energy).
- */
- if(((mknb_func.coul==MKNB_COUL_NORMAL || mknb_func.coul==MKNB_COUL_RF) && mknb_func.do_force) ||
- (mknb_func.vdw==MKNB_VDW_LJ && mknb_func.coul) || mknb_func.vdw==MKNB_VDW_BHAM) {
- mknb_assign("rinvsq","%s*%s",rinv,rinv);
- nflops++;
- }
-
- strcpy(fs_minus_tabscale_rinv,"");
- strcpy(fs_minus_rinv,"");
- strcpy(fs_rinvsq,"");
-
-
- if(mknb_func.coul==MKNB_COUL_TAB)
- {
- mknb_comment("Calculate table index");
- mknb_assign("r","%s*%s",rsq,rinv);
- nflops++;
- nflops += mknb_calc_table_index("r");
- }
-
- switch(mknb_func.coul) {
- case MKNB_COUL_NO:
- break;
- case MKNB_COUL_NORMAL:
- nflops += mknb_coul_normal(rinv);
- break;
- case MKNB_COUL_RF:
- nflops += mknb_coul_rf(rsq,rinv);
- break;
- case MKNB_COUL_TAB:
- nflops += mknb_coul_tab(rsq,rinv);
- break;
- case MKNB_COUL_GB:
- nflops += mknb_coul_gb(rsq,rinv);
- break;
- default:
- fprintf(stderr,"Error: Coulomb type %d undefined (mknb_interactions.c)\n",mknb_func.coul);
- exit(0);
- }
-
- if(mknb_func.vdw==MKNB_VDW_TAB && mknb_func.coul!=MKNB_COUL_TAB)
- {
- mknb_comment("Calculate table index");
- mknb_assign("r","%s*%s",rsq,rinv);
- nflops++;
- nflops += mknb_calc_table_index("r");
- }
-
- switch(mknb_func.vdw) {
- case MKNB_VDW_NO:
- break;
- case MKNB_VDW_LJ:
- nflops += mknb_vdw_lj(rsq,rinv);
- break;
- case MKNB_VDW_BHAM:
- nflops += mknb_vdw_bham(rsq,rinv);
- break;
- case MKNB_VDW_TAB:
- nflops += mknb_vdw_tab(rsq,rinv);
- break;
- default:
- fprintf(stderr,"Error: VdW type %d undefined (check mknb_interactions.c)",mknb_func.vdw);
- }
-
- /* Assembly the scalar force (actually f/dr, since we will multiply with vectorial dr) */
- if(strlen(fs_minus_tabscale_rinv)>0) {
- if(strlen(fs_minus_rinv)>0) {
- sprintf(tmp,"(%s)*tabscale+%s",fs_minus_tabscale_rinv,fs_minus_rinv);
- nflops+=2;
- } else {
- sprintf(tmp,"(%s)*tabscale",fs_minus_tabscale_rinv);
- nflops++;
- }
- strcpy(fs_minus_rinv,tmp);
- }
-
- if(strlen(fs_rinvsq)>0 && strlen(fs_minus_rinv)>0) {
- mknb_assign("fscal","(%s)*rinvsq-(%s)*%s",fs_rinvsq,fs_minus_rinv,rinv);
- nflops += 3;
- } else if(strlen(fs_rinvsq)>0) {
- mknb_assign("fscal","(%s)*rinvsq",fs_rinvsq);
- nflops++;
- } else if(strlen(fs_minus_rinv)>0) {
- mknb_assign("fscal","-(%s)*%s",fs_minus_rinv,rinv);
- nflops += 2;
- }
-
- return nflops;
-}
-
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-#ifndef _MKNB_INTERACTIONS_H_
-#define _MKNB_INTERACTIONS_H_
-
-
-/*! \file mknb_interactions.h
- * \brief Kernel generator (only for compile): Parwise interactions
- *
- * \internal
- *
- * \note This file is only used to generate the inner loop kernels
- * at compile time, which in turn are included in Gromacs.
- * This code itself is NOT linked into the Gromacs library, so
- * it does not need to be threadsafe.
- *
- * This file is only used to generate the inner loop kernels
- * at compile time, which in turn are included in Gromacs.
- * This code itself is NOT linked into the Gromacs library, so
- * it does not need to be threadsafe.
- */
-
-
-
-/*! \brief Kernel generator (only for compile): Evaluate an interaction
- *
- * \internal
- *
- * \note Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.
- *
- * This is the routine that writes the actual interaction between
- * a pair of atoms in mknb_interaction.c.
- *
- * The other routines of the nonbonded kernel generator are merely
- * responsible for iterating over atoms, loading coordinates, storing
- * forces, etc - but this is where it happens.
- *
- * When implementing a new type of interaction, you should change
- * this routine to add your interaction, and then (usually) modify
- * the loading of parameters in the outer and inner loop files.
- *
- * \param rsq Square distance (r*r) for the particle pair
- * \param rinv Inverse distance (1/r) for the particle pair
- *
- * \return Number of floating-point operations used for this
- * part of the nonbonded kernel. This is only used for
- * the flopcount reporting in Gromacs, the simulation
- * results do not depend on it being correct.
- */
-int
-mknb_calculate_interaction (char * rsq,
- char * rinv);
-
-
-
-#endif /* _MKNB_INTERACTIONS_H_ */
-
+++ /dev/null
-/*
- *
- * Gromacs 4.0 Copyright (c) 1991-2003
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-
-#include <mknb_metacode.h>
-
-/* This file is NOT threadsafe, but it is only used to create
- * the nonbonded loops during the build process, so it will never be
- * executed by multiple threads.
- */
-
-
-/* Global variables: */
-int mknb_fortran=0; /* 1 if fortran is used */
-int mknb_double=0; /* 1 if double precision */
-int mknb_keep_comments=0;
-int mknb_indent_level=0;
-FILE * mknb_output=NULL;
-
-
-
-
-/* Return the current indentation as a string */
-static char *
-mknb_indent(void)
-{
- static char buf[255];
- int i;
- int indent;
-
- if(mknb_fortran)
- indent = 6 + MKNB_FORTRAN_INDENT_STEP * mknb_indent_level;
- else
- indent = MKNB_C_INDENT_STEP * (mknb_indent_level+1);
-
- if(indent > 254)
- indent = 254;
-
- for(i=0; i<indent; i++)
- buf[i] = ' ';
-
- buf[i] = '\0';
-
- return buf;
-}
-
-
-/* Write the provided string as a comment in the file */
-void
-mknb_comment(char *s)
-{
- if(mknb_keep_comments) {
- if(mknb_fortran) {
- mknb_indent_level--;
- fprintf(mknb_output,"\nC%s%s\n",mknb_indent(),s);
- mknb_indent_level++;
- } else {
- fprintf(mknb_output,"\n%s/* %s */\n",mknb_indent(),s);
- }
- }
-}
-
-
-
-/* We need to separate argument and variable declarations.
- * The arguments are written directly to the output file,
- * while
- */
-
-
-
-/* Define a new floating-point variable */
-void
-mknb_declare_real(char *name)
-{
- char type_name[255];
-
-
-
- if(mknb_fortran)
- {
-#ifdef IBM_FORTRAN_CPP
- sprintf(type_name, "%-13s", "gmxreal");
-#else
- sprintf(type_name, "%-13s", mknb_double ? "real*8" : "real*4");
-#endif
- }
- else
- sprintf(type_name, "%-13s", mknb_double ? "double" : "float");
-
- mknb_code("%s %s%s",type_name,name, mknb_fortran ? "" : ";");
-}
-
-/* Declare a single-precision floating point var. */
-void
-mknb_declare_real4(char *name)
-{
- char type_name[255];
-
- sprintf(type_name, "%-13s", mknb_fortran ? "real*4" : "float");
-
- mknb_code("%s %s%s", type_name ,name, mknb_fortran ? "" : ";");
-}
-
-
-/* Declare a constant fp variable */
-void
-mknb_declare_const_real(char *name, double value)
-{
- char type_name[255];
-
- if(mknb_fortran)
- {
-#ifdef IBM_FORTRAN_CPP
- sprintf(type_name, "%-13s", "gmxreal");
-#else
- sprintf(type_name, "%-13s", mknb_double ? "real*8" : "real*4");
-#endif
- mknb_code("%s %s",type_name,name);
- mknb_code(" parameter (%s = %f)",name,value);
- } else {
- sprintf(type_name, "%-13s",
- mknb_double ? "const double" : "const float");
- mknb_code("%s %s = %.16f;",type_name,name,value);
- }
-}
-
-/* Integer */
-void
-mknb_declare_int(char *name)
-{
- char type_name[255];
-
- sprintf(type_name, "%-13s", mknb_fortran ? "integer*4" : "int");
-
- mknb_code("%s %s%s", type_name ,name, mknb_fortran ? "" : ";");
-}
-
-
-/* integer constant */
-void
-mknb_declare_const_int(char *name, int value)
-{
- char type_name[255];
-
- sprintf(type_name, "%-13s", mknb_fortran ? "integer*4" : "const int");
-
- if(mknb_fortran) {
- mknb_code("%s %s", type_name ,name);
- mknb_code(" parameter (%s = %d)",name,value);
- } else
- mknb_code("%s %s = %d;", type_name ,name, value);
-}
-
-/* 4-byte Integer (same size as single precision fp) */
-void
-mknb_declare_int4(char *name)
-{
- char type_name[255];
-
- sprintf(type_name, "%-13s", mknb_fortran ? "integer*4" : "int");
-
- mknb_code("%s %s%s", type_name ,name, mknb_fortran ? "" : ";");
-}
-
-
-/* Arbitrary declaration */
-void
-mknb_declare_other(char *type_name,char *name)
-{
- char tmp[255];
- sprintf(tmp,"%-13s", type_name);
-
- mknb_code("%s %s%s", tmp, name, mknb_fortran ? "" : ";");
-}
-
-
-/* Reference an element in a list */
-char *
-mknb_array(char *a, char *idx)
-{
- static char buf[1024];
-
- sprintf(buf,"%s%c%s%c",a, mknb_fortran ? '(' : '[',
- idx, mknb_fortran ? ')' : ']');
-
- return buf;
-}
-
-
-/* Split a line to adhere to the stupid 72 column limits of fortran,
- * and write it to the output file
- */
-static void
-mknb_fortran_splitline(char *line)
-{
- char tmpbuf[4096];
- int i,j,maxlen;
- int indent;
- maxlen=strlen(line);
-
- i=0;
-
- indent = MKNB_FORTRAN_INDENT_STEP*mknb_indent_level;
- /* we can write 72-indentation characters on each line */
-
- while(i+72-indent<maxlen) {
- /* set j to the last position */
- j=i+71-indent;
- if (j>=maxlen)
- j=maxlen;
-
- while(j>(i+1)) {
- if(line[j]=='+' ||
- line[j]=='-' ||
- line[j]=='/' ||
- (line[j]=='*' && line[j-1]!='*') || /* dont split "**" */
- line[j]==' ')
- break;
- j--;
- }
- if(j==i) {
- printf("Error: Couldn't break this line:\n%s\n",line);
- exit(1);
- }
- strncpy(tmpbuf,line+i,j-i+1);
- tmpbuf[j-i]=0;
-
- fprintf(mknb_output,"%s",tmpbuf);
- fprintf(mknb_output,"\n");
- fprintf(mknb_output," & ");
- i=j;
- }
- fprintf(mknb_output,"%s",line+i);
-}
-
-
-
-
-/* Print a line of code to the output file.
- * This routine does proper indentation, and also supports the
- * same type of variable-argument lists as printf, apart from
- * field widths.
- */
-void
-mknb_code(char *format, ...)
-{
- va_list ap;
- int d;
- double f;
- char *s;
- char tmp[4096];
- char outbuf[4096];
-
- sprintf(outbuf,"%s",mknb_indent());
-
- va_start(ap,format);
-
- while(*format) {
- if(*format!='%')
- sprintf(tmp,"%c",*format);
- else {
- switch(*(++format)) {
- case 'd': /* read an integer */
- d = va_arg(ap, int);
- sprintf(tmp,"%d",d);
- break;
- case 'f': /* read a (double precision) floating point number */
- f = va_arg(ap, double);
- sprintf(tmp,"%.16f",f);
- break;
- case 's': /* read a string */
- s = va_arg(ap, char *);
- sprintf(tmp,"%s",s);
- break;
- default:
- fprintf(stderr,
- "Error, unsupported format supplied to mknb_code():\nn");
-
- exit(-1);
- break;
- }
- }
- format++;
- strcat(outbuf,tmp);
- }
- va_end(ap);
-
- if(mknb_fortran)
- mknb_fortran_splitline(outbuf);
- else
- fprintf(mknb_output,"%s",outbuf);
-
- fprintf(mknb_output,"\n");
-}
-
-
-
-/* Prints an assignment.
- * This routine does proper indentation, and also supports the
- * same type of variable-argument lists as printf (both in
- * the left and right-hand side buffers), apart from field widths.
- *
- * a statement like mknb_assign("atom%d","data%d",3,5) will give
- *
- * atom3 = data5;
- *
- *
- * In contrast to mknb_code(), mknb_assign() appends a semicolon when the
- * language is not set to fortran.
- *
- */
-void
-mknb_assign(char *left, char *right, ...)
-{
- int i;
- char *format;
- char buf[4096],tmp[4096];
- char outbuf[4096];
- va_list ap;
- int d;
- double f;
- char *s;
-
-
- sprintf(outbuf,"%s",mknb_indent());
-
- va_start(ap,right);
-
- for(i=0;i<=1;i++) {
- /* first we do the left buffer, then repeat everything for the right. */
- if(i==0)
- format=left;
- else
- format=right;
-
- buf[0]='\0';
-
- while(*format) {
- if(*format!='%')
- sprintf(tmp,"%c",*format);
- else {
- switch(*(++format)) {
- case 'd': /* read an integer */
- d = va_arg(ap, int);
- sprintf(tmp,"%d",d);
- break;
- case 'f': /* read a (double precision) floating point number */
- f = va_arg(ap, double);
- sprintf(tmp,"%.16f",f);
- break;
- case 's': /* read a string */
- s = va_arg(ap, char *);
- sprintf(tmp,"%s",s);
- break;
- default:
- fprintf(stderr,
- "Error, unsupported format supplied to mknb_assign()\n");
- exit(-1);
- break;
- }
- }
- strcat(buf,tmp);
- format++;
- }
- if(i==1 && !mknb_fortran)
- strcat(buf,";");
-
- sprintf(tmp,"%-16s",buf);
- strcat(outbuf,tmp);
-
- if(i==0)
- strcat(outbuf," = ");
- }
- va_end(ap);
-
- if(mknb_fortran)
- mknb_fortran_splitline(outbuf);
- else
- fprintf(mknb_output,"%s",outbuf);
-
- fprintf(mknb_output,"\n");
-}
-
-
-
-/* Start a for loop and increase indentation.*/
-void
-mknb_start_loop(char *lvar,char *from,char *to)
-{
-
- mknb_code("");
-
- if(mknb_fortran)
- {
- mknb_code("do %s=%s,%s",lvar,from,to);
- }
- else
- {
- mknb_code("for(%s=%s; (%s<%s); %s++)", lvar,from,lvar,to,lvar);
- mknb_code("{");
- }
- mknb_indent_level++;
-}
-
-
-/* decrease indentation and close for loop */
-void
-mknb_end_loop(void)
-{
- mknb_indent_level--;
-
- if(mknb_fortran)
- mknb_code("end do");
- else
- mknb_code("}");
-
- mknb_code("");
-}
-
-
-void
-mknb_start_if(char *cond)
-{
-
- mknb_code("");
-
- if(mknb_fortran)
- mknb_code("if (%s) then",cond);
- else
- {
- mknb_code("if(%s)", cond);
- mknb_code("{");
- }
- mknb_indent_level++;
-}
-
-void
-mknb_do_else()
-{
- mknb_indent_level--;
-
- if(mknb_fortran)
- mknb_code("else");
- else
- {
- mknb_code("}");
- mknb_code("else");
- mknb_code("{");
- }
- mknb_indent_level++;
-}
-
-
-
-void
-mknb_end_if(void)
-{
- mknb_indent_level--;
-
- if (mknb_fortran)
- mknb_code("endif");
- else
- mknb_code("}");
-
- mknb_code("");
-
-}
-
-
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-
-#ifndef _MKNB_METACODE_H_
-#define _MKNB_METACODE_H_
-
-#include <stdio.h>
-
-/*! \file mknb_metacode.h
- * \brief Kernel generator (only for compile): C/Fortran statements
- *
- * \internal
- *
- * <b>This file is only used to generate the inner loop kernels
- * at compile time, which in turn are included in Gromacs.
- * This code itself is NOT linked into the Gromacs library, so
- * it does not need to be threadsafe.</b>
- *
- * mknb_metacode.h contains utility routines and variables for
- * writing code in either C or Fortran using our very primitive
- * and limited meta-language. It is a separate file since it
- * is essentially independent of the actual loops we write
- * for the nonbonded routines.
- *
- * It tries to split fortran lines correctly over multiple lines
- * if they are more than 72 characters, but check the generated
- * code to make sure...
- */
-
-
-
-
-
-/*! \brief Kernel generator (only for compile): Current Language
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * This code is only being executed at compile time,
- * so we allow the use of some ugly global variables.
- *
- * If this variable has the value 1, Fortran code is being
- * generated, otherwise C code.
- */
-extern int
-mknb_fortran;
-
-
-
-
-/*! \brief Kernel generator (only for compile): Current fp precision
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Global variable, 1 if using double, 0 for single.
- */
-extern int
-mknb_double;
-
-
-
-
-/*! \brief Kernel generator (only for compile): Generate comments or not
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Global variable, comments are thrown away unless this is 1.
- */
-extern int
-mknb_keep_comments;
-
-
-
-
-/*! \brief Kernel generator (only for compile): Current indentation level
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * For each level (integer), lines will be indented 4(C) or 2(F77) spaces.
- * This will be changed when you open/close new loops, or sometimes
- * manually. Since this code is only run single-threaded at
- * compile time that is ok (although a bit ugly).
- */
-extern int
-mknb_indent_level;
-
-#define MKNB_C_INDENT_STEP 4
-#define MKNB_FORTRAN_INDENT_STEP 2
-
-
-
-/*! \brief Kernel generator (only for compile): Name of current output file
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * All code generated will be written to this file.
- */
-extern FILE *
-mknb_output;
-
-
-
-
-/*! \brief Kernel generator (only for compile): Add comment to output
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Note that the comment will only be written to the C/Fortran file
- * if keep_comments is 1, since this makes them compile faster in the
- * distribution.
- *
- * \param text Comment text
- */
-void
-mknb_comment (char * text);
-
-
-
-
-/*! \brief Kernel generator (only for compile): Declare floating-point variable
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Depending on the current precision this will be either single or double.
- *
- * \param name Name of the variable
- */
-void
-mknb_declare_real (char * name);
-
-
-
-
-
-/*! \brief Kernel generator (only for compile): Declare 4-byte fp variable
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * This variable will always be exactly 4 bytes, even
- * when the current precision is double.
- * This is necessary to move between integer and floating-point
- * registers to perform the single precision table lookup used for
- * our fast inverse square root algorithm.
- *
- * \param name Name of the variable
- */
-void
-mknb_declare_real4 (char * name);
-
-
-
-
-/*! \brief Kernel generator (only for compile): Declare fp constant
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * This will be a 'const' variable in C, and a parameter in Fortran.
- *
- * \param name Name of the constant
- * \param val Constant value
- */
-void
-mknb_declare_const_real (char * name,
- double val);
-
-
-
-
-/*! \brief Kernel generator (only for compile): Declare an integer variable
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * \param name Name of the variable
- */
-void
-mknb_declare_int (char * name);
-
-
-
-
-/*! \brief Kernel generator (only for compile): Declare 4-byte integer variable
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * This variable will always be exactly 4 bytes.
- * This is necessary to move between integer and floating-point
- * registers to perform the single precision table lookup used for
- * our fast inverse square root algorithm.
- *
- * \param name Name of the variable
- */
-void
-mknb_declare_int4 (char * name);
-
-
-
-
-/*! \brief Kernel generator (only for compile): Declare an integer constant
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * This will be a 'const' variable in C, and a parameter in Fortran.
- *
- * \param name Name of the constant
- * \param val Constant value
- */
-void
-mknb_declare_const_int (char * name,
- int val);
-
-
-
-/*! \brief Kernel generator (only for compile): Generic type declaration
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Arbitrary variable declaration where you provide your own type.
- * Note that you will have to take care of C/Fortran differences
- * manually. In the generated code it will appear as
- * "type_name name;" in C, and without the semicolon in Fortran.
- *
- * \param type_name Name of the variable type
- * \param name Name of the variable
- */
-void
-mknb_declare_other (char * type_name,
- char * name);
-
-
-
-
-
-/*! \brief Kernel generator (only for compile): Reference element in a vector
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * This statement will generate the code vector[idx] in C,
- * and vector(idx) in Fortran.
- * Note that the code does not take into account that C start
- * counting on 0 and Fortran on 1 - you will have to account
- * for that manually when necessary.
- *
- * \param vector Name of array
- * \param idx Index of element to access
- *
- * \return Text string with the code
- *
- */
-char *
-mknb_array (char * vector,
- char * idx);
-
-
-
-
-/*! \brief Kernel generator (only for compile): Formatted output to file
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Print a line of code to the output file.
- * This routine does proper indentation based on the global
- * indentation variable in mknb_metacode.h, and also supports the
- * same type of variable-argument lists as printf, with the
- * exception of field widths.
- *
- * This is meant as a low-level routine for raw output, so
- * we do not append any semicolon when the language is C.
- *
- * \param format printf-like format string
- */
-void
-mknb_code (char * format,
- ... );
-
-
-
-
-/*! \brief Kernel generator (only for compile): Generate an assignment a=b
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * This routine does proper indentation, and also supports the
- * same type of variable-argument lists as printf both in
- * the left and right-hand side buffers, apart from field widths.
- *
- * a statement like <tt>assign("atom%d","data%d",3,5)</tt> will produce
- *
- * <tt>atom3 = data5;</tt> (in C)
- *
- * In contrast to code(), this routine appends a semicolon when
- * the language is set to C.
- */
-void
-mknb_assign (char * left,
- char * right,
- ...);
-
-
-
-
-/*! \brief Kernel generator (only for compile): Start for loop block
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * In C, this will generate the statement:
- *
- * <tt>for(var=from;var<from;var++) {</tt>
- *
- * i.e., the loop will be executed to-from times,
- * with the first value being lvar=from, and the
- * last lvar=to-1.
- *
- * In Fortran, you will get the statement:
- *
- * <tt>FOR var=from,to DO</tt>
- *
- * i.e., the loop will be executed to-from+1 times,
- * with the first value being lvar=from, and the
- * last lvar=to.
- *
- * Take care - you will probably need to provide
- * different limits depending on language!
- *
- * \param var Loop variable
- * \param from First value for variable
- * \param to Last value for variable when using
- * Fortran, one more than last value in C.
- */
-void
-mknb_start_loop (char * var,
- char * from,
- char * to);
-
-
-
-
-/*! \brief Kernel generator (only for compile): End an open for loop block
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- */
-void
-mknb_end_loop (void);
-
-
-
-
-/*! \brief Kernel generator (only for compile): Open a new if-block
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Starts a new if-block, which will be executed
- * when the provided condition is true.
- *
- * \param cond Condition to determine if
- * block should be executed.
- * This will be written literally to
- * the output, so you will need to
- * account for C/Fortran differences
- * yourself.
- */
-void
-mknb_start_if (char * cond);
-
-
-
-
-/*! \brief Kernel generator (only for compile): Close if-, open else-block
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- */
-void
-mknb_do_else (void);
-
-
-
-
-/*! \brief Kernel generator (only for compile): End an open if/else block
- *
- * \internal
- *
- * <b>Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.</b>
- *
- * Each start_if() statement should be followed by this,
- * possible with a do_else() somewhere in between.
- */
-void
-mknb_end_if (void);
-
-
-
-#endif /* _MKNB_METACODE_H_ */
-
-
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-
-/* This file is NOT threadsafe, but it is only used to create
- * the nonbonded functions during the build process, so it will never be
- * executed by multiple threads.
- */
-
-#include <string.h>
-#include <mknb_common.h>
-#include <mknb_innerloop.h>
-#include <mknb_metacode.h>
-
-
-int
-mknb_load_shift_vector()
-{
- mknb_comment("Load shift vector for this list");
-
- /* index in the shift vector for this list */
- mknb_assign("is3","3*%s%s",mknb_array("shift","n"),
- (mknb_fortran) ? "+1" : "");
-
- /* load vector corresponding to this index */
- mknb_assign("shX",mknb_array("shiftvec","is3"));
- mknb_assign("shY",mknb_array("shiftvec","is3+1"));
- mknb_assign("shZ",mknb_array("shiftvec","is3+2"));
-
- return 0; /* no flops in this function */
-}
-
-int
-mknb_zero_outer_potential()
-{
- mknb_comment("Zero the potential energy for this list");
- if(mknb_func.coul)
- mknb_assign("vctot","0"); /* zero local potentials */
- if(mknb_func.vdw)
- mknb_assign("Vvdwtot","0");
- if(mknb_func.coul==MKNB_COUL_GB && mknb_func.do_force)
- mknb_assign("dvdasum","0");
-
- return 0; /* no flops in this function */
-}
-
-int
-mknb_load_outer_coordinates()
-{
- int i,firsti,nflops;
- char tmp[255];
-
- /* TIP4P water doesnt have any coulomb interaction
- * on atom 1, so we skip it if we dont do LJ
- */
- firsti = ((mknb_func.vdw==MKNB_VDW_NO) &&
- (mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR)) ? 2 : 1;
-
- mknb_comment("Load i atom data, add shift vector");
- nflops = 0;
-
- for(i=firsti;i<=mknb_func.ni;i++) {
- sprintf(tmp,"ii3+%d",3*(i-1));
- mknb_assign("ix%d","shX + %s",i,mknb_array("pos",tmp));
- sprintf(tmp,"ii3+%d",3*(i-1)+1);
- mknb_assign("iy%d","shY + %s",i,mknb_array("pos",tmp));
- sprintf(tmp,"ii3+%d",3*(i-1)+2);
- mknb_assign("iz%d","shZ + %s",i,mknb_array("pos",tmp));
- nflops += 3; /* three additions per iteration */
- }
- return nflops;
-}
-
-
-int
-mknb_zero_outer_forces()
-{
- int i,firsti;
-
- /* TIP4P water doesnt have any coulomb interaction
- * on atom 1, so we skip it if we dont do LJ
- */
- firsti = ((mknb_func.vdw==MKNB_VDW_NO) &&
- (mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR)) ? 2 : 1;
-
- mknb_comment("Clear i atom forces");
- if(mknb_func.do_force)
- for(i=firsti;i<=mknb_func.ni;i++) {
- mknb_assign("fix%d","0",i);
- mknb_assign("fiy%d","0",i);
- mknb_assign("fiz%d","0",i);
- }
- return 0; /* no flops in this function */
-}
-
-
-int
-mknb_load_outer_parameters()
-{
- /* If we do water or water-water interactions, the
- * parameters for the outer atoms are constant and
- * already calculated outside the loops.
- *
- * For normal interactions we have to load e.g. charge
- * if we do coulomb, and the atomtype for VdW.
- * The actual VdW parameters for the pair of atoms
- * is looked up in the core of the inner loop, but the
- * constant 2*ntype*type[ii] can be calculated now.
- *
- * For generalized-born loops we also load 1/sqrt(a)
- */
- int nflops = 0;
-
- if(mknb_func.water==MKNB_WATER_NO) {
- mknb_comment("Load parameters for i atom");
-
- /* Coulomb parameters */
- if(mknb_func.coul) {
- mknb_assign("iq","facel*%s",mknb_array("charge","ii"));
- nflops++;
- }
-
- /* GB parameters - inverse sqrt of born radius */
- if(mknb_func.coul==MKNB_COUL_GB)
- mknb_assign("isai",mknb_array("invsqrta","ii"));
-
- /* VdW parameters */
- if(mknb_func.vdw)
- mknb_assign("nti","%d*ntype*%s",mknb_func.nvdw_parameters,
- mknb_array("type","ii"));
-
- }
- return nflops;
-}
-
-
-
-
-int
-mknb_update_outer_forces()
-{
- int i,firsti,nflops=0;
- char tmp[255],fsumx[255],fsumy[255],fsumz[255];
-
- mknb_comment("Add i forces to mem and shifted force list");
-
- /* TIP4P water doesnt have any coulomb interaction
- * on atom 1, so we skip it if we dont do LJ
- */
- firsti = ((mknb_func.vdw==MKNB_VDW_NO) &&
- (mknb_func.water==MKNB_WATER_TIP4P_SINGLE ||
- mknb_func.water==MKNB_WATER_TIP4P_PAIR)) ? 2 : 1;
-
- if(mknb_func.do_force) {
- fsumx[0]=fsumy[0]=fsumz[0]=0;
- for(i=firsti;i<=mknb_func.ni;i++) {
- sprintf(tmp,"ii3+%d",3*(i-1));
-
- mknb_assign(mknb_array("faction",tmp),"%s + fix%d",
- mknb_array("faction",tmp),i);
-
- sprintf(tmp,"ii3+%d",3*(i-1)+1);
-
- mknb_assign(mknb_array("faction",tmp),"%s + fiy%d",
- mknb_array("faction",tmp),i);
-
- sprintf(tmp,"ii3+%d",3*(i-1)+2);
-
- mknb_assign(mknb_array("faction",tmp),"%s + fiz%d",
- mknb_array("faction",tmp),i);
-
- sprintf(tmp,"+fix%d",i); strcat(fsumx,tmp);
- sprintf(tmp,"+fiy%d",i); strcat(fsumy,tmp);
- sprintf(tmp,"+fiz%d",i); strcat(fsumz,tmp);
- nflops += 6; /* 2*3 additions per iteration */
- }
-
- mknb_assign(mknb_array("fshift","is3"),"%s%s",
- mknb_array("fshift","is3"),fsumx);
-
- mknb_assign(mknb_array("fshift","is3+1"),"%s%s",
- mknb_array("fshift","is3+1"),fsumy);
-
- mknb_assign(mknb_array("fshift","is3+2"),"%s%s",
- mknb_array("fshift","is3+2"),fsumz);
-
- }
- return nflops;
-}
-
-int
-mknb_update_outer_potential()
-{
- char tmp[32];
- int nflops = 0;
-
- mknb_comment("Add potential energies to the group for this list");
-
- mknb_assign("ggid", "%s%s", mknb_array("gid","n"),
- (mknb_fortran) ? "+1" : "");
-
- if(mknb_func.coul) {
- sprintf(tmp,"%s",mknb_array("Vc","ggid"));
- mknb_assign(tmp,"%s + vctot",tmp);
- nflops++;
- }
- if(mknb_func.vdw) {
- sprintf(tmp,"%s",mknb_array("Vvdw","ggid"));
- mknb_assign(tmp,"%s + Vvdwtot",tmp);
- nflops++;
- }
- /* Update dVda=dVda+0.5*dvdasum*(1/a) for Generalized-born.
- * To save a couple of flops in the inner loop, each element
- * in this list should be divided by the born radius after
- * calling the nonbonded routine.
- */
- if(mknb_func.coul==MKNB_COUL_GB && mknb_func.do_force) {
- mknb_assign(mknb_array("dvda","ii"),
- "%s + dvdasum*isai*isai",
- mknb_array("dvda","ii"));
- nflops++;
- }
-
- return nflops;
-}
-
-
-void
-mknb_outerloop(void) {
- int i,nflops = 0;
- char tmp[255];
- int indent;
-
-
- if(mknb_options.threads) {
- mknb_comment("Loop over thread workunits");
- if(mknb_fortran) {
- char space[25];
- indent = MKNB_FORTRAN_INDENT_STEP*mknb_indent_level;
- for(i=0 ; i<indent ; i++)
- space[i]=' ';
- space[i]=0;
- fprintf(mknb_output,
- " 10 %scall f77kernelsync(mtx,count,nri,nthreads,nn0,nn1)\n",space);
- /* since f77 use call-by-reference we can send the pointer of the
- * count variable and the mutex to c without fortran knowing about it!
- */
- mknb_indent_level++;
- mknb_code("if(nn1.gt.nri) nn1=nri");
- mknb_comment("Start outer loop over neighborlists");
- mknb_start_loop("n", "nn0+1", "nn1");
- } else {
- /* C */
- mknb_code("");
- mknb_code("do");
- mknb_code("{");
- mknb_indent_level++;
- mknb_code("tMPI_Thread_mutex_lock((tMPI_Thread_mutex_t *)mtx);");
- mknb_assign("nn0","*count");
- mknb_comment("Take successively smaller chunks (at least 10 lists)");
- mknb_assign("nn1","nn0+(nri-nn0)/(2*nthreads)+10");
- /* take sucessively smaller chunks */
- mknb_assign("*count","nn1");
- mknb_code("tMPI_Thread_mutex_unlock((tMPI_Thread_mutex_t *)mtx);");
- mknb_code("if(nn1>nri) nn1=nri;");
- mknb_comment("Start outer loop over neighborlists");
- mknb_start_loop("n", "nn0", "nn1");
- }
-
- } else {
- mknb_comment("Start outer loop over neighborlists");
- mknb_start_loop("n", (mknb_fortran) ? "1" : "0", "nri");
- }
-
- /* load shift index and then shift vector for this list */
- nflops += mknb_load_shift_vector();
-
- mknb_comment("Load limits for loop over neighbors");
-
- mknb_assign("nj0", "%s%s", mknb_array("jindex","n"),
- (mknb_fortran) ? "+1" : "");
-
- mknb_assign("nj1", mknb_array("jindex","n+1"));
-
- mknb_comment("Get outer coordinate index");
-
- mknb_assign("ii", "%s%s", mknb_array("iinr","n"),
- (mknb_fortran) ? "+1" : "");
-
- mknb_assign("ii3", "3*ii%s", (mknb_fortran) ? "-2" : "");
- nflops += mknb_load_outer_coordinates();
- nflops += mknb_load_outer_parameters();
-
- nflops += mknb_zero_outer_potential();
- nflops += mknb_zero_outer_forces();
-
- /* do the inner loop ( separate nflops, so no return value) */
- mknb_innerloop();
- nflops += mknb_update_outer_forces();
- nflops += mknb_update_outer_potential();
-
- /* Update innerloop counter (for accounting) if we did threads */
- mknb_comment("Increment number of inner iterations");
- if(mknb_options.threads)
- mknb_assign("ninner","ninner + nj1 - nj0");
-
- /* close outer loop */
- sprintf(tmp,"Outer loop uses %d flops/iteration",nflops);
- mknb_comment(tmp);
- mknb_end_loop();
-
- if(mknb_options.threads) {
- mknb_comment("Increment number of outer iterations");
- mknb_assign("nouter","nouter + nn1 - nn0");
- mknb_indent_level--;
- if(mknb_fortran)
- mknb_code("if(nn1.lt.nri) goto 10");
- else
- {
- mknb_code("}");
- mknb_code("while (nn1<nri);");
- mknb_code("");
- }
- }
-}
-
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This file is part of Gromacs Copyright (c) 1991-2004
- * David van der Spoel, Erik Lindahl, University of Groningen.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-#ifndef _MKNB_OUTERLOOP_H_
-#define _MKNB_OUTERLOOP_H_
-
-
-
-
-/*! \file mknb_outerloop.h
- * \brief Kernel generator (only for compile): Loop over neighborlists
- *
- * \internal
- *
- * \note This file is only used to generate the inner loop kernels
- * at compile time, which in turn are included in Gromacs.
- * This code itself is NOT linked into the Gromacs library, so
- * it does not need to be threadsafe.
- *
- * This file is only used to generate the inner loop kernels
- * at compile time, which in turn are included in Gromacs.
- * This code itself is NOT linked into the Gromacs library, so
- * it does not need to be threadsafe.
- */
-
-
-/*! \brief Kernel generator (only for compile): Outer loop over neighborlists.
- *
- * \internal
- *
- * \note Only defined/used in the nonbonded kernel generator
- * program mknb. This program is run once at compile
- * time to create the inner loops, and then discarded.
- * This source is NOT linked into any Gromacs library.
- *
- * This routine will open a loop, load indices, coordinates and
- * parameters for the outer (also known as 'i') particle, and
- * determine the limits for the inner loop. It then calls the
- * inner loop generating code mknb_innerloop(), and after that
- * routine returns we update the potentials and forces on the
- * outer/i-atom.
- *
- * The parameters to be loaded are determined by the current
- * values in the 'func' structure global to this file.
- */
-void
-mknb_outerloop(void);
-
-
-#endif /* _MKNB_OUTERLOOP_H_ */
-