51 #include <gsl/gsl_multimin.h> 123 double index_scale = -1.;
148 index_scale = (double) nt / (
double) nd;
149 for (i=1; i<nd; i++) {
150 p_index = (lround) (i * index_scale);
155 index_scale = (double) nd / (
double) nt;
156 for (i=1; i<nt; i++) {
157 p_index = (lround) (i * index_scale);
163 double penalty_factor = 10.;
183 int main(
int argc,
char *argv[])
188 int opt_help =
FALSE;
189 int opt_verbose =
FALSE;
190 int opt_pathfile =
FALSE;
191 int num_args_left = -1;
192 FILE *file_ptr = NULL;
193 FILE *pathfile_ptr = NULL;
194 char basename[FILENAME_MAX];
195 memset(basename,
'\0', FILENAME_MAX);
196 char infilename[FILENAME_MAX];
197 memset(infilename,
'\0', FILENAME_MAX);
198 char outfilename[FILENAME_MAX];
199 memset(outfilename,
'\0', FILENAME_MAX);
200 char pathfilename[FILENAME_MAX];
201 memset(pathfilename,
'\0', FILENAME_MAX);
208 char junk_char =
'\0';
212 int found_header_end =
FALSE;
213 int found_data_end =
FALSE;
215 time_t start_time = -1;
216 time_t end_time = -1;
217 double total_time = -1.;
218 double program_version = 0.2;
230 double rmax = 1000.0e-6;
231 double zmax = 2000.0e-6;
232 int specified_zmax =
FALSE;
234 int specified_lz1 =
FALSE;
236 int specified_lz2 =
FALSE;
242 int specified_ez1 =
FALSE;
244 int specified_ez2 =
FALSE;
252 int specified_nt =
FALSE;
253 double nt_scale = -1.;
254 int specified_nt_scale =
FALSE;
263 double crnt = 80.0e-9;
276 int isource, jsource;
277 isource = jsource = -1;
282 int specified_pz =
FALSE;
284 iprobe = jprobe = -1;
288 int opt_global_kappa =
FALSE;
289 double alpha_so = 0.218;
290 double theta_so = 0.447;
291 double kappa_so = 0.007;
292 double alpha_sp = 0.2;
293 double theta_sp = 0.4;
294 double kappa_sp = 0.01;
295 double alpha_sr = 0.218;
296 double theta_sr = 0.447;
297 double kappa_sr = 0.007;
298 double kappa_outside = 0.007;
299 int specified_kappa_outside =
FALSE;
303 double dstar_so, dstar_sp, dstar_sr, dstar_max;
304 dstar_so = dstar_sp = dstar_sr = dstar_max = -1.;
306 double dfree = 1.24e-09;
312 double *alphas = NULL;
316 double *tdata = NULL;
317 double *pdata = NULL;
323 param_struct.
nt = -1;
324 param_struct.
nd = -1;
325 param_struct.
nz = -1;
326 param_struct.
nr = -1;
329 param_struct.
iz1 = -1;
330 param_struct.
iz2 = -1;
334 param_struct.
dt = -1.;
335 param_struct.
dr = -1.;
336 param_struct.
sd = -1.;
337 param_struct.
st = -1.;
353 param_struct.
dfree = -1.;
355 param_struct.
t = NULL;
356 param_struct.
s = NULL;
357 param_struct.
invr = NULL;
358 param_struct.
p = NULL;
359 param_struct.
t_data = NULL;
360 param_struct.
p_data = NULL;
364 double minalpha = 0.001;
365 double maxalpha = 0.25;
366 double mintheta = 0.001;
367 double maxtheta = 0.75;
368 double minkappa = 0.0;
369 double maxkappa = 0.1;
370 double alpha_fit = -1.;
371 double theta_fit = -1.;
372 double kappa_fit = -1.;
374 gsl_vector *steps = NULL;
375 gsl_vector *simplex = NULL;
376 double alpha_step = 0.1;
377 double theta_step = 0.2;
378 double kappa_step = 0.002;
380 const gsl_multimin_fminimizer_type *fit_algorithm =
381 gsl_multimin_fminimizer_nmsimplex;
382 gsl_multimin_fminimizer *fit_state = NULL;
383 gsl_multimin_function fit_func;
387 double fit_size = -1.;
388 double fit_tol = 1.e-4;
394 start_time = time(NULL);
407 if ((argc < 2) || (argv[argc-1][0] ==
'-'))
426 strcpy(outfilename, infilename);
429 strng = index(outfilename,
'.');
431 strcat(infilename,
".txt");
432 strcat(outfilename,
".dat");
434 strcpy(strng,
".dat");
439 if ((file_ptr = fopen(infilename,
"r")) == NULL) {
440 fprintf(stderr,
"Error opening input file %s\n", infilename);
452 linelength = strlen(
string);
456 if (
string[0] ==
'#') {
458 fprintf(stderr,
"Warning: Maximum # of comment lines " 459 "exceeded.\nWill not copy more comment lines to " 460 "the output file.\n");
462 strcpy(comments.line[comments.n],
string);
465 }
else if (linelength < 3) {
466 found_header_end =
TRUE;
470 fprintf(stderr,
"Warning: Line %d seems to be too long\n", i+1);
474 if (fscanf(file_ptr,
"%*[^\n] %[\n]", &junk_char) == EOF)
475 error(
"fscanf returned EOF");
478 if (sscanf(
string,
"%s = %s", parameter, value) == EOF)
479 error(
"scanf returned EOF");
480 if (
STREQ(parameter,
"dfree")) {
488 if (dfree > 0.01) dfree *= 1e-9;
490 if (
STREQ(parameter,
"trn")) trn = atof(value);
491 if (
STREQ(parameter,
"current")) {
495 if (
STREQ(parameter,
"delay")) sd = atof(value);
496 if (
STREQ(parameter,
"duration")) st = atof(value);
497 if (
STREQ(parameter,
"source_z")) {
501 error(
"source_z = %f microns but should be 0 " 502 "(or not specified in the output file)", sz);
504 if (
STREQ(parameter,
"probe_z")) {
509 if (
STREQ(parameter,
"probe_r")) {
513 if (
STREQ(parameter,
"nolayer")) nolayer = atoi(value);
514 if (
STREQ(parameter,
"lz1")) {
516 specified_lz1 =
TRUE;
519 if (
STREQ(parameter,
"lz2")) {
521 specified_lz2 =
TRUE;
524 if (
STREQ(parameter,
"ez1")) {
526 specified_ez1 =
TRUE;
529 if (
STREQ(parameter,
"ez2")) {
531 specified_ez2 =
TRUE;
534 if (
STREQ(parameter,
"alpha_so")) alpha_so = atof(value);
535 if (
STREQ(parameter,
"alpha_sr")) alpha_sr = atof(value);
536 if (
STREQ(parameter,
"theta_so")) theta_so = atof(value);
537 if (
STREQ(parameter,
"theta_sr")) theta_sr = atof(value);
538 if (
STREQ(parameter,
"kappa_so")) kappa_so = atof(value);
539 if (
STREQ(parameter,
"kappa_sr")) kappa_sr = atof(value);
549 if (
STREQ(parameter,
"nt")) {
553 if (
STREQ(parameter,
"nt_scale")) {
554 nt_scale = atof(value);
555 specified_nt_scale =
TRUE;
557 if (
STREQ(parameter,
"nr")) nr = atoi(value);
558 if (
STREQ(parameter,
"nz")) nz = atoi(value);
559 if (
STREQ(parameter,
"rmax")) {
563 if (
STREQ(parameter,
"zmax")) {
567 if (
STREQ(parameter,
"tmax")) tmax = atof(value);
571 if (!found_header_end)
572 error(
"Did not find blank line after header");
575 printf(
"Found end of header\n");
579 error(
"EOF (or error) reached before reading data");
581 linelength = strlen(
string);
583 error(
"The line after the header has %d characters " 584 "(should be 1 or 2)", linelength);
588 error(
"EOF (or error) reached before reading data");
596 printf(
"Reading data from file\n");
598 if (fscanf(file_ptr,
"%lf%lf%*[^\n] %[\n]",
599 &tdata[j], &pdata[j], &junk_char) == EOF)
601 found_data_end =
TRUE;
606 error(
"Read maximum number of lines in output file (%d)\n" 607 "but did not reach end of file", j);
610 printf(
"Found end of data\n");
615 printf(
"The number of data points is %d\n", nd);
624 static struct option long_opts[] = {
625 {
"help", no_argument, NULL,
'h'},
626 {
"verbose", no_argument, NULL,
'v'},
627 {
"global_kappa", no_argument, NULL,
'g'},
628 {
"nr", required_argument, NULL, 0},
629 {
"nz", required_argument, NULL, 0},
630 {
"nt", required_argument, NULL, 0},
631 {
"nt_scale", required_argument, NULL, 0},
632 {
"ez1", required_argument, NULL, 0},
633 {
"ez2", required_argument, NULL, 0},
634 {
"alpha_so", required_argument, NULL, 0},
635 {
"alpha_sp", required_argument, NULL, 0},
636 {
"alpha_sr", required_argument, NULL, 0},
637 {
"theta_so", required_argument, NULL, 0},
638 {
"theta_sp", required_argument, NULL, 0},
639 {
"theta_sr", required_argument, NULL, 0},
640 {
"kappa_so", required_argument, NULL, 0},
641 {
"kappa_sp", required_argument, NULL, 0},
642 {
"kappa_sr", required_argument, NULL, 0},
643 {
"kappa_outside", required_argument, NULL, 0},
644 {
"alpha_step", required_argument, NULL, 0},
645 {
"theta_step", required_argument, NULL, 0},
646 {
"kappa_step", required_argument, NULL, 0},
647 {
"minalpha", required_argument, NULL, 0},
648 {
"maxalpha", required_argument, NULL, 0},
649 {
"mintheta", required_argument, NULL, 0},
650 {
"maxtheta", required_argument, NULL, 0},
651 {
"minkappa", required_argument, NULL, 0},
652 {
"maxkappa", required_argument, NULL, 0},
653 {
"tmax", required_argument, NULL, 0},
654 {
"fit_tol", required_argument, NULL, 0},
655 {
"itermax", required_argument, NULL, 0},
656 {
"outfile", required_argument, NULL, 0},
657 {
"pathfile", required_argument, NULL, 0},
658 {NULL, no_argument, NULL, 0}
661 while ((opt = getopt_long(argc, argv,
"hvg",
662 long_opts, &opt_index)) != -1) {
674 opt_global_kappa =
TRUE;
678 if (
STREQ(
"nr", long_opts[opt_index].name)) {
680 }
else if (
STREQ(
"nz", long_opts[opt_index].name)) {
682 }
else if (
STREQ(
"nt", long_opts[opt_index].name)) {
685 }
else if (
STREQ(
"nt_scale", long_opts[opt_index].name)) {
686 nt_scale = atof(optarg);
687 specified_nt_scale =
TRUE;
688 }
else if (
STREQ(
"ez1", long_opts[opt_index].name)) {
690 specified_ez1 =
TRUE;
692 }
else if (
STREQ(
"ez2", long_opts[opt_index].name)) {
694 specified_ez2 =
TRUE;
696 }
else if (
STREQ(
"alpha_so", long_opts[opt_index].name)) {
697 alpha_so = atof(optarg);
698 }
else if (
STREQ(
"alpha_sp", long_opts[opt_index].name)) {
699 alpha_sp = atof(optarg);
700 }
else if (
STREQ(
"alpha_sr", long_opts[opt_index].name)) {
701 alpha_sr = atof(optarg);
702 }
else if (
STREQ(
"theta_so", long_opts[opt_index].name)) {
703 theta_so = atof(optarg);
704 }
else if (
STREQ(
"theta_sp", long_opts[opt_index].name)) {
705 theta_sp = atof(optarg);
706 }
else if (
STREQ(
"theta_sr", long_opts[opt_index].name)) {
707 theta_sr = atof(optarg);
708 }
else if (
STREQ(
"kappa_so", long_opts[opt_index].name)) {
709 kappa_so = atof(optarg);
710 }
else if (
STREQ(
"kappa_sp", long_opts[opt_index].name)) {
711 kappa_sp = atof(optarg);
712 }
else if (
STREQ(
"kappa_sr", long_opts[opt_index].name)) {
713 kappa_sr = atof(optarg);
714 }
else if (
STREQ(
"kappa_outside", long_opts[opt_index].name)) {
715 kappa_outside = atof(optarg);
716 specified_kappa_outside =
TRUE;
717 }
else if (
STREQ(
"alpha_step", long_opts[opt_index].name)) {
718 alpha_step = atof(optarg);
719 }
else if (
STREQ(
"theta_step", long_opts[opt_index].name)) {
720 theta_step = atof(optarg);
721 }
else if (
STREQ(
"kappa_step", long_opts[opt_index].name)) {
722 kappa_step = atof(optarg);
723 }
else if (
STREQ(
"minalpha", long_opts[opt_index].name)) {
724 minalpha = atof(optarg);
725 }
else if (
STREQ(
"maxalpha", long_opts[opt_index].name)) {
726 maxalpha = atof(optarg);
727 }
else if (
STREQ(
"mintheta", long_opts[opt_index].name)) {
728 mintheta = atof(optarg);
729 }
else if (
STREQ(
"maxtheta", long_opts[opt_index].name)) {
730 maxtheta = atof(optarg);
731 }
else if (
STREQ(
"minkappa", long_opts[opt_index].name)) {
732 minkappa = atof(optarg);
733 }
else if (
STREQ(
"maxkappa", long_opts[opt_index].name)) {
734 maxkappa = atof(optarg);
735 }
else if (
STREQ(
"tmax", long_opts[opt_index].name)) {
737 }
else if (
STREQ(
"fit_tol", long_opts[opt_index].name)) {
738 fit_tol = atof(optarg);
739 }
else if (
STREQ(
"itermax", long_opts[opt_index].name)) {
740 itermax = atoi(optarg);
741 }
else if (
STREQ(
"outfile", long_opts[opt_index].name)) {
743 }
else if (
STREQ(
"pathfile", long_opts[opt_index].name)) {
750 error(
"Missing argument for a command-line option '-%c'",
755 error(
"Unknown command line option '-%c'", optopt);
759 error(
"Problem in parsing command line options");
765 num_args_left = argc - optind;
766 if ((num_args_left != 1) || opt_help)
771 printf(
"The name of the input file is %s\n", infilename);
772 printf(
"The name of the output file will be %s\n", outfilename);
774 printf(
"The name of the simplex path file will be %s\n",
779 if (
STREQ(infilename, outfilename))
780 error(
"The input and output filenames cannot be the same.");
781 if (
STREQ(infilename, pathfilename))
782 error(
"The input and simplex path filenames cannot be the same.");
783 if (
STREQ(outfilename, pathfilename))
784 error(
"The output and simplex path filenames cannot be the same.");
786 if (specified_ez1 && !specified_ez2)
787 error(
"You specified ez1 but did not specify ez2");
788 if (specified_ez2 && !specified_ez1)
789 error(
"You specified ez2 but did not specify ez1");
790 if (specified_ez1 && specified_zmax)
791 error(
"You specified ez1 and ez2, so you should not specify zmax");
794 if (ez1 > 0)
error(
"Bottom of cylinder ez1 = %f > 0\n", ez1);
795 if (ez2 < 0)
error(
"Top of cylinder ez2 = %f < 0\n", ez2);
796 if (ez1 > lz1)
error(
"Bottom of cylinder ez1 = %f > lz1 = %f\n",
798 if (ez2 < lz2)
error(
"Top of cylinder ez2 = %f < lz2 = %f\n",
804 if (specified_pz ==
FALSE) {
807 printf(
"Warning: probe location set to default value of %g m = " 808 "%f microns\n (relative to source)",
812 if (specified_lz1 ==
FALSE) {
813 lz1 = - 50.0e-6 / 2.0;
815 printf(
"Warning: lz1 set to default value of %g m = " 816 "%f microns\n (relative to source)",
820 if (specified_lz2 ==
FALSE) {
823 printf(
"Warning: lz2 set to default value of %g m = " 824 "%f microns\n (relative to source)",
829 if (specified_kappa_outside) {
830 kappa_sr = kappa_outside;
831 kappa_so = kappa_outside;
832 if (opt_global_kappa) {
833 error(
"You're fitting for global kappa but specified " 834 "kappa_outside.\nWhen you fit for global kappa, " 835 "kappa_sr and kappa_so are set = kappa_sp.");
852 printf(
"\nNOTE: nolayer option given; the diffusion " 853 "parameters of \nthe homogeneous environment " 854 "are set to the SR values\n");
858 if (opt_global_kappa) {
862 printf(
"NOTE: kappa will be the same in all layers (-g)\n" 863 "kappa_sr and kappa_so set to kappa_sp\n");
888 coord_shift = (-ez1);
890 coord_shift = (zmax - (lz1+lz2))/2.;
901 if (fabs(dr - dz) > 1.0e-15) {
906 sz = round(sz / dz) * dz;
907 pz = round(pz / dz) * dz;
908 pr = round(pr / dr) * dr;
911 iz1 = (long) (lz1 / dz);
912 lz1 = iz1 * dz + dz / 2.0;
914 iz2 = (long) (lz2 / dz);
915 lz2 = iz2 * dz + dz / 2.0;
919 dstar_so = theta_so * dfree;
920 dstar_sp = theta_sp * dfree;
921 dstar_sr = theta_sr * dfree;
922 dstar_max =
MAX(dstar_so, dstar_sp);
923 dstar_max =
MAX(dstar_max, dstar_sr);
927 if ( ((iz2 - iz1) < 2) && (nolayer == 0) )
928 error(
"Layer has too few discrete steps to continue.");
931 if (specified_nt ==
TRUE)
934 dt = 0.9 * dr*dr / (6.0 * dstar_max);
937 if (specified_nt_scale ==
TRUE) {
939 if (nt_scale < 0.)
error(
"nt_scale < 0");
944 nt = lround(tmax / dt);
946 ns = lround(st / dt);
948 nds = lround(sd / dt);
952 error(
"Source delay (%f) should be < tmax (%f)", sd, tmax);
954 error(
"Source duration (%f) should be < tmax (%f)", st, tmax);
956 error(
"Source delay (%f) + duration (%f) should be < tmax (%f)",
968 printf(
"\nIn main(): The command used was\n\t%s\n(%d words)\n\n",
969 comments.command, i);
977 printf(
"Output from fit-layer.c, version %.1f:\n", program_version);
978 printf(
"# Note that the z-values (sz, pz, lz1, and lz2) ");
979 printf(
"have been shifted \n# by %f microns ", 1.0e6*coord_shift);
981 printf(
"to have the volume go from z=0 to z=zmax.\n");
983 printf(
"to center the SP layer in the volume.\n");
985 printf(
"nr x nz = %d x %d\n", nr, nz);
986 printf(
"rmax x zmax = %f x %f microns\n", 1.0e6 * rmax, 1.0e6 * zmax);
987 printf(
"dr x dz = %f x %f microns\n", 1.0e6 * dr, 1.0e6 * dz);
988 printf(
"(sr, sz) = (%f, %f) microns\n", 1.0e6 * sr, 1.0e6 * sz);
989 printf(
"(pr, pz) = (%f, %f) microns\n", 1.0e6 * pr, 1.0e6 * pz);
990 printf(
"Electrode distance = %f microns\n",
991 1.0e6 * sqrt(
SQR(pr-sr) +
SQR(pz-sz)));
992 printf(
"(iz1, iz2) = (%d, %d)\n", iz1, iz2);
993 printf(
"(lz1, lz2) = (%f, %f) microns\n", 1.0e6 * lz1, 1.0e6 * lz2);
994 printf(
"Layer thickness = %f microns\n", 1.0e6 * (lz2 - lz1));
995 printf(
"Layer discrete steps = %d\n", iz2 - iz1);
996 printf(
"Nolayer flag = %d\n" , nolayer);
997 printf(
"dfree = %g m^2/s\n", dfree);
998 printf(
"alpha_so = %.4f, theta_so = %.4f, " 999 "lambda_so = %.4f, kappa_so = %.6f\n",
1000 alpha_so, theta_so, 1.0/sqrt(theta_so), kappa_so);
1001 printf(
"Starting alpha_sp = %.4f, theta_sp = %.4f, " 1002 "lambda_sp = %.4f, kappa_sp = %.6f\n",
1003 alpha_sp, theta_sp, 1.0/sqrt(theta_sp), kappa_sp);
1004 printf(
"Starting alpha_step = %.4f, theta_step = %.4f\n",
1005 alpha_step, theta_step);
1006 printf(
"Constraints: minalpha = %.8f, maxalpha = %.8f\n",
1007 minalpha, maxalpha);
1008 printf(
"Constraints: mintheta = %.8f, maxtheta = %.8f\n",
1009 mintheta, maxtheta);
1010 printf(
"Constraints: minkappa = %.8f, maxkappa = %.8f\n",
1011 minkappa, maxkappa);
1012 printf(
"Stopping criteria: simplex size < %g or # iterations = %d\n",
1014 printf(
"alpha_sr = %.4f, theta_sr = %.4f, " 1015 "lambda_sr = %.4f, kappa_sr = %.6f\n",
1016 alpha_sr, theta_sr, 1.0/sqrt(theta_sr), kappa_sr);
1017 if (opt_global_kappa)
1018 printf(
"NOTE: kappa_sr and kappa_so set to kappa_sp (-g)\n");
1019 printf(
"nt = %d\n", nt);
1020 printf(
"tmax = %f s\n", tmax);
1021 printf(
"dt = %f ms\n", 1.0e3 * dt);
1022 printf(
"von Neumann dt / (dr^2/(6*dstar)) = %f\n",
1023 dt * 6.0 * dstar_max / (dr*dr));
1024 printf(
"ns = %d\n", ns);
1025 printf(
"source delay sd = %f s\n", sd);
1026 printf(
"source duration st = %f s\n", st);
1027 printf(
"Current = %g nA\n", 1.0e9 * crnt);
1028 printf(
"Transport number = %f\n", trn);
1029 printf(
"Start time = %s",
string);
1034 if ((file_ptr = fopen(outfilename,
"w")) == NULL) {
1035 fprintf(stderr,
"Error opening output file %s\n", outfilename);
1040 fprintf(file_ptr,
"# Fit-layer Output File\n");
1041 fprintf(file_ptr,
"# ~~~~~~~~~~~~~~~~~~~~~\n");
1042 fprintf(file_ptr,
"# Command used to run program:\n");
1043 fprintf(file_ptr,
"# %s\n", comments.command);
1046 if (comments.n > 0) {
1047 fprintf(file_ptr,
"# --------------------------------------\n");
1048 fprintf(file_ptr,
"# Comments from input parameter file:\n");
1049 for (j=0; j<comments.n; j++)
1050 fprintf(file_ptr,
"%s", comments.line[j]);
1051 fprintf(file_ptr,
"# --------------------------------------\n");
1056 fprintf(file_ptr,
"# Output from fit-layer.c, version %.1f:\n", program_version);
1057 fprintf(file_ptr,
"# Note that the z-values (sz, pz, lz1, and lz2) ");
1058 fprintf(file_ptr,
"have been shifted \n# by %f microns ", 1.0e6*coord_shift);
1059 if (specified_ez1) {
1060 fprintf(file_ptr,
"to have the volume go from z=0 to z=zmax.\n");
1062 fprintf(file_ptr,
"to center the SP layer in the volume.\n");
1064 fprintf(file_ptr,
"# nr x nz = %d x %d\n", nr, nz);
1065 fprintf(file_ptr,
"# rmax x zmax = %f x %f microns\n", 1.0e6 * rmax, 1.0e6 * zmax);
1066 fprintf(file_ptr,
"# dr x dz = %f x %f microns\n", 1.0e6 * dr, 1.0e6 * dz);
1067 fprintf(file_ptr,
"# (sr, sz) = (%f, %f) microns\n", 1.0e6 * sr, 1.0e6 * sz);
1068 fprintf(file_ptr,
"# (pr, pz) = (%f, %f) microns\n", 1.0e6 * pr, 1.0e6 * pz);
1069 fprintf(file_ptr,
"# Electrode distance = %f microns\n",
1070 1.0e6 * sqrt(
SQR(pr-sr) +
SQR(pz-sz)));
1071 fprintf(file_ptr,
"# (iz1, iz2) = (%d, %d)\n", iz1, iz2);
1072 fprintf(file_ptr,
"# (lz1, lz2) = (%f, %f) microns\n", 1.0e6 * lz1, 1.0e6 * lz2);
1073 fprintf(file_ptr,
"# Layer thickness = %f microns\n", 1.0e6 * (lz2 - lz1));
1074 fprintf(file_ptr,
"# Layer discrete steps = %d\n", iz2 - iz1);
1075 fprintf(file_ptr,
"# Nolayer flag = %d\n" , nolayer);
1076 fprintf(file_ptr,
"# dfree = %g m^2/s\n", dfree);
1077 fprintf(file_ptr,
"# alpha_so = %.4f, theta_so = %.4f, " 1078 "lambda_so = %.4f, kappa_so = %.6f\n",
1079 alpha_so, theta_so, 1.0/sqrt(theta_so), kappa_so);
1080 fprintf(file_ptr,
"# Starting alpha_sp = %.4f, theta_sp = %.4f, " 1081 "lambda_sp = %.4f, kappa_sp = %.6f\n",
1082 alpha_sp, theta_sp, 1.0/sqrt(theta_sp), kappa_sp);
1083 fprintf(file_ptr,
"# Starting alpha_step = %.4f, theta_step = %.4f\n",
1084 alpha_step, theta_step);
1085 fprintf(file_ptr,
"# Constraints: minalpha = %.8f, maxalpha = %.8f\n",
1086 minalpha, maxalpha);
1087 fprintf(file_ptr,
"# Constraints: mintheta = %.8f, maxtheta = %.8f\n",
1088 mintheta, maxtheta);
1089 fprintf(file_ptr,
"# Constraints: minkappa = %.8f, maxkappa = %.8f\n",
1090 minkappa, maxkappa);
1091 fprintf(file_ptr,
"# Stopping criteria: simplex size < %g or # iterations = %d\n",
1093 fprintf(file_ptr,
"# alpha_sr = %.4f, theta_sr = %.4f, " 1094 "lambda_sr = %.4f, kappa_sr = %.6f\n",
1095 alpha_sr, theta_sr, 1.0/sqrt(theta_sr), kappa_sr);
1096 if (opt_global_kappa)
1097 fprintf(file_ptr,
"# NOTE: kappa_sr and kappa_so set to kappa_sp (-g)\n");
1098 fprintf(file_ptr,
"# nt = %d\n", nt);
1099 fprintf(file_ptr,
"# tmax = %f s\n", tmax);
1100 fprintf(file_ptr,
"# dt = %f ms\n", 1.0e3 * dt);
1101 fprintf(file_ptr,
"# von Neumann dt / (dr^2/(6*dstar)) = %f\n",
1102 dt * 6.0 * dstar_max / (dr*dr));
1103 fprintf(file_ptr,
"# ns = %d\n", ns);
1104 fprintf(file_ptr,
"# Source delay sd = %f s\n", sd);
1105 fprintf(file_ptr,
"# Source duration st = %f s\n", st);
1106 fprintf(file_ptr,
"# Current = %g nA\n", 1.0e9 * crnt);
1107 fprintf(file_ptr,
"# Transport number = %f\n", trn);
1108 fprintf(file_ptr,
"# Start time = %s",
string);
1116 for (j=0; j<nr+1; j++) {
1117 for (i=0; i<iz1+1; i++) alphas[
INDEX(i,j)] = alpha_sr;
1118 for (i=iz1+1; i<iz2+1; i++) alphas[
INDEX(i,j)] = alpha_sp;
1119 for (i=iz2+1; i<nz; i++) alphas[
INDEX(i,j)] = alpha_so;
1126 param_struct.
invr[0] = 1.0 / dr;
1127 param_struct.
invr[1] = 0.0;
1128 for (j=2; j<nr+1; j++) {
1129 param_struct.
invr[j] = 1.0 / ((j-1.)*dr);
1135 isource = lround(sz/dz);
1136 jsource = 1+lround(sr/dr);
1137 param_struct.
s[
INDEX(isource,jsource)]
1138 = (1.0 / alphas[
INDEX(isource,jsource)]) *
1139 sa * dt * 4.0 / (
PI *
SQR(dr) * dz);
1145 for (k=0; k<nt; k++)
1148 iprobe = lround(pz/dz);
1149 jprobe = 1+lround(pr/dr);
1155 printf(
"About to fit parameters\n");
1161 printf(
"\nSimplex fitting -- vertex changes:\n");
1162 printf(
"Iter\talpha_fit\ttheta_fit\tkappa_fit\tmse \tfit size\n");
1163 printf(
"%d\t%f\t%f\t%f\n",
1164 0, alpha_sp, theta_sp, kappa_sp);
1168 if ((pathfile_ptr = fopen(pathfilename,
"w")) == NULL) {
1169 fprintf(stderr,
"Error opening simplex path file %s\n",
1173 fprintf(pathfile_ptr,
"Simplex fitting -- vertex changes:\n");
1174 fprintf(pathfile_ptr,
1175 "Iter\talpha_fit\ttheta_fit\tkappa_fit\tmse \tfit size\n");
1176 fprintf(pathfile_ptr,
"%d\t%f\t%f\t%f\n",
1177 0, alpha_sp, theta_sp, kappa_sp);
1180 param_struct.
nt = nt;
1181 param_struct.
nd = nd;
1182 param_struct.
nz = nz;
1183 param_struct.
nr = nr;
1184 param_struct.
iprobe = iprobe;
1185 param_struct.
jprobe = jprobe;
1186 param_struct.
iz1 = iz1;
1187 param_struct.
iz2 = iz2;
1188 param_struct.
nolayer = nolayer;
1191 param_struct.
dt = dt;
1192 param_struct.
dr = dr;
1193 param_struct.
sd = sd;
1194 param_struct.
st = st;
1210 param_struct.
dfree = dfree;
1217 for (k=0; k<nt; k++) {
1218 param_struct.
t[k] = t[k];
1219 param_struct.
p[k] = p[k];
1223 for (k=0; k<nd; k++) {
1224 param_struct.
t_data[k] = tdata[k];
1225 param_struct.
p_data[k] = pdata[k];
1232 simplex = gsl_vector_alloc(3);
1233 gsl_vector_set(simplex, 0, alpha_sp);
1234 gsl_vector_set(simplex, 1, theta_sp);
1235 gsl_vector_set(simplex, 2, kappa_sp);
1238 steps = gsl_vector_alloc(3);
1239 gsl_vector_set(steps, 0, alpha_step);
1240 gsl_vector_set(steps, 1, theta_step);
1241 gsl_vector_set(steps, 2, kappa_step);
1246 fit_func.params = ¶m_struct;
1248 fit_state = gsl_multimin_fminimizer_alloc(fit_algorithm, 3);
1249 gsl_multimin_fminimizer_set(fit_state, &fit_func, simplex, steps);
1254 fit_status = gsl_multimin_fminimizer_iterate(fit_state);
1256 if (fit_status)
break;
1258 fit_size = gsl_multimin_fminimizer_size(fit_state);
1259 fit_status = gsl_multimin_test_size(fit_size, fit_tol);
1262 if (fit_status == GSL_SUCCESS) printf(
"Finished fit\n");
1264 alpha_fit = gsl_vector_get(fit_state->x, 0);
1265 theta_fit = gsl_vector_get(fit_state->x, 1);
1266 kappa_fit = gsl_vector_get(fit_state->x, 2);
1267 mse = fit_state->fval;
1270 printf(
"%d\t%f\t%f\t%f\t%g\t%g\n",
1271 (
int) fit_iter, alpha_fit, theta_fit, kappa_fit, mse, fit_size);
1274 fprintf(pathfile_ptr,
"%d\t%f\t%f\t%f\t%g\t%g\n",
1275 (
int) fit_iter, alpha_fit, theta_fit, kappa_fit, mse, fit_size);
1277 }
while (fit_status == GSL_CONTINUE && fit_iter < itermax);
1279 if (fit_status != GSL_SUCCESS) {
1280 printf(
"Warning: failed to converge, status = %d, " 1281 "# iterations = %zd\n", fit_status, fit_iter);
1283 fprintf(pathfile_ptr,
"Warning: failed to converge, " 1284 "status = %d, # iterations = %zd\n", fit_status, fit_iter);
1288 fclose(pathfile_ptr);
1291 double lambda_fit = 1./sqrt(theta_fit);
1293 printf(
"Fitted alpha = %f\n", alpha_fit);
1294 printf(
"Fitted theta = %f (lambda = %f)\n",
1295 theta_fit, lambda_fit);
1296 if (opt_global_kappa)
1297 printf(
"Fitted kappa = %f s^-1 (in all layers)\n", kappa_fit);
1299 printf(
"Fitted kappa = %f s^-1\n", kappa_fit);
1304 end_time = time(NULL);
1307 printf(
"End time = %s",
string);
1309 total_time = difftime(end_time, start_time);
1311 printf(
"Total time = %d seconds = %f minutes = %f hours\n",
1312 (
int) round(total_time), total_time/60., total_time/3600.);
1322 if ((file_ptr = fopen(outfilename,
"a")) == NULL) {
1323 fprintf(stderr,
"Error opening output file %s\n", outfilename);
1327 fprintf(file_ptr,
"# End time = %s",
string);
1328 fprintf(file_ptr,
"# Total time = %d seconds = %f minutes = %f hours\n",
1329 (
int) round(total_time), total_time/60., total_time/3600.);
1330 fprintf(file_ptr,
"# --------------------------------------\n");
1331 fprintf(file_ptr,
"# Results of fitting:\n");
1332 fprintf(file_ptr,
"# Number of iterations = %d\n", (
int)fit_iter);
1333 fprintf(file_ptr,
"# Fitted alpha = %f\n", alpha_fit);
1334 fprintf(file_ptr,
"# Fitted theta = %f (lambda = %f)\n",
1335 theta_fit, lambda_fit);
1336 if (opt_global_kappa)
1337 fprintf(file_ptr,
"# Fitted kappa = %f s^-1 (in all layers)\n", kappa_fit);
1339 fprintf(file_ptr,
"# Fitted kappa = %f s^-1\n", kappa_fit);
1340 fprintf(file_ptr,
"# Final mean squared error = %g\n", mse);
1341 fprintf(file_ptr,
"# Final simplex size = %g\n", fit_size);
1343 fprintf(file_ptr,
"# Solution: alpha_sp\ttheta_sp\tlambda_sp\tkappa_sp" 1344 "\t MSE\tsimplex size\t# iter.\tTime (s)" 1345 "\tTime (m)\tTime (h) \n");
1346 fprintf(file_ptr,
"# Solution: %f\t%f\t%f\t%f\t%f\t%g \t%7d\t%8d\t%f\t%f\n",
1347 alpha_fit, theta_fit, lambda_fit, kappa_fit,
1348 mse, fit_size, (
int) fit_iter,
1349 (
int) round(total_time), total_time/60., total_time/3600.);
1350 fprintf(file_ptr,
"# --------------------------------------\n");
1351 fprintf(file_ptr,
"# Probe concentration data:\n");
1352 fprintf(file_ptr,
"# time \t c (model) \t t (data) " 1360 for (i=0; i<1000; i++) {
1361 k = (i * nt) / 1000;
1362 l = (i * nd) / 1000;
1363 fprintf(file_ptr,
"%#12.8g\t%#12.8g\t%#12.8g\t%#12.8g\n", param_struct.
t[k], param_struct.
p[k],
1367 for (i=0; i<nt; i++) {
1368 fprintf(file_ptr,
"%#12.8g\t%#12.8g\t%#12.8g\t%#12.8g\n", param_struct.
t[i], param_struct.
p[i],
1371 fprintf(file_ptr,
"\n\n\n");
1387 free(param_struct.
t);
1388 free(param_struct.
s);
1389 free(param_struct.
invr);
1390 free(param_struct.
t_data);
1391 free(param_struct.
p_data);
1392 free(param_struct.
p);
1394 gsl_vector_free(simplex);
1395 gsl_vector_free(steps);
1396 gsl_multimin_fminimizer_free(fit_state);
1399 printf(
"All done\n");
1401 return(EXIT_SUCCESS);
double * p_data
Probe concentration data.
int iprobe
z-index of probe location.
double st
Duration of source.
double dfree
Free diffusion coefficient.
double maxkappa
Upper boundary for kappa_sp (add penalty if kappa_sp is out of bounds).
double theta_sr
Permeability in SR layer.
int nz
Number of support points in z (rows of concentration matrix).
double * invr
Array of 1/r values.
double * t_data
Time array for data.
double maxtheta
Upper boundary for theta_sp (add penalty if theta_sp is out of bounds).
double dr
Spacing in r (in this program, same as spacing in z).
double theta_sp
Permeability in SP layer.
double minalpha
Lower boundary for alpha_sp (add penalty if alpha_sp is out of bounds).
int nr
Number of support points in r (columns of concentration matrix).
int nt
Number of support points in time.
double alpha_so
Extracellular volume fraction in SO layer.
double sd
Source delay (time before source starts).
int iz2
z-index of SP-SO boundary.
int main(int argc, char *argv[])
Main program.
int iz1
z-index of SR-SP boundary.
double dt
Spacing in time.
double theta_so
Permeability in SO layer.
double maxalpha
Upper boundary for alpha_sp (add penalty if alpha_sp is out of bounds).
double alpha_sp
Extracellular volume fraction in SP layer.
int jprobe
r-index of probe location.
double minkappa
Lower boundary for kappa_sp (add penalty if kappa_sp is out of bounds).
Typedef for struct for passing parameters and arrays to mse function.
double mintheta
Lower boundary for theta_sp (add penalty if theta_sp is out of bounds).
double * p
Probe concentration calculated from model.
double kappa_sr
Nonspecific clearance factor in SR layer.
int nolayer
Flag for no layer (homogenous environment).
double kappa_sp
Nonspecific clearance factor in SP layer.
double kappa_so
Nonspecific clearance factor in SO layer.
double * t
Time array for model.
double calc_mse_fit_layer(const gsl_vector *x, void *params)
Mean squared error function for simplex fitting.
double alpha_sr
Extracellular volume fraction in SR layer.
int nd
Number of data points.
int opt_global_kappa
True if user specifies that kappa be the same in all layers.