예제 #1
0
파일: membed.c 프로젝트: aeszter/gromacs
void get_input(const char *membed_input, real *xy_fac, real *xy_max, real *z_fac, real *z_max,
		int *it_xy, int *it_z, real *probe_rad, int *low_up_rm, int *maxwarn, 
		int *pieces, gmx_bool *bALLOW_ASYMMETRY)
{
    warninp_t wi;
    t_inpfile *inp;
    int       ninp;

    wi = init_warning(TRUE,0);
    
    inp = read_inpfile(membed_input, &ninp, NULL, wi);
    ITYPE ("nxy", *it_xy, 1000);
    ITYPE ("nz", *it_z, 0);
    RTYPE ("xyinit", *xy_fac, 0.5);
    RTYPE ("xyend", *xy_max, 1.0);
    RTYPE ("zinit", *z_fac, 1.0);
    RTYPE ("zend", *z_max, 1.0);
    RTYPE ("rad", *probe_rad, 0.22);
    ITYPE ("ndiff", *low_up_rm, 0);
    ITYPE ("maxwarn", *maxwarn, 0);
    ITYPE ("pieces", *pieces, 1);
    EETYPE("asymmetry", *bALLOW_ASYMMETRY, yesno_names);
 
    write_inpfile(membed_input,ninp,inp,FALSE,wi);
}
예제 #2
0
static int usbdevfs_revalidate(struct dentry *dentry, int flags)
{
	struct inode *inode = dentry->d_inode;

        if (!inode)
                return 0;
	if (ITYPE(inode->i_ino) == IBUS && !inode->u.usbdev_i.p.bus)
		return 0;
	if (ITYPE(inode->i_ino) == IDEVICE && !inode->u.usbdev_i.p.dev)
		return 0;
	return 1;
}
예제 #3
0
static int usbdevfs_remount(struct super_block *s, int *flags, char *data)
{
	struct list_head *ilist = s->u.usbdevfs_sb.ilist.next;
	struct inode *inode;
	int ret;

	if ((ret = parse_options(s, data))) {
		printk(KERN_WARNING "usbdevfs: remount parameter error\n");
		return ret;
	}

	for (; ilist != &s->u.usbdevfs_sb.ilist; ilist = ilist->next) {
		inode = list_entry(ilist, struct inode, u.usbdev_i.slist);

		switch (ITYPE(inode->i_ino)) {
			case ISPECIAL :
				inode->i_uid = s->u.usbdevfs_sb.listuid;
				inode->i_gid = s->u.usbdevfs_sb.listgid;
				inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG;
				break;
			case IBUS :
				inode->i_uid = s->u.usbdevfs_sb.busuid;
				inode->i_gid = s->u.usbdevfs_sb.busgid;
				inode->i_mode = s->u.usbdevfs_sb.busmode | S_IFDIR;
				break;
			case IDEVICE :
				inode->i_uid = s->u.usbdevfs_sb.devuid;
				inode->i_gid = s->u.usbdevfs_sb.devgid;
				inode->i_mode = s->u.usbdevfs_sb.devmode | S_IFREG;
				break;
		}
	}

	return 0;
}
예제 #4
0
static void usbdevfs_read_inode(struct inode *inode)
{
	struct special *spec;

	inode->i_ctime = inode->i_mtime = inode->i_atime = CURRENT_TIME;
	inode->i_mode = S_IFREG;
	inode->i_gid = inode->i_uid = 0;
	inode->u.usbdev_i.p.dev = NULL;
	inode->u.usbdev_i.p.bus = NULL;
	switch (ITYPE(inode->i_ino)) {
	case ISPECIAL:
		if (inode->i_ino == IROOT) {
			inode->i_op = &usbdevfs_root_inode_operations;
			inode->i_fop = &usbdevfs_root_file_operations;
			inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
			return;
		}
		if (inode->i_ino <= IROOT || inode->i_ino > IROOT+NRSPECIAL)
			return;
		spec = &special[inode->i_ino-(IROOT+1)];
		inode->i_fop = spec->fops;
		return;

	case IDEVICE:
		return;

	case IBUS:
		return;

	default:
		return;
        }
}
예제 #5
0
static int usbdevfs_bus_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
	struct inode *inode = filp->f_dentry->d_inode;
	unsigned long ino = inode->i_ino;
	struct usb_bus *bus;

	/* sanity check */
	if (ITYPE(ino) != IBUS)
		return -EINVAL;
	switch ((unsigned int)filp->f_pos) {
	case 0:
		if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0)
			return 0;
		filp->f_pos++;
		/* fall through */

	case 1:
		if (filldir(dirent, "..", 2, filp->f_pos, IROOT, DT_DIR) < 0)
			return 0;
		filp->f_pos++;
		/* fall through */

	default:
		lock_kernel();
		bus = usbdevfs_findbus(IBUSNR(ino));
		bus_readdir(bus->root_hub, IDEVICE | ((bus->busnum & 0xff) << 8), filp->f_pos-2, filp, dirent, filldir);
		unlock_kernel();
		return 0;
	}
}
예제 #6
0
static struct dentry *usbdevfs_root_lookup(struct inode *dir, struct dentry *dentry)
{
	int busnr;
	unsigned long ino = 0;
	unsigned int i;
	struct inode *inode;

