/* Copyright 2000 Charles G. Wright
* This software may be distributed under the terms of the
* GNU General Public License.
*
* $Id: SOLsurfaceBase.java,v 1.1 2000-06-15 10:15:04-05 chuckles Exp chuckles $
*/
import java.math.*;
import java.awt.*;
import java.awt.event.*;
/**
This class represents a surface of specific area exposed to the sun.
* The SOLorientation object required by the constructor specifies
* the surface's orientation and location on Earth's surface. This object
* defines the area and ground reflectance.
*
It contains methods to calculate:
*
- diffuse irradiance
*
- diffuse radiation
*
- diffuse irradiance simple
*
- diffuse radiation simple
*
- ground reflected irradiance
*
- ground reflected radiation
*
- direct irradiance
*
- direct radiation
*
- total radiation
*/
public class SOLsurfaceBase{
// Instance variables
public double area;
/** Name of object. Useful when displaying multiple instances of
* SOLsurfaceBase.*/
public String name;
// Ground Reflectance.
/** Ground reflectance associated with this surface. Between 0 and 1.*/
public double rho;
protected SOLorientation orientation;
protected SOLlocation location;
// Following are coefficients for calculation of Diffuse
// irradiance deviations from simple model (from Perez).
private static final double[] F11 = {-0.008, 0.130, 0.330, 0.568, 0.873, 1.132, 1.060, 0.678};
private static final double[] F12 = { 0.588, 0.683, 0.487, 0.187, -0.392, -1.237, -1.6, -0.327};
private static final double[] F13 = {-0.062, -0.151, -0.221, -0.295, -0.362, -0.412, -0.359, -0.25};
private static final double[] F21 = {-0.060, -0.019, 0.055, 0.109, 0.226, 0.288, 0.264, 0.156};
private static final double[] F22 = { 0.072, 0.066, -0.064, -0.152, -0.462, -0.823, -1.127, -1.377};
private static final double[] F23 = {-0.022, -0.029, -0.026, -0.014, 0.001, 0.056, 0.131, 0.251};
/** Create a SOLsurfaceBase object, given
*
- A SOLorientation object,
*
- The area of the surface (m2),
*
- The ground reflectance.
*/
public SOLsurfaceBase(SOLorientation orientation, double area, double rho, String name){
this.orientation = orientation;
// Add this surface to the list of surfaces at this orientation.
orientation.surfaces.addElement(this);
this.area = area;
this.location = orientation.location;
this.rho = rho;
this.name = name;
}
//-------------------------- private methods --------------------------
// clearness index
private double getClearness(double Dh, double I, double Z){
double kZ3 = 1.041 * Z * Z * Z;
double clearness = (((Dh + I) / Dh) + kZ3)/(1 + kZ3);
//System.out.println("[getClearness]: clearness=" + clearness + " Dh=" + Dh + " I=" + I + " Z=" + Z);
return(clearness);
}
// brightness index - Dh = Diffuse Horizontal, h = elevation (meters), alt = solar altitude (degrees)
private double getBrightness(double Dh, double h, double alt){
//calculate relative optical air mass
double pp0 = 1.0 - (h / 10000);
double m = pp0 / (Math.sin(SOLlocation.toRadians(alt)) + 0.50572 * Math.pow(alt + 6.07995, -1.6364));
double brightness = Dh * m / 1353;
//System.out.println("[getBrightness]: Dh="+Dh+" m="+m+" brightness="+brightness);
return(brightness);
}
private int findF1F2Index(double Dh, double I, int daynum, int solar_time, double Z){
int i = 1;
double clearness = getClearness(Dh, I, Z);
for (; i < 9; i++){
if (clearness < (i)) return(i-1);
}
// System.out.println("shouldn't be here");
return(i-2);
}
//------------------------ Public methods -----------------------------------
//--------------------- diffuse, perez ---------------------------------------
/** Return diffuse irradiance on the surface, calculated according to
* Perez (1990) (in Watts/m2), given
* - Diffuse Horizontal Irradiance (Dh),
*
- Direct Normal Irradiance (I),
*
- Day Number in the year (daynum),
*
- Elevation at the site.
*/
public double getDiffuseIrradiance(double Dh, double I, int daynum, int solar_time){
if (Dh > 0.0){
double alt = location.getSolarAltitude(daynum, solar_time);
//keep zenith angle in radians
double Z = SOLlocation.toRadians(90.0 - alt);
double cos_theta = orientation.getCosTheta(daynum, solar_time);
double ab = Math.max(0.0, cos_theta) / Math.max(0.087, Math.cos(Z));
double beta = SOLlocation.toRadians(orientation.surface_tilt);
//System.out.println("-----------------------------------------");
//System.out.println("[getDiffuseIrradiance]: Dh=" + Dh + " I=" + I + " daynum=" + daynum + " stime=" +
// solar_time + " Z=" + Z + " cos theta=" + cos_theta);
int i = findF1F2Index(Dh, I, daynum, solar_time, Z);
double brightness = getBrightness(Dh, location.elevation, alt);
double F1 = F11[i] + (F12[i] * brightness) + (F13[i] * Z);
double F2 = F21[i] + (F22[i] * brightness) + (F23[i] * Z);
//System.out.println(F11[i]+" "+F12[i]+" "+F13[i]+" "+F21[i]+" "+F22[i]+" "+F23[i]);
double costerm = Math.cos(beta/2);
// isotropic component
double r1 = (1 - F1)* costerm * costerm;
// circumsolar component
double r2 = F1 * ab;
// horizon and zenith component
double r3 = F2 * Math.sin(beta);
double ratio = r1 + r2 + r3;
double Dhsurface = Dh * ratio;
//System.out.println("ratio="+ratio+" r1="+r1+" r2="+r2+" r3="+r3+" cos_theta= "+cos_theta);
//System.out.println("F1="+F1+" F2="+F2+" ab="+ab+" Dh="+Dh+
// " Dhsurface="+Dhsurface+" tilt="+orientation.surface_tilt);
return(Dhsurface);
} else {
return(0.0);
}
}
/** Return diffuse radiation on the surface (in Watts),
* calculated according to Perez (1990),
* given
* - Diffuse Horizontal Irradiance (Dh),
*
- Direct Normal Irradiance (I),
*
- Day Number in the year (daynum),
*
- Elevation at the site.
*/
public double getDiffuseRadiation(double Dh, double I, int daynum, int solar_time){
return getDiffuseIrradiance(Dh, I, daynum, solar_time) * area;
}
//------------------------------------------------------------------------
//------------------- simple diffuse ----------------------
/** Return diffuse irradiance (in Watts/m2) by the simpler formula,
* Dh(cos2(tilt)), given
* Diffuse horizontal irradiance.
*/
public double getDiffuseIrradianceSimple(double Dh){
double costerm = Math.cos(SOLlocation.toRadians((orientation.surface_tilt) / 2));
return(Dh * costerm * costerm);
}
/** Return diffuse Radiation on the surface (in Watts) by the simpler formula,
* Dh(cos2(tilt)), given
* Diffuse horizontal irradiance.
*/
public double getDiffuseRadiationSimple(double Dh){
return getDiffuseIrradianceSimple(Dh) * area;
}
//------------------------------------------------------------
//----------------- ground reflected -------------------------------
/** Return ground reflected irradiance on the surface (in Watts/m2), given
*- The global horizontal irradiance (W/m2)
*
- The ground reflectance.
*/
public double getGroundReflectedIrradiance(double Ih){
double beta = SOLlocation.toRadians(orientation.surface_tilt);
double sinterm = Math.sin(beta / 2);
return(rho * Ih * sinterm * sinterm);
}
/** Return ground reflected radiation on the surface, given
*- The global horizontal irradiance (in Watts)
*
- The ground reflectance.
*/
public double getGroundReflectedRadiation(double Ih){
return getGroundReflectedIrradiance(Ih) * area;
}
//------------------------------------------------------------------
//-------------------- direct ----------------------------------------
/** Return the direct irradiance on the surface (in W/m2), given
*- Direct normal irradiance,
*
- Day number in the year.
*/
public double getDirectIrradiance(double I, int daynum, int solar_time){
if (I > 0.0){
return (I * orientation.getCosTheta(daynum, solar_time));
} else {
return 0.0;
}
}
/** Return the direct radiation on the surface (in Watts), given
*- Direct normal irradiance,
*
- Day number in the year.
*/
public double getDirectRadiation(double I, int daynum, int solar_time){
if (I > 0.0){
return getDirectIrradiance(I, daynum, solar_time) * area;
} else {
return 0.0;
}
}
//---------------------------------------------------------------------
//----------------------- total -----------------------
/** Return the total irradiance (Watts/m2) on the surface, given
* - Diffuse horizontal irradiance (w/m2),
*
- Direct normal irradiance (w/m2),
*
- Global horizontal irradiance (w/m2),
*
- Day number in year,
- Elevation (meters).
*/
public double getTotalIncidentRadiation(double Dh, double I,
double Ih, int daynum,
int solar_time){
return (getDirectRadiation(I, daynum, solar_time) +
getGroundReflectedRadiation(Ih) +
getDiffuseRadiation(Dh, I, daynum, solar_time));
}
//-----------------------------------------------------
public String getName(){
return name;
}
public double getArea(){
return area;
}
public void setArea(double area){
this.area = area;
}
public void setRho(double rho){
this.rho = rho;
}
} /* End of class SOLsurfaceBase */