Esempio n. 1
0
//record parameters. we will determine which ones need to be adjusted later
param_g *record_params(system_t *system) {
    char last_atomtype[MAXLINE];
    last_atomtype[0] = '\0';  //initialize last_atomtype
    atom_t *atom_ptr;

    param_g *rval = calloc(1, sizeof(param_g));
    memnullcheck(rval, sizeof(param_g), __LINE__ - 1, __FILE__);
    param_t *param_list = calloc(1, sizeof(param_t));  //return value
    memnullcheck(param_list, sizeof(param_t), __LINE__ - 1, __FILE__);

    param_t *param_ptr = param_list;  //used to seek through param list
    param_t *prev_param_ptr = 0;

    rval->alpha = system->polar_damp;
    rval->last_alpha = system->polar_damp;

    for (atom_ptr = system->molecules->atoms; atom_ptr; atom_ptr = atom_ptr->next) {
        if (strcasecmp(atom_ptr->atomtype, last_atomtype)) {
            strcpy(param_ptr->atomtype, atom_ptr->atomtype);

            param_ptr->charge = atom_ptr->charge;
            param_ptr->epsilon = atom_ptr->epsilon;
            param_ptr->sigma = atom_ptr->sigma;
            param_ptr->omega = atom_ptr->omega;
            param_ptr->pol = atom_ptr->polarizability;
            param_ptr->c6 = atom_ptr->c6;
            param_ptr->c8 = atom_ptr->c8;
            param_ptr->c10 = atom_ptr->c10;

            param_ptr->last_charge = param_ptr->charge;
            param_ptr->last_epsilon = param_ptr->epsilon;
            param_ptr->last_sigma = param_ptr->sigma;
            param_ptr->last_omega = param_ptr->omega;
            param_ptr->last_pol = param_ptr->pol;
            param_ptr->last_c6 = param_ptr->c6;
            param_ptr->last_c8 = param_ptr->c8;
            param_ptr->last_c10 = param_ptr->c10;

            param_ptr->next = calloc(1, sizeof(param_t));
            memnullcheck(param_ptr->next, sizeof(param_t), __LINE__ - 1, __FILE__);
            prev_param_ptr = param_ptr;
            param_ptr = param_ptr->next;

            strcpy(last_atomtype, atom_ptr->atomtype);
        }
    }

    prev_param_ptr->next = NULL;
    free(param_ptr);

    //count ntypes
    for (param_ptr = param_list; param_ptr; param_ptr = param_ptr->next) {
        for (atom_ptr = system->molecules->atoms; atom_ptr; atom_ptr = atom_ptr->next)
            if (!strcasecmp(param_ptr->atomtype, atom_ptr->atomtype))
                ++(param_ptr->ntypes);
    }

    rval->type_params = param_list;
    return rval;
}
Esempio n. 2
0
void free_my_pairs ( molecule_t * molecule ) {
	int i = 0;
	pair_t ** ptr_array = NULL;
	atom_t * aptr;
	pair_t * pptr;

	//build an array of pairs
	for ( aptr = molecule->atoms; aptr; aptr = aptr->next ) {
		for ( pptr = aptr->pairs; pptr; pptr = pptr->next ) {
			ptr_array = realloc(ptr_array, sizeof(pair_t *)*(i+1));
			memnullcheck(ptr_array,sizeof(pair_t *)*(i+1),__LINE__-1, __FILE__);
			ptr_array[i] = pptr;
			++i;
		}
	}

	//free the pairs
	for (--i; i>=0; i--) free(ptr_array[i]);

	//zero out the heads
	for (aptr = molecule->atoms; aptr; aptr=aptr->next )
		aptr->pairs = NULL;

	//free the temp array
	free(ptr_array);

	return;
}
Esempio n. 3
0
// free all pairs
void free_all_pairs(system_t * system) {
	int i, j;
	pair_t *pair_ptr;
	pair_t **ptr_array = NULL;

	j=0; //pair array index
	//build an array of all pair pointers
	for ( i=0; i< system->natoms ; i++ ) {
		for ( pair_ptr = system->atom_array[i]->pairs; pair_ptr; pair_ptr = pair_ptr->next ) {
				ptr_array = realloc(ptr_array, sizeof(pair_t *)*(j + 1));
				memnullcheck(ptr_array,sizeof(pair_t *)*(j+1),__LINE__-1, __FILE__);
				ptr_array[j] = pair_ptr;
				j++;
		}
	}

	/* free the whole array of ptrs */
	while ( j-- ) free(ptr_array[j]);

	/* zero out the heads */
	for ( i=0; i< system->natoms; i++ ) 
		system->atom_array[i]->pairs = NULL;

	/* free our temporary array */
	if(ptr_array) free(ptr_array);
}
Esempio n. 4
0
void allocqmrotation(system_t *system, molecule_t *molecule_ptr) {
    int i;

    molecule_ptr->quantum_rotational_energies = calloc(system->quantum_rotation_level_max, sizeof(double));
    memnullcheck(molecule_ptr->quantum_rotational_energies,
                 system->quantum_rotation_level_max * sizeof(double), __LINE__ - 1, __FILE__);
    molecule_ptr->quantum_rotational_eigenvectors = calloc(system->quantum_rotation_level_max, sizeof(complex_t *));
    memnullcheck(molecule_ptr->quantum_rotational_eigenvectors,
                 system->quantum_rotation_level_max * sizeof(complex_t *), __LINE__ - 1, __FILE__);
    for (i = 0; i < system->quantum_rotation_level_max; i++) {
        molecule_ptr->quantum_rotational_eigenvectors[i] =
            calloc((system->quantum_rotation_l_max + 1) * (system->quantum_rotation_l_max + 1), sizeof(complex_t));
        memnullcheck(molecule_ptr->quantum_rotational_eigenvectors[i],
                     (system->quantum_rotation_l_max + 1) * (system->quantum_rotation_l_max + 1) * sizeof(complex_t), __LINE__ - 1, __FILE__);
    }
    molecule_ptr->quantum_rotational_eigensymmetry = calloc(system->quantum_rotation_level_max, sizeof(int));
    memnullcheck(molecule_ptr->quantum_rotational_eigensymmetry,
                 system->quantum_rotation_level_max * sizeof(int), __LINE__ - 1, __FILE__);

    return;
}
Esempio n. 5
0
void addSorbateToList( system_t * system, char *sorbate_type ){

	// grow array
	system->sorbateInfo = realloc(system->sorbateInfo, system->sorbateCount*sizeof(sorbateInfo_t));
	memnullcheck(system->sorbateInfo, system->sorbateCount*sizeof(sorbateInfo_t), __LINE__-1, __FILE__);

	// set sorbate type for the new element
	strcpy( system->sorbateInfo[system->sorbateCount-1].id, sorbate_type );
	
	// send a status update to stdout
	char buffer[MAXLINE];
	sprintf(buffer, "INPUT: System will track individual stats for sorbate %s.\n", 
		system->sorbateInfo[system->sorbateCount-1].id );
	output( buffer );

	return;
}
Esempio n. 6
0
//free vdw pointer which keeps track of e_iso energies
void free_vdw_eiso(vdw_t * vdw_eiso_info) {
	vdw_t * vp;
	vdw_t ** varray = NULL;
	int i=0;

	for ( vp = vdw_eiso_info; vp; vp=vp->next ) {
		varray = realloc(varray, sizeof(vdw_t *)*(i+1));
		memnullcheck(varray,sizeof(vdw_t *)*(i+1), __LINE__-1, __FILE__);
		varray[i]=vp;
		i++;
	}

	while ( i>0 ) {
		i--;
		free(varray[i]);
	}

	free(varray);

	return;
}
Esempio n. 7
0
void free_my_atoms ( molecule_t * molecules ) {
	int i = 0;
	atom_t * aptr;
	atom_t ** aarray = NULL;

	//build an array of atoms
	for ( aptr= molecules->atoms; aptr; aptr=aptr->next ) {
		aarray = realloc(aarray, sizeof(atom_t *)*(i+1));
		memnullcheck(aarray,sizeof(atom_t *)*(i+1), __LINE__-1, __FILE__);
		aarray[i] = aptr;
		i++;
	}

	//free the atoms
	while ( i-- )
		free(aarray[i]);

	//free the temp array
	free(aarray);

	return;
}
Esempio n. 8
0
// free all molecules
void free_all_molecules(system_t * system, molecule_t * molecules) {

	int i;
	molecule_t **marray = NULL;
	molecule_t *mptr;

	/* build the ptr array */  // we can't free all of system->molecule_array since it's redundant
	for(mptr = molecules, i = 0; mptr; mptr = mptr->next) {
		free_my_atoms(mptr);
		marray = realloc(marray, sizeof(molecule_t *)*(i + 1));
		memnullcheck(marray,sizeof(molecule_t *)*(i + 1),__LINE__-1, __FILE__);
		marray[i] = mptr;
		i++;
	}

	/* free the whole array of ptrs */
	for(--i; i >= 0; i--) free(marray[i]);

	/* free our temporary arrays */
	free(marray);

	return;
}
Esempio n. 9
0
/* apply what was already determined in checkpointing */
void make_move(system_t *system) {
    int i, j, k, p, q;
    cavity_t *cavities_array;
    int cavities_array_counter, random_index;
    double com[3], rand[3];
    molecule_t *molecule_ptr;
    atom_t *atom_ptr;
    pair_t *pair_ptr;

    /* update the cavity grid prior to making a move */
    if (system->cavity_bias) {
        cavity_update_grid(system);
        system->checkpoint->biased_move = 0;
    }

    switch (system->checkpoint->movetype) {
        case MOVETYPE_INSERT: /* insert a molecule at a random pos and orientation */
            /* umbrella sampling */
            if (system->cavity_bias && system->cavities_open) {
                /* doing a biased move - this flag lets mc.c know about it */
                system->checkpoint->biased_move = 1;
                /* make an array of possible insertion points */
                cavities_array = calloc(system->cavities_open, sizeof(cavity_t));
                memnullcheck(cavities_array, system->cavities_open * sizeof(cavity_t), __LINE__ - 1, __FILE__);
                for (i = 0, cavities_array_counter = 0; i < system->cavity_grid_size; i++) {
                    for (j = 0; j < system->cavity_grid_size; j++) {
                        for (k = 0; k < system->cavity_grid_size; k++) {
                            if (!system->cavity_grid[i][j][k].occupancy) {
                                for (p = 0; p < 3; p++)
                                    cavities_array[cavities_array_counter].pos[p] = system->cavity_grid[i][j][k].pos[p];
                                ++cavities_array_counter;
                            }
                        } /* end k */
                    }     /* end j */
                }         /* end i */
                /* insert randomly at one of the free cavity points */
                random_index = (system->cavities_open - 1) - (int)rint(((double)(system->cavities_open - 1)) * get_rand(system));
                for (p = 0; p < 3; p++)
                    com[p] = cavities_array[random_index].pos[p];
                /* free the insertion array */
                free(cavities_array);
            }  // end umbrella

            else {
                /* insert the molecule to a random location within the unit cell */
                for (p = 0; p < 3; p++)
                    rand[p] = 0.5 - get_rand(system);
                for (p = 0; p < 3; p++)
                    for (q = 0, com[p] = 0; q < 3; q++)
                        com[p] += system->pbc->basis[q][p] * rand[q];
            }

            /* process the inserted molecule */
            for (atom_ptr = system->checkpoint->molecule_backup->atoms; atom_ptr; atom_ptr = atom_ptr->next) {
                /* move the molecule back to the origin and then assign it to com */
                for (p = 0; p < 3; p++)
                    atom_ptr->pos[p] += com[p] - system->checkpoint->molecule_backup->com[p];
            }

            /* update the molecular com */
            for (p = 0; p < 3; p++)
                system->checkpoint->molecule_backup->com[p] = com[p];
            /* give it a random orientation */
            rotate(system, system->checkpoint->molecule_backup, system->pbc, 1.0);

            // insert into the list
            if (system->num_insertion_molecules) {
                // If inserting a molecule from an insertion list, we will always insert at the end
                system->checkpoint->head->next = system->checkpoint->molecule_backup;
                system->checkpoint->molecule_backup->next = NULL;
            } else {
                if (!system->checkpoint->head) {  // if we're at the start of the list:
                    system->molecules = system->checkpoint->molecule_backup;
                } else {
                    system->checkpoint->head->next = system->checkpoint->molecule_backup;
                }
                system->checkpoint->molecule_backup->next = system->checkpoint->molecule_altered;
            }

            /* set new altered and tail to reflect the insertion */
            system->checkpoint->molecule_altered = system->checkpoint->molecule_backup;
            system->checkpoint->tail = system->checkpoint->molecule_altered->next;
            system->checkpoint->molecule_backup = NULL;

            if (system->num_insertion_molecules) {  //multi sorbate
                // Free all pair memory in the list
                for (molecule_ptr = system->molecules; molecule_ptr; molecule_ptr = molecule_ptr->next) {
                    for (atom_ptr = molecule_ptr->atoms; atom_ptr; atom_ptr = atom_ptr->next) {
                        pair_ptr = atom_ptr->pairs;
                        while (pair_ptr) {
                            pair_t *temp = pair_ptr;
                            pair_ptr = pair_ptr->next;
                            free(temp);
                        }
                    }
                }
                // Generate new pairs lists for all atoms in system
                setup_pairs(system);
            }  // only one sorbate
            else
                update_pairs_insert(system);

            //reset atom and molecule id's
            enumerate_particles(system);

            break;
        case MOVETYPE_REMOVE: /* remove a randomly chosen molecule */

            if (system->cavity_bias) {
                if (get_rand(system) < pow((1.0 - system->avg_observables->cavity_bias_probability),
                                     ((double)system->cavity_grid_size * system->cavity_grid_size * system->cavity_grid_size)))
                    system->checkpoint->biased_move = 0;
                else
                    system->checkpoint->biased_move = 1;
            }

            /* remove 'altered' from the list */
            if (!system->checkpoint->head) { /* handle the case where we're removing from the start of the list */
                system->checkpoint->molecule_altered = system->molecules;
                system->molecules = system->molecules->next;
            } else {
                system->checkpoint->head->next = system->checkpoint->tail;
            }
            free_molecule(system, system->checkpoint->molecule_altered);
            system->checkpoint->molecule_altered = NULL; /* Insurance against memory errors */
            update_pairs_remove(system);

            //reset atom and molecule id's
            enumerate_particles(system);

            break;
        case MOVETYPE_DISPLACE:

            /* change coords of 'altered' */
            if (system->rd_anharmonic)
                displace_1D(system, system->checkpoint->molecule_altered, system->move_factor);
            else if (system->spectre)
                spectre_displace(system, system->checkpoint->molecule_altered, system->move_factor,
                                 system->spectre_max_charge, system->spectre_max_target);
            else if (system->gwp) {
                if (system->checkpoint->molecule_altered->atoms->gwp_spin) {
                    displace(system, system->checkpoint->molecule_altered, system->pbc, system->gwp_probability, system->rot_factor);
                    displace_gwp(system, system->checkpoint->molecule_altered, system->gwp_probability);
                } else
                    displace(system, system->checkpoint->molecule_altered, system->pbc, system->move_factor, system->rot_factor);
            } else
                displace(system, system->checkpoint->molecule_altered, system->pbc, system->move_factor, system->rot_factor);

            break;
        case MOVETYPE_ADIABATIC:
            /* change coords of 'altered' */
            displace(system, system->checkpoint->molecule_altered, system->pbc, system->adiabatic_probability, 1.0);

            break;
        case MOVETYPE_SPINFLIP:

            if (get_rand(system) < 0.5)
                system->checkpoint->molecule_altered->nuclear_spin = NUCLEAR_SPIN_PARA;
            else
                system->checkpoint->molecule_altered->nuclear_spin = NUCLEAR_SPIN_ORTHO;

            break;
        case MOVETYPE_VOLUME:

            volume_change(system);  // I don't want to contribute to the god damned mess -- kmclaugh

            break;
        default:
            error(
                "MC_MOVES: invalid mc move\n");
            die(-1);
    }

    return;
}
Esempio n. 10
0
int surface_dimer_parameters(system_t *system, param_g *params) {

	int i = 0; // generic counter
	
	molecule_t *molecule_ptr;
	atom_t *atom_ptr;
	param_t *param_ptr;
	
	// Default bond partner for atoms without explicit site neighbor
	atom_t *origin = calloc( sizeof(atom_t), 1 ); // calloc sets pos[] fields all to 0
	memnullcheck( origin, sizeof(atom_t), __LINE__-1, __FILE__);

	system->polar_damp = params->alpha;

	for (molecule_ptr = system->molecules; molecule_ptr; molecule_ptr = molecule_ptr->next) {
	
		for (atom_ptr = molecule_ptr->atoms; atom_ptr; atom_ptr = atom_ptr->next) {
	
			for (param_ptr = params->type_params; param_ptr; param_ptr = param_ptr->next) {
	
				if( !strcasecmp( param_ptr->atomtype, atom_ptr->atomtype )) {

					atom_ptr->charge  = param_ptr->charge;
					atom_ptr->epsilon = param_ptr->epsilon;
					atom_ptr->sigma   = param_ptr->sigma;
					atom_ptr->omega   = param_ptr->omega;
					atom_ptr->polarizability = param_ptr->pol;
					atom_ptr->c6 = param_ptr->c6;
					atom_ptr->c8 = param_ptr->c8;
					atom_ptr->c10 = param_ptr->c10;

					double perturbation_vector[3];

					// Find the the atom that defines the bond axis and store for easy reference
					atom_t *snPtr = 0;
					if( atom_ptr->site_neighbor_id == 0 )
						snPtr = origin;
					else {
						snPtr = find_atom_by_id( system, atom_ptr->site_neighbor_id );
						if( !snPtr ) {
							snPtr = origin;
							printf( "\n*** WARNING ***\n" );
							printf( "Bonding partner for atom %d not found ",      atom_ptr->bond_id );
							printf( "--> %d, possibly invalid. Using origin.\n\n", atom_ptr->site_neighbor_id );
						}
					}

					// Generate the vector along which the dr perturbations will occur
					for (i = 0; i < 3; i++)
						perturbation_vector[i] = atom_ptr->pos[i] - snPtr->pos[i];

					// Determine how much the bond vector should be scaled to increase the length by dr.
					double scale = find_scale_factor(perturbation_vector[0], perturbation_vector[1], perturbation_vector[2], param_ptr->dr);
					
					// Scale the perturbation vector
					for (i = 0; i < 3; i++)
						perturbation_vector[i] *= scale;
					
					// Add the vector back to the bond partner coordinates to get the new position.
					for (i = 0; i < 3; i++)
						atom_ptr->pos[i] = snPtr->pos[i] + perturbation_vector[i];

				}
			} // for param_ptr
		} // for atom_ptr
	} // for molecule_ptr

	free(origin);

	return (0);
}
Esempio n. 11
0
/* make an exact copy of src */
molecule_t *copy_molecule(system_t *system, molecule_t *src) {
    molecule_t *dst;
    atom_t *atom_dst_ptr, *prev_atom_dst_ptr, *atom_src_ptr;
    pair_t *pair_dst_ptr, *prev_pair_dst_ptr, *pair_src_ptr;

    /* allocate the start of the new lists */
    dst = calloc(1, sizeof(molecule_t));
    memnullcheck(dst, sizeof(molecule_t), __LINE__ - 1, __FILE__);
    /* copy molecule attributes */
    dst->id = src->id;
    strcpy(dst->moleculetype, src->moleculetype);
    dst->mass = src->mass;
    dst->frozen = src->frozen;
    dst->adiabatic = src->adiabatic;
    dst->spectre = src->spectre;
    dst->target = src->target;
    dst->nuclear_spin = src->nuclear_spin;
    dst->rot_partfunc_g = src->rot_partfunc_g;
    dst->rot_partfunc_u = src->rot_partfunc_u;
    dst->rot_partfunc = src->rot_partfunc;
    memcpy(dst->com, src->com, 3 * sizeof(double));
    memcpy(dst->wrapped_com, src->wrapped_com, 3 * sizeof(double));

#ifdef QM_ROTATION
    int i, j;
    if (system->quantum_rotation) {
        dst->quantum_rotational_energies = calloc(system->quantum_rotation_level_max, sizeof(double));
        memnullcheck(dst->quantum_rotational_energies, system->quantum_rotation_level_max * sizeof(double), __LINE__ - 1, __FILE__);
        dst->quantum_rotational_eigenvectors = calloc(system->quantum_rotation_level_max, sizeof(complex_t *));
        memnullcheck(dst->quantum_rotational_eigenvectors, system->quantum_rotation_level_max * sizeof(complex_t *), __LINE__ - 1, __FILE__);
        for (i = 0; i < system->quantum_rotation_level_max; i++) {
            dst->quantum_rotational_eigenvectors[i] = calloc((system->quantum_rotation_l_max + 1) * (system->quantum_rotation_l_max + 1), sizeof(complex_t));
            memnullcheck(dst->quantum_rotational_eigenvectors[i], (system->quantum_rotation_l_max + 1) * (system->quantum_rotation_l_max + 1) * sizeof(complex_t), __LINE__ - 1, __FILE__);
        }
        dst->quantum_rotational_eigensymmetry = calloc(system->quantum_rotation_level_max, sizeof(int));
        memnullcheck(dst->quantum_rotational_eigensymmetry, system->quantum_rotation_level_max * sizeof(int), __LINE__ - 1, __FILE__);

        memcpy(dst->quantum_rotational_energies, src->quantum_rotational_energies, system->quantum_rotation_level_max * sizeof(double));
        for (i = 0; i < system->quantum_rotation_level_max; i++) {
            for (j = 0; j < (system->quantum_rotation_l_max + 1) * (system->quantum_rotation_l_max + 1); j++) {
                dst->quantum_rotational_eigenvectors[i][j].real = src->quantum_rotational_eigenvectors[i][j].real;
                dst->quantum_rotational_eigenvectors[i][j].imaginary = src->quantum_rotational_eigenvectors[i][j].imaginary;
            }
        }
        memcpy(dst->quantum_rotational_eigensymmetry, src->quantum_rotational_eigensymmetry, system->quantum_rotation_level_max * sizeof(int));
    }
#endif /* QM_ROTATION */

    dst->next = NULL;

    /* new atoms list */
    dst->atoms = calloc(1, sizeof(atom_t));
    memnullcheck(dst->atoms, sizeof(atom_t), __LINE__ - 1, __FILE__);
    prev_atom_dst_ptr = dst->atoms;

    for (atom_dst_ptr = dst->atoms, atom_src_ptr = src->atoms; atom_src_ptr; atom_dst_ptr = atom_dst_ptr->next, atom_src_ptr = atom_src_ptr->next) {
        atom_dst_ptr->id = atom_src_ptr->id;
        strcpy(atom_dst_ptr->atomtype, atom_src_ptr->atomtype);
        atom_dst_ptr->frozen = atom_src_ptr->frozen;
        atom_dst_ptr->adiabatic = atom_src_ptr->adiabatic;
        atom_dst_ptr->spectre = atom_src_ptr->spectre;
        atom_dst_ptr->target = atom_src_ptr->target;
        atom_dst_ptr->mass = atom_src_ptr->mass;
        atom_dst_ptr->charge = atom_src_ptr->charge;
        atom_dst_ptr->gwp_alpha = atom_src_ptr->gwp_alpha;
        atom_dst_ptr->gwp_spin = atom_src_ptr->gwp_spin;
        atom_dst_ptr->polarizability = atom_src_ptr->polarizability;
        atom_dst_ptr->omega = atom_src_ptr->omega;
        atom_dst_ptr->epsilon = atom_src_ptr->epsilon;
        atom_dst_ptr->sigma = atom_src_ptr->sigma;
        atom_dst_ptr->gwp_spin = atom_src_ptr->gwp_spin;
        atom_dst_ptr->c6 = atom_src_ptr->c6;
        atom_dst_ptr->c8 = atom_src_ptr->c8;
        atom_dst_ptr->c10 = atom_src_ptr->c10;
        atom_dst_ptr->c9 = atom_src_ptr->c9;

        memcpy(atom_dst_ptr->pos, atom_src_ptr->pos, 3 * sizeof(double));
        memcpy(atom_dst_ptr->wrapped_pos, atom_src_ptr->wrapped_pos, 3 * sizeof(double));
        memcpy(atom_dst_ptr->ef_static, atom_src_ptr->ef_static, 3 * sizeof(double));
        memcpy(atom_dst_ptr->ef_induced, atom_src_ptr->ef_induced, 3 * sizeof(double));
        memcpy(atom_dst_ptr->mu, atom_src_ptr->mu, 3 * sizeof(double));
        memcpy(atom_dst_ptr->old_mu, atom_src_ptr->old_mu, 3 * sizeof(double));
        memcpy(atom_dst_ptr->new_mu, atom_src_ptr->new_mu, 3 * sizeof(double));

        atom_dst_ptr->pairs = calloc(1, sizeof(pair_t));
        memnullcheck(atom_dst_ptr->pairs, sizeof(pair_t), __LINE__ - 1, __FILE__);
        pair_dst_ptr = atom_dst_ptr->pairs;
        prev_pair_dst_ptr = pair_dst_ptr;
        for (pair_src_ptr = atom_src_ptr->pairs; pair_src_ptr; pair_src_ptr = pair_src_ptr->next) {
            pair_dst_ptr->rd_energy = pair_src_ptr->rd_energy;
            pair_dst_ptr->es_real_energy = pair_src_ptr->es_real_energy;
            pair_dst_ptr->es_self_intra_energy = pair_src_ptr->es_self_intra_energy;

            pair_dst_ptr->frozen = pair_src_ptr->frozen;
            pair_dst_ptr->rd_excluded = pair_src_ptr->rd_excluded;
            pair_dst_ptr->es_excluded = pair_src_ptr->es_excluded;
            //			pair_dst_ptr->charge = pair_src_ptr->charge;
            //			pair_dst_ptr->gwp_alpha = pair_src_ptr->gwp_alpha;
            //			pair_dst_ptr->gwp_spin = pair_src_ptr->gwp_spin;
            pair_dst_ptr->epsilon = pair_src_ptr->epsilon;
            pair_dst_ptr->lrc = pair_src_ptr->lrc;
            pair_dst_ptr->sigma = pair_src_ptr->sigma;
            pair_dst_ptr->r = pair_src_ptr->r;
            pair_dst_ptr->rimg = pair_src_ptr->rimg;

            pair_dst_ptr->next = calloc(1, sizeof(pair_t));
            memnullcheck(pair_dst_ptr->next, sizeof(pair_t), __LINE__ - 1, __FILE__);
            prev_pair_dst_ptr = pair_dst_ptr;
            pair_dst_ptr = pair_dst_ptr->next;
        }
        prev_pair_dst_ptr->next = NULL;
        free(pair_dst_ptr);
        /* handle an empty list */
        if (!atom_src_ptr->pairs) atom_dst_ptr->pairs = NULL;

        prev_atom_dst_ptr = atom_dst_ptr;
        atom_dst_ptr->next = calloc(1, sizeof(atom_t));
        memnullcheck(atom_dst_ptr->next, sizeof(atom_t), __LINE__ - 1, __FILE__);
    }

    prev_atom_dst_ptr->next = NULL;
    free(atom_dst_ptr);

    return (dst);
}
Esempio n. 12
0
int main(int argc, char **argv) {

	char linebuf[MAXLINE];
	char input_file[MAXLINE];
	system_t *system;
	time_t t = time(NULL);
	struct tm tm = *localtime(&t);

	/* set the default rank */
	rank = 0; size = 1;

	/* check args */
	if(argc < 2) usage(argv[0]);

	/* start up the MPI chain */
#ifdef MPI
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &size);
#endif /* MPI */
	
	if( !rank ) {
		sprintf(linebuf, "MPMC (Massively Parallel Monte Carlo) r%d - 2012-2017 GNU Public License\n", VERSION);
		output(linebuf);
		sprintf(linebuf, "MAIN: processes started on %d cores @ %d-%d-%d %d:%d:%d\n", size, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
		output(linebuf);
	}
	
#ifndef MPI
	FILE *procfile;
	FILE *host;
	char nodename[MAXLINE];
	char cpu[MAXLINE];
	struct stat info;

	// These system calls were causing a fork() that does not play nice with some
	// MPI implementations (causing some processes to never end... )
	
	/* Collect and output hostname & processor info */
	if(access("/proc/cpuinfo",R_OK)!=-1) {                                          // Linux
		host = popen("hostname","r");
		fgets(nodename, MAXLINE, host);
		sprintf(linebuf, "MAIN: Job running on node -> %s", nodename);
		output(linebuf);
		pclose(host);
		
		procfile = fopen("/proc/cpuinfo", "r");
		while (!feof(procfile)) {
			fgets(cpu, MAXLINE, procfile);
			if(strncasecmp(cpu,"model name",10)==0) {
			sprintf(linebuf, "MAIN: CPU -> %s", cpu);
			output(linebuf);
			break;
		}
	}
	fclose(procfile);
	} else if (stat("/Applications",&info)==0) {                                  // Mac OS
		output("MAIN: Mac OS detected\n");
		host = popen("hostname", "r");
		fgets(nodename, MAXLINE, host);
		sprintf(linebuf, "MAIN: Job running on node -> %s", nodename);
		output(linebuf);
		pclose(host);
		
		procfile = popen("sysctl -n machdep.cpu.brand_string","r");
		fgets(cpu, MAXLINE, procfile);
		sprintf(linebuf, "MAIN: CPU -> %s", cpu);
		output(linebuf);
		pclose(procfile);
	}
#endif // !MPI

	/* get the config file arg */
	strcpy(input_file, argv[1]);
	sprintf(linebuf, "MAIN: running parameters found in %s\n", input_file);
	output(linebuf);

	/* read the input files and setup the simulation */
	system = setup_system(input_file);
	if(!system) {
		error("MAIN: could not initialize the simulation\n");
		die(1);
	} else {
		output("MAIN: the simulation has been initialized\n");
	}
	
	/* install the signal handler to catch SIGTERM cleanly */
	terminate_handler(-1, system);
	signal(SIGTERM, ((void *)(terminate_handler)));
	signal(SIGUSR1, ((void *)(terminate_handler)));
	signal(SIGUSR2, ((void *)(terminate_handler)));
	output("MAIN: signal handler installed\n");

	/* allocate space for the statistics */
	system->nodestats = calloc(1, sizeof(nodestats_t));
	memnullcheck(system->nodestats,sizeof(nodestats_t), __LINE__-1, __FILE__);
	system->avg_nodestats = calloc(1, sizeof(avg_nodestats_t));
	memnullcheck(system->avg_nodestats,sizeof(avg_nodestats_t), __LINE__-1, __FILE__);
	system->observables = calloc(1, sizeof(observables_t));
	memnullcheck(system->observables,sizeof(observables_t), __LINE__-1, __FILE__);
	system->avg_observables = calloc(1, sizeof(avg_observables_t));
	memnullcheck(system->avg_observables,sizeof(avg_observables_t), __LINE__-1, __FILE__);
	system->checkpoint = calloc(1, sizeof(checkpoint_t));
	memnullcheck(system->checkpoint,sizeof(checkpoint_t), __LINE__-1, __FILE__);
	system->checkpoint->observables = calloc(1, sizeof(observables_t));
	memnullcheck(system->checkpoint->observables,sizeof(observables_t), __LINE__-1, __FILE__);
	system->grids = calloc(1,sizeof(grid_t));
	memnullcheck(system->grids,sizeof(grid_t), __LINE__-1, __FILE__);
	system->grids->histogram = calloc(1,sizeof(histogram_t));
	memnullcheck(system->grids->histogram,sizeof(histogram_t), __LINE__-1, __FILE__);
	system->grids->avg_histogram = calloc(1,sizeof(histogram_t));
	memnullcheck(system->grids->avg_histogram,sizeof(histogram_t), __LINE__-1, __FILE__);

	/* if polarization active, allocate the necessary matrices */
	if(system->polarization && !system->cuda && !system->polar_zodid)
		thole_resize_matrices(system);

	/* if histogram calculation flag is set, allocate grid */
	if(system->calc_hist){
		setup_histogram(system);
		allocate_histogram_grid(system);
	}

	/* seed the rng if neccessary */
	if ( system->ensemble != ENSEMBLE_TE && system->ensemble != ENSEMBLE_REPLAY )
		seed_rng(system, rank);

#ifdef MPI
	MPI_Barrier(MPI_COMM_WORLD);
	sprintf(linebuf, "MAIN: all %d cores are in sync\n", size);
	output(linebuf);
#endif /* MPI */

	/* start the MC simulation */
	if(system->ensemble == ENSEMBLE_UVT) {
		output("MAIN: *******************************************************\n");
		output("MAIN: *** starting Grand Canonical Monte Carlo simulation ***\n");
		output("MAIN: *******************************************************\n");
	} else if(system->ensemble == ENSEMBLE_NVT) {
		output("MAIN: *************************************************\n");
		output("MAIN: *** starting Canonical Monte Carlo simulation ***\n");
		output("MAIN: *************************************************\n");
	} else if(system->ensemble == ENSEMBLE_NVE) {
		output("MAIN: ******************************************************\n");
		output("MAIN: *** starting Microcanonical Monte Carlo simulation ***\n");
		output("MAIN: ******************************************************\n");
	} else if(system->ensemble == ENSEMBLE_SURF) {	/* surface run */
		output("MAIN: *****************************************************\n");
		output("MAIN: *** starting potential energy surface calculation ***\n");
		output("MAIN: *****************************************************\n");
	} else if(system->ensemble == ENSEMBLE_REPLAY) {	/* surface fitting run */
		output("MAIN: **********************************\n");
		output("MAIN: *** starting trajectory replay ***\n");
		output("MAIN: **********************************\n");
	} else if(system->ensemble == ENSEMBLE_SURF_FIT) {	/* surface fitting run */
		output("MAIN: *************************************************************\n");
		output("MAIN: *** starting potential energy surface fitting calculation ***\n");
		output("MAIN: *************************************************************\n");
	} else if(system->ensemble == ENSEMBLE_TE) {	/* surface fitting run */
		output("MAIN: *************************************************\n");
		output("MAIN: *** starting single-point energy calculation  ***\n");
		output("MAIN: *************************************************\n");
	}



	if(system->ensemble == ENSEMBLE_SURF) { /* surface */
		if(surface(system) < 0) {
			error("MAIN: surface module failed on error, exiting\n");
			die(1);
		}
	}
	
	
	else if(system->ensemble == ENSEMBLE_SURF_FIT) { /* surface fitting */
	    
		if( system->surf_fit_arbitrary_configs ) {
			if( surface_fit_arbitrary( system ) < 0 ) {
				error("MAIN: surface fitting module (for arbitrary configurations) failed on error, exiting\n");
				die(1);
			}
		}
		else if(surface_fit(system) < 0) {
			error("MAIN: surface fitting module failed on error, exiting\n");
			die(1);
		}
	}
	
	
	else if(system->ensemble == ENSEMBLE_REPLAY) { /* replay trajectory and recalc energies, etc. */
		if(replay_trajectory(system) < 0) {
			error("MAIN: trajectory replay failed, exiting\n");
			die(1);
		}
	}
	
	
	else if(system->ensemble == ENSEMBLE_TE) {
		if(calculate_te(system) < 0) {
			error("MAIN: single-point energy calculation failed, exiting\n");
			die(1);
		}
	}
	
	
	else { //else run monte carlo
		if(mc(system) < 0) {
			error("MAIN: MC failed on error, exiting\n");
			die(1);
		}
	}



	/* cleanup */
	output("MAIN: freeing all data structures....");
	cleanup(system);
	output("...done\n");

	output("MAIN: simulation exiting successfully\n\n");
	die(0);

	return 0;
}
Esempio n. 13
0
/* returns the number of iterations required */
int thole_iterative(system_t *system) {
    int i, N, p;
    int iteration_counter, keep_iterating;
    atom_t **aa;  //atom array
    int *ranked_array;

    aa = system->atom_array;
    N = system->natoms;

    /* array for ranking */
    ranked_array = calloc(N, sizeof(int));
    memnullcheck(ranked_array, N * sizeof(int), __LINE__ - 1, __FILE__);
    for (i = 0; i < N; i++) ranked_array[i] = i;

    //set all dipoles to alpha*E_static * polar_gamma
    init_dipoles(system);

    /* if ZODID is enabled, then stop here and just return the alpha*E dipoles */
    if (system->polar_zodid) {
        free(ranked_array);
        return (0);
    }

    /* iterative solver of the dipole field equations */
    keep_iterating = 1;
    iteration_counter = 0;
    while (keep_iterating) {
        iteration_counter++;

        /* divergence detection */
        /* if we fail to converge, then return dipoles as alpha*E */
        if (iteration_counter >= MAX_ITERATION_COUNT && system->polar_precision) {
            for (i = 0; i < N; i++)
                for (p = 0; p < 3; p++) {
                    aa[i]->mu[p] = aa[i]->polarizability * (aa[i]->ef_static[p] + aa[i]->ef_static_self[p]);
                    aa[i]->ef_induced_change[p] = 0.0;  //so we don't break palmo
                }
            //set convergence failure flag
            system->iter_success = 1;

            free(ranked_array);
            return (iteration_counter);
        }

        //zero out induced e-field
        for (i = 0; i < system->natoms; i++)
            for (p = 0; p < 3; p++)
                aa[i]->ef_induced[p] = 0;

        //save the current dipole information if we want to calculate precision (or if needed for relaxation)
        if (system->polar_rrms || system->polar_precision > 0 || system->polar_sor || system->polar_esor) {
            for (i = 0; i < N; i++)
                for (p = 0; p < 3; p++)
                    aa[i]->old_mu[p] = aa[i]->mu[p];
        }

        // contract the dipoles with the field tensor (gauss-seidel/gs-ranked optional)
        contract_dipoles(system, ranked_array);

        if (system->polar_rrms || system->polar_precision > 0)
            calc_dipole_rrms(system);

        /* determine if we are done... */
        keep_iterating = are_we_done_yet(system, iteration_counter);

        // if we would be finished, we want to contract once more to get the next induced field for palmo
        if (system->polar_palmo && !keep_iterating)
            palmo_contraction(system, ranked_array);

        //new gs_ranking if needed
        if (system->polar_gs_ranked && keep_iterating)
            update_ranking(system, ranked_array);

        /* save the dipoles for the next pass */
        for (i = 0; i < N; i++) {
            for (p = 0; p < 3; p++) {
                /* allow for different successive over-relaxation schemes */
                if (system->polar_sor)
                    aa[i]->mu[p] = system->polar_gamma * aa[i]->new_mu[p] + (1.0 - system->polar_gamma) * aa[i]->old_mu[p];
                else if (system->polar_esor)
                    aa[i]->mu[p] = (1.0 - exp(-system->polar_gamma * iteration_counter)) * aa[i]->new_mu[p] + exp(-system->polar_gamma * iteration_counter) * aa[i]->old_mu[p];
                else
                    aa[i]->mu[p] = aa[i]->new_mu[p];
            }
        }

    }  //end iterate
    free(ranked_array);

    /* return the iteration count */
    return (iteration_counter);
}
Esempio n. 14
0
molecule_t *read_insertion_molecules(system_t *system) {

	int j;

	molecule_t *molecules, 
	           *molecule_ptr;

	atom_t     *atom_ptr, 
	           *prev_atom_ptr;

	char       linebuf[MAXLINE], *n;

	FILE       *fp;
	char       token_atom[MAXLINE], token_atomid[MAXLINE], token_atomtype[MAXLINE],
	           token_moleculetype[MAXLINE],
	           token_frozen[MAXLINE],
	           token_moleculeid[MAXLINE],
	           token_x[MAXLINE], token_y[MAXLINE], token_z[MAXLINE],
	           token_mass[MAXLINE],
	           token_charge[MAXLINE],
	           token_alpha[MAXLINE], token_epsilon[MAXLINE], token_sigma[MAXLINE], 
	           token_omega[MAXLINE], token_gwp_alpha[MAXLINE],
		   token_c6[MAXLINE], token_c8[MAXLINE], token_c10[MAXLINE], token_c9[MAXLINE];
	
	int        current_frozen, 
	           current_adiabatic,
	           current_spectre, 
	           current_target,
	           current_moleculeid, 
	           current_atomid,
	           current_site_neighbor;
	double     current_x, current_y, current_z,
	           current_mass,  current_charge, 
	           current_alpha, current_epsilon, current_sigma, current_omega, current_gwp_alpha,
		   current_c6, current_c8, current_c10, current_c9; 

	int        atom_counter;


	// allocate the start of the list 
	molecules           = calloc(1, sizeof(molecule_t));
	memnullcheck(molecules,sizeof(molecule_t),__LINE__-1, __FILE__);
	molecule_ptr        = molecules;
	molecule_ptr->id    = 1;
	molecule_ptr->atoms = calloc(1, sizeof(atom_t));
	memnullcheck(molecule_ptr->atoms,sizeof(atom_t),__LINE__-1, __FILE__);
	atom_ptr            = molecule_ptr->atoms;
	prev_atom_ptr       = atom_ptr;
	
	// open the molecule input file 
	fp = fopen(system->insert_input, "r");
	filecheck(fp,system->insert_input,READ);

	// clear the linebuffer and read the tokens in 
	atom_counter = 0;
	memset(linebuf, 0, MAXLINE);
	n = fgets(linebuf, MAXLINE, fp);
	while(n) {

		// clear the tokens 
		memset( token_atom,         0, MAXLINE);
		memset( token_atomid,       0, MAXLINE);
		memset( token_atomtype,     0, MAXLINE);
		memset( token_moleculetype, 0, MAXLINE);
		memset( token_frozen,       0, MAXLINE);
		memset( token_moleculeid,   0, MAXLINE);
		memset( token_x,            0, MAXLINE);
		memset( token_y,            0, MAXLINE);
		memset( token_z,            0, MAXLINE);
		memset( token_mass,         0, MAXLINE);
		memset( token_charge,       0, MAXLINE);
		memset( token_alpha,        0, MAXLINE);
		memset( token_epsilon,      0, MAXLINE);
		memset( token_sigma,        0, MAXLINE);
		memset( token_omega,        0, MAXLINE);
		memset( token_gwp_alpha,    0, MAXLINE);
		memset(token_c6,            0, MAXLINE);
		memset(token_c8,            0, MAXLINE);
		memset(token_c10,           0, MAXLINE);
		memset(token_c9,            0, MAXLINE);

		// parse the input line 
		sscanf(linebuf, "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", 
		       token_atom, token_atomid, token_atomtype, 
		       token_moleculetype, 
		       token_frozen, 
		       token_moleculeid, 
		       token_x, token_y, token_z, 
		       token_mass, token_charge, 
		       token_alpha, token_epsilon, token_sigma, token_omega, token_gwp_alpha,
		       token_c6, token_c8, token_c10, token_c9
		);

		if(!strcasecmp(token_atom, "ATOM") && strcasecmp(token_moleculetype, "BOX")) {

			current_frozen = 0; current_adiabatic = 0; current_spectre = 0; current_target = 0;
			if(!strcasecmp(token_frozen, "F"))
				current_frozen = 1;
			if(!strcasecmp(token_frozen, "A"))
				current_adiabatic = 1;
			if(!strcasecmp(token_frozen, "S"))
				current_spectre = 1;
			if(!strcasecmp(token_frozen, "T"))
				current_target = 1;

			current_moleculeid    = atoi(token_moleculeid);
			current_atomid        = atoi(token_atomid);
			current_x             = atof(token_x);
			current_y             = atof(token_y);
			current_z             = atof(token_z);
			current_mass          = atof(token_mass);	// mass in amu 
			current_charge        = atof(token_charge);
			current_charge       *= E2REDUCED;		// convert charge into reduced units  
			current_alpha         = atof(token_alpha);
			current_epsilon       = atof(token_epsilon);
			current_sigma         = atof(token_sigma);
			current_omega         = atof(token_omega);
			current_gwp_alpha     = atof(token_gwp_alpha);
			current_c6            = atof(token_c6);
			current_c8            = atof(token_c8);
			current_c10           = atof(token_c10);
			current_c9            = atof(token_c9);

			if ( system->cdvdw_sig_repulsion ) {
				if ( current_epsilon != 1.0 ) {
					error("warning: setting epsilon to 1.0 (due to sig_repulsion)\n");
					current_epsilon = 1.0;
				}
			}
			else if ( system->polarvdw ) {
				if ( current_sigma != 1.0 ) {
					error("warning: setting sigma to 1.0 (due to polarvdw)\n");
					current_sigma = 1.0;
				}
			}

			// Functionality of site_neighbor disabled in favor of omega/gwp_alpha parameters
			// Current behavior is to default to atom 0, typically the center of mass for
			// the molecule.
			current_site_neighbor = 0;

			if(current_frozen)
				current_charge *= system->scale_charge;

			if(molecule_ptr->id != current_moleculeid) {
				molecule_ptr->next = calloc(1, sizeof(molecule_t));
				memnullcheck(molecule_ptr->next,sizeof(molecule_t),__LINE__-1, __FILE__);
				molecule_ptr = molecule_ptr->next;
				molecule_ptr->atoms = calloc(1, sizeof(atom_t));
				memnullcheck(molecule_ptr->atoms,sizeof(atom_t),__LINE__-1, __FILE__);
				prev_atom_ptr->next = NULL;
				free(atom_ptr);
				atom_ptr = molecule_ptr->atoms;
			}
			strcpy(molecule_ptr->moleculetype, token_moleculetype);

			molecule_ptr->id        = current_moleculeid;
			molecule_ptr->frozen    = current_frozen;
			molecule_ptr->adiabatic = current_adiabatic;
			molecule_ptr->spectre   = current_spectre;
			molecule_ptr->target    = current_target;
			molecule_ptr->mass     += current_mass;

#ifdef QM_ROTATION
			/* if quantum rot calc. enabled, allocate the necessary structures */
			if(system->quantum_rotation && !molecule_ptr->frozen && !molecule_ptr->quantum_rotational_energies )
				allocqmrotation(system,molecule_ptr);
#endif /* QM_ROTATION */

#ifdef XXX
			/* if quantum vib calc. enabled, allocate the necessary structures */
			if(system->quantum_vibration && !molecule_ptr->frozen)
				allocqmvibration(system,molecule_ptr);
#endif /* XXX */

			++atom_counter;
			atom_ptr->id        = atom_counter;
			atom_ptr->bond_id   = current_atomid;
			memset(atom_ptr->atomtype, 0, MAXLINE);
			strcpy(atom_ptr->atomtype, token_atomtype);
			atom_ptr->frozen    = current_frozen;
			atom_ptr->adiabatic = current_adiabatic;
			atom_ptr->spectre   = current_spectre;
			atom_ptr->target    = current_target;
			atom_ptr->pos[0]    = current_x;
			atom_ptr->pos[1]    = current_y;
			atom_ptr->pos[2]    = current_z;
			atom_ptr->mass      = current_mass;
			atom_ptr->charge    = current_charge;
			atom_ptr->polarizability = current_alpha;
			atom_ptr->epsilon   = current_epsilon;
			atom_ptr->sigma     = current_sigma;
			atom_ptr->omega     = current_omega;
			atom_ptr->gwp_alpha = current_gwp_alpha;
			atom_ptr->c6 = current_c6;
			atom_ptr->c8 = current_c8;
			atom_ptr->c10 = current_c10;
			atom_ptr->c9 = current_c9;
			if(current_gwp_alpha != 0.)
				atom_ptr->gwp_spin = 1;
			else
				atom_ptr->gwp_spin = 0;

			atom_ptr->site_neighbor_id = current_site_neighbor;
			atom_ptr->next = calloc(1, sizeof(atom_t));
			memnullcheck(atom_ptr->next,sizeof(atom_t),__LINE__-1, __FILE__);
			prev_atom_ptr  = atom_ptr;
			atom_ptr       = atom_ptr->next;
		}

		memset(linebuf, 0, MAXLINE);
		n = fgets(linebuf, MAXLINE, fp);
	}

	// terminate the atom list 
	prev_atom_ptr->next = NULL;
	free(atom_ptr);



	// Count the molecules and create an array of pointers, where each pointer
	// points directly to a molecule in the linked list. While counting the 
	// molecules, check to see whether or not each sorbate is included in the
	// sorbate statistics list, if it is not, we will create an entry for it
	// so that each unique class of sorbate will have its own node in the stats
	// list.
	/////////////////////////////////////////////////////////////////////////////

	// count	
	int molecule_counter = 0;
	for(molecule_ptr = molecules; molecule_ptr; molecule_ptr = molecule_ptr->next) { 
		molecule_counter++;
		// Check to see if this molecule is a new sorbate.
		if( sorbateIs_Not_InList(system, molecule_ptr->moleculetype) ) {
			system->sorbateCount++;
			addSorbateToList(system, molecule_ptr->moleculetype);
			for ( j=0; j<system->sorbateCount; j++ ) {
				if( !strcasecmp( system->sorbateInfo[j].id, molecule_ptr->moleculetype )){
					system->sorbateInfo[j].mass = molecule_ptr->mass;
					break;
				}
			}
		}
	}

	// allocate space for array that will give direct access to insertion-candidate
	// molecules in the linked list. 
	system->insertion_molecules_array = malloc( molecule_counter * sizeof(molecule_t*) );
	memnullcheck(system->insertion_molecules_array, molecule_counter*sizeof(molecule_t *), __LINE__-1, __FILE__);

	// point array pointers to their corresponding molecules
	molecule_counter=0;
	for(molecule_ptr = molecules; molecule_ptr; molecule_ptr = molecule_ptr->next) { 
		system->insertion_molecules_array[ molecule_counter ] = molecule_ptr;
		molecule_counter++;
	}
	system->num_insertion_molecules = molecule_counter;

	  //  ERROR CHECKING OF SOME SORT MAY NEED TO GO HERE
	 //   WHAT'S ALLOWED/DISALLOWED FOR INSERTED MOLECULES?
	/////////////////////////////////////////////////////////

	fclose(fp);
	
	return(molecules);
}
Esempio n. 15
0
molecule_t *read_molecules(FILE * fp, system_t *system) {

	molecule_t *molecules, *molecule_ptr;
	atom_t *atom_ptr, *prev_atom_ptr;
	char linebuf[MAXLINE];
	char token_atom[MAXLINE], token_atomid[MAXLINE], token_atomtype[MAXLINE], token_moleculetype[MAXLINE],
		token_frozen[MAXLINE], token_moleculeid[MAXLINE], token_x[MAXLINE], token_y[MAXLINE], token_z[MAXLINE],
		token_mass[MAXLINE], token_charge[MAXLINE], token_alpha[MAXLINE], token_epsilon[MAXLINE],
		token_sigma[MAXLINE], token_omega[MAXLINE], token_gwp_alpha[MAXLINE], token_c6[MAXLINE], token_c8[MAXLINE], token_c10[MAXLINE], token_c9[MAXLINE];
	int current_frozen, current_adiabatic, current_spectre, current_target, current_moleculeid, 
		current_atomid, current_site_neighbor, moveable, spectres, targets, atom_counter;
	double current_x, current_y, current_z,
		current_mass, current_charge, current_alpha, current_epsilon, 
		current_sigma, current_omega, current_gwp_alpha, current_c6,
		current_c8, current_c10, current_c9; //, current_molecule_mass; (unused variable)

	fpos_t file_pos;
	fgetpos(fp,&file_pos); //get file pointer position, we will restore this when done

	/* allocate the start of the list */
	molecules = calloc(1, sizeof(molecule_t));
	memnullcheck(molecules,sizeof(molecule_t), __LINE__-1, __FILE__);
	molecule_ptr = molecules;
	molecule_ptr->id = 1;
	molecule_ptr->atoms = calloc(1, sizeof(atom_t));
	memnullcheck(molecule_ptr->atoms,sizeof(atom_t),__LINE__-1, __FILE__);
	atom_ptr = molecule_ptr->atoms;
	prev_atom_ptr = atom_ptr;

	/* clear the linebuffer and read the tokens in */
	atom_counter = 0;
	memset(linebuf, 0, MAXLINE);

	while(fgets(linebuf,MAXLINE,fp)) {
		/* clear the tokens */
		memset(token_atom,         0, MAXLINE);
		memset(token_atomid,       0, MAXLINE);
		memset(token_atomtype,     0, MAXLINE);
		memset(token_moleculetype, 0, MAXLINE);
		memset(token_frozen,       0, MAXLINE);
		memset(token_moleculeid,   0, MAXLINE);
		memset(token_x,            0, MAXLINE);
		memset(token_y,            0, MAXLINE);
		memset(token_z,            0, MAXLINE);
		memset(token_mass,         0, MAXLINE);
		memset(token_charge,       0, MAXLINE);
		memset(token_alpha,        0, MAXLINE);
		memset(token_epsilon,      0, MAXLINE);
		memset(token_sigma,        0, MAXLINE);
		memset(token_omega,        0, MAXLINE);
		memset(token_gwp_alpha,    0, MAXLINE);
		memset(token_c6,           0, MAXLINE);
		memset(token_c8,           0, MAXLINE);
		memset(token_c10,          0, MAXLINE);
		memset(token_c9,          0, MAXLINE);

		/* parse the line */
		sscanf(linebuf, "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", 
			token_atom, token_atomid, token_atomtype, token_moleculetype, token_frozen, 
			token_moleculeid, token_x, token_y, token_z, token_mass, token_charge, 
			token_alpha, token_epsilon, token_sigma, token_omega, token_gwp_alpha,
			token_c6, token_c8, token_c10, token_c9);

		if(!strncasecmp(token_atom, "END", 3)) break; //we've reached the end of the current molecule, quit looping

		if(!strcasecmp(token_atom, "ATOM") && strcasecmp(token_moleculetype, "BOX")) {

			current_frozen = 0; current_adiabatic = 0; current_spectre = 0; current_target = 0;
			if(!strcasecmp(token_frozen, "F"))
				current_frozen = 1;
			if(!strcasecmp(token_frozen, "A"))
				current_adiabatic = 1;
			if(!strcasecmp(token_frozen, "S"))
				current_spectre = 1;
			if(!strcasecmp(token_frozen, "T"))
				current_target = 1;

			current_moleculeid    = atoi(token_moleculeid);
			current_atomid        = atoi(token_atomid);
			current_x             = atof(token_x);
			current_y             = atof(token_y);
			current_z             = atof(token_z);
			current_mass          = atof(token_mass);	/* mass in amu */
			current_charge        = atof(token_charge);
			current_charge       *= E2REDUCED;		/* convert charge into reduced units  */
			current_alpha         = atof(token_alpha);
			current_epsilon       = atof(token_epsilon);
			current_sigma         = atof(token_sigma);
			current_omega         = atof(token_omega);
			current_gwp_alpha     = atof(token_gwp_alpha);
			current_c6            = atof(token_c6);
			current_c8            = atof(token_c8);
			current_c10           = atof(token_c10);
			current_c9            = atof(token_c9);

			if ( system->cdvdw_sig_repulsion ) {
				if ( current_epsilon != 1.0 ) {
					error("warning: setting epsilon to 1.0 (due to sig_repulsion)\n");
					current_epsilon = 1.0;
				}
			}
			else if ( system->polarvdw && !system->cdvdw_exp_repulsion ) {
				if ( current_sigma != 1.0 ) {
					error("warning: setting sigma to 1.0 (due to polarvdw)\n");
					current_sigma = 1.0;
				}
			}
			// Functionality of site_neighbor disabled in favor of omega/gwp_alpha parameters
			// Current behavior is to default to atom 0, typically the center of mass for
			// the molecule.
			current_site_neighbor = 0; //atoi( token_site_neighbor );
                        
			if(current_frozen)
				current_charge *= system->scale_charge;

			if(molecule_ptr->id != current_moleculeid) {
				molecule_ptr->next = calloc(1, sizeof(molecule_t));
				memnullcheck(molecule_ptr,sizeof(molecule_t),__LINE__-1, __FILE__);
				molecule_ptr = molecule_ptr->next;
				molecule_ptr->atoms = calloc(1, sizeof(atom_t));
				memnullcheck(molecule_ptr->atoms,sizeof(atom_t),__LINE__-1, __FILE__);
				prev_atom_ptr->next = NULL;
				free(atom_ptr);
				atom_ptr = molecule_ptr->atoms;
			}

			strcpy(molecule_ptr->moleculetype, token_moleculetype);

			molecule_ptr->id        = current_moleculeid;
			molecule_ptr->frozen    = current_frozen;
			molecule_ptr->adiabatic = current_adiabatic;
			molecule_ptr->spectre   = current_spectre;
			molecule_ptr->target    = current_target;
			molecule_ptr->mass     += current_mass;

#ifdef QM_ROTATION
			/* if quantum rot calc. enabled, allocate the necessary structures */
			if(system->quantum_rotation && !molecule_ptr->frozen && !molecule_ptr->quantum_rotational_energies )
				allocqmrotation(system,molecule_ptr);
#endif /* QM_ROTATION */

#ifdef XXX
			/* if quantum vib calc. enabled, allocate the necessary structures */
			if(system->quantum_vibration && !molecule_ptr->frozen)
				allocqmvibration(system,molecule_ptr);
#endif /* XXX */

			++atom_counter;
			atom_ptr->id        = atom_counter;
			atom_ptr->bond_id   = current_atomid;
			memset(atom_ptr->atomtype, 0, MAXLINE);
			strcpy(atom_ptr->atomtype, token_atomtype);
			atom_ptr->frozen    = current_frozen;
			atom_ptr->adiabatic = current_adiabatic;
			atom_ptr->spectre = current_spectre;
			atom_ptr->target = current_target;
			atom_ptr->pos[0] = current_x;
			atom_ptr->pos[1] = current_y;
			atom_ptr->pos[2] = current_z;
			atom_ptr->mass = current_mass;
			atom_ptr->charge = current_charge;
			atom_ptr->polarizability = current_alpha;
			atom_ptr->epsilon = current_epsilon;
			atom_ptr->sigma = current_sigma;
			atom_ptr->omega = current_omega;
			atom_ptr->gwp_alpha = current_gwp_alpha;
			atom_ptr->c6 = current_c6;
			atom_ptr->c8 = current_c8;
			atom_ptr->c10 = current_c10;
			atom_ptr->c9 = current_c9;
			if(current_gwp_alpha != 0.)
				atom_ptr->gwp_spin = 1;
			else
				atom_ptr->gwp_spin = 0;

			atom_ptr->site_neighbor_id = current_site_neighbor;
			atom_ptr->next = calloc(1, sizeof(atom_t));
			memnullcheck(atom_ptr->next,sizeof(atom_t),__LINE__-1, __FILE__);
			prev_atom_ptr  = atom_ptr;
			atom_ptr       = atom_ptr->next;
		}

		memset(linebuf, 0, MAXLINE);
	}

	/* terminate the atom list */
	prev_atom_ptr->next = NULL;
	free(atom_ptr);

	/* scan the list, make sure that there is at least one moveable molecule */
	moveable = 0;
	spectres = 0;
	targets = 0;
	for(molecule_ptr = molecules; molecule_ptr; molecule_ptr = molecule_ptr->next) {
		if(!molecule_ptr->frozen ) ++moveable;
		if(molecule_ptr ->target ) ++targets;
		if(molecule_ptr ->spectre) ++spectres;
	}

	if(system->spectre) {
		if(!spectres || !targets) {
			error("INPUT: either no targets or spectres found\n");
			return(NULL);
		}
	} else {
		if(!moveable) {
			error("INPUT: no moveable molecules found, there must be at least one in your PQR file\n");
			return(NULL);
		}
	}
	if (!atom_counter) {
		free(molecules);
		free(molecule_ptr);
		return(NULL);
	}

	//if we're going to read box info, we need to rewind our file
	if ( system->read_pqr_box_on )
		fsetpos(fp,&file_pos);

	return(molecules);
}
Esempio n. 16
0
File: mc.c Progetto: mpmccode/mpmc
/* implements the Markov chain */
int mc(system_t *system) {
    int j, msgsize;
    double initial_energy, final_energy, current_energy;
    double rot_partfunc;
    observables_t *observables_mpi;
    avg_nodestats_t *avg_nodestats_mpi;
    sorbateInfo_t *sinfo_mpi = 0;
    double *temperature_mpi = 0;
    char *snd_strct = 0, *rcv_strct = 0;
    system->count_autorejects = 0;  // initialize counter for skipped close (unphysical) contacts
                                    // char linebuf[MAXLINE];  (unused variable)
#ifdef MPI
    MPI_Datatype msgtype;
#endif /* MPI */

    /* allocate the statistics structures */
    observables_mpi = calloc(1, sizeof(observables_t));
    memnullcheck(observables_mpi, sizeof(observables_t), __LINE__ - 1, __FILE__);
    avg_nodestats_mpi = calloc(1, sizeof(avg_nodestats_t));
    memnullcheck(avg_nodestats_mpi, sizeof(avg_nodestats_t), __LINE__ - 1, __FILE__);
    // if multiple-sorbates, allocate sorb statistics struct
    if (system->sorbateCount > 1) {
        sinfo_mpi = calloc(system->sorbateCount, sizeof(sorbateInfo_t));
        memnullcheck(sinfo_mpi, sizeof(sorbateInfo_t), __LINE__ - 1, __FILE__);
        system->sorbateGlobal = calloc(system->sorbateCount, sizeof(sorbateAverages_t));
        memnullcheck(system->sorbateGlobal, sizeof(sorbateAverages_t), __LINE__ - 1, __FILE__);
    }

    // compute message size
    msgsize = sizeof(observables_t) + sizeof(avg_nodestats_t);
    if (system->calc_hist) msgsize += system->n_histogram_bins * sizeof(int);
    if (system->sorbateCount > 1) msgsize += system->sorbateCount * sizeof(sorbateInfo_t);

#ifdef MPI
    MPI_Type_contiguous(msgsize, MPI_BYTE, &msgtype);
    MPI_Type_commit(&msgtype);
#endif /* MPI */

    /* allocate MPI structures */
    snd_strct = calloc(msgsize, 1);
    memnullcheck(snd_strct, sizeof(msgsize), __LINE__ - 1, __FILE__);
    if (!rank) {
        rcv_strct = calloc(size, msgsize);
        memnullcheck(rcv_strct, size * sizeof(msgsize), __LINE__ - 1, __FILE__);
        temperature_mpi = calloc(size, sizeof(double));  //temperature list for parallel tempering
        memnullcheck(temperature_mpi, size * sizeof(double), __LINE__ - 1, __FILE__);
    }

    /* update the grid for the first time */
    if (system->cavity_bias) cavity_update_grid(system);

    /* set volume observable */
    system->observables->volume = system->pbc->volume;

    /* get the initial energy of the system */
    initial_energy = energy(system);

#ifdef QM_ROTATION
    /* solve for the rotational energy levels */
    if (system->quantum_rotation) quantum_system_rotational_energies(system);
#endif /* QM_ROTATION */

    /* be a bit forgiving of the initial state */
    if (!isfinite(initial_energy))
        initial_energy = system->observables->energy = MAXVALUE;

    /* if root, open necessary output files */
    if (!rank)
        if (open_files(system) < 0) {
            error(
                "MC: could not open files\n");
            return (-1);
        }

    // write initial observables to stdout and logs
    if (!rank) {
        calc_system_mass(system);
        // average in the initial values once  (we don't want to double-count the initial state when using MPI)
        update_root_averages(system, system->observables, system->avg_observables);
        // average in the initial sorbate values
        if (system->sorbateCount > 1) {
            update_sorbate_info(system);                             //local update
            update_root_sorb_averages(system, system->sorbateInfo);  //global update
        }
        // write initial observables exactly once
        if (system->file_pointers.fp_energy)
            write_observables(system->file_pointers.fp_energy, system, system->observables, system->temperature);
        if (system->file_pointers.fp_energy_csv)
            write_observables_csv(system->file_pointers.fp_energy_csv, system, system->observables, system->temperature);
        output(
            "MC: initial values:\n");
        write_averages(system);
    }

    /* save the initial state */
    checkpoint(system);

    /* main MC loop */
    for (system->step = 1; system->step <= system->numsteps; (system->step)++) {
        /* restore the last accepted energy */
        initial_energy = system->observables->energy;

        /* perturb the system */
        make_move(system);

        /* calculate the energy change */
        final_energy = energy(system);

#ifdef QM_ROTATION
        /* solve for the rotational energy levels */
        if (system->quantum_rotation && (system->checkpoint->movetype == MOVETYPE_SPINFLIP))
            quantum_system_rotational_energies(system);
#endif /* QM_ROTATION */
        if (system->checkpoint->movetype != MOVETYPE_REMOVE)
            rot_partfunc = system->checkpoint->molecule_altered->rot_partfunc;
        else
            rot_partfunc = system->checkpoint->molecule_backup->rot_partfunc;

        /* treat a bad contact as a reject */
    if (!isfinite(final_energy)){
            system->observables->energy = MAXVALUE;
            system->nodestats->boltzmann_factor = 0;
        } else
            boltzmann_factor(system, initial_energy, final_energy, rot_partfunc);

        /* Metropolis function */
        if ((get_rand(system) < system->nodestats->boltzmann_factor) && (system->iter_success == 0)) {
            /////////// ACCEPT

            current_energy = final_energy;

            /* checkpoint */
            checkpoint(system);
            register_accept(system);

            /* SA */
            if (system->simulated_annealing) {
                if (system->simulated_annealing_linear == 1) {
                    system->temperature = system->temperature + (system->simulated_annealing_target - system->temperature) / (system->numsteps - system->step);
                    if (system->numsteps - system->step == 0)
                        system->temperature = system->simulated_annealing_target;
                } else
                    system->temperature = system->simulated_annealing_target + (system->temperature - system->simulated_annealing_target) * system->simulated_annealing_schedule;
            }

        } else {
            /////////////// REJECT

            current_energy = initial_energy;  //used in parallel tempering

            //reset the polar iterative failure flag
            system->iter_success = 0;

            /* restore from last checkpoint */
            restore(system);
            register_reject(system);

        }  // END REJECT

        // perform parallel_tempering
        if ((system->parallel_tempering) && (system->step % system->ptemp_freq == 0))
            temper_system(system, current_energy);

        /* track the acceptance_rate */
        track_ar(system->nodestats);

        /* each node calculates its stats */
        update_nodestats(system->nodestats, system->avg_nodestats);

        /* do this every correlation time, and at the very end */
        if (!(system->step % system->corrtime) || (system->step == system->numsteps)) {
            /* copy observables and avgs to the mpi send buffer */
            /* histogram array is at the end of the message */
            if (system->calc_hist) {
                zero_grid(system->grids->histogram->grid, system);
                population_histogram(system);
            }

            // update frozen and total system mass
            calc_system_mass(system);

            // update sorbate info on each node
            if (system->sorbateCount > 1)
                update_sorbate_info(system);

/*write trajectory files for each node -> one at a time to avoid disk congestion*/
#ifdef MPI
            for (j = 0; j < size; j++) {
                MPI_Barrier(MPI_COMM_WORLD);
                if (j == rank) write_states(system);
            }
#else
            write_states(system);
#endif

            /*restart files for each node -> one at a time to avoid disk congestion*/
            if (write_molecules_wrapper(system, system->pqr_restart) < 0) {
                error(
                    "MC: could not write restart state to disk\n");
                return (-1);
            }

/*dipole/field data for each node -> one at a time to avoid disk congestion*/
#ifdef MPI
            if (system->polarization) {
                for (j = 0; j < size; j++) {
                    MPI_Barrier(MPI_COMM_WORLD);
                    if (j == rank) {
                        write_dipole(system);
                        write_field(system);
                    }
                }
            }
#else
            if (system->polarization) {
                write_dipole(system);
                write_field(system);
            }
#endif

            /* zero the send buffer */
            memset(snd_strct, 0, msgsize);
            memcpy(snd_strct, system->observables, sizeof(observables_t));
            memcpy(snd_strct + sizeof(observables_t), system->avg_nodestats, sizeof(avg_nodestats_t));
            if (system->calc_hist)
                mpi_copy_histogram_to_sendbuffer(snd_strct + sizeof(observables_t) + sizeof(avg_nodestats_t),
                                                 system->grids->histogram->grid, system);
            if (system->sorbateCount > 1)
                memcpy(snd_strct + sizeof(observables_t) + sizeof(avg_nodestats_t) + (system->calc_hist) * system->n_histogram_bins * sizeof(int),  //compensate for the size of hist data, if neccessary
                       system->sorbateInfo,
                       system->sorbateCount * sizeof(sorbateInfo_t));

            if (!rank) memset(rcv_strct, 0, size * msgsize);

#ifdef MPI
            MPI_Gather(snd_strct, 1, msgtype, rcv_strct, 1, msgtype, 0, MPI_COMM_WORLD);
            MPI_Gather(&(system->temperature), 1, MPI_DOUBLE, temperature_mpi, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
//need to gather shit for sorbate stats also
#else
            memcpy(rcv_strct, snd_strct, msgsize);
            temperature_mpi[0] = system->temperature;
#endif /* MPI */
            /* head node collects all observables and averages */
            if (!rank) {
                /* clear avg_nodestats to avoid double-counting */
                clear_avg_nodestats(system);
                //loop for each core -> shift data into variable_mpi, then average into avg_observables
                for (j = 0; j < size; j++) {
                    /* copy from the mpi buffer */
                    memcpy(observables_mpi, rcv_strct + j * msgsize, sizeof(observables_t));
                    memcpy(avg_nodestats_mpi, rcv_strct + j * msgsize + sizeof(observables_t), sizeof(avg_nodestats_t));
                    if (system->calc_hist)
                        mpi_copy_rcv_histogram_to_data(rcv_strct + j * msgsize + sizeof(observables_t) + sizeof(avg_nodestats_t), system->grids->histogram->grid, system);
                    if (system->sorbateCount > 1)
                        memcpy(sinfo_mpi,
                               rcv_strct + j * msgsize + sizeof(observables_t) + sizeof(avg_nodestats_t) + (system->calc_hist) * system->n_histogram_bins * sizeof(int),  //compensate for the size of hist data, if neccessary
                               system->sorbateCount * sizeof(sorbateInfo_t));

                    /* write observables */
                    if (system->file_pointers.fp_energy)
                        write_observables(system->file_pointers.fp_energy, system, observables_mpi, temperature_mpi[j]);
                    if (system->file_pointers.fp_energy_csv)
                        write_observables_csv(system->file_pointers.fp_energy_csv, system, observables_mpi, temperature_mpi[j]);
                    if (system->file_pointers.fp_xyz) {
                        write_molecules_xyz(system, system->file_pointers.fp_xyz);  //L
                    }
                    /* collect the averages */
                    /* if parallel tempering, we will collect obserables from the coldest bath. this can't be done for
					 * nodestats though, since nodestats are averaged over each corrtime, rather than based on a single 
					 * taken at the corrtime */
                    update_root_nodestats(system, avg_nodestats_mpi, system->avg_observables);
                    if (!system->parallel_tempering) {
                        update_root_averages(system, observables_mpi, system->avg_observables);
                        if (system->calc_hist) update_root_histogram(system);
                        if (system->sorbateCount > 1) update_root_sorb_averages(system, sinfo_mpi);
                    } else if (system->ptemp->index[j] == 0) {
                        update_root_averages(system, observables_mpi, system->avg_observables);
                        if (system->calc_hist) update_root_histogram(system);
                        if (system->sorbateCount > 1) update_root_sorb_averages(system, sinfo_mpi);
                    }
                }

                /* write the averages to stdout */
                if (system->file_pointers.fp_histogram)
                    write_histogram(system->file_pointers.fp_histogram, system->grids->avg_histogram->grid, system);

                if (write_performance(system->step, system) < 0) {
                    error(
                        "MC: could not write performance data to stdout\n");
                    return (-1);
                }
                if (write_averages(system) < 0) {
                    error(
                        "MC: could not write statistics to stdout\n");
                    return (-1);
                }

            } /* !rank */
        }     /* corrtime */
    }         /* main loop */

    /* write output, close any open files */
    free(snd_strct);

    // restart files for each node
    if (write_molecules_wrapper(system, system->pqr_output) < 0) {
        error(
            "MC: could not write final state to disk\n");
        return (-1);
    }

    if (!rank) {
        close_files(system);
        free(rcv_strct);
        free(temperature_mpi);
    }

    if (system->sorbateCount > 1) {
        free(system->sorbateGlobal);
        free(sinfo_mpi);
    }

    free(observables_mpi);
    free(avg_nodestats_mpi);

    printf(
        "MC: Total auto-rejected moves: %i\n", system->count_autorejects);

    return (0);
}
Esempio n. 17
0
/* changing it so it rotates around the three principal axises - Adam Hogan */
void molecule_rotate_quaternion(molecule_t *molecule, double alpha, double beta, double gamma, int reverse_flag) {

	atom_t *atom_ptr;
	double com[3];
	int i, ii, n;
	double *new_coord_array;

	/* count the number of atoms in a molecule, and allocate new coords array */
	for(atom_ptr = molecule->atoms, n = 0; atom_ptr; atom_ptr = atom_ptr->next)
		++n;
	new_coord_array = calloc(n*3, sizeof(double));
	memnullcheck(new_coord_array,n*3*sizeof(double),__LINE__-1, __FILE__);

	/* save the com coordinate */
	com[0] = molecule->com[0];
	com[1] = molecule->com[1];
	com[2] = molecule->com[2];

	/* translate the molecule to the origin */
	for(atom_ptr = molecule->atoms; atom_ptr; atom_ptr = atom_ptr->next) {
		atom_ptr->pos[0] -= com[0];
		atom_ptr->pos[1] -= com[1];
		atom_ptr->pos[2] -= com[2];
	}

	/* construct the rotation quaternions */
	struct quaternion first, second, third, total, total_conjugate, position, answer;
	//total = quaternion with no rotation
	quaternion_construct_xyzw(&total,0.,0.,0.,1.);
	//first = rotation around z axis
	quaternion_construct_axis_angle_degree(&first,0.,0.,1.,alpha);
	//second = rotation around y axis
	quaternion_construct_axis_angle_degree(&second,0.,1.,0.,beta);
	//third = rotation around z axis
	quaternion_construct_axis_angle_degree(&third,1.,0.,0.,gamma);
	//combine all rotations into total
	quaternion_multiplication(&first,&total,&total);
	quaternion_multiplication(&second,&total,&total);
	quaternion_multiplication(&third,&total,&total);
	//if we are undoing a rotation we need to conjugate total
	if (reverse_flag) quaternion_conjugate(&total,&total);
	quaternion_conjugate(&total,&total_conjugate);

	for(atom_ptr = molecule->atoms, i = 0; atom_ptr; atom_ptr = atom_ptr->next, i++) {

		ii = i*3;
		//position = position vector
		quaternion_construct_xyzw(&position,atom_ptr->pos[0],atom_ptr->pos[1],atom_ptr->pos[2],0.);

		//answer = total*(position*total_conjugate)
		quaternion_multiplication(&position,&total_conjugate,&answer);
		quaternion_multiplication(&total,&answer,&answer);

		//set the new coords
		new_coord_array[ii+0] = answer.x;
		new_coord_array[ii+1] = answer.y;
		new_coord_array[ii+2] = answer.z;

	}

	/* set the new coordinates and then translate back from the origin */
	for(atom_ptr = molecule->atoms, i = 0; atom_ptr; atom_ptr = atom_ptr->next, i++) {

		ii = i*3;
		atom_ptr->pos[0] = new_coord_array[ii+0];
		atom_ptr->pos[1] = new_coord_array[ii+1];
		atom_ptr->pos[2] = new_coord_array[ii+2];

		atom_ptr->pos[0] += com[0];
		atom_ptr->pos[1] += com[1];
		atom_ptr->pos[2] += com[2];

	}

	/* free our temporary array */
	free(new_coord_array);

}
Esempio n. 18
0
/* now with quaternions AH */
void rotate(system_t *system, molecule_t *molecule, pbc_t *pbc, double scale) {
    atom_t *atom_ptr;
    double u1, u2, u3;
    double com[3];
    int i, ii, n;
    double *new_coord_array;

    struct quaternion position_vector, rnd_rotation, rnd_rotation_conjugate, answer;

    // create a random rotation
    // http://planning.cs.uiuc.edu/node198.html
    u1 = get_rand(system);
    u2 = get_rand(system);
    u3 = get_rand(system);

    // simple linear interpolation for adjusting the scale
    quaternion_construct_xyzw(&rnd_rotation, scale*sqrt(1-u1)*sin(2*M_PI*u2), scale*sqrt(1-u1)*cos(2*M_PI*u2), scale*sqrt(u1)*sin(2*M_PI*u3), 1-scale+scale*sqrt(u1)*cos(2*M_PI*u3)); /* make a random quaternion */
    quaternion_normalize(&rnd_rotation);
    quaternion_conjugate(&rnd_rotation, &rnd_rotation_conjugate);          /* needed to transform coordinates */

    /* count the number of atoms in a molecule, and allocate new coords array */
    for (atom_ptr = molecule->atoms, n = 0; atom_ptr; atom_ptr = atom_ptr->next)
        ++n;
    new_coord_array = calloc(n * 3, sizeof(double));
    memnullcheck(new_coord_array, n * 3 * sizeof(double), __LINE__ - 1, __FILE__);

    /* save the com coordinate */
    com[0] = molecule->com[0];
    com[1] = molecule->com[1];
    com[2] = molecule->com[2];

    /* translate the molecule to the origin */
    for (atom_ptr = molecule->atoms; atom_ptr; atom_ptr = atom_ptr->next) {
        atom_ptr->pos[0] -= com[0];
        atom_ptr->pos[1] -= com[1];
        atom_ptr->pos[2] -= com[2];
    }

    /* quaternion multiply */
    for (atom_ptr = molecule->atoms, i = 0; atom_ptr; atom_ptr = atom_ptr->next, i++) {
        ii = i * 3;

        //position_vector = position
        quaternion_construct_xyzw(&position_vector, atom_ptr->pos[0], atom_ptr->pos[1], atom_ptr->pos[2], 0.);

        //answer = rnd_rotation*(position*rnd_rotation_conjugate)
        quaternion_multiplication(&position_vector, &rnd_rotation_conjugate, &answer);
        quaternion_multiplication(&rnd_rotation, &answer, &answer);

        //set the new coords
        new_coord_array[ii + 0] = answer.x;
        new_coord_array[ii + 1] = answer.y;
        new_coord_array[ii + 2] = answer.z;
    }

    /* set the new coordinates and then translate back from the origin */
    for (atom_ptr = molecule->atoms, i = 0; atom_ptr; atom_ptr = atom_ptr->next, i++) {
        ii = i * 3;
        atom_ptr->pos[0] = new_coord_array[ii + 0];
        atom_ptr->pos[1] = new_coord_array[ii + 1];
        atom_ptr->pos[2] = new_coord_array[ii + 2];

        atom_ptr->pos[0] += com[0];
        atom_ptr->pos[1] += com[1];
        atom_ptr->pos[2] += com[2];
    }

    /* free our temporary array */
    free(new_coord_array);
}
Esempio n. 19
0
/* rotate a molecule about three Euler angles - same as normal function but for a single mol and without random angles */
void molecule_rotate_euler(molecule_t *molecule, double alpha, double beta, double gamma, int reverse_flag) {

	atom_t *atom_ptr;
	double rotation_matrix[3][3];
	double com[3];
	int i, ii, n;
	double *new_coord_array;

	//reverse the rotation?
	if (reverse_flag)
	{
		//switch around alpha and gamma
		double temp;
		temp = alpha;
		alpha = gamma;
		gamma = temp;
		alpha *= -1.;
		beta *= -1.;
		gamma *= -1.;
	}

	/* count the number of atoms in a molecule, and allocate new coords array */
	for(atom_ptr = molecule->atoms, n = 0; atom_ptr; atom_ptr = atom_ptr->next)
		++n;
	new_coord_array = calloc(n*3, sizeof(double));
	memnullcheck(new_coord_array,n*3*sizeof(double),__LINE__-1, __FILE__);

	/* save the com coordinate */
	com[0] = molecule->com[0];
	com[1] = molecule->com[1];
	com[2] = molecule->com[2];

	/* translate the molecule to the origin */
	for(atom_ptr = molecule->atoms; atom_ptr; atom_ptr = atom_ptr->next) {
		atom_ptr->pos[0] -= com[0];
		atom_ptr->pos[1] -= com[1];
		atom_ptr->pos[2] -= com[2];
	}

	/* construct the 3D rotation matrix */
	rotation_matrix[0][0] = cos(gamma)*cos(beta)*cos(alpha) - sin(gamma)*sin(alpha);
	rotation_matrix[0][1] = sin(gamma)*cos(beta)*cos(alpha) + cos(gamma)*sin(alpha);
	rotation_matrix[0][2] = -sin(beta)*cos(alpha);
	rotation_matrix[1][0] = -cos(gamma)*cos(beta)*sin(alpha) - sin(gamma)*cos(alpha);
	rotation_matrix[1][1] = -sin(gamma)*cos(beta)*sin(alpha) + cos(gamma)*cos(alpha);
	rotation_matrix[1][2] = sin(beta)*sin(alpha);
	rotation_matrix[2][0] = cos(gamma)*sin(beta);
	rotation_matrix[2][1] = sin(gamma)*sin(beta);
	rotation_matrix[2][2] = cos(beta);

	/* matrix multiply */
	for(atom_ptr = molecule->atoms, i = 0; atom_ptr; atom_ptr = atom_ptr->next, i++) {

		ii = i*3;
		new_coord_array[ii+0] = rotation_matrix[0][0]*atom_ptr->pos[0] + rotation_matrix[0][1]*atom_ptr->pos[1] + rotation_matrix[0][2]*atom_ptr->pos[2];
		new_coord_array[ii+1] = rotation_matrix[1][0]*atom_ptr->pos[0] + rotation_matrix[1][1]*atom_ptr->pos[1] + rotation_matrix[1][2]*atom_ptr->pos[2];
		new_coord_array[ii+2] = rotation_matrix[2][0]*atom_ptr->pos[0] + rotation_matrix[2][1]*atom_ptr->pos[1] + rotation_matrix[2][2]*atom_ptr->pos[2];

	}

	/* set the new coordinates and then translate back from the origin */
	for(atom_ptr = molecule->atoms, i = 0; atom_ptr; atom_ptr = atom_ptr->next, i++) {

		ii = i*3;
		atom_ptr->pos[0] = new_coord_array[ii+0];
		atom_ptr->pos[1] = new_coord_array[ii+1];
		atom_ptr->pos[2] = new_coord_array[ii+2];

		atom_ptr->pos[0] += com[0];
		atom_ptr->pos[1] += com[1];
		atom_ptr->pos[2] += com[2];

	}

	/* free our temporary array */
	free(new_coord_array);

}
Esempio n. 20
0
/* parallel tempering is treated differently than the other types of MC moves, because it is done
 * IN ADDITION to any other moves: i.e. some random move is performed and the energy is calculated
 * before and after. once that is all figured out, we then perform a temper step. The boltzmann factor
 * that is calculated will NOT be averaged into the BF quantity. It can be, but care must be taken so
 * there is no double-counting, and it really isn't so important to do so. */
void temper_system(system_t *system, double current_energy) {
#ifdef MPI
    // system->ptemp->index[j] is a mapping from core -> bath_index (bath_index 0 is lowest temperature, etc.)
    // bath2core maps from bath_index -> core
    // only half of the cores will be responsible for carrying out the calculations
    // partner_list maps from core -> swap partner, if core is a master. core -> -1, if core is a slave.
    int *bath2core, *partner_list, *is_master, master, slave, *update_index, new_index_val;
    double slave_energy, boltzmann_factor, *update_templist, new_templist_val;
    int i, j, lucky, accept_move;
    MPI_Status status;

    slave_energy = 0;

    //make the bath index
    bath2core = calloc(size, sizeof(int));
    memnullcheck(bath2core, size * sizeof(int), __LINE__ - 1, __FILE__);
    for (i = 0; i < size; i++)
        for (j = 0; j < size; j++)
            if (system->ptemp->index[j] == i) bath2core[i] = j;

    //choose the lucky bath. it's not really lucky.. this is just the first bath that we consider for swapping
    if (!rank) lucky = floor(get_rand(system) * size);
    MPI_Bcast(&lucky, 1, MPI_INT, 0, MPI_COMM_WORLD);

    //we will use this array to designate whether a particular core is a master or slave
    is_master = calloc(size, sizeof(int));
    memnullcheck(is_master, size * sizeof(int), __LINE__ - 1, __FILE__);

    //build the partner list
    partner_list = calloc(size, sizeof(int));
    memnullcheck(partner_list, size * sizeof(int), __LINE__ - 1, __FILE__);
    master = lucky;
    slave = (lucky + 1) % size;  //this assigns the slave bath index to the variable
    do {
        partner_list[bath2core[slave]] = bath2core[master];  //partner_list maps slave to master core
        partner_list[bath2core[master]] = bath2core[slave];  //partner_list maps master to slave
        is_master[bath2core[master]] = 1;                    //master flag is on
        is_master[bath2core[slave]] = 0;                     //master flag is off
        //now generate the next master
        master = (master + 2) % size;
        slave = (slave + 2) % size;
    } while ((master != lucky) && (slave != lucky));
    if (slave == lucky) {
        partner_list[bath2core[master]] = -1;  //if odd # of cores, we have one member unassigned
        is_master[bath2core[master]] = -1;     //neither master nor slave
    }
    //all cores (except 1 if size is odd) are mapped

    //communicate the energy to the master nodes
    if (!is_master[rank]) {
        MPI_Send(&current_energy, 1, MPI_DOUBLE, partner_list[rank], 0, MPI_COMM_WORLD);     //slave sends it's energy
        MPI_Recv(&accept_move, 1, MPI_INT, partner_list[rank], 1, MPI_COMM_WORLD, &status);  //receive result (accept/reject)
    } else if (is_master[rank] == 1) {
        //master receives energy from slave
        MPI_Recv(&slave_energy, 1, MPI_DOUBLE, partner_list[rank], 0, MPI_COMM_WORLD, &status);
        //calculate boltzmann factor exp(dE*dB)
        boltzmann_factor = exp((current_energy - slave_energy) *
                               (1.0 / system->ptemp->templist[rank] - 1.0 / system->ptemp->templist[partner_list[rank]]));
        if (get_rand(system) < boltzmann_factor)
            accept_move = 1;
        else
            accept_move = 0;
        //communicate the move result to slave
        MPI_Send(&accept_move, 1, MPI_INT, partner_list[rank], 1, MPI_COMM_WORLD);
    } else
        accept_move = 0;  //no partner

    if (accept_move) {
        //reassign local temperature
        system->temperature = system->ptemp->templist[partner_list[rank]];
        //update our temperature and index values to prepare for transmission to root
        new_templist_val = system->ptemp->templist[partner_list[rank]];
        new_index_val = system->ptemp->index[partner_list[rank]];
        //reassign fugacities
        if (!system->user_fugacities && system->fugacities) {
            MPI_Send(system->fugacities, 1, MPI_DOUBLE, partner_list[rank], 2, MPI_COMM_WORLD);           //send fugacity
            MPI_Recv(system->fugacities, 1, MPI_DOUBLE, partner_list[rank], 2, MPI_COMM_WORLD, &status);  //receive fugacity
        }
    } else {  //reject
        new_templist_val = system->ptemp->templist[rank];
        new_index_val = system->ptemp->index[rank];
    }

    //now we need to update the templist and index on each core
    update_templist = calloc(size, sizeof(double));
    update_index = calloc(size, sizeof(int));
    memnullcheck(update_templist, size * sizeof(double), __LINE__ - 1, __FILE__);
    memnullcheck(update_index, size * sizeof(int), __LINE__ - 1, __FILE__);
    // create updated arrays on head node
    MPI_Gather(&new_templist_val, 1, MPI_DOUBLE, update_templist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    MPI_Gather(&new_index_val, 1, MPI_INT, update_index, 1, MPI_INT, 0, MPI_COMM_WORLD);
    // build the updated array
    if (!rank) {
        for (i = 0; i < size; i++) {
            system->ptemp->templist[i] = update_templist[i];
            system->ptemp->index[i] = update_index[i];
        }
    }
    // transmit to each core
    MPI_Bcast(system->ptemp->templist, size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    MPI_Bcast(system->ptemp->index, size, MPI_INT, 0, MPI_COMM_WORLD);

    if (accept_move)
        system->nodestats->accept_ptemp++;
    else if (is_master[rank] != -1)
        system->nodestats->reject_ptemp++;

    free(update_templist);
    free(update_index);
    free(bath2core);
    free(is_master);
    free(partner_list);
#endif  //MPI
    return;
}