示例#1
0
    def swin(self, pob, sob, tob, stat, dates):
        """ toposcale surface pressure using hypsometric equation - move to own 
		class 

		EDITS Feb 20 2020:
		
		-See https://www.evernote.com/Home.action?login=true#n=78e92684-4d64-4802-ab6c-2cb90b277e44&s=s500&ses=1&sh=5&sds=5&x=&
		- 

		EDITS Jul 11 2019:
		
		- removed elevation scaling as this degrade results - at least in WFJ test- Kris?
		- reimplemnt original additative ele method - better than beers, or at least less damaging
		- removed mask, why is this causing problems?
		- dotprod method (corripio) does not seem to work - I dont think it ever did as we used SWTopo ==FALSE
		- use Dozier cos corrction method (as in paper right)
		- So ... we have ele, illumination angle, self shading and svf correction. We do not have horizon correction (partly in self shading of course)


		"""

        ## Specific humidity routine.
        # mrvf=0.622.*vpf./(psf-vpf); #Mixing ratio for water vapor at subgrid.
        #  qf=mrvf./(1+mrvf); # Specific humidity at subgrid [kg/kg].
        # fout.q(:,:,n)=qf;
        """ Maybe follow Dubayah's approach (as in Rittger and Girotto) instead
		for the shortwave downscaling, other than terrain effects. """
        """ Height of the "grid" (coarse scale)"""
        Zc = sob.z
        """ toa """
        SWtoa = sob.tisr
        """ Downwelling shortwave flux of the "grid" using nearest neighbor."""
        SWc = sob.ssrd
        """Calculate the clearness index."""
        kt = SWc / SWtoa

        #kt[is.na(kt)==T]<-0 # make sure 0/0 =0
        #kt[is.infinite(kt)==T]<-0 # make sure 0/0 =0
        kt[kt < 0] = 0
        kt[kt > 1] = 0.8  #upper limit of kt
        self.kt = kt
        """
		Calculate the diffuse fraction following the regression of Ruiz-Arias 2010 
		
		"""
        kd = 0.952 - 1.041 * np.exp(-1 * np.exp(2.3 - 4.702 * kt))
        self.kd = kd
        """ Use this to calculate the downwelling diffuse and direct shortwave radiation at grid. """
        SWcdiff = kd * SWc
        SWcdir = (1 - kd) * SWc
        self.SWcdiff = SWcdiff
        self.SWcdir = SWcdir
        """ Use the above with the sky-view fraction to calculate the 
		downwelling diffuse shortwave radiation at subgrid. """
        self.SWfdiff = SWcdiff  #* stat.svf
        self.SWfdiff.set_fill_value(0)
        self.SWfdiff = self.SWfdiff.filled()
        """ Direct shortwave routine, modified from Joel. 
		Get surface pressure at "grid" (coarse scale). Can remove this
		part once surface pressure field is downloaded, or just check
		for existance. """

        #T1=Ttemp(thisp)
        #z1=ztemp(thisp)
        #p1=pob.levels(thisp)*1e2 #Convert to Pa.
        #Tbar=mean([T0 T1])
        """compute julian dates"""
        jd = sg.to_jd(dates)
        """
		Calculates a unit vector in the direction of the sun from the observer 
		position.
		"""
        sunv = sg.sunvector(jd=jd,
                            latitude=stat.lat,
                            longitude=stat.lon,
                            timezone=stat.tz)
        """
		Computes azimuth , zenith  and sun elevation 
		for each timestamp
		"""
        sp = sg.sunpos(sunv)
        self.sp = sp

        # Cosine of the zenith angle.
        sp.zen = sp.zen
        #sp.zen=sp.zen*(sp.zen>0) # Sun might be below the horizon.
        muz = np.cos(sp.zen)

        self.muz = muz
        # NB! psc must be in Pa (NOT hPA!).
        #if np.max(psc<1.5e3): # Obviously not in Pa
        #psc=psc*1e2

        # Compute air pressure at fine grid
        ztemp = pob.z
        Ttemp = pob.t
        statz = stat.ele * self.g
        dz = ztemp.transpose(
        ) - statz  # transpose not needed but now consistent with CGC surface pressure equations

        # compute air pressure at fine grid (could remove if download air pressure variable)
        self.psf = []
        # loop through timesteps
        for i in range(0, dates.size):

            # 	# find overlying layer
            thisp = dz[:, i] == np.min(dz[:, i][dz[:, i] > 0])

            # booleen indexing
            T1 = Ttemp[i, thisp]
            z1 = ztemp[i, thisp]
            p1 = pob.levels[thisp] * 1e2  #Convert to Pa.
            Tbar = np.mean([T1, tob.t[i]], axis=0)
            """ Hypsometric equation."""
            self.psf.append(p1 * np.exp(
                (z1 - statz) * (self.g / (Tbar * self.R))))

        self.psf = np.array(self.psf).squeeze()

        # Method 1 BEERS LAW
        if (BEERS == 'TRUE'):

            # compute air pressure at coarse grid
            dz = ztemp.transpose() - sob.z

            self.psc = []
            for i in range(0, dz.shape[1]):

                #thisp.append(np.argmin(dz[:,i][dz[:,i]>0]))
                thisp = dz[:, i] == np.min(dz[:, i][dz[:, i] > 0])
                z0 = sob.z[i]
                T0 = sob.t2m[i]
                T1 = Ttemp[i, thisp]
                z1 = ztemp[i, thisp]
                p1 = pob.levels[thisp] * 1e2  #Convert to Pa.
                Tbar = np.mean([T0, T1], axis=0)
                """ Hypsometric equation."""
                self.psc.append(p1 * np.exp(
                    (z1 - z0) * (self.g / (Tbar * self.R))))

            self.psc = np.array(self.psc).squeeze()

            # Calculate the "broadband" absorption coefficient. Elevation correction
            # from Kris
            ka = (self.g * muz / (self.psc)) * np.log(SWtoa / SWcdir)
            #ka.set_fill_value(0)
            #ka = ka.filled()

            # set inf (from SWtoa/SWcdir at nigh, zero division) to 0 (night)
            ka[ka == -np.inf] = 0
            ka[ka == np.inf] = 0
            # Note this equation is obtained by inverting Beer's law, i.e. use
            #I_0=I_inf x exp[(-ka/mu) int_z0**inf rho dz]
            # Along with hydrostatic equation to convert to pressure coordinates then
            # solve for ka using p(z=inf)=0.

            # Method 1 Beers law
            # Now you can (finally) find the direct component at subgrid.
            self.SWfdir = SWtoa * np.exp(-ka * self.psf / (self.g * muz))
            #self.SWfdir=SWcdir

        # Method 2 ORIGINAL ELEVATION Correction
        # https://hal.archives-ouvertes.fr/hal-00470155/document
        """ele diff in km"""
        coarseZ = Zc[0] / 9.9

        dz = (stat.ele - coarseZ) / 1000  # fine - coase in knm

        s = SWtoa
        b = SWcdir
        zen = sp.zen

        thetaz = (np.pi / 180) * zen  #radians
        m = 1 / np.cos(thetaz)
        k = -np.log(b / s) / m
        k.set_fill_value(0)
        k = k.filled()
        #k[is.na(k)==T]<-0 #correct b=0/s=0 problem

        t = np.exp(1)**(-k * dz * np.cos(thetaz))
        t[t > 1] < -1.1  #to constrain to reasonable values
        t[t < 0.8] < -0.9  #to constrain to reasonable values
        db = (1 - t) * SWcdir

        self.SWfdir = SWcdir + db  #additative correction

        #======================================
        """ Then perform the terrain correction. [Corripio 2003 / rpackage insol port]."""
        """compute mean horizon elevation - why negative hor.el possible??? Have tested seesm OK """

        # In [485]: (((np.arccos(np.sqrt(0.9))*180.)/np.pi)*2)-20
        # Out[485]: 16.869897645844034

        # In [486]: (((np.arccos(np.sqrt(1))*180.)/np.pi)*2)-0
        # Out[486]: 0.0

        # In [487]: (((np.arccos(np.sqrt(0.9))*180.)/np.pi)*2)-0
        # Out[487]: 36.869897645844034

        # In [488]: (((np.arccos(np.sqrt(0.9))*180.)/np.pi)*2)-10
        # Out[488]: 26.869897645844034

        # In [489]: (((np.arccos(np.sqrt(0.95))*180.)/np.pi)*2)-10
        # Out[489]: 15.841932763167158

        horel = (((np.arccos(np.sqrt(stat.svf)) * 180) / np.pi) * 2) - stat.slp

        if horel < 0:
            horel = 0
        self.meanhorel = horel
        """
		normal vector - Calculates a unit vector normal to a surface defined by 
		slope inclination and slope orientation.
		"""
        nv = sg.normalvector(slope=stat.slp, aspect=stat.asp)
        """
		Method 1: Computes the intensity according to the position of the sun (sunv) and 
		dotproduct normal vector to slope.
		From corripio r package THIS IS GOOD

		# consider october 31 29018 at 46/9 UTC=0

		dt= datetime.datetime(2018, 10, 31, 12, 0) 
		In [471]: sg.to_jd(dt)                                                                                                                                              
		Out[471]: 2458423.0  

		sunv=sg.sunvector(jd=2458423 , latitude=46, longitude=9, timezone=0)
		sp=sg.sunpos(sunv)

		- sun is in the south:
		In [456]: sp.azi                                                                                                                                                    
		Out[456]: array([192.82694139])  

		- at quite low ele
		In [455]: sp.sel                                                                                                                                                    
		Out[455]: array([19.94907576])  
		

		# FLAT CASE
		In [449]: nv = sg.normalvector(slope=0, aspect=0)                                                                                                                                                                                                                                                                            
		In [450]: np.dot(sunv ,np.transpose(nv))                                                                                                                            
		Out[450]: array([[0.34118481]])      

		# SOOUTH SLOPE CASE = enhanced rad wrt. flat case
				nv = sg.normalvector(slope=30, aspect=180)  
		In [446]: np.dot(sunv ,np.transpose(nv))                                                                                                                            
		Out[446]: array([[0.75374406]])  

		# NORTH SLOPE CASE = self shaded
		In [447]: nv = sg.normalvector(slope=30, aspect=0)                                                                                                                  
		                                                                                                                                                                    
		In [448]: np.dot(sunv ,np.transpose(nv))                                                                                                                            
		Out[448]: array([[-0.16279463]])    


		"""

        dotprod = np.dot(sunv, np.transpose(nv))
        dprod = dotprod.squeeze()
        dprod[dprod < 0] = 0  #negative indicates selfshading
        self.dprod = dprod
        """Method 2: Illumination angles. Dozier and self shading"""  # THIS IS WRONG
        # 		eg consider south facting 30 degree slope on 31 oct 2018 at midday at 46,9 utc=0

        # In [420]: sp.azi
        # Out[420]: array([192.82694139])

        # In [421]: stat.slp
        # Out[421]: 30

        # In [422]: stat.asp
        # Out[422]: 180

        # In [423]: sp.azi
        # Out[423]: array([192.82694139])

        # In [424]: sp.sel
        # Out[424]: array([19.94907576])

        # In [425]: ^I^I saz=sp.azi
        #      ...: ^I^I cosis=muz*np.cos(stat.slp)+np.sin(sp.zen)*np.sin(stat.slp)*np.cos(sp.azi-stat.asp)# cosine of illumination angle at subgrid.
        #      ...: ^I^I cosic=muz # cosine of illumination angle at grid (slope=0).
        #      ...: ^I^I cosi = (cosis/cosic)
        #      ...:

        # In [427]: cosi
        # Out[427]: array([-1.14169945])

        # negative cosi shows sun below horizon!

        # saz=sp.azi
        # cosis=muz*np.cos(stat.slp)+np.sin(sp.zen)*np.sin(stat.slp)*np.cos(sp.azi-stat.asp)# cosine of illumination angle at subgrid.
        # cosic=muz # cosine of illumination angle at grid (slope=0).
        # cosi = (cosis/cosic)

        # #If ratio of illumination angle subgrid/ illum angle grid is negative the point is selfshaded
        # cosi[cosi<0]=0 #WRONG!!!
        """
		CAST SHADOWS: SUN ELEVATION below hor.el set to 0 - binary mask
		"""
        selMask = sp.sel
        selMask[selMask < horel] = 0
        selMask[selMask > 0] = 1
        self.selMask = selMask
        """
		derive incident radiation on slope accounting for self shading and cast 
		shadow and solar geometry
		BOTH formulations seem to be broken
		"""
        #self.SWfdirCor=selMask*(cosis/cosic)*self.SWfdir # this is really wrong!
        #self.SWfdirCor=(cosis/cosic)*self.SWfdir
        self.SWfdirCor = dprod * self.SWfdir * selMask  # this is bad WHYYY?
        #self.SWfdirCor=dprod*self.SWfdir
        self.SWfglob = self.SWfdiff + self.SWfdirCor
        #self.SWfglob = self.SWfdiff+ self.SWfdir
        """ 
示例#2
0
        def swin1D(pob, sob, tob, stat, dates, index):
            # many arrays transposed
            """ toposcale surface pressure using hypsometric equation - move to own 
				class 

				index: index of station array (numeric)
				"""
            g = 9.81
            R = 287.05  # Gas constant for dry air.
            tz = 0  # ERA5 is always utc0, used to compute sunvector
            ztemp = pob.z[:, index, :].T
            Ttemp = pob.t[:, index, :].T
            statz = stat.ele[index] * g
            dz = ztemp.T - statz  # transpose not needed but now consistent with CGC surface pressure equations

            psf = []
            # loop through timesteps
            #for i in range(starti,endi):
            for i in range(0, dates.size):

                # 	# find overlying layer
                thisp = dz[:, i] == np.min(dz[:, i][dz[:, i] > 0])

                # booleen indexing
                T1 = Ttemp[i, thisp]
                z1 = ztemp[i, thisp]
                p1 = pob.levels[thisp] * 1e2  #Convert to Pa.
                Tbar = np.mean([T1, tob.t[i, index]], axis=0)
                """ Hypsometric equation."""
                psf.append(p1 * np.exp((z1 - statz) * (g / (Tbar * R))))

            psf = np.array(psf).squeeze()

            ## Specific humidity routine.
            # mrvf=0.622.*vpf./(psf-vpf); #Mixing ratio for water vapor at subgrid.
            #  qf=mrvf./(1+mrvf); # Specific humidity at subgrid [kg/kg].
            # fout.q(:,:,n)=qf;
            """ Maybe follow Dubayah's approach (as in Rittger and Girotto) instead
				for the shortwave downscaling, other than terrain effects. """
            """ Height of the "grid" (coarse scale)"""
            Zc = sob.z[:, index]  # should this be a single value or vector?
            """ toa """
            SWtoa = sob.tisr[:, index]
            """ Downwelling shortwave flux of the "grid" using nearest neighbor."""
            SWc = sob.ssrd[:, index]
            """Calculate the clearness index."""
            kt = SWc / SWtoa

            #kt[is.na(kt)==T]<-0 # make sure 0/0 =0
            #kt[is.infinite(kt)==T]<-0 # make sure 0/0 =0
            kt[kt < 0] = 0
            kt[kt > 1] = 0.8  #upper limit of kt
            kt = kt
            """
				Calculate the diffuse fraction following the regression of Ruiz-Arias 2010 
				
				"""
            kd = 0.952 - 1.041 * np.exp(-1 * np.exp(2.3 - 4.702 * kt))
            kd = kd
            """ Use this to calculate the downwelling diffuse and direct shortwave radiation at grid. """
            SWcdiff = kd * SWc
            SWcdir = (1 - kd) * SWc
            SWcdiff = SWcdiff
            SWcdir = SWcdir
            """ Use the above with the sky-view fraction to calculate the 
				downwelling diffuse shortwave radiation at subgrid. """
            SWfdiff = stat.svf[index] * SWcdiff
            SWfdiff = np.nan_to_num(SWfdiff)  # convert nans (night) to 0
            """ Direct shortwave routine, modified from Joel. 
				Get surface pressure at "grid" (coarse scale). Can remove this
				part once surface pressure field is downloaded, or just check
				for existance. """

            ztemp = pob.z[:, index, :].T
            Ttemp = pob.t[:, index, :].T
            dz = ztemp.transpose() - sob.z[:, index]

            psc = []
            for i in range(0, dz.shape[1]):

                #thisp.append(np.argmin(dz[:,i][dz[:,i]>0]))
                thisp = dz[:, i] == np.min(dz[:, i][dz[:, i] > 0])
                z0 = sob.z[i, index]
                T0 = sob.t2m[i, index]
                T1 = Ttemp[i, thisp]
                z1 = ztemp[i, thisp]
                p1 = pob.levels[thisp] * 1e2  #Convert to Pa.
                Tbar = np.mean([T0, T1], axis=0)
                """ Hypsometric equation."""
                psc.append(p1 * np.exp((z1 - z0) * (g / (Tbar * R))))

            psc = np.array(psc).squeeze()

            #T1=Ttemp(thisp)
            #z1=ztemp(thisp)
            #p1=pob.levels(thisp)*1e2 #Convert to Pa.
            #Tbar=mean([T0 T1])
            """compute julian dates"""
            jd = sg.to_jd(dates)
            """
				Calculates a unit vector in the direction of the sun from the observer 
				position.
				"""
            sunv = sg.sunvector(jd=jd,
                                latitude=stat.lat[index],
                                longitude=stat.lon[index],
                                timezone=tz)
            """
				Computes azimuth , zenith  and sun elevation 
				for each timestamp
				"""
            sp = sg.sunpos(sunv)
            sp = sp

            # Cosine of the zenith angle.
            sp.zen = sp.zen
            #sp.zen=sp.zen*(sp.zen>0) # Sun might be below the horizon.
            muz = np.cos(sp.zen)
            muz = muz
            # NB! psc must be in Pa (NOT hPA!).
            #if np.max(psc<1.5e3): # Obviously not in Pa
            #psc=psc*1e2

            # Calculate the "broadband" absorption coefficient. Elevation correction
            # from Kris
            ka = (g * muz / (psc)) * np.log(SWtoa / SWcdir)
            #ka.set_fill_value(0)
            #ka = ka.filled()
            # set inf (from SWtoa/SWcdir at nigh, zero division) to 0 (night)
            ka[ka == -np.inf] = 0
            ka[ka == np.inf] = 0

            # Note this equation is obtained by inverting Beer's law, i.e. use
            #I_0=I_inf x exp[(-ka/mu) int_z0**inf rho dz]
            # Along with hydrostatic equation to convert to pressure coordinates then
            # solve for ka using p(z=inf)=0.

            # Now you can (finally) find the direct component at subgrid.
            SWfdir = SWtoa * np.exp(-ka * psf / (g * muz))
            """ Then perform the terrain correction. [Corripio 2003 / rpackage insol port]."""
            """compute mean horizon elevation - why negative hor.el possible??? """
            horel = (((np.arccos(np.sqrt(stat.svf[index])) * 180) / np.pi) *
                     2) - stat.slp[index]
            if horel < 0:
                horel = 0
            meanhorel = horel
            """
				normal vector - Calculates a unit vector normal to a surface defined by 
				slope inclination and slope orientation.
				"""
            nv = sg.normalvector(slope=stat.slp[index], aspect=stat.asp[index])
            """
				Method 1: Computes the intensity according to the position of the sun (sunv) and 
				dotproduct normal vector to slope.
				From corripio r package
				"""
            dotprod = np.dot(sunv, np.transpose(nv))
            dprod = dotprod.squeeze()
            dprod[dprod < 0] = 0  #negative indicates selfshading
            dprod = dprod
            """Method 2: Illumination angles. Dozier"""
            saz = sp.azi
            cosis = muz * np.cos(stat.slp[index]) + np.sin(
                sp.zen) * np.sin(stat.slp[index]) * np.cos(
                    sp.azi - stat.asp[index]
                )  # cosine of illumination angle at subgrid.
            cosic = muz  # cosine of illumination angle at grid (slope=0).
            """
				SUN ELEVATION below hor.el set to 0 - binary mask
				"""
            selMask = sp.sel
            selMask[selMask < horel] = 0
            selMask[selMask > 0] = 1
            selMask = selMask
            """
				derive incident radiation on slope accounting for self shading and cast 
				shadow and solar geometry
				BOTH formulations seem to be broken
				"""
            #SWfdirCor=selMask*(cosis/cosic)*SWfdir
            SWfdirCor = selMask * dprod * SWfdir

            SWfglob = SWfdiff + SWfdirCor
            return SWfglob
            """ 
