def radial_differential( fcur, pos): # for lsode
  

    global rd_com, idata, lastgoodf, lastgoodpos, Rpos, Zpos, ood, tol, Ri, Zi, dR, dZ

    out=local_gradient( idata, pos[0], pos[1], status=0, dfdr=0., dfdz=0. )
    status=out.status
    dfdr=out.dfdr[0][0]
    dfdz=out.dfdz[0][0]
    
    ood = 0

    if status ==0 :
    # No error in localgradient.
        lastgoodf = fcur 
        lastgoodpos = pos

    # If status NE 0 then an error occurred.
    # Allow dfdz to cause an error so escape LSODE
    else:
        ood = 1 # Out Of Domain

  #if numpy.size(boundary) > 1 :
  #  # Got a boundary - check for crossings
  #  
  #  cpos , ncross, inds2 = line_crossings([ri0, pos[0]], [zi0, pos[1]], 0, 
  #                        boundary[0,:], boundary[1,:], 1, ncross=0, inds2=0)
  #  if (ncross % 2) == 1 : # Odd number of boundary crossings
  #    # Check how far away the crossing is
  #      if numpy.sqrt( (pos[0] - cpos[0,0])**2 + (pos[1] - cpos[1,0])**2 ) > tol :
  #      # Need to trigger an error
  #      #PRINT, "HIT BOUNDARY:", SQRT( (pos[0] - cpos[0,0])^2 + (pos[1] - cpos[1,0])^2 )
  #          status = 'a.bcd' # gibberish
  #    
  
    #dRdi = numpy.interp(pos[0],numpy.arange(Rpos.size).astype(float),deriv(Rpos)) 
    #dZdi = numpy.interp(pos[1],numpy.arange(Zpos.size).astype(float),deriv(Zpos)) 
    dRdi = numpy.interp(pos[0],Ri,dR) 
    dZdi = numpy.interp(pos[1],Zi,dZ) 
    
      

  # Check mismatch between fcur and f ? 
    Br = dfdz/dZdi
    Bz = -dfdr/dRdi
    B2 = Br**2 + Bz**2

    return [-Bz/B2/dRdi, Br/B2/dZdi]
Example #2
0
def radial_differential( fcur, pos):


    global rd_com, idata, lastgoodf, lastgoodpos, Rpos, Zpos, ood, tol, Ri, Zi, dR, dZ

    out=local_gradient( idata, pos[0], pos[1], status=0, dfdr=0., dfdz=0. )
    status=out.status
    dfdr=out.dfdr[0][0]
    dfdz=out.dfdz[0][0]

    ood = 0

    if status ==0 :
    # No error in localgradient.
        lastgoodf = fcur
        lastgoodpos = pos

    # If status NE 0 then an error occurred.
    # Allow dfdz to cause an error so escape LSODE
    else:
        ood = 1 # Out Of Domain

  #if numpy.size(boundary) > 1 :
  #  # Got a boundary - check for crossings
  #
  #  cpos , ncross, inds2 = line_crossings([ri0, pos[0]], [zi0, pos[1]], 0,
  #                        boundary[0,:], boundary[1,:], 1, ncross=0, inds2=0)
  #  if (ncross % 2) == 1 : # Odd number of boundary crossings
  #    # Check how far away the crossing is
  #      if numpy.sqrt( (pos[0] - cpos[0,0])**2 + (pos[1] - cpos[1,0])**2 ) > tol :
  #      # Need to trigger an error
  #      #PRINT, "HIT BOUNDARY:", SQRT( (pos[0] - cpos[0,0])^2 + (pos[1] - cpos[1,0])^2 )
  #          status = 'a.bcd' # gibberish
  #

    #dRdi = numpy.interp(pos[0],numpy.arange(Rpos.size).astype(float),deriv(Rpos))
    #dZdi = numpy.interp(pos[1],numpy.arange(Zpos.size).astype(float),deriv(Zpos))
    dRdi = numpy.interp(pos[0],Ri,dR)
    dZdi = numpy.interp(pos[1],Zi,dZ)



  # Check mismatch between fcur and f ?
    Br = old_div(dfdz,dZdi)
    Bz = old_div(-dfdr,dRdi)
    B2 = Br**2 + Bz**2

    return [-Bz/B2/dRdi, Br/B2/dZdi]
Example #3
0
def create_grid( F, R, Z, in_settings, critical,
                      boundary=None,  
                      iter=None, 
                      fpsi=None, fast=None):#, # f(psi) = R*Bt current function
                      #nrad_flexible,
                      #single_rad_grid, 
                      #xpt_mindist, xpt_mul, strictbndry,debug):

   # if size(nrad_flexible) == 0 :
    #    nrad_flexible = 0

    if iter==None:
        iter = 0
    if iter > 3:
        print("ERROR: Too many iterations")
        return #, {error:1}


   
  #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  # Check the settings
  # If a setting is missing, set a default value
  
   # inspect.getargspec(create_grid)
    
 # if N_PARAMS() LT 3 THEN BEGIN
  #  PRINT, "ERROR: Need at least a 2D array of psi values, R and Z arrays"
  #  RETURN, {error:1}
  #ENDIF ELSE IF N_PARAMS() LT 4 THEN BEGIN
  #  ; Settings omitted. Set defaults
  #  print "Settings not given -> using default values"
   # settings = {psi_inner:0.9, 
    #            psi_outer:1.1, 
     #           nrad:36, 
      #          npol:64, 
       #         rad_peaking:0.0, 
        #        pol_peaking:0.0, 
         #       parweight:0.0}
 # ENDIF ELSE BEGIN
  # print "Checking settings"
    settings = in_settings # So the input isn't changed
  #  str_check_present, settings, 'psi_inner', 0.9
  #  str_check_present, settings, 'psi_outer', 1.1
  #  str_check_present, settings, 'nrad', 36
  #  str_check_present, settings, 'npol', 64
  #  str_check_present, settings, 'rad_peaking', 0.0
  #  str_check_present, settings, 'pol_peaking', 0.0
  #  str_check_present, settings, 'parweight', 0.0
  #ENDELSE

    s = numpy.ndim(F)
    s1 = numpy.shape(F)
    if s != 2:
        print("ERROR: First argument must be 2D array of psi values")
        return #, {error:1}
    nx = s1[0]
    ny = s1[1]
  
    s = numpy.ndim(R)
    s1 = numpy.size(R)
    if s != 1  or s1 != nx :
        print("ERROR: Second argument must be 1D array of major radii")
        return # {error:1}
  
    s = numpy.ndim(Z)
    s1 = numpy.size(Z)
    if s != 1  or s1 != ny:
        print("ERROR: Second argument must be 1D array of heights")
        return # {error:1}


  # Get an even number of points for efficient FFTs
    if nx % 2 == 1:
    # odd number of points in R. Cut out last point
        R = R[0:(nx-1)]
        F = F[0:(nx-1), :]
        nx = nx - 1
  
    if ny % 2 == 1:
    # Same for Z
        Z = Z[0:(ny-1)]
        F = F[:,0:(ny-1)]
        ny = ny - 1
  


    if boundary != None:
        s = numpy.ndim(boundary)
        s1= numpy.shape(boundary)
        if s != 2  or s1[0] != 2:
            print("WARNING: boundary must be a 2D array: [2, n]. Ignoring")
            boundary = 0
        else:       
        # Calculate indices
            bndryi = numpy.zeros((2,1188))
            bndryi[0,:] = numpy.interp(bndryi[0,:], R, numpy.arange(0.,nx))
            bndryi[1,:] = numpy.interp(bndryi[1,:], Z, numpy.arange(0.,ny))

  
        if bndryi == None :
            bndryi = numpy.zeros((2,4))
            bndryi[0,:] = [1, nx-1, nx-1, 1]
            bndryi[1,:] = [1, 1, ny-1, ny-1]
 
  
  #;;;;;;;;;;;;;; Psi interpolation data ;;;;;;;;;;;;;;
  
    interp_data = Bunch(nx=nx, ny=ny, 
                 method=0, 
                 f= F)       # Always include function
               
    if fast == 'fast':
        print("Using Fast settings")
        interp_data.method = 2
  

  #;;;;;;;;;;;;;;; First plot ;;;;;;;;;;;;;;;;

    nlev = 100
    minf = numpy.min(F)
    maxf = numpy.max(F)
    levels = numpy.arange(numpy.float(nlev))*(maxf-minf)/numpy.float(nlev-1) + minf

    Rr=numpy.tile(R,ny).reshape(ny,nx).T
    Zz=numpy.tile(Z,nx).reshape(nx,ny)


    contour( Rr, Zz, F, levels=levels)
    
          #  arrange the plot on the screen      
    #mngr = get_current_fig_manager()
    #geom = mngr.window.geometry()
    #x,y,dx,dy = geom.getRect()
    #mngr.window.setGeometry(100, 100, dx, dy)


  
  #  if boundary != None :
  #      plot(boundary[0,:],boundary[1,:],'r-')
  
    show(block=False)  
    
  #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  

    n_opoint = critical.n_opoint
    n_xpoint = critical.n_xpoint
    primary_opt = critical.primary_opt
    inner_sep   = critical.inner_sep
    opt_ri = critical.opt_ri
    opt_zi = critical.opt_zi
    opt_f  = critical.opt_f
    xpt_ri = numpy.array(critical.xpt_ri).flatten()
    xpt_zi = numpy.array(critical.xpt_zi).flatten()
    xpt_f  = numpy.array(critical.xpt_f).flatten()
    
    


  # Overplot the separatrices, O-points
  #oplot_critical, F, R, Z, critical

  # Psi normalisation factors

    faxis = opt_f[primary_opt]
    
    fnorm = xpt_f[inner_sep] - opt_f[primary_opt]
    


  # From normalised psi, get range of f
    f_inner = faxis + numpy.min(settings.psi_inner)*fnorm
    f_outer = faxis + numpy.max(settings.psi_outer)*fnorm
    
  
  # Check the number of x-points
    if critical.n_xpoint == 0 :
    #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    # Grid entirely in the core
    	print("Generating grid entirely in the core")

    nrad = numpy.sum(settings.nrad) # Add up all points
    npol = numpy.sum(settings.npol)
    rad_peaking = settings.rad_peaking[0] # Just the first region
    pol_peaking = settings.pol_peaking[0]

    # work out where to put the surfaces in the core
    fvals = radial_grid(nrad, f_inner, f_outer, 1, 1, [xpt_f[inner_sep]], rad_peaking)

    fvals = fvals.flatten()
    # Create a starting surface
    sind = numpy.int(old_div(nrad, 2))
    start_f = fvals[sind]
    

  #  contour_lines( F, numpy.arange(nx).astype(float), numpy.arange(ny).astype(float), levels=[start_f])
    cs=contour( Rr, Zz, F,  levels=[start_f])

    p = cs.collections[0].get_paths()
 #
 #  You might get more than one contours for the same start_f. We need to keep the closed one  
    vn=numpy.zeros(numpy.size(p))
    
      
    v = p[0].vertices
    vn[0]=numpy.shape(v)[0]
    xx=[v[:,0]]
    yy=[v[:,1]]
    
    if numpy.shape(vn)[0] > 1:
        for i in range(1,numpy.shape(vn)[0]):
            v = p[i].vertices
            vn[i]=numpy.shape(v)[0]
            xx.append(v[:,0])
            yy.append(v[:,1])
            #xx = [xx,v[:,0]]
            #yy = [yy,v[:,1]]

    print("PRIMARY: ", primary_opt, opt_ri[primary_opt], opt_zi[primary_opt])

    if numpy.shape(vn)[0] > 1 :
        # Find the surface closest to the o-point
        opt_r = numpy.interp(opt_ri[primary_opt], numpy.arange(len(R)), R)
        opt_z = numpy.interp(opt_zi[primary_opt], numpy.arange(len(Z)), Z)
        
        ind = closest_line(xx, yy, opt_r, opt_z)
        
        x=xx[ind]
        y=yy[ind]
        print("Contour: ", ind)
    else:
        ind = 0
        x=xx[0]
        y=yy[0]
          

