|
k-dot-p 0.1
|
#include "oneoff_optimize_1d_argprocess.h++"#include <math.h>#include <stdio.h>#include <glib.h>#include <gio/gio.h>#include <gio/gunixinputstream.h>#include <stdlib.h>#include "kdotp/makestruct_argprocess.h++"#include <libmodelxx/function_specification.h++>#include "config.h"
Include dependency graph for oneoff_optimize_1d_argprocess.c++:Go to the source code of this file.
Functions | |
| void | program_print_version (FILE *f) |
| void | libkdotp_print_version (FILE *f) |
| void | libmodelxx_print_version (FILE *f) |
| void | liblapackwrap_print_version (FILE *f) |
| void | libpostproc_print_version (FILE *f) |
| void | libpostproccalx_print_version (FILE *f) |
| void | print_version_info (void) |
| struct template_parameter_range * | new_template_parameter_range (char *name, double from, double to, double step) |
| double * | get_double_for_string (const char *s) |
| unsigned * | get_unsigned_for_string (const char *s) |
| int | set_quikmat (struct quikmat *m, char *matstring) |
| int | process_args (int argc, char **argv, struct args *args) |
| double* get_double_for_string | ( | const char * | s | ) |
Returns a pointer to a malloc'ed double if successful, else returns NULL
Definition at line 70 of file oneoff_optimize_1d_argprocess.c++.
Referenced by process_args().
{
double v;
int n = sscanf(s, "%lg", &v);
if(n != 1) return NULL;
double* pv = (double*)malloc(sizeof(double));
if(pv == NULL) return NULL;
*pv = v;
return pv;
}
Here is the caller graph for this function:| unsigned* get_unsigned_for_string | ( | const char * | s | ) |
Definition at line 79 of file oneoff_optimize_1d_argprocess.c++.
Referenced by process_args().
{
unsigned v;
int n = sscanf(s, "%u", &v);
if(n != 1) return NULL;
unsigned* pv = (unsigned*)malloc(sizeof(unsigned));
if(pv == NULL) return NULL;
*pv = v;
return pv;
}
Here is the caller graph for this function:| void libkdotp_print_version | ( | FILE * | f | ) |
| void liblapackwrap_print_version | ( | FILE * | f | ) |
| void libmodelxx_print_version | ( | FILE * | f | ) |
| void libpostproc_print_version | ( | FILE * | f | ) |
| void libpostproccalx_print_version | ( | FILE * | f | ) |
| struct template_parameter_range* new_template_parameter_range | ( | char * | name, |
| double | from, | ||
| double | to, | ||
| double | step | ||
| ) | [read] |
Definition at line 57 of file oneoff_optimize_1d_argprocess.c++.
References kdotp::libmodelxx::postprocessing::template_parameter_range::from, kdotp::libmodelxx::postprocessing::template_parameter_range::stepsize, kdotp::libmodelxx::postprocessing::template_parameter_range::symbol, and kdotp::libmodelxx::postprocessing::template_parameter_range::to.
{
struct template_parameter_range *tpr = (struct template_parameter_range*)malloc(sizeof(template_parameter_range));
if(tpr == NULL) return NULL;
tpr->symbol = name;
tpr->from = from;
tpr->to = to;
tpr->stepsize = step;
return tpr;
}
| void print_version_info | ( | void | ) |
Definition at line 46 of file oneoff_optimize_1d_argprocess.c++.
References libkdotp_print_version(), liblapackwrap_print_version(), libmodelxx_print_version(), libpostproc_print_version(), libpostproccalx_print_version(), PACKAGE_NAME, program_print_version(), and VERSION.
{
program_print_version(stdout);
libmodelxx_print_version(stdout);
libkdotp_print_version(stdout);
liblapackwrap_print_version(stdout);
libpostproc_print_version(stdout);
libpostproc_print_version(stdout);
libpostproccalx_print_version(stdout);
printf("autotools info:\n\tProject: %s\n\tVersion: %s\n", PACKAGE_NAME, VERSION);
}
Here is the call graph for this function:| int process_args | ( | int | argc, |
| char ** | argv, | ||
| struct args * | args | ||
| ) |
Definition at line 131 of file oneoff_optimize_1d_argprocess.c++.
References args::assignment_expr, args::assignments, args::blocksize, args::continuous, args::do_nofield_comparison, kdp::constants::e, file_info::filename, args::filestreams, get_double_for_string(), get_unsigned_for_string(), file_info::instream, instream, args::mat0, args::mat1, args::matdb, args::maxx, args::min_stepsize, args::minx, args::multiplier, args::N_blocks, args::N_starting_points, new_template_parameter_range(), args::optimizer_material, print_version(), print_version_info(), args::seed_value, set_quikmat(), args::stepsize, args::template_parameters, and quikmat::x.
{
int errored = 0;
gchar **file_names = NULL;
gboolean print_version = FALSE;
gchar** parameters=NULL;
GString *s = g_string_new("/home/solarion/dist/share/materials-databases/matdb.txt");
args->matdb = s->str;
args->N_starting_points=10;
/*Set the random seed value to a random value (done internally when seed is 0) by default*/
args->seed_value=0;
args->blocksize=4;
g_string_free(s, FALSE);
s = g_string_new("OptimizerMaterial");
args->optimizer_material = s->str;
args->continuous = FALSE;
#ifdef HAVE_MPI
args->mpi = FALSE;
args->temperature = 0;
args->anneal_start = 0;
args->anneal_end = 0;
args->num_anneal_steps = 0;
args->anneal_cycles = 0;
args->calculation_steps_per_annealing_step = 0;
#endif
g_string_free(s, FALSE);
char* mdb = NULL;
char* optmat = NULL;
int raw_startingpoints = 10;
char* mat1=NULL;
char* mat0=NULL;
char* assignments = NULL;
args->assignments = NULL;
args->assignment_expr = NULL;
int raw_blocksize;
args->minx=0.0;
args->maxx=1.0;
args->stepsize=0.1;
args->min_stepsize=0.001;
args->multiplier=0.33;
args->N_blocks = 0;
args->do_nofield_comparison = FALSE;
char* annealing_program=NULL;
GOptionEntry options[] = {
{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &file_names,},
{ "version", 'v', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &print_version, "Print version information about this program", NULL },
{ "matdb", 'm', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING, &(mdb), "Use an alternate materials database file.", NULL },
{"parameter", 'p', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING_ARRAY, ¶meters, "Provide a template parameter argument, in the form param,value (single value) or param,start,stop,step (sequence)\n", NULL},
{ "optmat", 'o', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING, &(optmat), "Material name specifying the region to be optimized", NULL },
{ "mat1", '1', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING, &(mat1), "Material name specifying one material to use in the optimizer. Must be of the form mata/x/matb for alloys of MatA_x MatB_{1-x}.", NULL },
{ "mat0", '0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING, &(mat0), "Material name specifying the other material to be used in the optimizer. Must be of the form mata/x/matb for alloys of MatA_x MatB_{1-x}.", NULL },
{ "startingpoints", 's', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &(raw_startingpoints), "Number of random starting structures", NULL },
{ "blocksize", 'b', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &(raw_blocksize), "Size of a block of material in gridsites (optimization is done in blocks for accuracy; ignored if num_blocks is set to a nonzero value)", NULL },
{ "num_blocks", 'B', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &(args->N_blocks), "Number of blocks to use (leave unspecified to use blocksize instead)", NULL },
/*The seed can be signed here; this will allow full access to the bits*/
{ "seed", 'S', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT64, (long unsigned*)&(args->seed_value), "Seed to use for the random number generator (to reproduce a run; default is random)", NULL },
{ "minx", 'x', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_DOUBLE, &(args->minx), "Minimum allowable alloying for continuous alloying. (default is 0; ignored for digital alloys)", NULL},
{ "maxx", 'X', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_DOUBLE, &(args->maxx), "Maximum allowable alloying for continuous alloying (default is 1; ignored for digital alloys)", NULL},
{ "multiplier", 'u', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_DOUBLE, &(args->multiplier), "Alloying step multiplier (sets the next alloying stepsize after a successful optimization at one alloying stepsize) for continuous alloying (ignored for digital alloys)", NULL},
{ "stepsize", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_DOUBLE, &(args->stepsize), "Initial alloying step size (how much to change x for the first optimization step; subsequent steps are set by stepsize=multiplier*stepsize) for continuous alloying (ignored for digital alloys)", NULL},
{ "converged_stepsize", 'T', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_DOUBLE, &(args->min_stepsize), "Consider alloying converged when stepsize reaches this value or smaller for continuous alloying (ignored for digital alloys)", NULL},
{"assignments", 'a', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING, &assignments, "Provide initial material assignments. Can be a single float, a comma-separated list of floats, or a function. If digital alloying, 0 <= v < 0.5 is assigned 0; 0.5 <= v <= 1.0 is assigned 1.\n", NULL},
{ "continuous", 'c', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &(args->continuous), "Do a continuous optimization, not a digital alloying. NOTE that mat1 and mat2 must be a single material, not an alloy", NULL },
#ifdef HAVE_MPI
{ "mpi", 'M', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &(args->mpi), "Use the MPI variant of the digital alloying algorithm. Currently ignored for continuous optimization. If an annealing option is not given, it uses a steepest-descent-related Monte Carlo method.", NULL },
{ "anneal-temperature", 'A', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_DOUBLE, &(args->temperature), "If specified, simulated annealing will be used at the specified temperature instead of the steepest-descent mode. Requires the MPI option. Temperature is in units of 1e-13 eV m.", NULL },
{ "annealing-program", 'P', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING, &(annealing_program), "If specified, simulated annealing will be used with the specified program instead of the steepest-descent mode. Requires the MPI option. The program is specified in the form of num_cycles,start_temperature,stop_temperature,num_temperature_steps. Temperature is in units of 1e-13 eV m.", NULL },
#endif
{ "compare_noefield", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &(args->do_nofield_comparison), "Instead of simply optimizing alpha, optimize the *change* in alpha between the structure as specified and the structure with no applied electric field.", NULL },
/*At some point, we should allow for a starting point*/
{NULL}
};
GOptionContext *ctx;
ctx = g_option_context_new("- sets up a structure for k-dot-p calculations");
g_option_context_add_main_entries(ctx, options, "Options");
g_option_context_parse(ctx, &argc, &argv, NULL);
gchar* htext = g_option_context_get_help(ctx, FALSE, NULL);
g_option_context_free(ctx);
if(mdb != NULL) {
free(args->matdb);
args->matdb = mdb;
}
if(optmat != NULL) {
free(args->optimizer_material);
args->optimizer_material = optmat;
}
#ifdef HAVE_MPI
if(args->temperature != 0) args->temperature *= 1e-13;
if((args->temperature != 0) && (annealing_program != NULL)) {
fprintf(stderr, "ERROR: both a fixed annealing temperature as well as an annealing program were specified! Only one may be given at a time.\n");
errored=1;
}
if(annealing_program != NULL) {
char** segments;
int N_temp_steps;
segments = g_strsplit(annealing_program, ",", 5);
if(segments == NULL) {
fprintf(stderr, "ERROR: unable to break the specified annealing program (%s) into comma-delimited parts.\n", annealing_program);
errored=1;
}else if(segments[0] == NULL) {
fprintf(stderr, "ERROR: unable to find the number of annealing cycles in the annealing program (%s).\n", annealing_program);
errored=1;
}else if(segments[1] == NULL) {
fprintf(stderr, "ERROR: unable to find the starting temperature in the annealing program (%s).\n", annealing_program);
errored=1;
}else if(segments[2] == NULL) {
fprintf(stderr, "ERROR: unable to find the stopping temperature in the annealing program (%s).\n", annealing_program);
errored=1;
}else if(segments[3] == NULL) {
fprintf(stderr, "ERROR: unable to find the number of temperature steps per cycle in the annealing program (%s).\n", annealing_program);
errored=1;
}else if(segments[4] == NULL) {
fprintf(stderr, "ERROR: unable to find the number of calculations per annealing step in the annealing program (%s).\n", annealing_program);
errored=1;
}else{
/*All the values are there; calculate them*/
double* dv;
unsigned* iv;
iv = get_unsigned_for_string(segments[0]);
if(iv == NULL) {
fprintf(stderr, "ERROR: unable to find an unsigned integer for the number of annealing cycles (%s).\n", segments[0]);
errored=1;
}else{
args->anneal_cycles = *iv;
if(*iv == 0) {
fprintf(stderr, "ERROR: specifying 0 annealing cycles is useless; I'm assuming this was in error.\n");
errored=1;
}
free(iv);
}
dv = get_double_for_string(segments[1]);
if(dv == NULL) {
fprintf(stderr, "ERROR: unable to find an double-precision number for the annealing cycle start (%s).\n", segments[1]);
errored=1;
}else{
args->anneal_start = *dv*1e-13;
if(args->anneal_start <= 0) {
fprintf(stderr, "ERROR: annealing cycle starting temperature must be > 0 (got %g).\n", *dv);
errored=1;
}
free(dv);
}
dv = get_double_for_string(segments[2]);
if(dv == NULL) {
fprintf(stderr, "ERROR: unable to find an double-precision number for the annealing cycle end (%s).\n", segments[2]);
errored=1;
}else{
args->anneal_end = *dv*1e-13;
if(args->anneal_start <= 0) {
fprintf(stderr, "ERROR: annealing cycle ending temperature must be > 0 (got %g).\n", *dv);
errored=1;
}
if(args->anneal_start >= args->anneal_end) {
fprintf(stderr, "ERROR: annealing starting temperature (%g) is greater than or equal to the ending temperature (%g)!\n", args->anneal_start, args->anneal_end);
errored=1;
}
free(dv);
}
iv = get_unsigned_for_string(segments[3]);
if(iv == NULL) {
fprintf(stderr, "ERROR: unable to find an unsigned integer for the number of annealing steps per cycle (%s).\n", segments[3]);
errored=1;
}else{
args->num_anneal_steps = *iv;
if(*iv == 0) {
fprintf(stderr, "ERROR: specifying 0 annealing steps is useless; I'm assuming this was in error.\n");
errored=1;
}
free(iv);
}
iv = get_unsigned_for_string(segments[4]);
if(iv == NULL) {
fprintf(stderr, "ERROR: unable to find an unsigned integer for the number of calculation steps per annealing step (%s).\n", segments[4]);
errored=1;
}else{
args->calculation_steps_per_annealing_step = *iv;
if(*iv == 0) {
fprintf(stderr, "ERROR: specifying 0 calculations per annealing step is useless; I'm assuming this was in error.\n");
errored=1;
}
free(iv);
}
}
}
#endif
if(raw_startingpoints <= 0) {
fprintf(stderr, "ERROR: starting points given (%d) was less than or equal to zero! This is nonsensical.\n", raw_startingpoints);
errored=1;
}else{
args->N_starting_points=raw_startingpoints;
}
if(raw_blocksize <= 0) {
fprintf(stderr, "ERROR: block size (%d) given was less than or equal to zero! This is nonsensical.\n", raw_blocksize);
errored=1;
}else{
args->blocksize=raw_blocksize;
}
if((mat1 == NULL) || (mat0 == NULL)) {
fprintf(stderr, "ERROR: you MUST supply the two material types for the digital alloy optimizer.\n");
errored=1;
}else{
fprintf(stderr, "mat1=(%s) mat0=(%s)\n", mat1, mat0);
errored=set_quikmat(&(args->mat1), mat1);
errored=set_quikmat(&(args->mat0), mat0);
}
args->filestreams = NULL;
GFileInputStream *instream;
GError *gerr = NULL;
if(file_names != NULL) {
for(int i = 0; file_names[i] != NULL; i++) {
struct file_info *fi = (struct file_info*)malloc(sizeof(struct file_info));
if(fi == NULL) {
fprintf(stderr, "ERROR: unable to allocate input file info struct!\n");
return 500;
}
if((file_names[i][0] == '-') && (file_names[i][1] == '\0')) {
fi->instream = (GInputStream*)g_unix_input_stream_new(0, FALSE);
fi->filename = g_string_new("-");
}else{
GFile *f = g_file_new_for_commandline_arg(file_names[i]);
gerr = NULL;
instream = g_file_read(f, NULL, &gerr);
if(gerr != NULL) {
fprintf(stderr, "makestruct: ERROR reading in structure file (%s): %s", g_file_get_uri(f), gerr->message);
return 100;
}
g_object_unref(f);
fi->instream = (GInputStream*)instream;
fi->filename = g_string_new(file_names[i]);
}
args->filestreams = g_list_append(args->filestreams, fi);
}
}
if(args->filestreams == NULL) {
fprintf(stderr, "ERROR: you MUST give at least one file to process!\n");
errored=1;
}
if(args->continuous) {
if(args->mat1.x != 1) {
fprintf(stderr, "ERROR: you MUST not give an alloy for continuous alloying (material 1 was an alloy.)\n");
errored=1;
}
if(args->mat0.x != 1) {
fprintf(stderr, "ERROR: you MUST not give an alloy for continuous alloying (material 0 was an alloy.)\n");
errored=1;
}
}
if(assignments != NULL) {
char** strs = g_strsplit(assignments, ",", -1);
if(strs[0] == NULL) {
fprintf(stderr, "ERROR: initial material assignment argument was given, but no data was!\n");
errored == 1;
}else{
/*Try to convert the first argument into a double. If we can't, it's an equation.*/
double* pv = get_double_for_string(strs[0]);
if(pv == NULL) {
if(strs[1] != NULL) {
/*Need to set up the equation parser*/
fprintf(stderr, "ERROR: First number given was not a float (%s), but you provided multiple arguments! You may only specify one equation to use for initial material assignments.\n", strs[0]);
errored == 1;
}else{
/*Need to set up the equation parser*/
fprintf(stderr, "ERROR: Equations are not yet supported. Sorry. One thing at a time.\n");
errored == 1;
}
}
/*If the first arg wasn't an equation, we're good.*/
if(pv != NULL) {
free(pv);
for(unsigned i=0; strs[i] != NULL; i++) {
double* pv = get_double_for_string(strs[i]);
if(pv == NULL) {
fprintf(stderr, "ERROR: Unable to convert %udth number (%s) to a float!\n", i, strs[i]);
errored == 1;
break;
}
/*OK. I'm a softie. <0.5 => 0; >=0.5 => 1*/
if(args->continuous) {
if(*pv < 0.5) {
*pv = 0.0;
}else{
*pv = 1.0;
}
}
args->assignments = g_list_append(args->assignments, pv);
}
}
}
g_strfreev(strs);
}
char** tparam_entry;
args->template_parameters = NULL;
if(parameters != NULL) {
for(unsigned i=0; parameters[i] != NULL; i++) {
tparam_entry = g_strsplit(parameters[i], ",", -1);
int len=g_strv_length(tparam_entry);
struct template_parameter_range* tpr;
if(len == 2) {
/*parameter,value form*/
tpr = new_template_parameter_range(tparam_entry[0], strtod(tparam_entry[1], NULL), strtod(tparam_entry[1], NULL), strtod(tparam_entry[1], NULL));
}else if(len == 4) {
tpr = new_template_parameter_range(tparam_entry[0], strtod(tparam_entry[1], NULL), strtod(tparam_entry[2], NULL), strtod(tparam_entry[3], NULL));
}else{
fprintf(stderr, "ERROR: invalid parameteter entry: incorrect number of parameter range arguments (got %d; expected 2 or 4; should be either parameter,value or parameter,start,stop,step)", len);
return 15;
}
if(tpr == NULL) {
fprintf(stderr, "ERROR: unable to allocate space for new template parameter range (parameter is %s)\n", tparam_entry[0]);
return 16;
}
args->template_parameters = g_list_append(args->template_parameters, tpr);
}
}
if(print_version){
print_version_info();
return 1;
}
if(errored){
printf("%s", htext);
printf("\n\n**For version and compilation information, run with --version***\n");
return 3;
}
return 0;
}
Here is the call graph for this function:| void program_print_version | ( | FILE * | f | ) |
| int set_quikmat | ( | struct quikmat * | m, |
| char * | matstring | ||
| ) |
Sets a quikmat from a string.
| m | ptr to a quikmat struct |
| matstring | string to convert from |
Definition at line 95 of file oneoff_optimize_1d_argprocess.c++.
References quikmat::mat1, quikmat::mat2, and quikmat::x.
Referenced by process_args().
{
char** matpieces;
matpieces = g_strsplit(matstring, "/", 4);
if(matpieces[0] == NULL) {
/*This is a single material.*/
GString* s = g_string_new(matstring);
m->mat1 = s->str;
g_string_free(s, FALSE);
m->mat2 = NULL;
m->x = 1.0;
return 0;
}
GString* s = g_string_new(matpieces[0]);
m->mat1 = s->str;
g_string_free(s, FALSE);
if(matpieces[1] == NULL) {
/*Again a single material. Ship it.*/
m->mat2 = NULL;
m->x = 1.0;
return 0;
}
int val = sscanf(matpieces[1], "%lg", &(m->x));
if((val != 1) || isnan(m->x) || isinf(m->x) || (m->x <=0) || (m->x >= 1)) {
fprintf(stderr, "Got invalid number %g (%s) as material percentage in material string (%s)\n", m->x, matpieces[1], matstring);
m->mat2 = NULL;
return 1;
}
if(matpieces[2] == NULL) {
fprintf(stderr, "Got no second alloy material in material string (%s)\n", matstring);
m->mat2 = NULL;
return 2;
}
m->mat2 = matpieces[2];
return 0;
}
Here is the caller graph for this function: