More Grumbine Science: Technical followup on the simplest climate model
<?xml version="1.0" encoding="UTF-8"?>
<!--Xholon Workbook http://www.primordion.com/Xholon/wb/ (C) Ken Webb Sun Jun 03 2012 16:23:44 GMT-0400 (EDT)-->
<XholonWorkbook>
<Notes><![CDATA[
Xholon
------
Title: More Grumbine Science: Technical followup on the simplest climate model
Description:
Url: http://moregrumbinescience.blogspot.ca/2012/03/technical-followup-on-simplest-climate.html
InternalName:
YoutubeId:
Keywords:
My Notes
--------
Robert Grumbine, in his More Grumbine Science blog, has several posts discussing a simplest meaningful climate model, with a focus on the Earth's atmosphere. In this workbook, I'll start with an earlier post from August 5, 2008, where he presents the following, with explanations, as the simplest model::
T = (S*(1-a)/r^2/4/s)^(1/4)
His result is T = 255 K (-18 C, 0 F), where T is the temperature at the top of Earth's atmosphere as measured by satellites. Read the blog posts for details.
In my calculations, I don't use the r value, which is the distance from the Sun to the Earth. It is not needed for now because it has a value of 1 astronomical unit, and 1^2 is still just 1. The value of S is the solar constant in Watts per square meter (W/m^2) at that distance, so r is redundant. Instead of 1/4, I directly use 0.25. Instead of s = 5.67*10^(-8), I use the equivalent s = 5.67e-8 .
On this page I am implementing 3 versions of the model, any of which can be edited directly on this page ::
1. Python
2. JavaScript
3. Xholon Workbook with JavaScript and jQuery
How to run the Python version with Ubuntu Linux (the operating system I'm using) ::
Copy the Python code from the editor below.
Open a linux terminal and enter "python".
Paste the Python code into the Python interpreter, and press the Enter key.
How to run the Python version at ideone.com ::
Enter the following URL in your browser
http://ideone.com/Hgm51
How to run the JavaScript version ::
Click the Run button above.
Copy the JavaScript code from the editor below.
Paste the code into the textarea in the overlay.
Click the Submit button in the overlay.
Observe the answer in the textarea in the overlay.
How to run the Xholon Workbook version ::
Click the Run button above.
Observe the answer in the textarea in the overlay.
Note that the source code (XML, JavaScript/jQuery) for the Xholon Workbook version is distributed across four different editors further down on this page. You can edit the content in any of these editors, and then press Refresh and Step to try the changes.
How to play with the input values while the Xholon Workbook version is running ::
method 1
Change the value in the ClimateSystem editor below.
Click Refresh in the overlay (or Run above).
Click Step to generate a new result.
method 2
This method requires Firefox with Firebug, or a similar environment.
Right-click SolarConstant in the overlay, and select "Inspect element with Firebug".
Firebug will open and highlight the corresponding HTML element.
Use Firebug to edit the val, which has an initial value of 1367.
Click the Step button in the overlay.
Observe the changed value of the Temperature, in Firebug and in the overlay textarea.
How to run the Xholon Workbook version in a separate browser tab or window ::
Click the "Run this workbook" link further down on the page.
Click the Step button on the new page.
A Wikipedia page has a similar model which calculates the average Earth temperature, in the atmosphere near the surface I believe. See the "Zero-dimensional models" section ::
http://en.wikipedia.org/wiki/Global_climate_model
My Xholon Workbook version can generate their result of 288 K after editing the contents of the ClimateSystembehavior editor below. In line 2, change ::
(4 * this.s.attr("val"))
to ::
(4 * 0.612 * this.s.attr("val"))
where 0.612 is the effective emissivity of Earth.
Other related posts include (from earliest to latest) ::
http://moregrumbinescience.blogspot.ca/2008/07/earth-temperature-1.html
* "the temperature as observed from space", and how satellites measure the Earth's temperature
* satellites typically observe a temperature several kilometers above the surface
* the Stefan-Boltzmann constant relates energy and temperature
http://moregrumbinescience.blogspot.ca/2008/08/simplest-meaningful-climate-model.html
* "the model is missing something important that affects the surface temperature, but not the temperature the earth shows to space. Whatever it is, its average effect is about 33 K (60 F)"
* includes a spreadsheet implementation of the model
http://moregrumbinescience.blogspot.ca/2008/08/building-simplest-climate-model.html
* "Where did the simplest model come from?"
* Robert explains the calculation in more detail
http://moregrumbinescience.blogspot.ca/2008/08/analyzing-simplest-climate-model.html
* what happens if you systematically change different input values in the calculation? Try it
http://moregrumbinescience.blogspot.ca/2008/09/summary1-of-simplest-climate-model.html
* some extra discussion
* one commenter includes links to other sites that have similar simple models with explanations
http://moregrumbinescience.blogspot.ca/2012/03/return-of-simplest-climate-model.html
* "a different approach"
* a new spreadsheet
* one commenter introduces a Python implementation
Also see my previous climate change models implemented in Java ::
http://www.primordion.com/Xholon/jnlp/
Links to the models are located toward the bottom of the page.
More *June 3 2012*
----
I've spent some time with Robert's spreadsheet, which contains two different calculations ::
(1) a one-time calculation, which is what I've re-implemented above, and
(2) an iterated calculation
Today I'll work on the iterated calculation. I've added XML structure and JavaScript code to the editors further down on this page.
How to run the iterated calculation ::
Click the Run button above.
Observe the one-time Temperature value in the textarea in the overlay.
Click the Pause button in the overlay, to unpause and start-up the simulation.
Continue to pause and unpause (using the Pause button), and optionally step one timestep at a time (using the Step button).
Compare with the values in Robert's spreadsheet
http://www.radix.net/~bobg/blogsupport/simplest2.ods
The results are the same as in the spreadsheet. My results are in tab-separated-value format (tsv), so they can be copied and pasted into a OpenOffice or Excel spreadsheet.
]]></Notes>
<script implName="lang:python:inline:"><![CDATA[
# this is a Python implementation of Robert's model
import math
S = 1367.0 # solar constant = 1367 Watts per square meter
a = 0.30 # albedo = a value between 0.0 and 1.0
s = 5.67e-8 # Stefan-Boltzman constant = 5.67*10^(-8)
T = math.pow((S * (1.0 - a)) / (4 * s), 0.25)
print "Temperature = " + str(T)
# result: Temperature = 254.862463154
]]></script>
<script implName="lang:javascript:inline:"><![CDATA[
// this is a JavaScript implementation of Robert's model
var S = 1367.0; // solar constant = 1367 Watts per square meter
var a = 0.30; // albedo = a value between 0.0 and 1.0
var s = 5.67e-8; // Stefan-Boltzman constant = 5.67*10^(-8)
var T = Math.pow((S * (1.0 - a)) / (4 * s), 0.25);
print("Temperature = " + T + "\n");
// result: Temperature = 254.86246315361737
]]></script>
<_-.XholonClass>
<!-- types of domain objects -->
<ClimateSystem/>
<!-- Robert has two types of calculations in his spreadsheet -->
<Calculation>
<OnetimeCalculation/>
<IteratedCalculation/>
</Calculation>
<!-- types of objects that are common to both calculations -->
<SolarConstant/>
<Albedo superClass="Dimensionless"/>
<StefanBoltzmanConstant/>
<Temperature/>
<!-- types of objects only used in the iterated calculation -->
<Rate/>
<Sd/>
</_-.XholonClass>
<xholonClassDetails>
<OnetimeCalculation>
<port name="S" connector="#xpointer(SolarConstant)"/>
<port name="a" connector="#xpointer(Albedo)"/>
<port name="s" connector="#xpointer(StefanBoltzmannConstant)"/>
<port name="T" connector="#xpointer(Temperature)"/>
</OnetimeCalculation>
<IteratedCalculation>
<port name="Sc" connector="#xpointer(SolarConstant)"/>
<port name="Albedo" connector="#xpointer(Albedo)"/>
<port name="sigma" connector="#xpointer(StefanBoltzmannConstant)"/>
<port name="Temperature" connector="#xpointer(Temperature[1])"/>
<port name="Tprime" connector="#xpointer(Temperature[2])"/>
<port name="t0" connector="#xpointer(Temperature[3])"/>
<port name="rate" connector="#xpointer(Rate)"/>
<port name="sd" connector="#xpointer(Sd)"/>
</IteratedCalculation>
</xholonClassDetails>
<ClimateSystem>
<OnetimeCalculation>
<SolarConstant>1367.0 W/m^2</SolarConstant> <!-- Sc -->
<Albedo>0.30</Albedo> <!-- this is a dimensionless value, with no units -->
<StefanBoltzmannConstant>5.67e-8</StefanBoltzmannConstant> <!-- sigma -->
<Temperature>0.0 K</Temperature> <!-- this is the value to be calculated, measured in degrees Kelvin -->
</OnetimeCalculation>
<IteratedCalculation>
<SolarConstant>1367.0 W/m^2</SolarConstant> <!-- Sc -->
<Albedo>0.0</Albedo> <!-- this is a dimensionless value, with no units -->
<StefanBoltzmannConstant>5.67e-8</StefanBoltzmannConstant> <!-- sigma -->
<Temperature>288.0 K</Temperature> <!-- initial value of "Temperature" -->
<Temperature>0.0 K</Temperature> <!-- initial value of "T'" Tprime -->
<Temperature>255.0 K</Temperature> <!-- value of "t0" -->
<Rate>0.01</Rate>
<Sd>10</Sd>
</IteratedCalculation>
</ClimateSystem>
<Blockbehavior implName="lang:python:inline:"><![CDATA[
]]></Blockbehavior>
<Blockbehavior implName="lang:javascript:inline:"><![CDATA[
]]></Blockbehavior>
<ClimateSystembehavior implName="lang:webEditionjs:inline:"><![CDATA[
function postConfigure() {
$("textarea#btstrp_console").css("font-family", '"Courier New", Monospaced');
$("textarea#btstrp_console").css("font-size", "11px");
$("textarea#btstrp_console").attr("rows", "20");
$("textarea#btstrp_console").attr("cols", "60");
}
]]></ClimateSystembehavior>
<OnetimeCalculationbehavior implName="lang:webEditionjs:inline:"><![CDATA[
function postConfigure() {
// =((1-0.3)*sc/4/sigma)^0.25 (this is the calculation performed in the spreadsheet)
// spreadsheet result: 254.8624631536
this.bindPorts(this.parent());
this.T.attr("val", Math.pow((this.S.attr("val") * (1.0 - this.a.attr("val"))) / (4 * this.s.attr("val")), 0.25));
print("\nOne-time Calculation Temperature = " + this.T.attr("val") + " " + this.T.attr("unit"));
// my result: Temperature = 254.86246315361737 K
}
]]></OnetimeCalculationbehavior>
<IteratedCalculationbehavior implName="lang:webEditionjs:inline:"><![CDATA[
function postConfigure() {
this.bindPorts(this.parent());
print("\n\nIterated Calculation");
print("\nIteration\tTemperature\tAlbedo\t\tTprime");
print("\n---------\t-----------\t------\t\t------");
// Albedo =0.8-0.5*EXP((-1)*(B2-t0)^2/2/sd^2)
var albedo = 0.8 - (0.5 * Math.exp((-1) * Math.pow(parseFloat(this.Temperature.attr("val")) - parseFloat(this.t0.attr("val")), 2) / 2 / Math.pow(parseFloat(this.sd.attr("val")), 2)));
this.Albedo.attr("val", albedo);
// Tprime =(sc*(1-C2)/4/sigma)^(1/4)
var tprime = Math.pow(parseFloat(this.Sc.attr("val")) * (1.0 - albedo) / 4 / parseFloat(this.sigma.attr("val")), 0.25);
this.Tprime.attr("val", tprime);
}
function act() {
this.bindPorts(this.parent());
print("\n" + this.application("getTimeStep")
+ "\t\t" + parseFloat(this.Temperature.attr("val")).toFixed(1)
+ "\t\t" + parseFloat(this.Albedo.attr("val")).toFixed(3)
+ "\t\t" + parseFloat(this.Tprime.attr("val")).toFixed(1));
// Temperature =B2+(D2-B2)*rate
var temperature = parseFloat(this.Temperature.attr("val"));
temperature = temperature + (this.Tprime.attr("val") - temperature) * this.rate.attr("val");
this.Temperature.attr("val", temperature);
// Albedo =0.8-0.5*EXP((-1)*(B2-t0)^2/2/sd^2)
var albedo = 0.8 - (0.5 * Math.exp((-1) * Math.pow(parseFloat(this.Temperature.attr("val")) - parseFloat(this.t0.attr("val")), 2) / 2 / Math.pow(parseFloat(this.sd.attr("val")), 2)));
this.Albedo.attr("val", albedo);
// Tprime =(sc*(1-C2)/4/sigma)^(1/4)
var tprime = Math.pow(parseFloat(this.Sc.attr("val")) * (1.0 - albedo) / 4 / parseFloat(this.sigma.attr("val")), 0.25);
this.Tprime.attr("val", tprime);
}
]]></IteratedCalculationbehavior>
<Blockbehavior implName="lang:bsh:inline:"><![CDATA[
]]></Blockbehavior>
<Blockbehavior implName="lang:jruby:inline:"><![CDATA[
]]></Blockbehavior>
<Blockbehavior implName="lang:groovy:inline:"><![CDATA[
]]></Blockbehavior>
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml,
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Climate System</title>
<rect id="ClimateSystem" fill="#98FB98" height="50" width="50" x="25" y="0"/>
</g>
</svg>
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient>
</XholonWorkbook>