	/* sanity check */
	if (dir->i_ino != IROOT)
		return ERR_PTR(-EINVAL);
	dentry->d_op = &usbdevfs_dentry_operations;
	busnr = dnumber(dentry);
	if (busnr >= 0 && busnr <= 255)
		ino = IBUS | (busnr << 8);
	if (!ino) {
		for (i = 0; i < NRSPECIAL; i++) {
			if (strlen(special[i].name) == dentry->d_name.len && 
			    !strncmp(special[i].name, dentry->d_name.name, dentry->d_name.len)) {
				ino = ISPECIAL | (i + IROOT + 1);
				break;
			}
		}
	}
	if (!ino)
		return ERR_PTR(-ENOENT);
	inode = iget(dir->i_sb, ino);
	if (!inode)
		return ERR_PTR(-EINVAL);
	if (inode && ITYPE(ino) == IBUS && inode->u.usbdev_i.p.bus == NULL) {
		iput(inode);
		inode = NULL;
	}
	d_add(dentry, inode);
	return NULL;
}
예제 #7
0
static struct dentry *usbdevfs_bus_lookup(struct inode *dir, struct dentry *dentry)
{
	struct inode *inode;
	int devnr;

	/* sanity check */
	if (ITYPE(dir->i_ino) != IBUS)
		return ERR_PTR(-EINVAL);
	dentry->d_op = &usbdevfs_dentry_operations;
	devnr = dnumber(dentry);
	if (devnr < 1 || devnr > 127)
		return ERR_PTR(-ENOENT);
	inode = iget(dir->i_sb, IDEVICE | (dir->i_ino & (0xff << 8)) | devnr);
	if (!inode)
		return ERR_PTR(-EINVAL);
	if (inode && inode->u.usbdev_i.p.dev == NULL) {
		iput(inode);
		inode = NULL;
	}
	d_add(dentry, inode);
	return NULL;
}
예제 #8
0
/*! \brief
 * Read parameters of an AWH bias dimension.
 *
 * \param[in,out] ninp_p     Number of read input file entries.
 * \param[in,out] inp_p      Input file entries.
 * \param[in] prefix         Prefix for dimension parameters.
 * \param[in,out] dimParams  AWH dimensional parameters.
 * \param[in] pull_params    Pull parameters.
 * \param[in,out] wi         Struct for bookeeping warnings.
 * \param[in] bComment       True if comments should be printed.
 */
