<?xml version="1.0" encoding="UTF-8"?>
<!--Xholon Workbook http://www.primordion.com/Xholon/wb/ (C) Ken Webb Mon May 21 2012 16:24:14 GMT-0400 (EDT)-->
<XholonWorkbook>
<Notes><![CDATA[
Xholon
------
Title: Using probablities to think about climate
Description:
Url: http://www.primordion.com/Xholon/wb/
InternalName:
YoutubeId:
Keywords:
My Notes
--------
How to run the app that's contained within this workbook ::
Click the Run button above.
Click the Step button (or Pause button) in the overlay.
Watch the temperature and other values.
Watch the exchange of messages between nodes.
This workbook explores the climate using some basic principles, and probabilities. It includes a very simple qualitative climate model. None of the numbers used here are intended to be correct, but are only used to show increases or decreases. The atmosphere and surface objects have temperatures measured in arbitrary degrees X. The model includes a few pools of energy (Sun, Earth's Atmosphere, Earth's Surface) measured as temperatures, that interact by sending photon radiation messages to each other.
How to view the exchange of messages between nodes, as a sequence diagram ::
Go to the following URL
http://www.websequencediagrams.com/
Copy all or some of the text (complete lines) from the textarea in the overlay.
Paste the text into the input area on the sequence diagram page.
The page generates and displays a PNG image.
How to demonstrate the conservation of energy and mass ::
Run the app long enough that all the charged particles in the Sun are converted to photons.
Sum all the counts.
The sum should equal the number of charged particles originally in the Sun. But until the energy in the system is converted to longwave and reflected shortwave photons in space, the sum may be one or a few units off. At any given time step, some of the energy is in the form of photon messages.
This works because the app makes simplistic and quantitatively-incorrect assumptions ::
that one unit of charged particles equals one unit of shortwave photon radiation,
that the energy in a unit of shortwave radiation equals the energy in a unit of longwave radiation,
that one unit of temperature equals one unit of radiation
Some basic principles ::
* A photon moves at the speed of light.
* Mass and energy are never created or destroyed, but only converted into other forms of mass or energy.
More information ::
* When a photon strikes the surface of the Earth and does not reflect back into the atmosphere, it ceases to be a photon. It can no longer travel at the speed of light. Another way of saying this is that it's rest mass is zero. A photon's energy is absorbed by whatever is close at hand on the ground. The surface heats up.
* The atmosphere is assumed to include greenhouse gases such as Carbon Dioxide. When a longwave photon strikes a carbon dioxide molecule, it may be absorbed by the molecule. The carbon dioxide molecule becomes more energetic. When it bangs into other molecules in the atmosphere, such as Oxygen and Nitrogen, some of the energy is taken by those molecules. The temperature of the atmosphere increases. Eventually, the energy is converted back into a photon, in this case a longwave photon. These new photons move in all directions. Eventually, 50% of them will move up into space, and 50% of them will be absorbed by the Earth's surface.
* In the app, photons are sent as HTML elements, but never become part of the HTML on the web page. They can only exist when in motion.
Sequence Diagrams ::
* Interactions between nodes are implemented by sending messages. Each message represents a shortwave (sunlight) or longwave (heat) photon. Each message is printed to the textarea in the overlay.
* Each message has
* a signal that defines what type of message it is
* optional data
* a sender
* a receiver
TODO ::
Use more probabilites
Include greenhouse and other gases as nodes within the atmosphere
See also ::
http://en.wikipedia.org/wiki/Photon
http://en.wikipedia.org/wiki/Conservation_of_energy
http://en.wikipedia.org/wiki/Conservation_of_mass-energy#Conservation_of_mass_and_energy
http://en.wikipedia.org/wiki/Sequence_diagram
]]></Notes>
<script implName="lang:python:inline:"><![CDATA[
import random
# Generate a pseudorandom number greater than or equal to 0.0 and less than 1.0
print random.random()
# Simulate the roll of a six-sided die, generating integers between 1 and 6
print random.randint(1, 6)
]]></script>
<script implName="lang:javascript:inline:"><![CDATA[
// Generate a pseudorandom number greater than or equal to 0.0 and less than 1.0
print("\n" + Math.random());
// Simulate the roll of a six-sided die, generating integers between 1 and 6
print("\n" + Math.ceil(Math.random() * 6));
]]></script>
<_-.XholonClass>
<!-- types of domain objects -->
<PhysicalSystem/>
<SolarSystem/>
<!-- large container objects -->
<Sun/>
<Space/>
<Earth/>
<Atmosphere/>
<Surface/>
<!-- small objects -->
<Photon>
<ShortwavePhoton/>
<LongwavePhoton/>
</Photon>
<Molecule>
<Hydrogen/>
<Helium/>
<Nitrogen/>
<Oxygen/>
<CarbonDioxide/>
</Molecule>
<!-- probabilities -->
<Probability/>
<!-- quantities -->
<Energy/>
<Temperature/> <!-- degrees X °X -->
<!-- counters -->
<Counter>
<ReflectedSwPhotonsFromAtmosphere/>
<ReflectedSwPhotonsFromSurface/>
<LwPhotonsFromAtmosphere/>
</Counter>
<!-- collections of objects -->
<ChargedParticles/>
<Probabilities/>
</_-.XholonClass>
<xholonClassDetails>
<Sun>
<port name="space" connector="#xpointer(ancestor::SolarSystem/Space)"/>
</Sun>
<Space>
<port name="earth" connector="#xpointer(ancestor::SolarSystem/Earth/Atmosphere)"/>
<port name="swAtm" connector="#xpointer(ReflectedSwPhotonsFromAtmosphere)"/>
<port name="swSrf" connector="#xpointer(ReflectedSwPhotonsFromSurface)"/>
<port name="lwAtm" connector="#xpointer(LwPhotonsFromAtmosphere)"/>
</Space>
<Atmosphere>
<port name="space" connector="#xpointer(ancestor::SolarSystem/Space)"/>
<port name="surface" connector="#xpointer(ancestor::Earth/Surface)"/>
<port name="temperature" connector="#xpointer(Temperature)"/>
<port name="pReflect" connector="#xpointer(ancestor::PhysicalSystem/Probabilities/Probability[@roleName='pReflectByAtmosphere'])"/>
<port name="pEmit" connector="#xpointer(ancestor::PhysicalSystem/Probabilities/Probability[@roleName='pEmitByAtmosphere'])"/>
<port name="pEmitUp" connector="#xpointer(ancestor::PhysicalSystem/Probabilities/Probability[@roleName='pEmitUpByAtmosphere'])"/>
</Atmosphere>
<Surface>
<port name="atmosphere" connector="#xpointer(ancestor::Earth/Atmosphere)"/>
<port name="temperature" connector="#xpointer(Temperature)"/>
<port name="pReflect" connector="#xpointer(ancestor::PhysicalSystem/Probabilities/Probability[@roleName='pReflectBySurface'])"/>
<port name="pEmit" connector="#xpointer(ancestor::PhysicalSystem/Probabilities/Probability[@roleName='pEmitBySurface'])"/>
</Surface>
</xholonClassDetails>
<PhysicalSystem>
<SolarSystem>
<Sun>
<!--
The Sun is made of plasma, "an electrically neutral medium of positive and negative particles" (Wikipedia: Sun, Plasma).
I'll guess there are about 1e40 charged particles in the Sun (1 with 40 zeros after it).
Wikipedia says Sun has mass of about 2e30 kg.
I'll make it 1 billion (1e9 1000000000) for now.
For now, it's set to 1000, which makes testing easier.
-->
<ChargedParticles>1000</ChargedParticles>
</Sun>
<Space>
<!-- counters -->
<ReflectedSwPhotonsFromAtmosphere>0</ReflectedSwPhotonsFromAtmosphere>
<ReflectedSwPhotonsFromSurface>0</ReflectedSwPhotonsFromSurface>
<LwPhotonsFromAtmosphere>0</LwPhotonsFromAtmosphere>
</Space>
<Earth>
<Atmosphere>
<Temperature unit="°X">0.0</Temperature> <!-- initial temperature -->
</Atmosphere>
<Surface>
<Temperature unit="°X">0.0</Temperature> <!-- initial temperature -->
</Surface>
</Earth>
</SolarSystem>
<!-- a probability is a number between 0.0 (never happens) and 1.0 (always happens) -->
<Probabilities>
<!-- the probability that an incoming shortwave photon will be reflected by the atmosphere -->
<Probability roleName="pReflectByAtmosphere">0.1</Probability>
<!-- the probability that an incoming shortwave photon will be reflected by the surface -->
<Probability roleName="pReflectBySurface">0.2</Probability>
<!-- the probability that the surface will emit a longwave photon, where surface temperature = 0.0 °C -->
<Probability roleName="pEmitBySurface">0.1</Probability>
<!-- the probability that the atmosphere will emit a longwave photon, atmosphere surface temperature = 0.0 °C -->
<Probability roleName="pEmitByAtmosphere">0.1</Probability>
<!-- the probability that a longwave photon from the atmosphere will be emitted up (toward space) rather than down (toward the surface) -->
<Probability roleName="pEmitUpByAtmosphere">0.5</Probability>
</Probabilities>
</PhysicalSystem>
<Blockbehavior implName="lang:python:inline:"><![CDATA[
]]></Blockbehavior>
<Blockbehavior implName="lang:javascript:inline:"><![CDATA[
]]></Blockbehavior>
<PhysicalSystembehavior implName="lang:webEditionjs:inline:"><![CDATA[
function postConfigure() {
$("textarea#btstrp_console").css("font-size", "11px");
$("textarea#btstrp_console").attr("rows", "10");
$("textarea#btstrp_console").attr("cols", "67");
var $this = this.parent();
$this.css("font-size", "14px");
$this.find(".SolarSystem").css("background-color", "black").css("color", "white").click();
$this.find(".Sun").css("background-color", "yellow").css("color", "black").click();
$this.find(".Space").css("background-color", "black").css("color", "white").click();
$this.find(".Earth").css("background-color", "#CD853F").click();
$this.find(".Atmosphere").css("background-color", "#4169E1").click();
$this.find(".Surface").css("background-color", "#3CB371").click();
print("\ntitle Using probablities to think about climate");
}
]]></PhysicalSystembehavior>
<Sunbehavior implName="lang:webEditionjs:inline:"><![CDATA[
function act() {
var sun = this.parent();
this.bindPorts(sun);
var amount = 1;
var plasma = sun.children(".ChargedParticles");
if (plasma.attr("val") > 0) {
plasma.decVal(amount);
plasma.text(plasma.getXhcName() + " " + plasma.attr("val"));
// assume that the Sun converts 1 unit of plasma into 1 unit of photons (where the units are unspecified)
var photonText = '';
for (var i = 0; i < amount; i++) {
photonText += '<div class="ShortwavePhoton"></div>';
}
var photons = $(photonText);
// send shortwave (SW) photons
this.space.sendMessage("SIG_SW", photons, sun);
}
}
]]></Sunbehavior>
<Spacebehavior implName="lang:webEditionjs:inline:"><![CDATA[
function processReceivedMessage(msg) {
var space = this.parent();
this.bindPorts(space);
switch (msg.signal) {
case "SIG_SW":
print("\n" + msg.sender.getXhcName() + "->" + msg.receiver.getXhcName() + ": " + msg.signal);
// assume that all the photons are directed toward the Earth
this.earth.sendMessage(msg.signal, msg.data, space);
break;
case "SIG_LW":
print("\n" + msg.sender.getXhcName() + "->" + msg.receiver.getXhcName() + ": " + msg.signal);
var lw = this.lwAtm;
lw.incVal(1);
lw.text(lw.getXhcName() + " " + lw.attr("val"));
break;
case "SIG_SW_REFLECTED":
print("\n" + msg.sender.getXhcName() + "->" + msg.receiver.getXhcName() + ": " + msg.signal);
var sw = null;
if (msg.sender.getXhcName() == "Atmosphere") {
sw = this.swAtm;
}
else { // "Surface"
sw = this.swSrf;
}
sw.incVal(1);
sw.text(sw.getXhcName() + " " + sw.attr("val"));
break;
default: break;
}
}
]]></Spacebehavior>
<Atmospherebehavior implName="lang:webEditionjs:inline:"><![CDATA[
function processReceivedMessage(msg) {
var atmosphere = this.parent();
this.bindPorts(atmosphere);
switch (msg.signal) {
case "SIG_SW":
print("\n" + msg.sender.getXhcName() + "->" + msg.receiver.getXhcName() + ": " + msg.signal);
if (Math.random() < parseFloat(this.pReflect.attr("val"))) {
// reflect the shortwave photon back to space
msg.sender.sendMessage("SIG_SW_REFLECTED", msg.data, atmosphere);
}
else {
this.surface.sendMessage(msg.signal, msg.data, atmosphere);
}
break;
case "SIG_LW":
print("\n" + msg.sender.getXhcName() + "->" + msg.receiver.getXhcName() + ": " + msg.signal);
var t = this.temperature;
t.incVal(1);
t.text(t.getXhcName() + " " + t.attr("val") + " " + t.attr("unit"));
break;
case "SIG_SW_REFLECTED":
// relay the shortwave photon back to space
this.space.sendMessage(msg.signal, msg.data, msg.sender);
break;
default: break;
}
}
function act() {
var atmosphere = this.parent();
this.bindPorts(atmosphere);
var t = this.temperature;
if (t.attr("val") > 0) {
// eventually, 50% of the temperature is radiated to space as longwave photons, and 50% to the surface
var r = Math.random();
if (r < 0.25) {
t.decVal(1);
this.space.sendMessage("SIG_LW", '<div class="LongwavePhoton"></div>', atmosphere);
}
else if (r >= 0.75) {
t.decVal(1);
this.surface.sendMessage("SIG_LW", '<div class="LongwavePhoton"></div>', atmosphere);
}
t.text(t.getXhcName() + " " + t.attr("val") + " " + t.attr("unit"));
}
}
]]></Atmospherebehavior>
<Surfacebehavior implName="lang:webEditionjs:inline:"><![CDATA[
function processReceivedMessage(msg) {
var surface = this.parent();
this.bindPorts(surface);
switch (msg.signal) {
case "SIG_SW":
print("\n" + msg.sender.getXhcName() + "->" + msg.receiver.getXhcName() + ": " + msg.signal);
if (Math.random() < parseFloat(this.pReflect.attr("val"))) {
msg.sender.sendMessage("SIG_SW_REFLECTED", msg.data, surface);
}
else {
// the photon is transformed into surface energy (heat and/or motion)
var t = this.temperature;
t.incVal(1);
t.text(t.getXhcName() + " " + t.attr("val") + " " + t.attr("unit"));
}
break;
case "SIG_LW":
print("\n" + msg.sender.getXhcName() + "->" + msg.receiver.getXhcName() + ": " + msg.signal);
var t = this.temperature;
t.incVal(1);
t.text(t.getXhcName() + " " + t.attr("val") + " " + t.attr("unit"));
break;
default: break;
}
}
function act() {
var surface = this.parent();
this.bindPorts(surface);
var t = this.temperature;
if (t.attr("val") > 0) {
t.decVal(1);
t.text(t.getXhcName() + " " + t.attr("val") + " " + t.attr("unit"));
this.atmosphere.sendMessage("SIG_LW", '<div class="LongwavePhoton"></div>', surface);
}
}
]]></Surfacebehavior>
<Probabilitiesbehavior implName="lang:webEditionjs:inline:"><![CDATA[
function postConfigure() {
this.parent().children(".Probability").each( function() {
var p = $(this);
p.text(p.attr("roleName") + " " + p.attr("val"));
});
this.remove();
}
]]></Probabilitiesbehavior>
<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>Using probablities to think about climate</title>
<rect id="PhysicalSystem" 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>