/sode/cfiles/main.c

https://github.com/oscarbenjamin/sode · C · 168 lines · 114 code · 31 blank · 23 comment · 16 complexity · 5136dde24929c0a78120e8572b9e7779 MD5 · raw file

  1. /*
  2. * weiner.c
  3. *
  4. * This file finds numerical solutions of the systems listed in examples but
  5. * implemented in c for speed comparison.
  6. */
  7. #include <stdio.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include <string.h>
  11. /* For generating standard normals. */
  12. #include "randnorm.h"
  13. #include "examples.h"
  14. #include "solvers.h"
  15. /* Struct to hold the data returned by parse_args */
  16. typedef struct InputOptionsStruct {
  17. SysInfo *sysinfo;
  18. double t1;
  19. double t2;
  20. double dtmax;
  21. double dtout;
  22. } InputOptions;
  23. /* Function used to process the command line args. */
  24. #define ARGUMENTS_INVALID 0
  25. #define ARGUMENTS_GOOD 1
  26. int parse_args(int argc, char *argv[], InputOptions *opts);
  27. #define SOLVE_FAILED 0
  28. #define SOLVE_SUCCEEDED 1
  29. int print_sode(InputOptions *opts);
  30. int main(int argc, char *argv[])
  31. {
  32. InputOptions opts;
  33. /* Initialise random seed and prepare for rng generation */
  34. randnorm_seed(RANDNORM_SEED_PID_TIME);
  35. /* Parse the input arguments */
  36. if(parse_args(argc, argv, &opts) == ARGUMENTS_INVALID)
  37. return 1;
  38. /* Actually solve and write the result to stdout */
  39. print_sode(&opts);
  40. return 0;
  41. }
  42. int print_help(int argc, char *argv[], char *errmsg)
  43. {
  44. if(errmsg != NULL)
  45. fprintf(stderr, "%s\n", errmsg);
  46. printf("usage: %s SYSNUM T1 T2 DTMAX DTOUT\n", argv[0]);
  47. printf("\n");
  48. printf("Numerically solve the stochastic ordinary differential\n");
  49. printf("equation representing a Weiner process.\n");
  50. return 0;
  51. }
  52. int invalid_arguments(int argc, char *argv[], char *errmsg) {
  53. print_help(argc, argv, errmsg);
  54. return ARGUMENTS_INVALID;
  55. }
  56. /* Used by main to process the input arguments */
  57. int parse_args(int argc, char *argv[], InputOptions *opts) {
  58. int n;
  59. char *sysstr, *t1str, *t2str, *dtmaxstr, *dtoutstr;
  60. /* Check the number of arguments first */
  61. if(argc != 5 + 1)
  62. return print_help(argc, argv, "Wrong number of arguments");
  63. /* Separate into named strings */
  64. sysstr = argv[1];
  65. t1str = argv[2];
  66. t2str = argv[3];
  67. dtmaxstr = argv[4];
  68. dtoutstr = argv[5];
  69. /* Check for the system name */
  70. opts->sysinfo = NULL;
  71. for(n=0; n<num_systems; n++)
  72. if(!strcmp(example_systems[n].sysname, sysstr))
  73. opts->sysinfo = &example_systems[n];
  74. if(opts->sysinfo == NULL)
  75. return invalid_arguments(argc, argv, "Unrecognised SYSNAME");
  76. /* Parse numeric arguments */
  77. if(!sscanf(t1str, "%lf", &opts->t1))
  78. return invalid_arguments(argc, argv, "Unable to parse T1");
  79. if(!sscanf(t2str, "%lf", &opts->t2))
  80. return invalid_arguments(argc, argv, "Unable to parse T2");
  81. if(!sscanf(dtmaxstr, "%lf", &opts->dtmax))
  82. return invalid_arguments(argc, argv, "Unable to parse DTMAX");
  83. if(!sscanf(dtoutstr, "%lf", &opts->dtout))
  84. return invalid_arguments(argc, argv, "Unable to parse DTOUT");
  85. /* Indicate success */
  86. return ARGUMENTS_GOOD;
  87. }
  88. void outfunc(const double *x, const double t, const size_t nvars)
  89. {
  90. size_t v;
  91. printf("%f", t);
  92. for(v=0; v<nvars; v++)
  93. printf(", %f", x[v]);
  94. printf("\n");
  95. }
  96. /* Solve the equations specified by the user */
  97. int print_sode(InputOptions *opts) {
  98. /* void solve_sode(vecfield drift, vecfield diffusion, size_t nvars,
  99. const double *x0, const double t0,
  100. const double dtmax, const double dtout,
  101. outputvec outfunc) {*/
  102. SysInfo *sys = opts->sysinfo;
  103. solve_sode(sys->drift, sys->diffusion, sys->nvars, sys->x0,
  104. opts->t1, opts->t2, opts->dtmax, opts->dtout, outfunc);
  105. return SOLVE_SUCCEEDED;
  106. }
  107. void sprint_time(char *timestr, size_t max) {
  108. time_t raw_time;
  109. struct tm *timeinfo;
  110. time(&raw_time);
  111. timeinfo = localtime(&raw_time);
  112. strftime(timestr, max, "%a, %d %b %Y %H:%M:%S %z", timeinfo);
  113. }
  114. int print_weiner()
  115. {
  116. double x1=0;
  117. double alpha=0, beta=1;
  118. double t1=0;
  119. double t2=100;
  120. double dt=0.0001;
  121. double sqrtdt = sqrt(dt);
  122. int nsteps=(int) ceil((t2 - t1) / dt);
  123. int i;
  124. double x=x1;
  125. double t=t1;
  126. char timestr[100];
  127. sprint_time(timestr, 100);
  128. printf("# Created by weiner.c at %s\n", timestr);
  129. printf("time, x\n");
  130. printf("%f, %f\n", t1, x1);
  131. for(i=0; i<nsteps; i++) {
  132. x += alpha * dt + beta * sqrtdt * RANDNORM_NORMAL();
  133. t += dt;
  134. printf("%f, %f\n", t, x);
  135. }
  136. return 0;
  137. }