static void readDimParams(int *ninp_p, t_inpfile **inp_p, const char *prefix,
                          AwhDimParams *dimParams, const pull_params_t *pull_params,
                          warninp_t wi, bool bComment)
{
    char       warningmsg[STRLEN];

    int        ninp = *ninp_p;
    t_inpfile *inp  = *inp_p;

    if (bComment)
    {
        CTYPE("The provider of the reaction coordinate, currently only pull is supported");
    }
    char opt[STRLEN];
    sprintf(opt, "%s-coord-provider", prefix);
    EETYPE(opt, dimParams->eCoordProvider, eawhcoordprovider_names);

    if (bComment)
    {
        CTYPE("The coordinate index for this dimension");
    }
    sprintf(opt, "%s-coord-index", prefix);
    int coordIndexInput;
    ITYPE(opt, coordIndexInput, 1);
    if (coordIndexInput <  1)
    {
        gmx_fatal(FARGS, "Failed to read a valid coordinate index for %s. "
                  "Note that the pull coordinate indexing starts at 1.", opt);
    }

    /* The pull coordinate indices start at 1 in the input file, at 0 internally */
    dimParams->coordIndex = coordIndexInput - 1;

    /* The pull settings need to be consistent with the AWH settings */
    if (!(pull_params->coord[dimParams->coordIndex].eType == epullEXTERNAL) )
    {
        gmx_fatal(FARGS, "AWH biasing can only be  applied to pull type %s",
                  EPULLTYPE(epullEXTERNAL));
    }

    if (dimParams->coordIndex >= pull_params->ncoord)
    {
        gmx_fatal(FARGS, "The given AWH coordinate index (%d) is larger than the number of pull coordinates (%d)",
                  coordIndexInput, pull_params->ncoord);
    }
    if (pull_params->coord[dimParams->coordIndex].rate != 0)
    {
        sprintf(warningmsg, "Setting pull-coord%d-rate (%g) is incompatible with AWH biasing this coordinate", coordIndexInput, pull_params->coord[dimParams->coordIndex].rate);
        warning_error(wi, warningmsg);
    }

    /* Grid params for each axis */
    int eGeom = pull_params->coord[dimParams->coordIndex].eGeom;

    if (bComment)
    {
        CTYPE("Start and end values for each coordinate dimension");
    }

    sprintf(opt, "%s-start", prefix);
    RTYPE(opt, dimParams->origin, 0.);

    sprintf(opt, "%s-end", prefix);
    RTYPE(opt, dimParams->end, 0.);

    if (gmx_within_tol(dimParams->end - dimParams->origin, 0, GMX_REAL_EPS))
    {
        sprintf(warningmsg, "The given interval length given by %s-start (%g) and %s-end (%g) is zero. "
                "This will result in only one point along this axis in the coordinate value grid.",
                prefix, dimParams->origin, prefix, dimParams->end);
        warning(wi, warningmsg);
    }
    /* Check that the requested interval is in allowed range */
    if (eGeom == epullgDIST)
    {
        if (dimParams->origin < 0 || dimParams->end < 0)
        {
            gmx_fatal(FARGS, "%s-start (%g) or %s-end (%g) set to a negative value. With pull geometry distance coordinate values are non-negative. "
                      "Perhaps you want to use geometry %s instead?",
                      prefix, dimParams->origin, prefix, dimParams->end, EPULLGEOM(epullgDIR));
        }
    }
    else if (eGeom == epullgANGLE || eGeom == epullgANGLEAXIS)
    {
        if (dimParams->origin < 0 || dimParams->end > 180)
        {
            gmx_fatal(FARGS, "%s-start (%g) and %s-end (%g) are outside of the allowed range 0 to 180 deg for pull geometries %s and %s ",
                      prefix, dimParams->origin, prefix, dimParams->end, EPULLGEOM(epullgANGLE), EPULLGEOM(epullgANGLEAXIS));
        }
    }
    else if (eGeom == epullgDIHEDRAL)
    {
        if (dimParams->origin < -180 || dimParams->end > 180)
        {
            gmx_fatal(FARGS, "%s-start (%g) and %s-end (%g) are outside of the allowed range -180 to 180 deg for pull geometry %s. ",
                      prefix, dimParams->origin, prefix, dimParams->end, EPULLGEOM(epullgDIHEDRAL));
        }
    }

    if (bComment)
    {
        CTYPE("The force constant for this coordinate (kJ/mol/nm^2 or kJ/mol/rad^2)");
    }
    sprintf(opt, "%s-force-constant", prefix);
    RTYPE(opt, dimParams->forceConstant, 0);
    if (dimParams->forceConstant <= 0)
    {
        warning_error(wi, "The force AWH bias force constant should be > 0");
    }

    if (bComment)
    {
        CTYPE("Estimated diffusion constant (nm^2/ps or rad^2/ps)");
    }
    sprintf(opt, "%s-diffusion", prefix);
    RTYPE(opt, dimParams->diffusion, 0);

    if (dimParams->diffusion <= 0)
    {
        const double diffusion_default = 1e-5;
        sprintf(warningmsg, "%s not explicitly set by user."
                " You can choose to use a default value (%g nm^2/ps or rad^2/ps) but this may very well be non-optimal for your system!",
                opt, diffusion_default);
        warning(wi, warningmsg);
        dimParams->diffusion = diffusion_default;
    }

    if (bComment)
    {
        CTYPE("Diameter that needs to be sampled around a point before it is considered covered.");
    }
    sprintf(opt, "%s-cover-diameter", prefix);
    RTYPE(opt, dimParams->coverDiameter, 0);

    if (dimParams->coverDiameter < 0)
    {
        gmx_fatal(FARGS, "%s (%g) cannot be negative.",
                  opt, dimParams->coverDiameter);
    }

    *ninp_p   = ninp;
    *inp_p    = inp;
}
예제 #9
0
AwhParams *readAndCheckAwhParams(int *ninp_p, t_inpfile **inp_p, const t_inputrec *ir, warninp_t wi)
{
    char       opt[STRLEN], prefix[STRLEN], prefixawh[STRLEN];

    AwhParams *awhParams;
    snew(awhParams, 1);

    int        ninp = *ninp_p;
    t_inpfile *inp  = *inp_p;

    sprintf(prefix, "%s", "awh");

    /* Parameters common for all biases */

    CTYPE("The way to apply the biasing potential: convolved or umbrella");
    sprintf(opt, "%s-potential", prefix);
    EETYPE(opt, awhParams->ePotential, eawhpotential_names);

    CTYPE("The random seed used for sampling the umbrella center in the case of umbrella type potential");
    sprintf(opt, "%s-seed", prefix);
    ITYPE(opt, awhParams->seed, -1);
    if (awhParams->seed == -1)
    {
        awhParams->seed = static_cast<int>(gmx::makeRandomSeed());
        fprintf(stderr, "Setting the AWH bias MC random seed to %" GMX_PRId64 "\n", awhParams->seed);
    }

    CTYPE("Data output interval in number of steps");
    sprintf(opt, "%s-nstout", prefix);
    ITYPE(opt, awhParams->nstOut, 100000);
    if (awhParams->nstOut <= 0)
    {
        char buf[STRLEN];
        sprintf(buf, "Not writing AWH output with AWH (%s = %d) does not make sense",
                opt, awhParams->nstOut);
        warning_error(wi, buf);
    }
    /* This restriction can be removed by changing a flag of print_ebin() */
    if (ir->nstenergy == 0 || awhParams->nstOut % ir->nstenergy != 0)
    {
        char buf[STRLEN];
        sprintf(buf, "%s (%d) should be a multiple of nstenergy (%d)",
                opt, awhParams->nstOut, ir->nstenergy);
        warning_error(wi, buf);
    }

    CTYPE("Coordinate sampling interval in number of steps");
    sprintf(opt, "%s-nstsample", prefix);
    ITYPE(opt, awhParams->nstSampleCoord, 10);

    CTYPE("Free energy and bias update interval in number of samples");
    sprintf(opt, "%s-nsamples-update", prefix);
    ITYPE(opt, awhParams->numSamplesUpdateFreeEnergy, 10);

    CTYPE("When true, biases with share-group>0 are shared between multiple simulations");
    sprintf(opt, "%s-share-multisim", prefix);
    EETYPE(opt, awhParams->shareBiasMultisim, yesno_names);

    CTYPE("The number of independent AWH biases");
    sprintf(opt, "%s-nbias", prefix);
    ITYPE(opt, awhParams->numBias, 1);
    if (awhParams->numBias <= 0)
    {
        gmx_fatal(FARGS, "%s needs to be an integer > 0", opt);
    }

    /* Read the parameters specific to each AWH bias */
    snew(awhParams->awhBiasParams, awhParams->numBias);

    for (int k = 0; k < awhParams->numBias; k++)
    {
        bool bComment = (k == 0);
        sprintf(prefixawh, "%s%d", prefix, k + 1);
        read_bias_params(&ninp, &inp, &awhParams->awhBiasParams[k], prefixawh, ir, wi, bComment);
    }

    /* Do a final consistency check before returning */
    checkInputConsistencyAwh(*awhParams, wi);

    if (ir->init_step != 0)
    {
        warning_error(wi, "With AWH init-step should be 0");
    }

    *ninp_p   = ninp;
    *inp_p    = inp;

    return awhParams;
}
예제 #10
0
/*! \brief
 * Read parameters of an AWH bias.
 *
 * \param[in,out] ninp_p         Number of read input file entries.
 * \param[in,out] inp_p          Input file entries.
 * \param[in,out] awhBiasParams  AWH dimensional parameters.
 * \param[in]     prefix         Prefix for bias parameters.
 * \param[in]     ir             Input parameter struct.
 * \param[in,out] wi             Struct for bookeeping warnings.
 * \param[in]     bComment       True if comments should be printed.
 */