# plot the start_f line     
    zc = cs.collections[0]
    setp(zc, linewidth=4)

    clabel(cs, [start_f],  # label the level
           inline=1,
           fmt='%9.6f',
           fontsize=14)
     
    draw()             
   
    show(block=False)  
   
#

    ans=query_yes_no('Press enter to create grid')  
    
    if ans != 1 : 
        show()
	sys.exit()
      
    start_ri, start_zi=transform_xy(x,y,R,Z)
    
    ## Make sure that the line goes clockwise
    #
    m = numpy.argmax(numpy.interp(start_zi,numpy.arange(Z.size).astype(float), Z))
    if (numpy.gradient(numpy.interp(start_ri, numpy.arange(R.size).astype(float), R)))[m] < 0.0:
      # R should be increasing at the top. Need to reverse
        start_ri = start_ri[::-1]
        start_zi = start_zi[::-1]
        print('points reversed')
        

    ## Last point should be the same as the first
    #
    # Smooth and refine the starting location
    np = numpy.size(start_ri)
    s = 3
    ar=numpy.append(numpy.append(start_ri[(np-s-1):(np-1)], start_ri), start_ri[1:s+1])
    start_ri = SMOOTH(ar, window_len=s)[s+1:(np+s+1)]
    az=numpy.append(numpy.append(start_zi[(np-s-1):(np-1)], start_zi), start_zi[1:s+1])
    start_zi = SMOOTH(az, window_len=s)[s+1:(np+s+1)]
    
    
    for i in range (np) :
        ri1=0.
        zi1=0.
        out=follow_gradient( interp_data, R, Z, start_ri[i], start_zi[i], start_f, ri1, zi1 )
        status=out.status
        ri1=out.rinext
        zi1=out.zinext

        start_ri[i] = ri1
        start_zi[i] = zi1
    
        
    a = grid_region(interp_data, R, Z,
                    start_ri, start_zi, 
                    fvals, 
                    sind, 
                    npol, 
                    boundary=boundary,
                    fpsi=fpsi, 
                    parweight=settings.parweight, 
                    oplot='oplot')
    
    
    plot( numpy.append(a.rxy[0,:], a.rxy[0,0]), numpy.append(a.zxy[0,:], a.zxy[0,0]), 'r')
    
          
    for i in range (1, nrad) :
        plot( numpy.append(a.rxy[i,:], a.rxy[i,0]), numpy.append(a.zxy[i,:], a.zxy[i,0]), 'r')


    for i in range (0, npol-1) :
        plot( a.rxy[:,i], a.zxy[:,i], 'r')
    
    draw()

    # Get other useful variables
    psixy = numpy.zeros((nrad, npol))
    for i in range (0, npol) :
        psixy[:,i] = old_div((fvals - faxis),fnorm) # to get normalised psi
    
    # Calculate magnetic field components
    dpsidR = numpy.zeros((nrad, npol))
    dpsidZ = numpy.zeros((nrad, npol))
    
    interp_data.method = 2
    
    

    for i in range (nrad) :
        for j in range (npol) :
            out = local_gradient( interp_data, a.rixy[i,j], a.zixy[i,j], status=0, dfdr=0., dfdz=0.)
            status=out.status
            dfdr=out.dfdr[0][0]
            dfdz=out.dfdz[0][0]
    # dfd* are derivatives wrt the indices. Need to multiply by dr/di etc
            dpsidR[i,j] = old_div(dfdr,numpy.interp(a.rixy[i,j], numpy.arange(R.size).astype(float),numpy.gradient(R))) 
            dpsidZ[i,j] = old_div(dfdz,numpy.interp(a.zixy[i,j], numpy.arange(Z.size).astype(float),numpy.gradient(Z))) 
                 

    # Set topology to connect in the core
    yup_xsplit = [nrad]
    ydown_xsplit = [nrad]
    yup_xin = [0]
    yup_xout = [-1]
    ydown_xin = [0]
    ydown_xout = [-1]

    #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    # Create result structure

    result = Bunch(error=0, # Signal success
              psi_inner=settings.psi_inner, psi_outer=settings.psi_outer, # Unchanged psi range
              nrad=nrad, npol=npol, #Number of points in radial and poloidal direction
              Rixy=a.rixy, Zixy=a.zixy, # Indices into R and Z of each point
              Rxy=a.rxy, Zxy=a.zxy, # Location of each grid point
              psixy=psixy, # Normalised psi for each point
              dpsidR=dpsidR, dpsidZ=dpsidZ, # Psi derivatives (for Bpol)
              faxis=faxis, fnorm=fnorm, # Psi normalisation factors
              settings=settings, # Settings used to create grid
              critical=critical, # Critical points
              yup_xsplit=yup_xsplit, # X index where domain splits (number of points in xin)
              ydown_xsplit=ydown_xsplit, 
              yup_xin=yup_xin, yup_xout=yup_xout, # Domain index to connect to
              ydown_xin=ydown_xin, ydown_xout=ydown_xout)

    return result
Example #4
0
def grid_region ( interp_data, R, Z, 
                      ri, zi,        # Starting line to grid.
                      fvals,         # Location of the surfaces
                      sind,          # Index in fvals of the starting line
                      npar,          # Number of points along the line
                      slast=None,   # Index in fvals of last successful point
                      sfirst=None, 
                      oplot=None, 
                      boundary=None, 
                      ffirst=None, flast=None, 
                      fpsi=None,  # f(psi) = R*Bt optional current function
                      parweight=None, # Space equally in parallel (1) or poloidal (0) distance
                      ydown_dist=None, yup_dist=None, 
                      ydown_space=None, yup_space=None ):
  
    nsurf = numpy.size(fvals)
  
    if sind >= 0 :
    # starting position is on one of the output surfaces
        f0 = fvals[sind]
        nin = sind
    else:
    # Starting position between surfaces
        n = old_div(numpy.size(ri),2)
        out=local_gradient (interp_data, ri[n], zi[n], status=0, f=f0)
        status=out.status
        f0=out.f[0][0]
    
        if fvals[0] < fvals[nsurf-1] :
            w = numpy.where(fvals < f0, nin)
        else:
            w = numpy.where(fvals >= f0, nin)
     
   
    nout = nsurf - nin - 1

    sfirst = 0      # Innermost successful index
    slast = nsurf-1 # Last successful index 

    ffirst = fvals[sfirst]
    flast = fvals[slast]

    print("    => Gridding range: ", numpy.min(fvals), numpy.max(fvals))
  
    nr = interp_data.nx
    nz = interp_data.ny


    ind = poloidal_grid(interp_data, R, Z, ri, zi, npar, fpsi=fpsi, 
                      ydown_dist=ydown_dist, yup_dist=yup_dist, 
                      ydown_space=ydown_space, yup_space=yup_space, 
                      parweight=parweight)
      
    rii = numpy.interp(ind, numpy.arange(ri.size).astype(float), ri)
    zii = numpy.interp(ind, numpy.arange(zi.size).astype(float), zi)
    

    #rii = int_func(SMOOTH(deriv(rii), 3)) + rii[0]
    #zii = int_func(SMOOTH(deriv(zii), 3)) + zii[0]
    #STOP
  
  # Refine the location of the starting point
    for i in range (npar) :
        ri1=0.
        zi1=0.
        out=follow_gradient( interp_data, R, Z, rii[i], zii[i], f0, ri1, zi1 )
        ri1=out.rinext
        zi1=out.zinext
 
        rii[i] = ri1
        zii[i] = zi1
   

  # From each starting point, follow gradient in both directions
  
    rixy = numpy.zeros((nsurf, npar))
    zixy = numpy.zeros((nsurf, npar))
    status=0
    
    print('Starting')

    for i in range (npar) :
    
      #  print 'i=', i

        if sind >= 0 :
            rixy[nin, i] = rii[i]
            zixy[nin, i] = zii[i]
        else:
      # fvals[nin] should be just outside the starting position
            ftarg = fvals[nin]
            
            rinext=0.
            zinext=0.
            
            out=follow_gradient( interp_data, R, Z, rii[i], zii[i],
                            ftarg, rinext, zinext, status=0 )
            status=out.status
            rinext=out.rinext
            zinext=out.zinext
            rixy[nin, i] = rinext
            zixy[nin, i] = zinext
        
            
            
        for j in range (nout) :
         #   print nin+j+1
            ftarg = fvals[nin+j+1]
      
            rinext=0.
            zinext=0.
            
             

            out=follow_gradient ( interp_data, R, Z, rixy[nin+j, i], zixy[nin+j, i],  
                                ftarg, rinext, zinext, status=status,  
                                boundary=boundary, fbndry=0.)
               
            status=out.status
            rinext=out.rinext
            zinext=out.zinext
            fbndry=out.fbndry
            
            
            #print "create_grid"
            #print ftarg, rinext, zinext

             

            if status == 1 :
                rixy[nin+j+1, i] = -1.0
                if nin+j < slast :
                    slast = nin+j # last good surface index
                fbndry = fvals[slast]
                if (fvals[1] - fvals[0])*(flast - fbndry) > 0 :
                    flast = 0.95*fbndry + 0.05*f0
                    break
                
            elif status == 2 :
        # Hit a boundary 
                rixy[nin+j+1, i] = rinext
                zixy[nin+j+1, i] = zinext
                if nin+j < slast :
                    slast = nin+j # Set the last point
                if (fvals[1] - fvals[0])*(flast - fbndry) > 0 :
                    flast = 0.95*fbndry + 0.05*f0
                break
                
            else :
                rixy[nin+j+1, i] = rinext
                zixy[nin+j+1, i] = zinext
            
            
            
            
      
        for j in range (nin) :
           # print nin-j-1
            ftarg = fvals[nin-j-1]
                 
                  
            rinext=0.
            zinext=0.

 
            out=follow_gradient ( interp_data, R, Z, rixy[nin-j, i], zixy[nin-j, i],  
                            ftarg, rinext, zinext, status=status,  
                                boundary=boundary, fbndry=fbndry )
            status=out.status
            rinext=out.rinext
            zinext=out.zinext
            fbndry=out.fbndry
            
            #print ftarg, rinext, zinext
       
       
            if status == 1 :
                rixy[nin-j-1, i] = -1.0
                if nin-j > sfirst :
                    sfirst = nin-j
                fbndry = fvals[sfirst]
                if (fvals[1] - fvals[0])*(ffirst - fbndry) < 0 :
                    ffirst = 0.95*fbndry + 0.05*f0
                break
      

            rixy[nin-j-1, i] = rinext
            zixy[nin-j-1, i] = zinext


            if status == 2 :
                if nin-j > sfirst :
                    sfirst = nin-j
                if (fvals[1] - fvals[0])*(ffirst - fbndry) < 0 :
                    ffirst = 0.95*fbndry + 0.05*f0
                break
           
            

        #print rixy[:,i], zixy[:,i]
        
        
        if oplot != None:
            numpy.interp(rixy[:, i], numpy.arange(R.size).astype(float), R)
            numpy.interp(zixy[:, i], numpy.arange(Z.size).astype(float), Z)
            figure (0)
            oplot_contour(rixy[:, i], zixy[:, i] , R, Z)

             

    

    return Bunch(rixy=rixy, zixy=zixy, rxy=numpy.interp(rixy, numpy.arange(R.size), R), zxy=numpy.interp(zixy, numpy.arange(Z.size), Z))
