Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Solar Calculator - Calculate Sunrise, Sunset, and Maximum Solar Radiation

, 10 Jan 2011 CPOL
A C# assembly for calculating Sunrise, Sunset, and Maximum Solar Radiation
SolarCalculator.zip
Astronomy
Properties
AstronomyTest
Properties
ConsoleCalculator
Properties
Include
nunit.framework.dll
Rhino.Mocks.dll
// AstronomyTest.cs - NUnit Test Cases for Astronomy
//
// Patrick Kalkman  pkalkie@gmail.cm
//
// (C) 2003 Patrick Kalkman http://www.semanticarchitecture.net
//
using System;
using NUnit.Framework;

namespace Astronomy
{
   /// <summary>
   /// Test for the Sun related calculations.
   /// The test values of the declination of the sun are 
   /// taken from http://www.wsanford.com/~wsanford/exo/sundials/DEC_Sun.html
   /// The test values for sunrise and sunset are taken from 
   /// http://home.hccnet.nl/v.d.horn/weersverwachting/zonsopkomst_zonsondergang.htm
   /// The test values for maximum solar radiation are taken from
   /// solrad.xls (Solar position and radiation calculator for Microsoft Excel/VBA By Greg Pelletier)
   /// </summary>
   [TestFixture]
   public class SunCalculatorTest
   {
      [Test]
      public void SunRiseTestNetherlands()
      {
         TestSunRise(new DateTime(2010, 4, 1), new DateTime(2010, 4, 1, 7, 15, 0), CreateSunCalculatorForUtrecht(true));
         TestSunRise(new DateTime(2010, 9, 1), new DateTime(2010, 9, 1, 6, 51, 0), CreateSunCalculatorForUtrecht(true));
         TestSunRise(new DateTime(2010, 1, 10), new DateTime(2010, 1, 10, 8, 45, 0), CreateSunCalculatorForUtrecht(false));
      }

      [Test]
      public void SunRiseTestLosAngeles()
      {
         TestSunRise(new DateTime(2010, 5, 28), new DateTime(2010, 5, 28, 5, 45, 0), CreateSunCalculatorForLosAngeles(true));
         TestSunRise(new DateTime(2011, 1, 7), new DateTime(2011, 1, 7, 7, 00, 0), CreateSunCalculatorForLosAngeles(false));
      }

      [Test]
      public void SunSetTestLosAngeles()
      {
         TestSunSet(new DateTime(2010, 5, 28), new DateTime(2010, 5, 28, 19, 57, 0), CreateSunCalculatorForLosAngeles(true));
         TestSunSet(new DateTime(2011, 1, 7), new DateTime(2011, 1, 7, 17, 00, 0), CreateSunCalculatorForLosAngeles(false));
      }

      [Test]
      public void SunSetTestNetherlands()
      {
         TestSunSet(new DateTime(2010, 4, 1), new DateTime(2010, 4, 1, 20, 13, 0), CreateSunCalculatorForUtrecht(true));
         TestSunSet(new DateTime(2010, 9, 1), new DateTime(2010, 9, 1, 20, 28, 0), CreateSunCalculatorForUtrecht(true));
         TestSunSet(new DateTime(2010, 1, 10), new DateTime(2010, 1, 10, 16, 50, 0), CreateSunCalculatorForUtrecht(false));
      }

      [Test]
      public void CalculateDeclinationOfTheSunTestNetherlands()
      {
         TestDeclinationOfTheSunCalculation(10, -22.05);
         TestDeclinationOfTheSunCalculation(40, -14.56);
         TestDeclinationOfTheSunCalculation(60, -8.03);
      }

      [Test]
      public void CalculateMaximumSolarRadiationTestNetherlands()
      {
         TestMaximumSolarRadiation(new DateTime(2010, 1, 24, 13, 0, 0), 261.62, false);
         TestMaximumSolarRadiation(new DateTime(2010, 1, 26, 16, 30, 0), 76.79, false);
         TestMaximumSolarRadiation(new DateTime(2010, 5, 1, 12, 0, 0), 717.65, true);
      }

      private static void TestMaximumSolarRadiation(DateTime dateTimeToCalculate, double expectedMaximumRadiation, bool useSummerTime)
      {
         //A difference of max 150 W/m2 is acceptable.
         SunCalculator sunCalculator = CreateSunCalculatorForUtrecht(useSummerTime);
         double maximumSolarRadiation = sunCalculator.CalculateMaximumSolarRadiation(dateTimeToCalculate);
         Assert.AreEqual(expectedMaximumRadiation, maximumSolarRadiation, 150);
      }

      private static void TestSunRise(DateTime sunRiseDateTime, DateTime expectedSunRiseDateTime, SunCalculator sunCalculator)
      {
         //A difference of max 15 minutes is acceptable.
         DateTime sunRise = sunCalculator.CalculateSunRise(sunRiseDateTime);
         TimeSpan difference = expectedSunRiseDateTime - sunRise;
         Assert.LessOrEqual(Math.Abs(difference.Minutes), 15);
      }

      private static void TestSunSet(DateTime sunSetDateTime, DateTime expectedSunSetDateTime, SunCalculator sunCalculator)
      {
         //A difference of max 15 minutes is acceptable.
         DateTime sunSet = sunCalculator.CalculateSunSet(sunSetDateTime);
         TimeSpan difference = expectedSunSetDateTime - sunSet;
         Assert.LessOrEqual(Math.Abs(difference.Minutes), 15);
      }

      private static void TestDeclinationOfTheSunCalculation(int dayNumber, double expectedValueInDegrees)
      {
         //A difference of 0.05 is acceptable.
         double expectedValueInRadians = expectedValueInDegrees * Math.PI / 180;
         SunCalculator sun = new SunCalculator();
         double calculatedDeclinationOfTheSun = sun.CalculateDeclination(dayNumber);
         Assert.AreEqual(expectedValueInRadians, calculatedDeclinationOfTheSun, 0.05);
      }

      private static SunCalculator CreateSunCalculatorForUtrecht(bool useSummerTime)
      {
         const Double LongituteUtrechtNetherlands = 5.127869;
         const Double LatitudeUtrechtNetherlands = 52.108192;
         return CreateSunCalculator(LongituteUtrechtNetherlands, LatitudeUtrechtNetherlands, 15, useSummerTime);
      }

      private static SunCalculator CreateSunCalculatorForLosAngeles(bool useSummerTime)
      {
         const Double LongituteLosAngeles = -118.243685;
         const Double LatitudeLosAngeles = 34.052234;

         return CreateSunCalculator(LongituteLosAngeles, LatitudeLosAngeles, -120, useSummerTime);
      }

      private static SunCalculator CreateSunCalculator(double longitude, double latitude, long longituteTimeZone, bool useSummerTime)
      {
         return new SunCalculator(longitude, latitude, longituteTimeZone, useSummerTime);
      }
   }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Patrick Kalkman
Architect http://www.hinttech.nl
Netherlands Netherlands
Patrick Kalkman is a senior Software Architect with more than 20 years professional development experience. He works for Hinttech where he develops state of the art web applications.

Patrick enjoys writing his blog. It discusses software architectures using semantic web technologies. Patrick can be reached at pkalkie@gmail.com.
 
Published Windows 8 apps:
 
Published Windows Phone apps:
 
Awards:

Best Mobile article of March 2012
Best Mobile article of June 2012
Follow on   Twitter

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411023.1 | Last Updated 10 Jan 2011
Article Copyright 2010 by Patrick Kalkman
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid