Changeset 2884

Show
Ignore:
Timestamp:
06/09/10 10:08:38 (20 months ago)
Author:
farhi
Message:

Collimator_radial: unactivate collimator when divergence=0

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/nlib/optics/Collimator_radial.comp

    r2733 r2884  
    4646* length:     (m)          Length/Distance between inner and outer slits. 
    4747* divergence: (min of arc) Divergence angle. May also be specified with the 
    48 *                            nslit parameter 
     48*                            nslit parameter. A zero value unactivates component. 
    4949* theta_min:  (deg)        Minimum Theta angle for the radial setting. 
    5050* theta_max:  (deg)        Maximum Theta angle for the radial setting. 
     
    120120   
    121121  if (nslit <= 0) 
    122     exit(printf("Collimator_radial: %s: number of channels must be positive nslit=%g.\n" 
    123                 "                   Specify alternatively divergence, xwidth and nchan.\n",  
    124                 NAME_CURRENT_COMP, nslit)); 
    125    
    126   if (verbose) { 
     122    printf("Collimator_radial: %s: number of channels must be positive nslit=%g.\n" 
     123                "WARNING            Specify alternatively divergence, xwidth and nchan.\n",  
     124                NAME_CURRENT_COMP, nslit); 
     125   
     126  if (verbose && nslit && width_of_slit) { 
    127127    printf("Collimator_radial: %s: divergence %g [min] %s" 
    128128           ". Total opening [%g:%g] [deg]\n", 
     
    148148  double intersect=0; 
    149149  double t0, t1, t2, t3; 
    150   /* determine intersection with inner and outer cylinders */ 
    151   intersect=cylinder_intersect(&t0,&t3,x,y,z,vx,vy,vz,radius,yheight); 
    152   if (!intersect) ABSORB; 
    153   else if (t3 > t0) t0 = t3; 
    154  
    155   intersect=cylinder_intersect(&t1,&t2,x,y,z,vx,vy,vz,radius+length,yheight); 
    156   if (!intersect) ABSORB; 
    157   else if (t2 > t1) t1 = t2; 
    158    
    159   /* propagate/determine neutron position at inner cylinder */ 
    160   if (t0 > 0 && t1 > t0) { 
    161     double input_chan=0; 
    162     double input_theta=0, output_theta=0; 
    163     double roc_theta=0; 
    164     double input_slit=0,  output_slit=0; 
    165      
    166     PROP_DT(t0); 
    167    
    168     /* apply ROC oscillation with a linear random distribution */ 
    169     if (roc) roc_theta = roc*randpm1()/2; else roc_theta=0; 
    170      
    171     /* angle on inner cylinder */ 
    172     input_theta = atan2(x, z) + roc_theta;   
    173      
    174     /* check if we are within min/max collimator input bounds */ 
    175     if (input_theta >= theta_min && input_theta <= theta_max) { 
    176       SCATTER; 
    177       /* input Soller channel index */ 
    178       if (width_of_Soller) { 
    179         input_chan = radius*(input_theta-theta_min)/width_of_Soller; 
    180         input_chan = input_chan-floor(input_chan); /* position within Soller [0:1] */ 
     150   
     151  if (width_of_slit && nslit) { 
     152    /* determine intersection with inner and outer cylinders */ 
     153    intersect=cylinder_intersect(&t0,&t3,x,y,z,vx,vy,vz,radius,yheight); 
     154    if (!intersect) ABSORB; 
     155    else if (t3 > t0) t0 = t3; 
     156 
     157    intersect=cylinder_intersect(&t1,&t2,x,y,z,vx,vy,vz,radius+length,yheight); 
     158    if (!intersect) ABSORB; 
     159    else if (t2 > t1) t1 = t2; 
     160     
     161    /* propagate/determine neutron position at inner cylinder */ 
     162    if (t0 > 0 && t1 > t0) { 
     163      double input_chan=0; 
     164      double input_theta=0, output_theta=0; 
     165      double roc_theta=0; 
     166      double input_slit=0,  output_slit=0; 
     167       
     168      PROP_DT(t0); 
     169     
     170      /* apply ROC oscillation with a linear random distribution */ 
     171      if (roc) roc_theta = roc*randpm1()/2; else roc_theta=0; 
     172       
     173      /* angle on inner cylinder */ 
     174      input_theta = atan2(x, z) + roc_theta;   
     175       
     176      /* check if we are within min/max collimator input bounds */ 
     177      if (input_theta >= theta_min && input_theta <= theta_max) { 
     178        SCATTER; 
     179        /* input Soller channel index */ 
     180        if (width_of_Soller) { 
     181          input_chan = radius*(input_theta-theta_min)/width_of_Soller; 
     182          input_chan = input_chan-floor(input_chan); /* position within Soller [0:1] */ 
     183           
     184          /* check if we hit an absorbing housing (between Sollers): ABSORB 
     185           *   total Soller aperture is width_of_Soller,  
     186           *   containg a slit pack  of aperture xwidth  
     187           */ 
     188          if (input_chan < (1-xwidth/width_of_Soller)/2  
     189           || input_chan > (1+xwidth/width_of_Soller)/2) ABSORB; 
     190        } 
     191 
     192        /* determine input slit index */ 
     193        input_slit = floor(input_theta*radius/width_of_slit); 
    181194         
    182         /* check if we hit an absorbing housing (between Sollers): ABSORB 
    183          *   total Soller aperture is width_of_Soller,  
    184          *   containg a slit pack  of aperture xwidth  
    185          */ 
    186         if (input_chan < (1-xwidth/width_of_Soller)/2  
    187          || input_chan > (1+xwidth/width_of_Soller)/2) ABSORB; 
    188       } 
    189  
    190       /* determine input slit index */ 
    191       input_slit = floor(input_theta*radius/width_of_slit); 
    192        
    193     } else /* neutron missed collimator input range */ 
    194       input_theta=4*PI; 
    195    
    196     /* propagate to outer cylinder */ 
    197     PROP_DT(t1-t0); 
    198      
    199     /* angle on outer cylinder */ 
    200     output_theta = atan2(x, z) + roc_theta; 
    201      
    202     /* check if we are within min/max collimator output bounds */ 
    203     if (output_theta >= theta_min && output_theta <= theta_max) { 
    204       /* check if we come from sides:   ABSORB */ 
    205       if (input_theta > 2*PI) ABSORB; /* input_theta=4*PI when missed input */ 
    206        
    207       if (approx) { 
    208         double phi=atan2(x, z)-atan2(vx, vz); /* difference between positional slit angle and velocity */ 
    209         if (fabs(phi) > divergence)  
    210           ABSORB; /* get outside transmission */ 
    211         else 
    212           p *= (1.0 - phi/divergence); 
    213       } else { 
    214         /* check if we have changed slit: ABSORB */ 
    215         /* slits are considered radial so that their output size is: 
    216            width_of_slit*(radius+length)/radius and it turns out this the same exp as for input 
    217          */ 
    218         output_slit = floor(output_theta*radius/width_of_slit); 
    219         if (input_slit != output_slit) ABSORB; 
    220       } 
    221       SCATTER; 
    222       p *= transmission; 
    223        
    224     } /* else neutron missed collimator output range */ 
    225    
    226   } /* else did not encounter collimator cylinders */ 
     195      } else /* neutron missed collimator input range */ 
     196        input_theta=4*PI; 
     197     
     198      /* propagate to outer cylinder */ 
     199      PROP_DT(t1-t0); 
     200       
     201      /* angle on outer cylinder */ 
     202      output_theta = atan2(x, z) + roc_theta; 
     203       
     204      /* check if we are within min/max collimator output bounds */ 
     205      if (output_theta >= theta_min && output_theta <= theta_max) { 
     206        /* check if we come from sides:   ABSORB */ 
     207        if (input_theta > 2*PI) ABSORB; /* input_theta=4*PI when missed input */ 
     208         
     209        if (approx) { 
     210          double phi=atan2(x, z)-atan2(vx, vz); /* difference between positional slit angle and velocity */ 
     211          if (fabs(phi) > divergence)  
     212            ABSORB; /* get outside transmission */ 
     213          else 
     214            p *= (1.0 - phi/divergence); 
     215        } else { 
     216          /* check if we have changed slit: ABSORB */ 
     217          /* slits are considered radial so that their output size is: 
     218             width_of_slit*(radius+length)/radius and it turns out this the same exp as for input 
     219           */ 
     220          output_slit = floor(output_theta*radius/width_of_slit); 
     221          if (input_slit != output_slit) ABSORB; 
     222        } 
     223        SCATTER; 
     224        p *= transmission; 
     225         
     226      } /* else neutron missed collimator output range */ 
     227     
     228    } /* else did not encounter collimator cylinders */ 
     229  } /* if nslit */ 
    227230 
    228231%}