Example #5
0
def poloidal_grid(interp_data, R, Z, ri, zi, n, fpsi=None, parweight=None,
                    ydown_dist=None, yup_dist=None, 
                    ydown_space=None, yup_space=None):

    if parweight  == None:
        parweight = 0.0  # Default is poloidal distance

    np = numpy.size(ri)
    
    if np == 0 :
    # Calculate poloidal distance along starting line
        drdi = numpy.gradient(numpy.interp(ri, numpy.arange(R.size).astype(float), R))
        dzdi = numpy.gradient(numpy.interp(zi, numpy.arange(Z.size).astype(float), Z))
    
        dldi = numpy.sqrt(drdi**2 + dzdi**2)
        poldist = int_func(numpy.arange(0.,np), dldi) # Poloidal distance along line
    else:
        rpos = numpy.interp(ri,numpy.arange(R.size).astype(float), R)
        zpos = numpy.interp(zi,numpy.arange(Z.size).astype(float),Z)
        
        dd = numpy.sqrt((zpos[1::] - zpos[0:(np-1)])**2 + (rpos[1::] - rpos[0:(np-1)])**2)
        dd = numpy.append(dd, numpy.sqrt((zpos[0] - zpos[np-1])**2 + (rpos[0] - rpos[np-1])**2))
        poldist = numpy.zeros(np)
        for i in range (1,np) :
            poldist[i] = poldist[i-1] + dd[i-1]
                

    if numpy.ndim(fpsi) == 2:
    # Parallel distance along line
    # Need poloidal and toroidal field
        ni = numpy.size(ri)
        bp = numpy.zeros(ni)
        bt = numpy.zeros(ni)
        m = interp_data.method
        interp_data.method = 2
        
        for i in range (ni) :
           
            out=local_gradient( interp_data, ri[i], zi[i], status=0, f=0., dfdr=0., dfdz=0.)
            f=out.f[0][0]
            dfdr=out.dfdr[0][0]
            dfdz=out.dfdz[0][0]
            status=out.status
            

     # dfd* are derivatives wrt the indices. Need to multiply by dr/di etc
            dfdr /= numpy.interp(ri[i],numpy.arange(R.size).astype(float),numpy.gradient(R))
            dfdz /= numpy.interp(zi[i],numpy.arange(Z.size).astype(float),numpy.gradient(Z))
      
            if i == 0 :
                btr = numpy.interp(f, fpsi[0,:], fpsi[1,:])
    
      
            bp[i] = old_div(numpy.sqrt(dfdr**2 + dfdz**2), numpy.interp(ri[i], numpy.arange(R.size).astype(float), R))
            bt[i] = numpy.abs( old_div(btr, numpy.interp( ri[i], numpy.arange(R.size).astype(float),R )))
     
        interp_data.method = m
        b = numpy.sqrt(bt**2 + bp**2)
        ddpar = dd * b / bp
        pardist = numpy.zeros(np)
        for i in range (1,np) :
            ip = (i + 1) % np
            pardist[i] = pardist[i-1] + ddpar[i] #0.5*(ddpar[i-1] + ddpar[ip])
     
    else:
        pardist = poldist # Just use the same poloidal distance

    print("PARWEIGHT: ", parweight)

    dist = parweight*pardist + (1. - parweight)*poldist


  # Divide up distance. No points at the end (could be x-point)
    if n >= 2 :
        if ydown_dist == None :
            ydown_dist = dist[np-1]* 0.5 / numpy.float(n)
        if yup_dist == None :
            yup_dist = dist[np-1] * 0.5 / numpy.float(n)

        if ydown_space == None :
            ydown_space = ydown_dist
        if yup_space == None :
            yup_space = ydown_dist
    #dloc = (dist[np-1] - ydown_dist - yup_dist) * FINDGEN(n)/FLOAT(n-1) + ydown_dist  # Distance locations
    
        fn = numpy.float(n-1)
        d = (dist[np-1] - ydown_dist - yup_dist) # Distance between first and last
        i = numpy.arange(0.,n)

            
        yd = numpy.min( ydown_space, 0.5*d/fn )
        yu = numpy.min( yup_space , 0.5*d/fn )
    # Fit to ai + bi^2 + c[i-sin(2pi*i/(n-1))*(n-1)/(2pi)]
    
    
        a = yd*2.
        b = old_div((2.*yu - a), fn)
        c = old_div(d,fn) - a - 0.5*b*fn
                
        dloc =  ydown_dist + a*i + 0.5*b*i**2 + c*(i - numpy.sin(2.*numpy.pi*i / fn)*fn/(2.*numpy.pi))
        
        ddloc = a  + b*i + c*(1. - numpy.cos(2.*numpy.pi*i / fn))
        
    
    # Fit to dist = a*i^3 + b*i^2 + c*i
        #c = ydown_dist*2.
        #b = 3.*(d/fn^2 - c/fn) - 2.*yup_dist/fn + c/fn
        #a = d/fn^3 - c/fn^2 - b/fn
        #dloc = ydown_dist + c*i + b*i^2 + a*i^3
    
    else :
        print("SORRY; Need 2 points in each region")
        sys.exit("Error message")


  # Get indices in ri, zi
    ind = numpy.interp(dloc, dist, numpy.arange(0.,np))

    return ind
