Example #1
0
void revert_parameters(system_t *system, param_g *params) {
    params->alpha = params->last_alpha;

    param_t *param_ptr;

    for (param_ptr = params->type_params; param_ptr; param_ptr = param_ptr->next) {
        param_ptr->charge = param_ptr->last_charge;
        param_ptr->epsilon = param_ptr->last_epsilon;
        param_ptr->sigma = param_ptr->last_sigma;
        param_ptr->omega = param_ptr->last_omega;
        param_ptr->pol = param_ptr->last_pol;
        param_ptr->c6 = param_ptr->last_c6;
        param_ptr->c8 = param_ptr->last_c8;
        param_ptr->c10 = param_ptr->last_c10;

        // the dr parameter cannot be reassigned, but rather has to be "undone"
        param_ptr->dr = -param_ptr->dr;
    }

    // Apply
    surface_dimer_parameters(system, params);

    return;
}
Example #2
0
/* fit potential energy parameters via simulated annealing */
int surface_fit(system_t *system) {

	//override default values if specified in input file
	double temperature    = ((system->fit_start_temp     ) ? system->fit_start_temp     : TEMPERATURE    );
	double max_energy     = ((system->fit_max_energy     ) ? system->fit_max_energy     : MAX_ENERGY     );
	double schedule       = ((system->fit_schedule       ) ? system->fit_schedule       : SCHEDULE       );

	//used only if qshift is on
	double quadrupole=0;

	int i, j,  // generic counters
	nCurves,   // number of curves to fit against
	nPoints,   // number of points in each curve
	nSteps;
	double *r_input=0; // Master list of r-values
	curveData_t *curve=0;   // Array to hold curve point data
	param_t *param_ptr;
	param_g *params;
	double r_min, r_max, r_inc;
	double current_error, last_error, global_minimum;
	qshiftData_t * qshiftData = NULL; //used only with qshift

	// ee_local variables
	int a = 0;
	int globalFound = 0;
	double oldGlobal = 0;
	double initEps[2];
	double initSig[2];
	double globalEps[2];
	double globalSig[2];

	// Record number of curves for convenient reference
	nCurves = system->fit_input_list.data.count;

	// Read the curve data from the input files into a local array
	curve =  readFitInputFiles( system, nCurves );
	if(!curve) {
			error( "SURFACE: An error occurred while reading the surface-fit input files.\n" );
			return (-1);
	}

	// Record number of points in each curve, for convenient reference
	nPoints = curve[0].nPoints;

	// Make a master list of R-values
	r_input = curve[0].r;
	curve[0].r = 0;

	// Free the memory used by all the remaining lists (i.e. all lists
	// other than the one whose address was just transferred).
	for( i=1; i<nCurves; i++ )
			free(curve[i].r);

	// Allocate memory for the output and global arrays
	if ( -1 == alloc_curves ( nCurves, nPoints, curve ) ) {
		free(r_input);
		return -1;
	}

	// Determine Independent Domain
	//////////////////////////////////
	r_min = r_input[0];
	r_max = r_input[nPoints-1];
	r_inc = r_input[1] - r_input[0];

	// Output the geometry for visual verification
	output_pqrs ( system, nCurves, curve );	

	// Get the Initial Error
	//////////////////////////////////

	//obtain curves
	get_curves ( system, nCurves, curve, r_min, r_max, r_inc );

	//calc current error
	current_error = error_calc ( system, nCurves, nPoints, curve, max_energy);

	//record parameters. we will determine which ones need to be adjusted later
	params = record_params ( system );

	// print some header info
	for(param_ptr = params->type_params; param_ptr; param_ptr = param_ptr->next) {
			printf( "SURFACE: Atom type: %d @ %s\n", param_ptr->ntypes, param_ptr->atomtype );
			
			if(param_ptr->epsilon != 0) {
				initEps[a] = param_ptr->epsilon;
				initSig[a] = param_ptr->sigma;
				a++;
			}
	}
	if ( ! system->fit_boltzmann_weight ) 
		printf("*** any input energy values greater than %f K will not contribute to the fit ***\n", max_energy);

	//write params and current_error to stdout
	printf("*** Initial Fit: \n");
	output_params ( temperature, current_error, params );
	printf("*****************\n");

	//set the minimum error we've found
	global_minimum = current_error;
	last_error     = current_error;
	for( j=0; j<nCurves; j++ )
			for(i = 0; i < nPoints; i++)
					curve[j].global[i] = curve[j].output[i];

	//initialize stuff for qshift
	if ( system->surf_qshift_on ) {
		qshiftData = malloc(sizeof(qshiftData_t));
		quadrupole = calcquadrupole(system);
	}

	// ANNEALING
	// Loop over temperature. When the temperature reaches MIN_TEMPERATURE
	// we quit. Assuming we find an error smaller than the initial error
	// we'll spit out a fit_geometry.pqr file, and you'll want to re-anneal.
	for(nSteps = 0; temperature > MIN_TEMPERATURE; ++nSteps) {

		// randomly perturb the parameters
		surf_perturb ( system, quadrupole, qshiftData, params );
	
		// apply the trial parameters
		surface_dimer_parameters ( system, params);
		get_curves ( system, nCurves, curve, r_min, r_max, r_inc );

		// calc error
		current_error = error_calc ( system, nCurves, nPoints, curve, max_energy);

		int condition =  0;
		if (system->surf_descent) condition = current_error < last_error;
		else condition = get_rand() < exp(-(current_error - last_error)/temperature);

 		//  DO MC at this 'temperature'
		if(condition) {
		//ACCEPT MOVE /////
			apply_new_parameters ( params );
			last_error = current_error;

			if(nSteps >= EQUIL) {
				nSteps = 0;

				//write params and current_error to stdout
				output_params ( temperature, current_error, params );

				// output the new global minimum
				if(current_error < global_minimum) {
					system->fit_best_square_error = global_minimum = current_error;
					new_global_min ( system, nCurves, nPoints, curve );

					// Store the LJ parameters corresponding to global min
					a = 0;
					globalFound = 1;
					oldGlobal = current_error;	// keep track for ee_local
					for(param_ptr = params->type_params; param_ptr; param_ptr = param_ptr->next) {
						if(param_ptr->epsilon != 0) {
							globalEps[a] = param_ptr->epsilon;
							globalSig[a] = param_ptr->sigma;
							a++;
						}
					}
				}
			}
		}
		else {
		// MOVE REJECTED ////
				revert_parameters ( system, params );
		} //END DO MONTE CARLO

		// decrement the temperature
		temperature = temperature*schedule;	// schedule
	} //END ANNEALING

	// Output the Fit Curves
	output_fit ( nCurves, nPoints, curve, max_energy, r_input );

	// Exhaustive Enumeration -- Chris Cioce
	if (system->ee_local) {
		int b, c, d, nE1, nE2, nS1, nS2;
		double currEps[2];
		double currSig[2];
		double newGlobal=0;
		double E1start, E1stop, E1incr, E2start, E2stop, E2incr, E1c, E2c; // E1, E2 (unused)
		double S1start, S1stop, S1incr, S2start, S2stop, S2incr, S1c, S2c; // S1, S2 (unused)

		if(globalFound == 1) {
			printf("\nEE_LOCAL ~> SA found an improved surface. Using current global minimum parameters for EE.\n");
			currEps[0] = globalEps[0];
			currEps[1] = globalEps[1];
			currSig[0] = globalSig[0];
			currSig[1] = globalSig[1];
		} else {
			printf("\nEE_LOCAL ~> SA did not find an improved surface. Using initial parameters for EE.\n");
			currEps[0] = initEps[0];
			currEps[1] = initEps[1];
			currSig[0] = initSig[0];
			currSig[1] = initSig[1];
		}

		for(a=0; a<2; a++) {
			printf("EE_LOCAL ~> InitEps[%d]: %f\tInitSig[%d]: %f\tGlobalEps[%d]: %f\tGlobalSig[%d]: %f\n",a,initEps[a],a,initSig[a],a,globalEps[a],a,globalSig[a]);
		}

		E1start = currEps[0] - (currEps[0]*system->range_eps);
		E1stop  = currEps[0] + (currEps[0]*system->range_eps);
		E1incr  = currEps[0] * system->step_eps;
		E2start = currEps[1] - (currEps[1]*system->range_eps);
		E2stop  = currEps[1] + (currEps[1]*system->range_eps);
		E2incr  = currEps[1] * system->step_eps;
		S1start = currSig[0] - (currSig[0]*system->range_sig);
		S1stop  = currSig[0] + (currSig[0]*system->range_sig);
		S1incr  = currSig[0] * system->step_sig;
		S2start = currSig[1] - (currSig[1]*system->range_sig);
		S2stop  = currSig[1] + (currSig[1]*system->range_sig);
		S2incr  = currSig[1] * system->step_sig;
		nE1 = ((E1stop - E1start) / E1incr) + 1;
		nE2 = ((E2stop - E2start) / E2incr) + 1;
		nS1 = ((S1stop - S1start) / S1incr) + 1;
		nS2 = ((S2stop - S2start) / S2incr) + 1;
		printf("EE_LOCAL ~> E1start = %f\tE1stop = %f\tE1incr = %f\tnE1 = %d\n",E1start,E1stop,E1incr,nE1);
		printf("EE_LOCAL ~> E2start = %f\tE2stop = %f\tE2incr = %f\tnE2 = %d\n",E2start,E2stop,E2incr,nE2);
		printf("EE_LOCAL ~> S1start = %f\tS1stop = %f\tS1incr = %f\tnS1 = %d\n",S1start,S1stop,S1incr,nS1);
		printf("EE_LOCAL ~> S2start = %f\tS2stop = %f\tS2incr = %f\tnS2 = %d\n",S2start,S2stop,S2incr,nS2);
		printf("EE_LOCAL ~> Will now perform %d total iterations in parameter subspace...\n",(nE1*nE2*nS1*nS2));

		E1c = E1start;
		E2c = E2start;
		S1c = S1start;
		S2c = S2start;

		// Set initial parameters
		for(param_ptr = params->type_params; param_ptr; param_ptr = param_ptr->next) {
			if(param_ptr->epsilon == currEps[0]) {
				param_ptr->epsilon = E1c;
			}
			if(param_ptr->epsilon == currEps[1]) {
				param_ptr->epsilon = E2c;
			}
			if(param_ptr->sigma == currSig[0]) {
				param_ptr->sigma = S1c;
			}
			if(param_ptr->sigma == currSig[1]) {
				param_ptr->sigma = S2c;
			}
		}

		// apply initial parameters
		surface_dimer_parameters ( system, params);
		get_curves ( system, nCurves, curve, r_min, r_max, r_inc );

		//calc current error
		current_error = error_calc ( system, nCurves, nPoints, curve, max_energy);

		//record parameters. we will determine which ones need to be adjusted later
		//params = record_params ( system );

		//write params and current_error to stdout <-- just for visual verification
		printf("*** Initial Fit: \n");
		output_params ( 0.0, current_error, params );
		printf("*****************\n");

		// Main loops
		globalFound = 0;
		int master = 1;
		for(a=0; a<=nE1; a++) {
			for(b=0; b<=nE2; b++) {
				for(c=0; c<=nS1; c++) {
					for(d=0; d<=nS2; d++) {
						//printf("MASTER: %d\ta: %d\t(%f)\tb: %d\t(%f)\tc: %d\t(%f)\td: %d\t(%f)\n", master, a, E1c, b, E2c, c, S1c, d, S2c);	// Debug output

						// apply parameters
						surface_dimer_parameters ( system, params);
						get_curves ( system, nCurves, curve, r_min, r_max, r_inc );

						// calc current error
						current_error = error_calc ( system, nCurves, nPoints, curve, max_energy);

						//output_params ( 0.0, current_error, params );	// Debug output

						// check for new global minimum
						if(current_error < global_minimum) {
							system->fit_best_square_error = global_minimum = current_error;
							new_global_min ( system, nCurves, nPoints, curve );

							// Store the LJ parameters corresponding to global min
							a = 0;
							globalFound = 1;
							newGlobal = current_error;
							for(param_ptr = params->type_params; param_ptr; param_ptr = param_ptr->next) {
								if(param_ptr->epsilon != 0) {
									globalEps[a] = param_ptr->epsilon;
									globalSig[a] = param_ptr->sigma;
									a++;
								}
							}
						}

						// Set updated S2 parameter
						for(param_ptr = params->type_params; param_ptr; param_ptr = param_ptr->next) {
							if(param_ptr->sigma == S2c) {
								param_ptr->sigma = (S2c+S2incr);
							}
						}
						S2c += S2incr;
						
						master++;
					} // END S2 loop

					// Set updated S1 & S2 parameters
					for(param_ptr = params->type_params; param_ptr; param_ptr = param_ptr->next) {
						if(param_ptr->sigma == S1c) {
							param_ptr->sigma = (S1c+S1incr);
						}
						if(param_ptr->sigma == S2c) {
							param_ptr->sigma = S2start;
						}
					}

					S1c += S1incr;
					S2c = S2start;

				} // END S1 loop

				// Set updated E2 & S1 parameters
				for(param_ptr = params->type_params; param_ptr; param_ptr = param_ptr->next) {
					if(param_ptr->epsilon == E2c) {
						param_ptr->epsilon = (E2c+E2incr);
					}
					if(param_ptr->sigma == S1c) {
						param_ptr->sigma = S1start;
					}
				}

				E2c += E2incr;
				S1c = S1start;

			} // END E2 loop

			// Set updated E1 & E2 parameters
			for(param_ptr = params->type_params; param_ptr; param_ptr = param_ptr->next) {
				if(param_ptr->epsilon == E1c) {
					param_ptr->epsilon = (E1c+E1incr);
				}
				if(param_ptr->epsilon == E2c) {
					param_ptr->epsilon = E2start;
				}
			}

			E1c += E1incr;
			E2c = E2start;

		} // END E1 loop

		// If a new global min is found, write to stdout
		// TODO: Adjust printf statements to prettify final output :D
		if(globalFound == 1) {
			printf("\nEE_LOCAL ~> EE found an improved surface. Parameters written to fit_geometry.pqr\n");
			//printf("EE_LOCAL ~> E1: %f\tS1: %f\tE2: %f\tS2: %f\n", globalEps[0], globalSig[0], globalEps[1], globalSig[1]);
			printf("EE_LOCAL ~> SA Global Min: %f\n", oldGlobal);
			printf("EE_LOCAL ~> EE Global Min: %f\n", newGlobal);
			printf("            ----------------------------\n");
			printf("            ----------------------------\n");
			printf("               ====> %.2f %% improvement\n\n", ((oldGlobal-newGlobal)/oldGlobal)*100);
		} else {
			printf("EE_LOCAL ~> EE was unable to find an improved surface versus SA. Oh well, at least you tried...and for that, we thank you!\n\n");
		}

	} // END ee_local

	// Return all memory back to the system
	free_all_mem (nCurves, curve, params, qshiftData, r_input);
	return(0);
}