<?xml version="1.0" encoding="UTF-8"?>
<!--Xholon Workbook http://www.primordion.com/Xholon/wb/ (C) Ken Webb Fri Jun 01 2012 17:14:42 GMT-0400 (EDT)-->
<XholonWorkbook>
<Notes><![CDATA[
Xholon
------
Title: This Week's Finds (Week 319)
Description:
Url: http://math.ucr.edu/home/baez/week319.html
InternalName:
YoutubeId:
Keywords:
My Notes
--------
John Baez' April 11, 2012 post is about "a climate model that runs on your web browser". John discusses a simple zero-dimensional energy balance model, that is quite similar to the model by Robert Grumbine that I discussed in my last post::
http://www.primordion.com/Xholon/wb/openwb.php?q=2402129&f=gist.github.com/raw/
The way the mathematics is presented is quite different, including the names of the variables. But it involves roughly the same quantities. The model is from a not-yet published book::
Gerald R. North, Simple Models of Global Climate.
Basic formula to use ::
Q = (A + B * T) / c
where A and B are given
Try different values of T and c
The page includes a slider that dynamically changes a graph built by Allan Erskine using JSXGraph. JSXGraph is something I need to learn more about. See ::
http://www.primordion.com/Xholon/wb/openwb.php?q=2406972&f=gist.github.com/raw/
This Xholon Workbook does a partial implementation of the Baez Erskine model. I've captured their variables inside a simple hierarchically-organized network structure, and written a few lines of JavaScript to confirm the formulae for calculating Coalbedo (c) and AverageInsolation (Q). To run this very simple model as an app in your web browser ::
Click the Run button at the top of this page.
Click the Step button.
The JavaScript will print the values of some variables.
Click the Step button again.
The JavaScript will recalculate the value of the AverageInsolation (Q).
The only purpose of this exercise is for me to take some notes, and quickly confirm some of what's in the April 11 post.
More **June 1 2012**
----
I'm adding the coalbedo graph from the Baez Erskine model, reusing much of the original JavaScript code, along with the JSXGraph and MathJax libraries. The code is in the ClimateSystembehavior editor located further down on this page. Feel free to edit the code and rerun or refresh the app.
]]></Notes>
<script implName="lang:python:inline:"><![CDATA[
print "a climate model that runs on your web browser"
]]></script>
<script implName="lang:javascript:inline:"><![CDATA[
print("\na simple zero-dimensional energy balance model");
]]></script>
<_-.XholonClass>
<!-- types of domain objects -->
<ClimateSystem/>
<!-- this type of model only involves 3 types of things -->
<!-- 1. "the average temperature of the Earth" -->
<Temperature/> <!-- average temperature of the Earth in ° Celcius -->
<!-- 2. "the average solar radiation coming in" -->
<SolarConstant/> <!-- "the solar power per square meter that would hit a panel hovering in space above the Earth's atmosphere and facing directly at the Sun" -->
<AverageInsolation/> <!-- Q "the amount of solar power per square meter hitting the top of the Earth's atmosphere, averaged over location and time of year" -->
<Albedo/>
<Coalbedo/> <!-- c(T) "the fraction of solar power that gets absorbed. The coalbedo depends on the temperature" -->
<!-- 3. "the average infrared radiation going out" -->
<!--<StefanBoltzmanConstant/>--> <!-- not used in this model; uses A and B constants instead -->
<Parameter/> <!-- A B C -->
</_-.XholonClass>
<xholonClassDetails>
<ClimateSystem>
<port name="S" connector="#xpointer(SolarConstant)"/>
<port name="Q" connector="#xpointer(AverageInsolation)"/>
<port name="a" connector="#xpointer(Albedo)"/>
<port name="c" connector="#xpointer(Coalbedo)"/>
<port name="T" connector="#xpointer(Temperature)"/>
<port name="A" connector="#xpointer(Parameter[1])"/>
<port name="B" connector="#xpointer(Parameter[2])"/>
<port name="C" connector="#xpointer(Parameter[3])"/>
</ClimateSystem>
</xholonClassDetails>
<ClimateSystem>
<SolarConstant>1367.0 W/m^2</SolarConstant>
<AverageInsolation>0.0 W/m^2</AverageInsolation> <!-- this value can be calculated -->
<Albedo>0.278</Albedo> <!-- this is a dimensionless value, with no units; 0.30 or 0.278 -->
<Coalbedo>0.0</Coalbedo> <!-- this value can be calculated -->
<!--<Temperature>0.0 °C</Temperature>--> <!-- this is the value to be calculated, measured in degrees Celcius -->
<Temperature>15.0 °C</Temperature> <!-- this is approximately the average yearly surface temperature of the Earth -->
<Parameter roleName="A">218 W/m^2</Parameter> <!-- watts/meter squared -->
<Parameter roleName="B">1.90 W/m^2</Parameter> <!-- watts/meter squared per degree Celsius -->
<Parameter roleName="C">5e6 J</Parameter> <!-- Earth's heat capacity in joules per degree per square meter, about 5 million joules per degree Celsius -->
</ClimateSystem>
<Blockbehavior implName="lang:python:inline:"><![CDATA[
# This works if pasted in as a last child of Block.
#height.incVal(0.02)
#print("Python wants something to do. Height:" + str(height))
]]></Blockbehavior>
<Blockbehavior implName="lang:javascript:inline:"><![CDATA[
// This works if pasted in as a last child of Block.
//height.incVal(0.02);
//print("JavaScript wants something to do. Height:" + height + "\n");
]]></Blockbehavior>
<ClimateSystembehavior implName="lang:webEditionjs:inline:"><![CDATA[
function postConfigure() {
this.xholoncreationservice('requireScript', 'jsxgraphcore.js');
this.xholoncreationservice('requireStyle', 'jsxgraph.css');
this.xholoncreationservice('requireScript', 'MathJax.js?config=default', 'http://cdn.mathjax.org/mathjax/latest/');
}
function act() {
this.bindPorts(this.parent());
if (this.application("getTimeStep") == 0) {
print("\nS = " + this.S.attr("val"));
print("\nQ = " + this.Q.attr("val"));
print("\na = " + this.a.attr("val"));
print("\nc = " + this.c.attr("val"));
// The following code is from the Baez Erskine model.
// use the existing SVG div, and remove any content it has
var coalbedoCharts = $("div#mySVGDiv");
coalbedoCharts.css("position", "relative").css("width", "300px").css("width", "300px");
coalbedoCharts.empty();
//coalbedoCharts.append('<div id="temperature-box" class="jxgbox" style="width:500px; height:500px; position:absolute; top:0px; left:0px;"></div>');
coalbedoCharts.append('<div id="coalbedo-box" class="jxgbox" style="position:absolute; width:280px; height:180px; top:0px; left:0px;"></div>');
// globals
var T_AXIS_LABEL = "\\(T\\)";
var Q_AXIS_LABEL = "\\(Q_\\textrm{eq}\\)";
var COALBEDO_T_AXIS_LABEL = "\\(T\\)";
var COALBEDO_AP_AXIS_LABEL = "\\(c\\)";
// gamma slider globals
var MIN_g = 0.0, START_g = 0.05, MAX_g = 0.1, STEP_g = 0.001;
var GAMMA_SLIDER_LABEL = "transition rate \\(\\gamma\\) from icy coalbedo \\(c_i\\) to ice-free coalbedo \\(c_f\\)";
// global constants used in model
var INSOLATION_A = this.A.attr("val") - 0, // watts per square meter
INSOLATION_RATE_B = this.B.attr("val") - 0, // watts per square meter per celsius
HEAT_CAPACITY_C = this.C.attr("val") - 0;
// rational approximation to tanh, as gratefully scraped from SO:
// http://stackoverflow.com/questions/6118028/fast-hyperbolic-tangent-approximation-in-javascript
function rational_tanh(x) {
if ( x < -3 ) return -1.0;
else if ( x > 3 ) return 1.0;
else return x * ( 27 + x * x ) / ( 27 + 9 * x * x );
}
function tanh(x) {
return rational_tanh(x);
}
function coalbedo(g, T) {
var ai = 0.35; // ice-i planet
var af = 0.7; // ice-free planet
var ap = ai + 0.5 * (af - ai) * (1.0 + tanh(g * T));
return ap;
}
/*function insolationEq(g, T) {
var A = INSOLATION_A;
var B = INSOLATION_RATE_B;
var ap = coalbedo(g, T);
var Qeq = (A + B * T) / ap;
return Qeq;
}*/
// JSXGraph setup
JXG.Options.text.useMathJax = true;
// setup the board for coalbedo graph
var coalbedoBoard = JXG.JSXGraph.initBoard(
'coalbedo-box',
{boundingbox: [-50, 0.75, 50, -0.1], axis:true, showCopyright:false, showNavigation:false, pan:false}
);
// setup the slider and add some text to label it
var s=coalbedoBoard.create('slider', [[-45,0.2],[35,0.2],[MIN_g,START_g,MAX_g]],{snapWidth:STEP_g});
coalbedoBoard.create('text', [-48, 0.1, function(){return GAMMA_SLIDER_LABEL; }]);
coalbedoBoard.create('functiongraph', [function(T){return coalbedo(s.Value(), T);}], {strokeWidth:3, highlight:false});
coalbedoBoard.create('text', [43, -0.05, function(){return COALBEDO_T_AXIS_LABEL;}]);
coalbedoBoard.create('text', [1, 0.6, function(){return COALBEDO_AP_AXIS_LABEL;}]);
} // end if
else {
print("\nQ = " + this.Q.attr("val"));
}
}
]]></ClimateSystembehavior>
<AverageInsolationbehavior implName="lang:webEditionjs:inline:"><![CDATA[
function act() {
// these 2 different ways of calculating Q should produce similar values
this.bindPorts(this.parent().parent());
if (this.application("getTimeStep") == 0) {
this.Q.attr("val", this.S.attr("val") / 4);
}
else {
var A = this.A.attr("val") - 0;
var B = this.B.attr("val") - 0;
var T = this.T.attr("val") - 0;
var c = this.c.attr("val") - 0;
var Q = (A + (B * T)) / c;
this.Q.attr("val", Q);
}
}
]]></AverageInsolationbehavior>
<Coalbedobehavior implName="lang:webEditionjs:inline:"><![CDATA[
function act() {
if (this.application("getTimeStep") == 0) {
this.bindPorts(this.parent().parent());
this.c.attr("val", 1 - this.a.attr("val"));
}
}
]]></Coalbedobehavior>
<Blockbehavior implName="lang:bsh:inline:"><![CDATA[
// This works if pasted in as a last child of Block.
//height.incVal(0.02);
//System.out.print("Java/Beanshell wants something to do. Height:" + height + "\n");
]]></Blockbehavior>
<Blockbehavior implName="lang:jruby:inline:"><![CDATA[
#require 'java'
# This works if pasted in as a last child of Block.
#$height.incVal(0.02)
#puts "Ruby wants something to do. Height: #{$height}"
]]></Blockbehavior>
<Blockbehavior implName="lang:groovy:inline:"><![CDATA[
// This works if pasted in as a last child of Block.
//height.incVal(0.02);
//System.out.print("Groovy wants something to do. Height:" + height + "\n");
]]></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>Block</title>
<rect id="PhysicalSystem/Block" 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>