Example #6
0
def follow_gradient(interp_data,
                    R,
                    Z,
                    ri0,
                    zi0,
                    ftarget,
                    ri,
                    zi,
                    status=0,
                    boundary=None,
                    fbndry=None,
                    ibndry=None):

    global rd_com, idata, lastgoodf, lastgoodpos, Rpos, Zpos, ood, tol, Ri, Zi, dR, dZ

    tol = 0.1

    Rpos = R
    Zpos = Z

    Ri = numpy.arange(Rpos.size).astype(float)
    Zi = numpy.arange(Zpos.size).astype(float)
    dR = deriv(Rpos)
    dZ = deriv(Zpos)

    ibndry = -1

    idata = interp_data

    if boundary != None:
        bndry = boundary
        ri0c = ri0
        zi0c = zi0
    else:
        bndry = 0

    ood = 0

    if ftarget == None: print(ftarget)

    # Get starting f
    out = local_gradient(interp_data,
                         ri0,
                         zi0,
                         status=status,
                         f=0.,
                         dfdr=None,
                         dfdz=None)
    status = out.status
    f0 = out.f
    if status == 1:
        ri = ri0
        zi = zi0
        status = 1
        return Bunch(status=status, ri=ri, zi=zi)

    fmax = ftarget  # Target (with maybe boundary in the way)

    # Call LSODE to follow gradient
    rzold = [ri0, zi0]
    rcount = 0

    solver = lsode(radial_differential, f0, rzold)
    rznew = solver.integrate(ftarget)
    nsteps = solver.steps

    lstat = 0
    #    print 'nsteps=',nsteps
    #print rzold, rznew
    #
    #sys.exit()
    #
    #   #         if nsteps > 100 : lstat = -1
    #            if lstat == -1 :
    #                print "  -> Excessive work "+str(f0)+" to "+str(ftarget)+" Trying to continue..."
    #                lstat = 2 # continue
    #                rcount = rcount + 1
    #                if rcount > 3 :
    #                    print "   -> Too many repeats. Giving Up."
    #
    #                    ri = lastgoodpos[0]
    #                    zi = lastgoodpos[1]
    #                    fmax = lastgoodf
    #
    #                    return Bunch(status=status,ri=ri,zi=zi)
    #
    #            # Get f at this new location
    #                out=local_gradient( interp_data, rznew[0], rznew[1], status=status, f=f0, dfdr=None, dfdz=None)
    #                status=out.status
    #                f0=out.f
    #
    #                if status == 1 :
    #                    ri = ri0
    #                    zi = zi0
    #                    status = 1
    #                    return Bunch(status=status, rinext=ri, zinext=zi)
    #
    #                rzold = rznew
    #
    #
    #            else :
    #                print "I break"
    #                break
    #
    #        print 'am I here?'
    #
    #        if status==0:
    #            print 'I break from try?'
    #            break
    #
    #        if lstat < 0 :
    #            print "Error in LSODE routine when following psi gradient."
    #            print "LSODE status: ", lstat
    #           #STOP
    #
    #
    #    except Exception as theError:
    #        print theError

    ri = rznew[0]
    zi = rznew[1]

    #   else:
    #   # An error occurred in LSODE.
    #   # lastgoodf contains the last known good f value
    #   #PRINT, "CAUGHT ERROR "+!ERROR_STATE.MSG
    #   #CATCH, /cancel
    #       ri = lastgoodpos[0]
    #       zi = lastgoodpos[1]
    #       fmax = lastgoodf
    #       if ood :
    #       # Gone Out Of Domain
    #           status = 2
    #           fbndry = lastgoodf
    #       #PRINT, "Out of domain at f = ", fbndry
    #       # Repeat to verify that this does work
    #           rzold = [ri0, zi0]
    #           try :
    #               fbndry = lastgoodf - 0.1*(ftarget - f0)
    #               if theError != 0 :
    #                   print "   Error again at ", fbndry
    #
    #
    #               solver=lsode(radial_differential, f0, rzold)
    #               rznew=solver.integrate(fbndry - f0)
    #           except Exception as theError:
    #               print theError
    #
    #           return Bunch(status=status, rinext=ri, zinext=zi)
    #
    #   # Otherwise just crossed a boundary
    #
    #   #CATCH, /cancel

    #if boundary != None:
    ## Check if the line crossed a boundary
    ##PRINT, "Checking boundary ", boundary[*,1:2], [ri0, ri], [zi0, zi]
    #    cpos, ncross, inds2 = line_crossings([ri0, ri], [zi0, zi], 0,
    #                      boundary[0,:], boundary[1,:], 1, ncross=0, inds2=0)
    #    if (ncross % 2) == 1 : # Odd number of boundary crossings
    #        if numpy.sqrt( (ri - cpos[0,0])**2 + (zi - cpos[1,0])**2 ) > 0.1 :
    #    #PRINT, "FINDING BOUNDARY", SQRT( (ri - cpos[0,0])^2 + (zi - cpos[1,0])^2 )
    #    # Use divide-and-conquer to find crossing point
    #
    #            tol = 1e-4 # Make the boundary crossing stricter
    #
    #            ibndry = inds2[0] # Index in boundary where hit
    #
    #            fcur = f0 # Current known good position
    #            rzold = [ri0,zi0]
    #            rzcur = rzold
    #            while True:
    #                fbndry = (fcur + fmax) / 2
    #     # Try to go half-way to fmax
    #                #CATCH, theError
    #                if theError != 0 :
    #        # Crossed boundary. Change fmax
    #                    #CATCH, /cancel
    #                    fmax = fbndry
    #                    ibndry = inds2[0] # refined boundary index
    #                else:
    #                    solver=lsode(radial_differential, f0, rzold)
    #                    rznew=solver.integrate(fbndry - f0)
    #
    #       # Didn't cross. Make this the new current location
    #                    fcur = fbndry
    #                    rzcur = rznew
    #
    #                    #CATCH, /cancel
    #
    #                if numpy.abs(fmax - fcur) < 0.01*numpy.abs(ftarget - f0):
    #                    break
    #            ri = rzcur[0]
    #            zi = rzcur[1]
    #            fbndry = fcur
    #
    #    #PRINT, "Hit boundary", ri, zi, " f =", fbndry
    #            status = 2
    #            return Bunch(status=status, rinext=ri, zinext=zi, fbndry=fbndry, ibndry=ibndry)

    #print "follow_gradient"
    #print ri, zi
    return Bunch(status=0, rinext=ri, zinext=zi, fbndry=fbndry, ibndry=ibndry)
