sandbox/acastillo/filaments/filaments.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    
    struct vortex_filament{
      int     n_seg;
      double  a;
      double* t;
      coord*  c;
      coord*  tvec;
      coord*  nvec;
      coord*  bvec;
      coord   pcar;
    };
    
    void draw_space_curve(int n, coord *p){
      for (int i = 0; i < n-1; i++){
        glBegin(GL_LINES);
          glVertex3f(p[i  ].x, p[i  ].y, p[i  ].z);
          glVertex3f(p[i+1].x, p[i+1].y, p[i+1].z);
        glEnd();
      }
    }
    
    void fd_derivative( int n, double delta_t0, coord shift, coord *X, coord *dX){
      for (int i = 1; i < n-1; i++){
        foreach_dimension()
        dX[i].x = (X[i+1].x - X[i-1].x)/(2*delta_t0);
      }
      foreach_dimension(){
        dX[0].x   = (X[1].x - X[n-2].x + shift.x)/(2*delta_t0);
        dX[n-1].x = (X[1].x - X[n-2].x + shift.x)/(2*delta_t0);
      }
    }
    
    #include <gsl/gsl_spline.h>
    #pragma autolink -lgsl -lgslcblas
    
    coord gsl_interp1d( int n, double* t0, coord * P0, double tq){
      coord Pq;
      gsl_interp_accel *acc = gsl_interp_accel_alloc();
    
      foreach_dimension(){
        double *P_x;
        P_x = malloc(sizeof(double)*n);
    
        for (int i = 0; i < n; i++)
          P_x[i] = P0[i].x;
        gsl_spline *spline_x = gsl_spline_alloc(gsl_interp_cspline, n);
        gsl_spline_init(spline_x, t0, P_x, n);
        Pq.x = gsl_spline_eval (spline_x, tq, acc);
        gsl_spline_free (spline_x);
    
        free(P_x);
      }
      gsl_interp_accel_free (acc);
      return Pq;
    }
    
    double frenet_projection (double pos, void *params){
      struct vortex_filament *p = (struct vortex_filament *) params;
    
      int n_seg = p->n_seg;
      double* t   = p->t;
      coord*  c   = p->c;
      coord*  tvec = p->tvec;
      coord*  nvec = p->nvec;
      coord*  bvec = p->bvec;
      coord   pcar = p->pcar;
    
      coord ccar, frenet[3];
      ccar = gsl_interp1d( n_seg, t, c, pos);
    
      frenet[0] = gsl_interp1d( n_seg, t, tvec, pos);
      frenet[1] = gsl_interp1d( n_seg, t, nvec, pos);
      frenet[2] = gsl_interp1d( n_seg, t, bvec, pos);
    
      return vecdot(vecdiff(pcar, ccar), frenet[0]);
    }
    
    #include <gsl/gsl_roots.h>
    #include <gsl/gsl_errno.h>
    double frenet_projection_min ( int n_seg, double as, double* t0, coord* c, coord* tvec, coord* nvec, coord* bvec, coord pcar, double r){
      struct vortex_filament params = {n_seg, as, t0, c, tvec, nvec, bvec, pcar};
    
      int status, verbose = 0;
      int iter = 0, max_iter = 100;
      const gsl_root_fsolver_type *T;
      gsl_root_fsolver *s;
    
      double x_lo = r - 0.25, x_hi = r + 0.25;
      gsl_function F;
    
      F.function = &frenet_projection;
      F.params = &params;
    
      T = gsl_root_fsolver_brent;
      s = gsl_root_fsolver_alloc (T);
      gsl_set_error_handler_off();
      gsl_root_fsolver_set (s, &F, x_lo, x_hi);
    
      if (verbose == 1) {
        printf ("using %s method\n", gsl_root_fsolver_name (s));
        printf ("%5s [%9s, %9s] %9s %10s %9s\n", "iter", "lower", "upper", "root", "err", "err(est)");
      }
    
      do {
        iter++;
        status = gsl_root_fsolver_iterate (s);
        r = gsl_root_fsolver_root (s);
        x_lo = gsl_root_fsolver_x_lower (s);
        x_hi = gsl_root_fsolver_x_upper (s);
        status = gsl_root_test_interval (x_lo, x_hi, 0, 1e-8);
    
        if ((status == GSL_SUCCESS) && (verbose == 1)){
          printf ("Converged:\n");
          printf ("%5d [%.7f, %.7f] %.7f %.7f\n", iter, x_lo, x_hi, r, x_hi - x_lo);
        }
    
      }
      while (status == GSL_CONTINUE && iter < max_iter);
      gsl_root_fsolver_free (s);
    
      return r;
    }