46 int main(
int argc,
char *argv[])
52 int opt_verbose =
FALSE;
53 int opt_pathfile =
FALSE;
54 int num_args_left = -1;
55 FILE *file_ptr = NULL;
56 FILE *pathfile_ptr = NULL;
57 char basename[FILENAME_MAX];
58 memset(basename,
'\0', FILENAME_MAX);
59 char infilename[FILENAME_MAX];
60 memset(infilename,
'\0', FILENAME_MAX);
61 char outfilename[FILENAME_MAX];
62 memset(outfilename,
'\0', FILENAME_MAX);
63 char pathfilename[FILENAME_MAX];
64 memset(pathfilename,
'\0', FILENAME_MAX);
71 char junk_char =
'\0';
76 time_t start_time = -1;
78 double total_time = -1.;
79 double program_version = 0.2;
91 double rmax = 1000.0e-6;
92 double zmax = 2000.0e-6;
93 int specified_zmax =
FALSE;
95 int specified_lz1 =
FALSE;
97 int specified_lz2 =
FALSE;
103 int specified_ez1 =
FALSE;
105 int specified_ez2 =
FALSE;
112 int specified_nt =
FALSE;
113 double nt_scale = -1.;
114 int specified_nt_scale =
FALSE;
123 double crnt = 80.0e-9;
124 double samplitude = -1.;
126 double sdelay = 10.0;
127 double sduration = 50.0;
130 int isource, jsource;
131 isource = jsource = -1;
136 int specified_pz =
FALSE;
138 iprobe = jprobe = -1;
142 int opt_global_kappa =
FALSE;
143 double alpha_so = 0.218;
144 double theta_so = 0.447;
145 double kappa_so = 0.0;
146 double alpha_sp = 0.2;
147 double theta_sp = 0.4;
148 double kappa_sp = 0.0;
149 double alpha_sr = 0.218;
150 double theta_sr = 0.447;
151 double kappa_sr = 0.0;
152 double kappa_outside = 0.0;
153 int specified_kappa_outside =
FALSE;
154 double dstar_so, dstar_sp, dstar_sr, dstar_max;
155 dstar_so = dstar_sp = dstar_sr = dstar_max = -1.;
157 double dfree = 1.24e-09;
163 double *alphas = NULL;
167 int opt_output_conc_image =
FALSE;
168 double image_spacing = 1.;
169 char imagebasename[FILENAME_MAX-32];
170 memset(imagebasename,
'\0', FILENAME_MAX-32);
179 more_sources.
source = NULL;
187 mse_rti_params.
nt = -1;
188 mse_rti_params.
spdist = -1.;
190 mse_rti_params.
sdelay = -1.;
192 mse_rti_params.
kappa = -1.;
193 mse_rti_params.
dfree = -1.;
194 mse_rti_params.
alpha = -1.;
195 mse_rti_params.
theta = -1.;
197 mse_rti_params.
t = NULL;
203 double alpha_start = 0.2;
204 double theta_start = 0.4;
205 double alpha_fit = -1.;
206 double theta_fit = -1.;
208 gsl_vector *steps = NULL;
209 gsl_vector *simplex = NULL;
210 double alpha_step = 0.1;
211 double theta_step = 0.2;
212 const gsl_multimin_fminimizer_type *fit_algorithm =
213 gsl_multimin_fminimizer_nmsimplex;
214 gsl_multimin_fminimizer *fit_state = NULL;
215 gsl_multimin_function fit_func;
219 double fit_size = -1.;
220 double fit_tol = 1.e-4;
224 start_time = time(NULL);
237 if ((argc < 2) || (argv[argc-1][0] ==
'-'))
250 if ((file_ptr = fopen(infilename,
"r")) == NULL) {
251 fprintf(stderr,
"Error opening input file %s\n", infilename);
263 linelength = strlen(
string);
267 if (
string[0] ==
'#') {
269 fprintf(stderr,
"Warning: Maximum # of comment lines " 270 "exceeded.\nWill not copy more comment lines to " 271 "the output file.\n");
273 strcpy(comments.line[comments.n],
string);
276 }
else if (linelength < 3) {
280 fprintf(stderr,
"Warning: Line %d seems to be too long\n", i+1);
284 if (fscanf(file_ptr,
"%*[^\n] %[\n]", &junk_char) == EOF)
285 error(
"fscanf returned EOF");
288 if (sscanf(
string,
"%s = %s", parameter, value) == EOF)
289 error(
"scanf returned EOF");
290 if (
STREQ(parameter,
"dfree")) {
298 if (dfree > 0.01) dfree *= 1e-9;
300 if (
STREQ(parameter,
"trn")) trn = atof(value);
301 if (
STREQ(parameter,
"current")) {
305 if (
STREQ(parameter,
"delay")) sdelay = atof(value);
306 if (
STREQ(parameter,
"duration")) sduration = atof(value);
307 if (
STREQ(parameter,
"source_z")) {
311 error(
"source_z = %f microns but should be 0 " 312 "(or not specified in the output file)", sz);
314 if (
STREQ(parameter,
"probe_z")) {
319 if (
STREQ(parameter,
"probe_r")) {
323 if (
STREQ(parameter,
"nolayer")) nolayer = atoi(value);
324 if (
STREQ(parameter,
"lz1")) {
326 specified_lz1 =
TRUE;
329 if (
STREQ(parameter,
"lz2")) {
331 specified_lz2 =
TRUE;
334 if (
STREQ(parameter,
"ez1")) {
336 specified_ez1 =
TRUE;
339 if (
STREQ(parameter,
"ez2")) {
341 specified_ez2 =
TRUE;
344 if (
STREQ(parameter,
"alpha_so")) alpha_so = atof(value);
345 if (
STREQ(parameter,
"alpha_sp")) alpha_sp = atof(value);
346 if (
STREQ(parameter,
"alpha_sr")) alpha_sr = atof(value);
347 if (
STREQ(parameter,
"theta_so")) theta_so = atof(value);
348 if (
STREQ(parameter,
"theta_sp")) theta_sp = atof(value);
349 if (
STREQ(parameter,
"theta_sr")) theta_sr = atof(value);
350 if (
STREQ(parameter,
"kappa_so")) kappa_so = atof(value);
351 if (
STREQ(parameter,
"kappa_sp")) kappa_sp = atof(value);
352 if (
STREQ(parameter,
"kappa_sr")) kappa_sr = atof(value);
353 if (
STREQ(parameter,
"nt")) {
357 if (
STREQ(parameter,
"nt_scale")) {
358 nt_scale = atof(value);
359 specified_nt_scale =
TRUE;
361 if (
STREQ(parameter,
"nr")) nr = atoi(value);
362 if (
STREQ(parameter,
"nz")) nz = atoi(value);
363 if (
STREQ(parameter,
"rmax")) {
367 if (
STREQ(parameter,
"zmax")) {
370 specified_zmax =
TRUE;
372 if (
STREQ(parameter,
"tmax")) tmax = atof(value);
384 static struct option long_opts[] = {
385 {
"help", no_argument, NULL,
'h'},
386 {
"verbose", no_argument, NULL,
'v'},
387 {
"global_kappa", no_argument, NULL,
'g'},
388 {
"nr", required_argument, NULL, 0},
389 {
"nz", required_argument, NULL, 0},
390 {
"nt", required_argument, NULL, 0},
391 {
"nt_scale", required_argument, NULL, 0},
392 {
"probe_z", required_argument, NULL, 0},
393 {
"probe_r", required_argument, NULL, 0},
394 {
"ez1", required_argument, NULL, 0},
395 {
"ez2", required_argument, NULL, 0},
396 {
"alpha_so", required_argument, NULL, 0},
397 {
"alpha_sp", required_argument, NULL, 0},
398 {
"alpha_sr", required_argument, NULL, 0},
399 {
"theta_so", required_argument, NULL, 0},
400 {
"theta_sp", required_argument, NULL, 0},
401 {
"theta_sr", required_argument, NULL, 0},
402 {
"kappa_so", required_argument, NULL, 0},
403 {
"kappa_sp", required_argument, NULL, 0},
404 {
"kappa_sr", required_argument, NULL, 0},
405 {
"kappa_outside", required_argument, NULL, 0},
406 {
"alpha_start", required_argument, NULL, 0},
407 {
"theta_start", required_argument, NULL, 0},
408 {
"alpha_step", required_argument, NULL, 0},
409 {
"theta_step", required_argument, NULL, 0},
410 {
"tmax", required_argument, NULL, 0},
411 {
"fit_tol", required_argument, NULL, 0},
412 {
"itermax", required_argument, NULL, 0},
413 {
"outfile", required_argument, NULL, 0},
414 {
"pathfile", required_argument, NULL, 0},
415 {
"images", required_argument, NULL, 0},
416 {
"image_spacing", required_argument, NULL, 0},
417 {
"additional_sources", required_argument, NULL, 0},
418 {NULL, no_argument, NULL, 0}
421 while ((opt = getopt_long(argc, argv,
"hvg",
422 long_opts, &opt_index)) != -1) {
434 opt_global_kappa =
TRUE;
438 if (
STREQ(
"nr", long_opts[opt_index].name)) {
440 }
else if (
STREQ(
"nz", long_opts[opt_index].name)) {
442 }
else if (
STREQ(
"nt", long_opts[opt_index].name)) {
445 }
else if (
STREQ(
"nt_scale", long_opts[opt_index].name)) {
446 nt_scale = atof(optarg);
447 specified_nt_scale =
TRUE;
448 }
else if (
STREQ(
"probe_z", long_opts[opt_index].name)) {
452 }
else if (
STREQ(
"probe_r", long_opts[opt_index].name)) {
455 }
else if (
STREQ(
"ez1", long_opts[opt_index].name)) {
457 specified_ez1 =
TRUE;
459 }
else if (
STREQ(
"ez2", long_opts[opt_index].name)) {
461 specified_ez2 =
TRUE;
463 }
else if (
STREQ(
"alpha_so", long_opts[opt_index].name)) {
464 alpha_so = atof(optarg);
465 }
else if (
STREQ(
"alpha_sp", long_opts[opt_index].name)) {
466 alpha_sp = atof(optarg);
467 }
else if (
STREQ(
"alpha_sr", long_opts[opt_index].name)) {
468 alpha_sr = atof(optarg);
469 }
else if (
STREQ(
"theta_so", long_opts[opt_index].name)) {
470 theta_so = atof(optarg);
471 }
else if (
STREQ(
"theta_sp", long_opts[opt_index].name)) {
472 theta_sp = atof(optarg);
473 }
else if (
STREQ(
"theta_sr", long_opts[opt_index].name)) {
474 theta_sr = atof(optarg);
475 }
else if (
STREQ(
"kappa_so", long_opts[opt_index].name)) {
476 kappa_so = atof(optarg);
477 }
else if (
STREQ(
"kappa_sp", long_opts[opt_index].name)) {
478 kappa_sp = atof(optarg);
479 }
else if (
STREQ(
"kappa_sr", long_opts[opt_index].name)) {
480 kappa_sr = atof(optarg);
481 }
else if (
STREQ(
"kappa_outside", long_opts[opt_index].name)) {
482 kappa_outside = atof(optarg);
483 specified_kappa_outside =
TRUE;
484 }
else if (
STREQ(
"alpha_start", long_opts[opt_index].name)) {
485 alpha_start = atof(optarg);
486 }
else if (
STREQ(
"theta_start", long_opts[opt_index].name)) {
487 theta_start = atof(optarg);
488 }
else if (
STREQ(
"alpha_step", long_opts[opt_index].name)) {
489 alpha_step = atof(optarg);
490 }
else if (
STREQ(
"theta_step", long_opts[opt_index].name)) {
491 theta_step = atof(optarg);
492 }
else if (
STREQ(
"tmax", long_opts[opt_index].name)) {
494 }
else if (
STREQ(
"fit_tol", long_opts[opt_index].name)) {
495 fit_tol = atof(optarg);
496 }
else if (
STREQ(
"itermax", long_opts[opt_index].name)) {
497 itermax = atoi(optarg);
498 }
else if (
STREQ(
"outfile", long_opts[opt_index].name)) {
500 }
else if (
STREQ(
"pathfile", long_opts[opt_index].name)) {
503 }
else if (
STREQ(
"images", long_opts[opt_index].name)) {
505 opt_output_conc_image =
TRUE;
506 }
else if (
STREQ(
"image_spacing", long_opts[opt_index].name)) {
507 image_spacing = atof(optarg);
508 }
else if (
STREQ(
"additional_sources", long_opts[opt_index].name)) {
510 strcpy(additional_sources_string, optarg);
512 error(
"additional_sources_string is too long");
514 token = strtok(additional_sources_string,
" ,");
515 more_sources.
n = atoi(token);
517 if (more_sources.
n > 0) {
521 if (more_sources.
source == NULL)
522 error(
"Cannot allocate memory for more_sources");
524 for (nsource = 0; nsource < more_sources.
n; nsource++) {
537 error(
"Missing argument for a command-line option '-%c'",
542 error(
"Unknown command line option '-%c'", optopt);
546 error(
"Problem in parsing command line options");
553 num_args_left = argc - optind;
554 if ((num_args_left != 1) || opt_help)
559 printf(
"The name of the input file is %s\n", infilename);
560 printf(
"The name of the output file will be %s\n", outfilename);
562 printf(
"The name of the simplex path file will be %s\n",
567 if (
STREQ(infilename, outfilename))
568 error(
"The input and output filenames cannot be the same.");
569 if (
STREQ(infilename, pathfilename))
570 error(
"The input and simplex path filenames cannot be the same.");
571 if (
STREQ(outfilename, pathfilename))
572 error(
"The output and simplex path filenames cannot be the same.");
574 if (specified_ez1 && !specified_ez2)
575 error(
"You specified ez1 but did not specify ez2");
576 if (specified_ez2 && !specified_ez1)
577 error(
"You specified ez2 but did not specify ez1");
578 if (specified_ez1 && specified_zmax)
579 error(
"You specified ez1 and ez2, so you should not specify zmax");
582 if (ez1 > 0)
error(
"Bottom of cylinder ez1 = %f > 0\n", ez1);
583 if (ez2 < 0)
error(
"Top of cylinder ez2 = %f < 0\n", ez2);
584 if (ez1 > lz1)
error(
"Bottom of cylinder ez1 = %f > lz1 = %f\n",
586 if (ez2 < lz2)
error(
"Top of cylinder ez2 = %f < lz2 = %f\n",
592 if (specified_pz ==
FALSE) {
595 printf(
"Warning: probe location set to default value of %g m = " 596 "%f microns\n (relative to source)",
600 if (specified_lz1 ==
FALSE) {
601 lz1 = - 50.0e-6 / 2.0;
603 printf(
"Warning: lz1 set to default value of %g m = " 604 "%f microns\n (relative to source)",
608 if (specified_lz2 ==
FALSE) {
611 printf(
"Warning: lz2 set to default value of %g m = " 612 "%f microns\n (relative to source)",
617 if (specified_kappa_outside) {
618 kappa_sr = kappa_outside;
619 kappa_so = kappa_outside;
620 if (opt_global_kappa) {
621 error(
"You've specified both global kappa and kappa_outside.\n" 622 "The global kappa option sets kappa_so and kappa_sr to kappa_sp.\n" 623 "When you specify kappa_outside, kappa_so and kappa_sr are set \n" 642 printf(
"\nNOTE: nolayer option given; the diffusion " 643 "parameters of \nthe homogeneous environment " 644 "are set to the SR values\n");
648 if (opt_global_kappa) {
652 printf(
"NOTE: kappa will be the same in all layers (-g)\n" 653 "kappa_sr and kappa_so set to kappa_sp\n");
678 coord_shift = (-ez1);
680 coord_shift = (zmax - (lz1+lz2))/2.;
690 if (fabs(dr - dz) > 1.0e-15) {
695 sz = round(sz / dz) * dz;
696 pz = round(pz / dz) * dz;
697 pr = round(pr / dr) * dr;
700 iz1 = (int) round((lz1 / dz));
701 lz1 = iz1 * dz + dz / 2.0;
703 iz2 = (int) round((lz2 / dz));
704 lz2 = iz2 * dz + dz / 2.0;
708 dstar_so = theta_so * dfree;
709 dstar_sp = theta_sp * dfree;
710 dstar_sr = theta_sr * dfree;
711 dstar_max =
MAX(dstar_so, dstar_sp);
712 dstar_max =
MAX(dstar_max, dstar_sr);
716 if ( ((iz2 - iz1) < 2) && (nolayer == 0) )
717 error(
"Layer has too few discrete steps to continue.");
720 if (specified_nt ==
TRUE)
723 dt = 0.9 * dr*dr / (6.0 * dstar_max);
726 if (specified_nt_scale ==
TRUE) {
728 if (nt_scale < 0.)
error(
"nt_scale < 0");
733 nt = lround(tmax / dt);
735 ns = lround(sduration / dt);
737 nds = lround(sdelay / dt);
741 error(
"Source delay (%f) should be < tmax (%f)", sdelay, tmax);
742 if (sduration >= tmax)
743 error(
"Source duration (%f) should be < tmax (%f)", sduration, tmax);
744 if (sdelay+sduration >= tmax)
745 error(
"Source delay (%f) + duration (%f) should be < tmax (%f)",
746 sdelay, sduration, tmax);
750 samplitude = crnt * trn /
FARADAY;
757 printf(
"\nIn main(): The command used was\n\t%s\n(%d words)\n\n",
758 comments.command, i);
766 printf(
"Output from 3layer.c, version %.1f:\n", program_version);
767 printf(
"Note that the z-values (sz, pz, lz1, and lz2) have been shifted \n");
768 printf(
"by %f microns to center the SP layer in the volume.\n",
770 printf(
"nr x nz = %d x %d\n", nr, nz);
771 printf(
"rmax x zmax = %f x %f microns\n", 1.0e6 * rmax, 1.0e6 * zmax);
772 printf(
"dr x dz = %f x %f microns\n", 1.0e6 * dr, 1.0e6 * dz);
773 printf(
"(sr, sz) = (%f, %f) microns\n", 1.0e6 * sr, 1.0e6 * sz);
774 printf(
"(pr, pz) = (%f, %f) microns\n", 1.0e6 * pr, 1.0e6 * pz);
775 printf(
"Electrode distance = %f microns\n",
776 1.0e6 * sqrt(
SQR(pr-sr) +
SQR(pz-sz)));
777 printf(
"(iz1, iz2) = (%d, %d)\n", iz1, iz2);
778 printf(
"(lz1, lz2) = (%f, %f) microns\n", 1.0e6 * lz1, 1.0e6 * lz2);
779 printf(
"Layer thickness = %f microns\n", 1.0e6 * (lz2 - lz1));
780 printf(
"Layer discrete steps = %d\n", iz2 - iz1);
781 printf(
"Nolayer flag = %d\n" , nolayer);
782 printf(
"dfree = %g m^2/s\n", dfree);
783 printf(
"alpha_so = %.4f, theta_so = %.4f, " 784 "lambda_so = %.4f, kappa_so = %.6f\n",
785 alpha_so, theta_so, 1.0/sqrt(theta_so), kappa_so);
786 printf(
"alpha_sp = %.4f, theta_sp = %.4f, " 787 "lambda_sp = %.4f, kappa_sp = %.6f\n",
788 alpha_sp, theta_sp, 1.0/sqrt(theta_sp), kappa_sp);
789 printf(
"alpha_sr = %.4f, theta_sr = %.4f, " 790 "lambda_sr = %.4f, kappa_sr = %.6f\n",
791 alpha_sr, theta_sr, 1.0/sqrt(theta_sr), kappa_sr);
792 if (opt_global_kappa)
793 printf(
"NOTE: kappa_sr and kappa_so set to kappa_sp (-g)\n");
794 printf(
"nt = %d\n", nt);
795 printf(
"tmax = %f s\n", tmax);
796 printf(
"dt = %f ms\n", 1.0e3 * dt);
797 printf(
"von Neumann dt / (dr^2/(6*dstar)) = %f\n",
798 dt * 6.0 * dstar_max / (dr*dr));
799 printf(
"ns = %d\n", ns);
800 printf(
"source delay sdelay = %f s\n", sdelay);
801 printf(
"source duration sduration = %f s\n", sduration);
802 printf(
"Current = %g nA\n", 1.0e9 * crnt);
803 printf(
"Transport number = %f\n", trn);
804 printf(
"Start time = %s",
string);
809 if ((file_ptr = fopen(outfilename,
"w")) == NULL) {
810 fprintf(stderr,
"Error opening output file %s\n", outfilename);
815 fprintf(file_ptr,
"# 3layer Output File\n");
816 fprintf(file_ptr,
"# ~~~~~~~~~~~~~~~~~~\n");
817 fprintf(file_ptr,
"# Command used to run program:\n");
818 fprintf(file_ptr,
"# %s\n", comments.command);
821 if (comments.n > 0) {
822 fprintf(file_ptr,
"# --------------------------------------\n");
823 fprintf(file_ptr,
"# Comments from input parameter file:\n");
824 for (j=0; j<comments.n; j++)
825 fprintf(file_ptr,
"%s", comments.line[j]);
826 fprintf(file_ptr,
"# --------------------------------------\n");
831 fprintf(file_ptr,
"# Output from 3layer.c, version %.1f:\n", program_version);
832 fprintf(file_ptr,
"# Note that the z-values (sz, pz, lz1, and lz2) ");
833 fprintf(file_ptr,
"have been shifted \n# by %f microns ", 1.0e6*coord_shift);
835 fprintf(file_ptr,
"to have the volume go from z=0 to z=zmax.\n");
837 fprintf(file_ptr,
"to center the SP layer in the volume.\n");
839 fprintf(file_ptr,
"# nr x nz = %d x %d\n", nr, nz);
840 fprintf(file_ptr,
"# rmax x zmax = %f x %f microns\n", 1.0e6 * rmax, 1.0e6 * zmax);
841 fprintf(file_ptr,
"# dr x dz = %f x %f microns\n", 1.0e6 * dr, 1.0e6 * dz);
842 fprintf(file_ptr,
"# (sr, sz) = (%f, %f) microns\n", 1.0e6 * sr, 1.0e6 * sz);
843 fprintf(file_ptr,
"# (pr, pz) = (%f, %f) microns\n", 1.0e6 * pr, 1.0e6 * pz);
844 fprintf(file_ptr,
"# Electrode distance = %f microns\n",
845 1.0e6 * sqrt(
SQR(pr-sr) +
SQR(pz-sz)));
846 fprintf(file_ptr,
"# (iz1, iz2) = (%d, %d)\n", iz1, iz2);
847 fprintf(file_ptr,
"# (lz1, lz2) = (%f, %f) microns\n", 1.0e6 * lz1, 1.0e6 * lz2);
848 fprintf(file_ptr,
"# Layer thickness = %f microns\n", 1.0e6 * (lz2 - lz1));
849 fprintf(file_ptr,
"# Layer discrete steps = %d\n", iz2 - iz1);
850 fprintf(file_ptr,
"# Nolayer flag = %d\n" , nolayer);
851 fprintf(file_ptr,
"# dfree = %g m^2/s\n", dfree);
852 fprintf(file_ptr,
"# alpha_so = %.4f, theta_so = %.4f, " 853 "lambda_so = %.4f, kappa_so = %.6f\n",
854 alpha_so, theta_so, 1.0/sqrt(theta_so), kappa_so);
855 fprintf(file_ptr,
"# alpha_sp = %.4f, theta_sp = %.4f, " 856 "lambda_sp = %.4f, kappa_sp = %.6f\n",
857 alpha_sp, theta_sp, 1.0/sqrt(theta_sp), kappa_sp);
858 fprintf(file_ptr,
"# alpha_sr = %.4f, theta_sr = %.4f, " 859 "lambda_sr = %.4f, kappa_sr = %.6f\n",
860 alpha_sr, theta_sr, 1.0/sqrt(theta_sr), kappa_sr);
861 if (opt_global_kappa)
862 fprintf(file_ptr,
"# NOTE: kappa_sr and kappa_so set to kappa_sp (-g)\n");
863 fprintf(file_ptr,
"# nt = %d\n", nt);
864 fprintf(file_ptr,
"# tmax = %f s\n", tmax);
865 fprintf(file_ptr,
"# dt = %f ms\n", 1.0e3 * dt);
866 fprintf(file_ptr,
"# von Neumann dt / (dr^2/(6*dstar)) = %f\n",
867 dt * 6.0 * dstar_max / (dr*dr));
868 fprintf(file_ptr,
"# ns = %d\n", ns);
869 fprintf(file_ptr,
"# Source delay sdelay = %f s\n", sdelay);
870 fprintf(file_ptr,
"# Source duration sduration = %f s\n", sduration);
871 fprintf(file_ptr,
"# Current = %g nA\n", 1.0e9 * crnt);
872 fprintf(file_ptr,
"# Transport number = %f\n", trn);
873 if (more_sources.
n > 0) {
874 fprintf(file_ptr,
"# Number of extra sources = %d\n", more_sources.
n);
875 for (nsource = 0; nsource < more_sources.
n; nsource++)
876 fprintf(file_ptr,
"# Additional source #%d: \n" 877 "#\tsz = %lf microns, sr = %lf microns, crnt = %lf nA\n",
879 1.0e6 * (more_sources.
source[nsource].
sz + coord_shift),
880 1.0e6 * more_sources.
source[nsource].
sr,
883 fprintf(file_ptr,
"# Start time = %s",
string);
891 for (j=0; j<nr+1; j++) {
892 for (i=0; i<iz1+1; i++) alphas[
INDEX(i,j)] = alpha_sr;
893 for (i=iz1+1; i<iz2+1; i++) alphas[
INDEX(i,j)] = alpha_sp;
894 for (i=iz2+1; i<nz; i++) alphas[
INDEX(i,j)] = alpha_so;
903 for (j=2; j<nr+1; j++) {
904 invr[j] = 1.0 / ((j-1.)*dr);
910 isource = lround(sz/dz);
911 jsource = 1+lround(sr/dr);
912 s[
INDEX(isource,jsource)]
913 = (1.0 / alphas[
INDEX(isource,jsource)]) *
914 samplitude * dt * 4.0 / (
PI *
SQR(dr) * dz);
917 if (more_sources.
n > 0) {
918 for (nsource = 0; nsource < more_sources.
n; nsource++) {
919 new_source.
sz = more_sources.
source[nsource].
sz;
920 new_source.
sr = more_sources.
source[nsource].
sr;
923 new_source.
sz += coord_shift;
925 isource = lround((new_source.
sz)/dz);
926 jsource = 1+lround(new_source.
sr/dr);
930 error(
"adding additional source %d; isource = %d < 0",
933 error(
"adding additional source %d; isource = %d > nz-1",
936 error(
"adding additional source %d; jsource = %d < 0",
939 error(
"adding additional source %d; jsource = %d > nr",
942 s[
INDEX(isource,jsource)]
943 += (1.0 / alphas[
INDEX(isource,jsource)]) *
944 samplitude * dt * 4.0 / (
PI *
SQR(dr) * dz);
955 iprobe = lround(pz/dz);
956 jprobe = 1+lround(pr/dr);
962 printf(
"About to calculate diffusion curve\n");
966 if (! opt_output_conc_image)
973 iz1, iz2, nolayer, dt, dr, sdelay, sduration,
974 alpha_so, theta_so, kappa_so,
975 alpha_sp, theta_sp, kappa_sp,
976 alpha_sr, theta_sr, kappa_sr,
978 imagebasename, image_spacing,
992 printf(
"\nFitting for apparent parameters/characteristic curve:\n");
993 printf(
"Iter\talpha_fit\ttheta_fit\tmse \tfit size\n");
994 printf(
"%d\t%f\t%f\n",
995 0, alpha_start, theta_start);
999 if ((pathfile_ptr = fopen(pathfilename,
"w")) == NULL) {
1000 fprintf(stderr,
"Error opening simplex path file %s\n",
1004 fprintf(pathfile_ptr,
"\nFitting for apparent parameters/characteristic curve:\n");
1005 fprintf(pathfile_ptr,
1006 "Iter\talpha_fit\ttheta_fit\tmse \tfit size\n");
1007 fprintf(pathfile_ptr,
"%d\t%f\t%f\n",
1008 0, alpha_start, theta_start);
1013 spdist = sqrt(
SQR(pr-sr) +
SQR(pz-sz));
1014 mse_rti_params.
nt = nt;
1015 mse_rti_params.
spdist = spdist;
1017 mse_rti_params.
sdelay = sdelay;
1019 mse_rti_params.
kappa = 0.;
1020 mse_rti_params.
dfree = dfree;
1025 for (k=0; k<nt; k++) {
1026 mse_rti_params.
t[k] = t[k];
1027 mse_rti_params.
p_model[k] = p[k];
1032 simplex = gsl_vector_alloc(2);
1033 gsl_vector_set(simplex, 0, alpha_start);
1034 gsl_vector_set(simplex, 1, theta_start);
1037 steps = gsl_vector_alloc(2);
1038 gsl_vector_set(steps, 0, alpha_step);
1039 gsl_vector_set(steps, 1, theta_step);
1044 fit_func.params = &mse_rti_params;
1046 fit_state = gsl_multimin_fminimizer_alloc(fit_algorithm, 2);
1047 gsl_multimin_fminimizer_set(fit_state, &fit_func, simplex, steps);
1051 fit_status = gsl_multimin_fminimizer_iterate(fit_state);
1053 if (fit_status)
break;
1055 fit_size = gsl_multimin_fminimizer_size(fit_state);
1056 fit_status = gsl_multimin_test_size(fit_size, fit_tol);
1059 if (fit_status == GSL_SUCCESS) printf(
"Finished fit\n");
1061 alpha_fit = gsl_vector_get(fit_state->x, 0);
1062 theta_fit = gsl_vector_get(fit_state->x, 1);
1063 mse = fit_state->fval;
1066 printf(
"%d\t%f\t%f\t%g\t%g\n",
1067 (
int) fit_iter, alpha_fit, theta_fit, mse, fit_size);
1070 fprintf(pathfile_ptr,
"%d\t%f\t%f\t%g\t%g\n",
1071 (
int) fit_iter, alpha_fit, theta_fit, mse, fit_size);
1073 }
while (fit_status == GSL_CONTINUE && fit_iter < itermax);
1075 if (fit_status != GSL_SUCCESS) {
1076 printf(
"Warning: failed to converge, status = %d, " 1077 "# iterations = %zd\n", fit_status, fit_iter);
1079 fprintf(pathfile_ptr,
"Warning: failed to converge, " 1080 "status = %d, # iterations = %zd\n", fit_status, fit_iter);
1084 fclose(pathfile_ptr);
1086 double lambda_fit = 1./sqrt(theta_fit);
1088 printf(
"Fitted alpha = %f\n", alpha_fit);
1089 printf(
"Fitted theta = %f (lambda = %f)\n",
1090 theta_fit, lambda_fit);
1095 end_time = time(NULL);
1098 printf(
"End time = %s",
string);
1100 total_time = difftime(end_time, start_time);
1102 printf(
"Total time = %d seconds = %f minutes = %f hours\n",
1103 (
int) round(total_time), total_time/60., total_time/3600.);
1108 if ((file_ptr = fopen(outfilename,
"a")) == NULL) {
1109 fprintf(stderr,
"Error opening output file %s\n", outfilename);
1113 fprintf(file_ptr,
"# End time = %s",
string);
1114 fprintf(file_ptr,
"# Total time = %d seconds = %f minutes = %f hours\n",
1115 (
int) round(total_time), total_time/60., total_time/3600.);
1116 fprintf(file_ptr,
"# --------------------------------------\n");
1117 fprintf(file_ptr,
"# Fit for characteristic curve:\n");
1118 fprintf(file_ptr,
"# Number of iterations = %d\n", (
int)fit_iter);
1119 fprintf(file_ptr,
"# Fitted apparent alpha = %f\n", alpha_fit);
1120 fprintf(file_ptr,
"# Fitted apparent theta = %f (lambda = %f)\n",
1121 theta_fit, lambda_fit);
1122 fprintf(file_ptr,
"# Final mean squared error = %g\n", mse);
1123 fprintf(file_ptr,
"# Final simplex size = %g\n", fit_size);
1124 fprintf(file_ptr,
"# Solution: apparent alpha\tapparent theta\t" 1125 "apparent lambda\t MSE\tsimplex size\t# iter." 1126 "\tTime (s)\tTime (m)\tTime (h) \n");
1127 fprintf(file_ptr,
"# Solution: %f\t%f\t%f\t%f\t%g \t%7d\t%8d\t%f\t%f\n",
1128 alpha_fit, theta_fit, lambda_fit, mse, fit_size, (
int) fit_iter,
1129 (
int) round(total_time), total_time/60., total_time/3600.);
1130 fprintf(file_ptr,
"# --------------------------------------\n");
1131 fprintf(file_ptr,
"# Probe concentration data:\n");
1132 fprintf(file_ptr,
"# time \t c (3-layer model) \t c (characteristic curve) \n");
1137 for (i=0; i<1000; i++) {
1138 k = (i * nt) / 1000;
1139 fprintf(file_ptr,
"%#12.8g\t%#12.8g\t%#12.8g\n",
1140 t[k], p[k], mse_rti_params.
p_theory[k]);
1143 for (i=0; i<nt; i++) {
1144 fprintf(file_ptr,
"%#12.8g\t%#12.8g\t%#12.8g\n",
1145 t[i], p[i], mse_rti_params.
p_theory[i]);
1147 fprintf(file_ptr,
"\n");
1161 free(mse_rti_params.
t);
1165 gsl_vector_free(simplex);
1166 gsl_vector_free(steps);
1167 gsl_multimin_fminimizer_free(fit_state);
1170 printf(
"All done\n");
1172 return(EXIT_SUCCESS);
int n
Number of additional sources.
double sr
r-coordinate of additional source
double * p_theory
Probe concentration from homogeneous model (characteristic curve)
double sduration
Duration of source.
double kappa
Nonspecific clearance factor.
double sdelay
Source delay (time before source starts)
int main(int argc, char *argv[])
Main program.
double * p_model
Probe concentration from multilayer model.
double sz
z-coordinate of additional source
double samplitude
Amplitude of source.
double dfree
Free diffusion coefficient.
double spdist
Distance between source and probe.
source_struct_type * source
Struct of parameters for each additional source.
double alpha
Extracellular volume fraction.
double crnt
Current of additional source.
double theta
Permeability.
int nt
Number of time points of calculation.