def follow_gradient( interp_data, R, Z, ri0, zi0, ftarget, ri, zi, status=0, 
                     boundary=None, fbndry=None, ibndry=None ):
  
    global rd_com, idata, lastgoodf, lastgoodpos, Rpos, Zpos, ood, tol, Ri, Zi, dR, dZ
      
    tol = 0.1

    Rpos = R
    Zpos = Z
    
    Ri=numpy.arange(Rpos.size).astype(float)
    Zi=numpy.arange(Zpos.size).astype(float)
    dR=deriv(Rpos)
    dZ=deriv(Zpos)
  
    ibndry = -1
  
    idata = interp_data

    if boundary != None :
        bndry = boundary
        ri0c = ri0
        zi0c = zi0
    else:
        bndry = 0
  
    ood = 0

    if ftarget==None : print ftarget

  # Get starting f
    out=local_gradient( interp_data, ri0, zi0, status=status, f=0., dfdr=None, dfdz=None)
    status=out.status
    f0=out.f
    if status == 1 :
        ri = ri0
        zi = zi0
        status = 1
        return Bunch(status=status, ri=ri, zi=zi)
    

    fmax = ftarget # Target (with maybe boundary in the way)


#   CATCH, theError
#    try :
    # Call LSODE to follow gradient
    rzold = [ri0, zi0]
    rcount = 0
  #      while True:

#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# toggle this for lsode            

    solver = lsode(radial_differential, f0, rzold) 
    rznew=solver.integrate(ftarget)
    nsteps = solver.steps

#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# toggle this for odeint            
                                    
 # get the value out of a list