static void read_bias_params(int *ninp_p, t_inpfile **inp_p, AwhBiasParams *awhBiasParams, const char *prefix,
                             const t_inputrec *ir, warninp_t wi, bool bComment)
{
    int        ninp;
    t_inpfile *inp;
    char       opt[STRLEN], prefixdim[STRLEN];
    char       warningmsg[STRLEN];

    /* These are assumed to be declared by the gromacs reading functions */
    ninp   = *ninp_p;
    inp    = *inp_p;

    if (bComment)
    {
        CTYPE("Estimated initial PMF error (kJ/mol)");
    }
    sprintf(opt, "%s-error-init", prefix);

    /* We allow using a default value here without warning (but warn the user if the diffusion constant is not set). */
    RTYPE(opt, awhBiasParams->errorInitial, 10);
    if (awhBiasParams->errorInitial <= 0)
    {
        gmx_fatal(FARGS, "%s (%d) needs to be > 0.", opt);
    }

    if (bComment)
    {
        CTYPE("Growth rate of the reference histogram determining the bias update size: exp-linear or linear");
    }
    sprintf(opt, "%s-growth", prefix);
    EETYPE(opt, awhBiasParams->eGrowth, eawhgrowth_names);

    if (bComment)
    {
        CTYPE("Start the simulation by equilibrating histogram towards the target distribution: no or yes");
    }
    sprintf(opt, "%s-equilibrate-histogram", prefix);
    EETYPE(opt, awhBiasParams->equilibrateHistogram, yesno_names);
    if (awhBiasParams->equilibrateHistogram && awhBiasParams->eGrowth != eawhgrowthEXP_LINEAR)
    {
        sprintf(warningmsg, "Option %s will only have an effect for histogram growth type '%s'.",
                opt, EAWHGROWTH(eawhgrowthEXP_LINEAR));
        warning(wi, warningmsg);
    }

    if (bComment)
    {
        CTYPE("Target distribution type: constant, cutoff, boltzmann or local-boltzmann");
    }
    sprintf(opt, "%s-target", prefix);
    EETYPE(opt, awhBiasParams->eTarget, eawhtarget_names);

    if ((awhBiasParams->eTarget == eawhtargetLOCALBOLTZMANN) &&
        (awhBiasParams->eGrowth == eawhgrowthEXP_LINEAR))
    {
        sprintf(warningmsg, "Target type '%s' combined with histogram growth type '%s' is not "
                "expected to give stable bias updates. You probably want to use growth type "
                "'%s' instead.",
                EAWHTARGET(eawhtargetLOCALBOLTZMANN), EAWHGROWTH(eawhgrowthEXP_LINEAR),
                EAWHGROWTH(eawhgrowthLINEAR));
        warning(wi, warningmsg);
    }

    if (bComment)
    {
        CTYPE("Boltzmann beta scaling factor for target distribution types 'boltzmann' and 'boltzmann-local'");
    }
    sprintf(opt, "%s-target-beta-scaling", prefix);
    RTYPE(opt, awhBiasParams->targetBetaScaling, 0);

    switch (awhBiasParams->eTarget)
    {
        case eawhtargetBOLTZMANN:
        case eawhtargetLOCALBOLTZMANN:
            if (awhBiasParams->targetBetaScaling < 0 || awhBiasParams->targetBetaScaling > 1)
            {
                gmx_fatal(FARGS, "%s = %g is not useful for target type %s.",
                          opt, awhBiasParams->targetBetaScaling, EAWHTARGET(awhBiasParams->eTarget));
            }
            break;
        default:
            if (awhBiasParams->targetBetaScaling != 0)
            {
                gmx_fatal(FARGS, "Value for %s (%g) set explicitly but will not be used for target type %s.",
                          opt, awhBiasParams->targetBetaScaling, EAWHTARGET(awhBiasParams->eTarget));
            }
            break;
    }

    if (bComment)
    {
        CTYPE("Free energy cutoff value for target distribution type 'cutoff'");
    }
    sprintf(opt, "%s-target-cutoff", prefix);
    RTYPE(opt, awhBiasParams->targetCutoff, 0);

    switch (awhBiasParams->eTarget)
    {
        case eawhtargetCUTOFF:
            if (awhBiasParams->targetCutoff <= 0)
            {
                gmx_fatal(FARGS, "%s = %g is not useful for target type %s.",
                          opt, awhBiasParams->targetCutoff, EAWHTARGET(awhBiasParams->eTarget));
            }
            break;
        default:
            if (awhBiasParams->targetCutoff != 0)
            {
                gmx_fatal(FARGS, "Value for %s (%g) set explicitly but will not be used for target type %s.",
                          opt, awhBiasParams->targetCutoff, EAWHTARGET(awhBiasParams->eTarget));
            }
            break;
    }

    if (bComment)
    {
        CTYPE("Initialize PMF and target with user data: no or yes");
    }
    sprintf(opt, "%s-user-data", prefix);
    EETYPE(opt, awhBiasParams->bUserData, yesno_names);

    if (bComment)
    {
        CTYPE("Group index to share the bias with, 0 means not shared");
    }
    sprintf(opt, "%s-share-group", prefix);
    ITYPE(opt, awhBiasParams->shareGroup, 0);
    if (awhBiasParams->shareGroup < 0)
    {
        warning_error(wi, "AWH bias share-group should be >= 0");
    }

    if (bComment)
    {
        CTYPE("Dimensionality of the coordinate");
    }
    sprintf(opt, "%s-ndim", prefix);
    ITYPE(opt, awhBiasParams->ndim, 0);

    if (awhBiasParams->ndim <= 0 ||
        awhBiasParams->ndim > c_biasMaxNumDim)
    {
        gmx_fatal(FARGS, "%s-ndim (%d) needs to be > 0 and at most %d\n", prefix,  awhBiasParams->ndim, c_biasMaxNumDim);
    }
    if (awhBiasParams->ndim > 2)
    {
        warning_note(wi, "For awh-dim > 2 the estimate based on the diffusion and the initial error is currently only a rough guideline."
                     " You should verify its usefulness for your system before production runs!");
    }
    snew(awhBiasParams->dimParams, awhBiasParams->ndim);
    for (int d = 0; d < awhBiasParams->ndim; d++)
    {
        bComment = bComment && d == 0;
        sprintf(prefixdim, "%s-dim%d", prefix, d + 1);
        readDimParams(&ninp, &inp, prefixdim, &awhBiasParams->dimParams[d], ir->pull, wi, bComment);
    }

    /* Check consistencies here that cannot be checked at read time at a lower level. */
    checkInputConsistencyAwhBias(*awhBiasParams, wi);

    *ninp_p   = ninp;
    *inp_p    = inp;
}
예제 #11
0
파일: pullio.c 프로젝트: Chadi-akel/cere
void read_pullparams(t_pull *pull, char *infile, char *outfile) 
{
  t_inpfile *inp;
  int ninp,i;
  char *tmp;           /* for the input parsing macros */
  char dummy[STRLEN];  /* idem */
  char grp1buf[STRLEN], grp2buf[STRLEN], grp3buf[STRLEN], grp4buf[STRLEN],
       grp5buf[STRLEN],
       bf1[STRLEN], bf2[STRLEN], dir[STRLEN], 
       refdir1[STRLEN],refdir2[STRLEN];

  int bReverse; int tmpref; int tmprun; 

  enum {erunSTART, erunAFM, erunConstraint, erunUmbrella, erunTest, erunNR};
  static char *runtypes[erunNR+1] = { 
    "start", "afm", "constraint", "umbrella", "test", NULL
  };
  enum {erefCom, erefComT0, erefDyn, erefDynT0, erefNR};
  static char *reftypes[erefNR+1] = {
    "com", "com_t0", "dynamic", "dynamic_t0", NULL
  };
  enum {ereverseTO_REF, ereverseFROM_REF, ereverseNR};
  static char *reversetypes[ereverseNR+1] = {
    "from_reference", "to_reference", NULL
  };
  enum {everboseYES, everboseNO, everboseNR};
  static char *verbosetypes[erefNR+1] = {
    "no", "yes", NULL
  };
  int nerror = 0;

  /* read input parameter file */
  fprintf(stderr,"Reading parameter file %s\n",infile);
  inp=read_inpfile(infile,&ninp);

  /* general options */
  CTYPE("GENERAL");
  EETYPE("verbose",         pull->bVerbose, verbosetypes, &nerror, TRUE);
  CTYPE("Runtype: start, afm, constraint, umbrella, test");
  EETYPE("runtype",         tmprun, runtypes, &nerror, TRUE);
  CTYPE("Groups to be pulled");
  STYPE("group_1",          grp1buf, "");
  STYPE("group_2",          grp2buf, "");
  STYPE("group_3",          grp3buf, "");
  STYPE("group_4",          grp4buf, "");
  CTYPE("The group for the reaction force.");
  STYPE("reference_group",  grp5buf, "");
  CTYPE("Ref. type: com, com_t0, dynamic, dynamic_t0");
  EETYPE("reftype",         tmpref, reftypes, &nerror, TRUE);
  CTYPE("Use running average for reflag steps for com calculation");
  ITYPE("reflag",           pull->reflag, 1);
  CTYPE("Select components for constraint vector. default: z-only");
  STYPE("direction",        dir, "0.0 0.0 1.0");
  CTYPE("Direction for start/afm: to_reference, from_reference");
  EETYPE("reverse",          pull->bReverse, reversetypes, &nerror, TRUE);

  /* options for dynamic reference groups */
  CTYPE("DYNAMIC REFERENCE GROUP OPTIONS");
  CTYPE("Cylinder radius for dynamic reaction force groups (nm)");
  RTYPE("r",                pull->r, 0.0);
  CTYPE("Switch from r to rc in case of dynamic reaction force");
  RTYPE("rc",   pull->rc,   0.0);
  CTYPE("Update frequency for dynamic reference groups (steps)");
  ITYPE("update",           pull->update, 1);

  /* constraint run options */
  CCTYPE("CONSTRAINT RUN OPTIONS");
  CTYPE("Tolerance of constraints, in nm");
  RTYPE("constraint_tolerance",            pull->constr_tol, 1E-6);

  /* options for AFM type pulling simulations */
  CCTYPE("AFM OPTIONS");
  CTYPE("pull rate in nm/timestep");
  RTYPE("pullrate",         pull->rate,    0.0);
  CTYPE("forceconstant in kJ/(mol*nm^2)");
  RTYPE("forceconstant",    pull->k, 0.0);

  /* umbrella sampling options */
  CCTYPE("UMBRELLA SAMPLING OPTIONS");
  CTYPE("Width of umbrella sampling potential in kJ/(mol*nm^2)");
  RTYPE("width",            pull->um_width, 0.0);

  /* options for making starting structures */
  CCTYPE("STARTING STRUCTURE OPTIONS");
  CTYPE("Start coord. for making starting struct, rel. to ref. grp.: x y z");
  STYPE("r0_group1",        bf1, "");
  STYPE("r0_group2",        bf2, ""); 
  /*  CTYPE("Constrain rotations around principle axes? Needs work");
      ITYPE("rotation_x",       pull->bRot[0], 0);
      ITYPE("rotation_y",       pull->bRot[1], 0);
      ITYPE("rotation_z",       pull->bRot[2], 0);
      CTYPE("Rate of rotation (degrees/step)");
      RTYPE("rotation_rate",    pull->rot_rate, 0.0);
  */
  RTYPE("tolerance",        pull->tolerance, 0.05);
  CTYPE("Rate of translation in all directions (nm/step)");
  RTYPE("translation_rate", pull->xlt_rate, 0.0); 
  CTYPE("Write out structure every ndegr degrees, transstep nm");
  ITYPE("ndegr",            pull->rot_incr, 0);
  RTYPE("transstep",        pull->xlt_incr, 0.001);

  write_inpfile(outfile,ninp,inp);
  for (i=0; (i<ninp); i++) {
    sfree(inp[i].name);
    sfree(inp[i].value);
  }
  sfree(inp);

  pull->runtype = (t_runtype)tmprun;
  pull->reftype = (t_reftype)tmpref;

  /* sort out the groups */
  fprintf(stderr,"Groups: %s %s %s %s %s\n",
	  grp1buf,grp2buf,grp3buf,grp4buf,grp4buf);

  if (!strcmp(grp1buf,"") || !strcmp(grp5buf,"")) 
    fatal_error(0,"Need to specify at least group_1 and reference_group");
  pull->pull.n = 1;
  if (strcmp(grp2buf,"")) 
    pull->pull.n += 1;
  if (strcmp(grp3buf,"")) 
    pull->pull.n += 1;
  if (strcmp(grp4buf,""))
    pull->pull.n += 1;
     
  fprintf(stderr,"Using %d pull groups\n",pull->pull.n);
     
  /* initialize the names of the groups */
  snew(pull->pull.grps,pull->pull.n);
  snew(pull->ref.grps,1);
  pull->pull.grps[0] = (char *)strdup(grp1buf);
  pull->pull.grps[1] = (char *)strdup(grp2buf);
  pull->pull.grps[2] = (char *)strdup(grp3buf);
  pull->pull.grps[3] = (char *)strdup(grp4buf);
  pull->ref.grps[0]  = (char *)strdup(grp5buf);

  if (pull->runtype == eStart) {
    snew(pull->pull.xtarget,pull->pull.n);
    string2rvec(bf1,pull->pull.xtarget[0]);
    if (pull->pull.n == 2)
      string2rvec(bf2,pull->pull.xtarget[1]);
  }

  string2rvec(dir,pull->dims);
  fprintf(stderr,"Using distance components %2.1f %2.1f %2.1f\n",
	  pull->dims[0],pull->dims[1],pull->dims[2]);

  if (pull->r > 0.001) 
    pull->bCyl = TRUE;
  else
    pull->bCyl = FALSE;
}