示例#3
0
    def swin(self, pob, sob, tob, stat, dates):
        """ toposcale surface pressure using hypsometric equation - move to own 
		class 
		EDITS Jul 11 2019:
		- removed elevation scaling as this degrade results - at least in WFJ test- Kris?
		- reimplemnt original additative ele method - better than beers, or at least less damaging
		- removed mask, why is this causing problems?
		- dotprod method (corripio) does not seem to work - I dont think it ever did as we used SWTopo ==FALSE
		- use Dozier cos corrction method (as in paper right)
		- So ... we have ele, illumination angle, self shading and svf correction. We do not have horizon correction (partly in self shading of course)


		"""

        ztemp = pob.z
        Ttemp = pob.t
        statz = stat.ele * self.g
        dz1 = ztemp - statz  # transpose not needed but now consistent with CGC surface pressure equations
        dz = dz1.transpose()

        self.psf = []
        # loop through timesteps
        for i in range(0, dates.size):

            # 	# find overlying layer
            thisp = dz[:, i] == np.min(dz[:, i][dz[:, i] > 0])

            # booleen indexing
            T1 = Ttemp[i, thisp]
            z1 = ztemp[i, thisp]
            p1 = pob.levels[thisp] * 1e2  #Convert to Pa.
            Tbar = np.mean([T1, tob.t[i]], axis=0)
            """ Hypsometric equation."""
            self.psf.append(p1 * np.exp(
                (z1 - statz) * (self.g / (Tbar * self.R))))

        self.psf = np.array(self.psf).squeeze()

        ## Specific humidity routine.
        # mrvf=0.622.*vpf./(psf-vpf); #Mixing ratio for water vapor at subgrid.
        #  qf=mrvf./(1+mrvf); # Specific humidity at subgrid [kg/kg].
        # fout.q(:,:,n)=qf;
        """ Maybe follow Dubayah's approach (as in Rittger and Girotto) instead
		for the shortwave downscaling, other than terrain effects. """
        """ Height of the "grid" (coarse scale)"""
        Zc = sob.z
        """ toa """
        SWtoa = sob.tisr
        """ Downwelling shortwave flux of the "grid" using nearest neighbor."""
        SWc = sob.ssrd
        """Calculate the clearness index."""
        kt = SWc / SWtoa

        #kt[is.na(kt)==T]<-0 # make sure 0/0 =0
        #kt[is.infinite(kt)==T]<-0 # make sure 0/0 =0
        kt[kt < 0] = 0
        kt[kt > 1] = 0.8  #upper limit of kt
        self.kt = kt
        """
		Calculate the diffuse fraction following the regression of Ruiz-Arias 2010 
		
		"""
        kd = 0.952 - 1.041 * np.exp(-1 * np.exp(2.3 - 4.702 * kt))
        self.kd = kd
        """ Use this to calculate the downwelling diffuse and direct shortwave radiation at grid. """
        SWcdiff = kd * SWc
        SWcdir = (1 - kd) * SWc
        self.SWcdiff = SWcdiff
        self.SWcdir = SWcdir
        """ Use the above with the sky-view fraction to calculate the 
		downwelling diffuse shortwave radiation at subgrid. """
        self.SWfdiff = stat.svf * SWcdiff
        self.SWfdiff.set_fill_value(0)
        self.SWfdiff = self.SWfdiff.filled()
        """ Direct shortwave routine, modified from Joel. 
		Get surface pressure at "grid" (coarse scale). Can remove this
		part once surface pressure field is downloaded, or just check
		for existance. """

        ztemp = pob.z
        Ttemp = pob.t
        dz = ztemp.transpose() - sob.z

        self.psc = []
        for i in range(0, dz.shape[1]):

            #thisp.append(np.argmin(dz[:,i][dz[:,i]>0]))
            thisp = dz[:, i] == np.min(dz[:, i][dz[:, i] > 0])
            z0 = sob.z[i]
            T0 = sob.t2m[i]
            T1 = Ttemp[i, thisp]
            z1 = ztemp[i, thisp]
            p1 = pob.levels[thisp] * 1e2  #Convert to Pa.
            Tbar = np.mean([T0, T1], axis=0)
            """ Hypsometric equation."""
            self.psc.append(p1 * np.exp(
                (z1 - z0) * (self.g / (Tbar * self.R))))

        self.psc = np.array(self.psc).squeeze()

        #T1=Ttemp(thisp)
        #z1=ztemp(thisp)
        #p1=pob.levels(thisp)*1e2 #Convert to Pa.
        #Tbar=mean([T0 T1])
        """compute julian dates"""
        jd = sg.to_jd(dates)
        """
		Calculates a unit vector in the direction of the sun from the observer 
		position.
		"""
        sunv = sg.sunvector(jd=jd,
                            latitude=stat.lat,
                            longitude=stat.lon,
                            timezone=stat.tz)
        """
		Computes azimuth , zenith  and sun elevation 
		for each timestamp
		"""
        sp = sg.sunpos(sunv)
        self.sp = sp

        # Cosine of the zenith angle.
        sp.zen = sp.zen
        #sp.zen=sp.zen*(sp.zen>0) # Sun might be below the horizon.
        muz = np.cos(sp.zen)
        self.muz = muz
        # NB! psc must be in Pa (NOT hPA!).
        #if np.max(psc<1.5e3): # Obviously not in Pa
        #psc=psc*1e2

        # Calculate the "broadband" absorption coefficient. Elevation correction
        # from Kris
        ka = (self.g * muz / (self.psc)) * np.log(SWtoa / SWcdir)
        #ka.set_fill_value(0)
        #ka = ka.filled()

        # set inf (from SWtoa/SWcdir at nigh, zero division) to 0 (night)
        ka[ka == -np.inf] = 0
        ka[ka == np.inf] = 0
        # Note this equation is obtained by inverting Beer's law, i.e. use
        #I_0=I_inf x exp[(-ka/mu) int_z0**inf rho dz]
        # Along with hydrostatic equation to convert to pressure coordinates then
        # solve for ka using p(z=inf)=0.

        # Method 1 Beers law
        # Now you can (finally) find the direct component at subgrid.
        self.SWfdir = SWtoa * np.exp(-ka * self.psf / (self.g * muz))
        #self.SWfdir=SWcdir

        # Method 2 ORIGINAL ELEVATION Correction
        """ele diff in km"""
        coarseZ = Zc[0] / 9.9

        dz = (stat.ele - coarseZ) / 1000  # fine - coase in knm

        s = SWtoa
        b = SWcdir
        zen = sp.zen

        thetaz = (np.pi / 180) * zen  #radians
        m = 1 / np.cos(thetaz)
        k = -np.log(b / s) / m
        k.set_fill_value(0)
        k = k.filled()
        #k[is.na(k)==T]<-0 #correct b=0/s=0 problem

        t = np.exp(1)**(-k * dz * np.cos(thetaz))
        t[t > 1] < -1.1  #to constrain to reasonable values
        t[t < 0.8] < -0.9  #to constrain to reasonable values
        db = (1 - t) * SWcdir

        #self.SWfdir=SWcdir+db #additative correction

        #======================================
        """ Then perform the terrain correction. [Corripio 2003 / rpackage insol port]."""
        """compute mean horizon elevation - why negative hor.el possible??? """
        horel = (((np.arccos(np.sqrt(stat.svf)) * 180) / np.pi) * 2) - stat.slp
        if horel < 0:
            horel = 0
        self.meanhorel = horel
        """
		normal vector - Calculates a unit vector normal to a surface defined by 
		slope inclination and slope orientation.
		"""
        nv = sg.normalvector(slope=stat.slp, aspect=stat.asp)
        """
		Method 1: Computes the intensity according to the position of the sun (sunv) and 
		dotproduct normal vector to slope.
		From corripio r package REMOVE THIS
		"""
        dotprod = np.dot(sunv, np.transpose(nv))
        dprod = dotprod.squeeze()
        dprod[dprod < 0] = 0  #negative indicates selfshading
        self.dprod = dprod
        """Method 2: Illumination angles. Dozier and self shading"""
        saz = sp.azi
        cosis = muz * np.cos(
            stat.slp) + np.sin(sp.zen) * np.sin(stat.slp) * np.cos(
                sp.azi - stat.asp)  # cosine of illumination angle at subgrid.
        cosic = muz  # cosine of illumination angle at grid (slope=0).
        cosi = (cosis / cosic)

        #If ratio of illumination angle subgrid/ illum angle grid is negative the point is selfshaded
        cosi[cosi < 0] = 0
        """
		CAST SHADOWS: SUN ELEVATION below hor.el set to 0 - binary mask
		"""
        selMask = sp.sel
        selMask[selMask < horel] = 0
        selMask[selMask > 0] = 1
        self.selMask = selMask
        """
		derive incident radiation on slope accounting for self shading and cast 
		shadow and solar geometry
		BOTH formulations seem to be broken
		"""
        #self.SWfdirCor=selMask*(cosis/cosic)*self.SWfdir # this is really wrong!
        self.SWfdirCor = (cosis / cosic) * self.SWfdir
        self.SWfdirCor = selMask * dprod * self.SWfdir  # this is bad
        #self.SWfdirCor=dprod*self.SWfdir
        self.SWfglob = self.SWfdiff + self.SWfdirCor
        #self.SWfglob = self.SWfdiff+ self.SWfdir
        """