#    x0 = chain.from_iterable(f0)
#    x0 = list(x0)[0]
#                       
#   # print x0, ftarget                  
#    solode=odeint(radial_differential,rzold,[x0,ftarget],full_output=True)
#
#    rznew=solode[0][1,:]
#    nsteps=solode[1]['nst'][0]

#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  
    lstat=0
#    print 'nsteps=',nsteps    
    #print rzold, rznew
    #
    #sys.exit()
#
#   #         if nsteps > 100 : lstat = -1
#            if lstat == -1 :
#                print "  -> Excessive work "+str(f0)+" to "+str(ftarget)+" Trying to continue..."
#                lstat = 2 # continue
#                rcount = rcount + 1
#                if rcount > 3 :
#                    print "   -> Too many repeats. Giving Up."
#          
#                    ri = lastgoodpos[0]
#                    zi = lastgoodpos[1]
#                    fmax = lastgoodf
#          
#                    return Bunch(status=status,ri=ri,zi=zi)
#         
#            # Get f at this new location
#                out=local_gradient( interp_data, rznew[0], rznew[1], status=status, f=f0, dfdr=None, dfdz=None)
#                status=out.status
#                f0=out.f
#
#                if status == 1 :
#                    ri = ri0
#                    zi = zi0
#                    status = 1
#                    return Bunch(status=status, rinext=ri, zinext=zi)
#            
#                rzold = rznew
#        
#                 
#            else :
#                print "I break"        
#                break
#        
#        print 'am I here?'
#        
#        if status==0:
#            print 'I break from try?'
#            break
#    
#        if lstat < 0 :
#            print "Error in LSODE routine when following psi gradient."
#            print "LSODE status: ", lstat
#           #STOP
#
#
#    except Exception as theError:
#        print theError
        
    
    ri = rznew[0]
    zi = rznew[1]
    
 #   else:
 #   # An error occurred in LSODE.
 #   # lastgoodf contains the last known good f value
 #   #PRINT, "CAUGHT ERROR "+!ERROR_STATE.MSG
 #   #CATCH, /cancel
 #       ri = lastgoodpos[0]
 #       zi = lastgoodpos[1]
 #       fmax = lastgoodf
 #       if ood :
 #       # Gone Out Of Domain
 #           status = 2
 #           fbndry = lastgoodf
 #       #PRINT, "Out of domain at f = ", fbndry
 #       # Repeat to verify that this does work
 #           rzold = [ri0, zi0]
 #           try :
 #               fbndry = lastgoodf - 0.1*(ftarget - f0)
 #               if theError != 0 :
 #                   print "   Error again at ", fbndry
 #      
 #               
 #               solver=lsode(radial_differential, f0, rzold)
 #               rznew=solver.integrate(fbndry - f0) 
 #           except Exception as theError:
 #               print theError
 #     
 #           return Bunch(status=status, rinext=ri, zinext=zi)
 #    
 #   # Otherwise just crossed a boundary
 #
 #   #CATCH, /cancel
    

  
    #if boundary != None:
    ## Check if the line crossed a boundary
    ##PRINT, "Checking boundary ", boundary[*,1:2], [ri0, ri], [zi0, zi]
    #    cpos, ncross, inds2 = line_crossings([ri0, ri], [zi0, zi], 0, 
    #                      boundary[0,:], boundary[1,:], 1, ncross=0, inds2=0)
    #    if (ncross % 2) == 1 : # Odd number of boundary crossings
    #        if numpy.sqrt( (ri - cpos[0,0])**2 + (zi - cpos[1,0])**2 ) > 0.1 :
    #    #PRINT, "FINDING BOUNDARY", SQRT( (ri - cpos[0,0])^2 + (zi - cpos[1,0])^2 )
    #    # Use divide-and-conquer to find crossing point
    #    
    #            tol = 1e-4 # Make the boundary crossing stricter
    #    
    #            ibndry = inds2[0] # Index in boundary where hit
    #    
    #            fcur = f0 # Current known good position
    #            rzold = [ri0,zi0]
    #            rzcur = rzold
    #            while True:
    #                fbndry = (fcur + fmax) / 2
    #     # Try to go half-way to fmax
    #                #CATCH, theError
    #                if theError != 0 :
    #        # Crossed boundary. Change fmax
    #                    #CATCH, /cancel
    #                    fmax = fbndry
    #                    ibndry = inds2[0] # refined boundary index
    #                else:
    #                    solver=lsode(radial_differential, f0, rzold)
    #                    rznew=solver.integrate(fbndry - f0) 
    #        
    #       # Didn't cross. Make this the new current location
    #                    fcur = fbndry
    #                    rzcur = rznew
    #        
    #                    #CATCH, /cancel
    #       
    #                if numpy.abs(fmax - fcur) < 0.01*numpy.abs(ftarget - f0):
    #                    break
    #            ri = rzcur[0]
    #            zi = rzcur[1]
    #            fbndry = fcur
    #    
    #    #PRINT, "Hit boundary", ri, zi, " f =", fbndry
    #            status = 2
    #            return Bunch(status=status, rinext=ri, zinext=zi, fbndry=fbndry, ibndry=ibndry)
 
    #print "follow_gradient"
    #print ri, zi
    return Bunch(status = 0, rinext=ri, zinext=zi, fbndry=fbndry, ibndry=ibndry)