PHY 411-506 Home Home  |  Course Outline  |  Lectures  |  Homework  |  Files

Lecture 38: April 25


The Gutenberg-Richter Law

Every year, very large numbers of earthquakes of different magnitudes occur on Earth. The distribution of earthquake sizes follows the Gutenberg-Richter Law.

There are a small number of extremely large earthquakes with magnitude greater than 7 each year, for example approximately 13 in 2000, and 5 in January of this year.

One-dimensional sandpile automaton

The following applet is based on the program Sandpile.java, which is similar to PROGRAM sandpile on page 519 of the textbook.

Here is the code which generates this applet:

// Sandpile.java

import comphys.graphics.*;
import comphys.Easy;
import java.awt.*;
import java.awt.event.*;

public class Sandpile extends Animation {

    int L = 20;                 // length of pile
    int grains;                 // total grains added
    int lost;                   // grains lost off edge
    int[] height;               // height
    int[] slope;                // local slope
    int[] change;               // change in height in toppling event
    int criticalSlope = 1;      // topples if slope > critSlope
    boolean random;             // add grain at random position
    boolean unstable;           // pile is unstable
    boolean[] move;             // move unstable grains to neighbor sites
    int t;                      // time step
    int[] N;                    // accumulate number of topplings
    int[] E;                    // accumulate avalanche sizes
    int maxHeight;              // for plotting

    void initial () {
        if (height == null || height.length < L) {
            height = new int[L];
            slope = new int[L];
            change = new int[L];
            move = new boolean[L];
            N = new int[L];
            E = new int[L];
        }
        for (int i = 0; i < L; i++) {
            height[i] = slope[i] = change[i] = 0;
            move[i] = false;
        }
        for (int i = 0; i < N.length; i++)
            N[i] = 0;
        for (int i = 0; i < E.length; i++)
            E[i] = 0;
        maxHeight = L;
        unstable = false;
        grains = lost = 0;
        t = 0;
    }

    int topplings;
    int unstableSites;

    void checkStability () {
        unstable = false;
        for (int i = 0; i < L; i++) {
            if (slope[i] > criticalSlope) {
                unstable = move[i] = true;
                ++unstableSites;
            } else {
                move[i] = false;
            }
        }
        if (unstable) {
            ++topplings;
        } else {
            if (unstableSites > E.length - 1) {
                int len = E.length;
                int[] temp = new int[unstableSites + 10];
                for (int i = 0; i < len; i++)
                    temp[i] = E[i];
                E = temp;
            }
            ++E[unstableSites];
            unstableSites = 0;
            if (topplings > N.length - 1) {
                int len = N.length;
                int[] temp = new int[topplings + 10];
                for (int i = 0; i < len; i++)
                    temp[i] = N[i];
                N = temp;
            }
            ++N[topplings];
            topplings = 0;
            ++t;
        }
    }

    void timeStep () {
        for (int i = 0; i < L; i++) {
            height[i] += change[i];
            change[i] = 0;
            if (height[i] > maxHeight)
                maxHeight = height[i];
        }
        for (int i = 0; i < L - 1; i++)
            slope[i] = height[i] - height[i + 1];
        slope[L - 1] = height[L - 1];
        checkStability();
        if (unstable) {
            for (int i = 0; i < L; i++) {
                if (move[i]) {
                    change[i] -= criticalSlope;
                    unstableSites += criticalSlope;
                    for (int j = 1; j <= criticalSlope; j++) {
                        if (i + j < L)
                            change[i + j] += 1;
                        else
                            ++lost;
                    }
                }
            }
        } else {                // add grain
            int site = 0;
            if (random)
                site = (int) (L * Math.random());
            change[site] = 1;
            ++grains;
        }
    }

    class Pile extends Plot {
        Pile () {
            setSize(300, 300);
        }
        
        public void paint () {
            clear();
            setWindow(0, maxHeight + 1, 0, maxHeight + 1);
            setColor("yellow");
            for (int i = 0; i < L; i++) {
                for (int j = 0; j < outer.height[i]; j++) {
                    if (j == outer.height[i] + change[i])
                        break;
                    boxArea(i + 0.1, i + 0.9, j + 0.1, j + 0.9);
                }
            }
            setColor("red");
            for (int i = 0; i < L; i++) {
                for (int j = outer.height[i]; j < outer.height[i] + change[i]; j++)
                    boxArea(i + 0.1, i + 0.9, j + 0.1, j + 0.9);
            }
        }
    }

    class PowerLaw extends Plot {
        PowerLaw () {
            setSize(300, 300);
        }

        // power law plot and exponent
        int maxIndex;
        double[] logData;
        double exponent;
        void analyze (int[] data) {
            if (logData == null || logData.length < data.length)
                logData = new double[data.length];
            maxIndex = 0;
            int numValues = 0;
            double maxValue = 0;
            double xAv = 0, yAv = 0, xxAv = 0, xyAv = 0;
            for (int i = 0; i < data.length; i++) {
                double value = 0;
                if (data[i] > 0) {
                    maxIndex = i;
                    value = Math.log(data[i]);
                    if (value > maxValue)
                        maxValue = value;
                    xAv += i;
                    yAv += value;
                    xxAv += i * (double) i;
                    xyAv += i * value;
                    ++numValues;
                } else {
                    logData[i] = 0;
                }
                logData[i] = value;
            }
            exponent = 0;
            if (numValues > 0) {
                for (int i = 0; i <= maxIndex; i++) {
                    logData[i] /= maxValue;
                }
                xAv /= numValues;
                yAv /= numValues;
                xxAv /= numValues;
                xyAv /= numValues;
                exponent = (xyAv - xAv * yAv) / (xxAv - xAv * xAv);
            }
        }

        public void paint () {
            clear();
            setWindow(-0.1, 1.1, -0.15, 2.25);
            // topplings
            setColor("green");
            analyze(N);
            if (maxIndex == 0)
                return;
            for (int i = 0; i <= maxIndex; i++) {
                double x1 = i / (maxIndex + 1.0);
                double x2 = (i + 1) / (maxIndex + 1.0);
                double y1 = 1.1;
                double y2 = 1.1 + logData[i];
                boxArea(x1, x2, y1, y2);
            }
            plotStringLeft("power = " + Easy.format(exponent, 3), 1, 2.0);
            setColor("black");
            plotString("log(N)", 0, 2.15);
            plotLine(0, 1.1, 1, 1.1);
            plotLine(0, 1.1, 0, 2.1);
            double d = 0.5 / (maxIndex + 1);
            plotStringCenter("0", d, 1);
            plotStringCenter("Topplings", 0.5, 1);
            plotStringCenter("" + maxIndex, 1 - d, 1);
            // unstable sites
            setColor("blue");
            analyze(E);
            if (maxIndex == 0)
                return;
            for (int i = 0; i <= maxIndex; i++) {
                double x1 = i / (maxIndex + 1.0);
                double x2 = (i + 1) / (maxIndex + 1.0);
                double y1 = 0;
                double y2 = logData[i];
                boxArea(x1, x2, y1, y2);
            }
            plotStringLeft("power = " + Easy.format(exponent, 3), 1, 0.9);
            setColor("black");
            d = 0.5 / (maxIndex + 1);
            plotLine(0, 0, 1, 0);
            plotLine(0, 0, 0, 1);
            plotStringCenter("0", d, -0.1);
            plotStringCenter("Unstable sites", 0.5, -0.1);
            plotStringCenter("" + maxIndex, 1 - d, -0.1);
        }
    }

    class Output extends Plot {
        Output () {
            setSize(610, 30);
        }

        public void paint () {
            clear();
            setWindow(0, 100, 0, 3);
            setColor("blue");
            boxArea(0, 100, 0, 3);
            setColor("white");
            plotString("Time step " + t, 5, 1);
            plotStringCenter("Grains added " + grains, 30, 1);
            plotStringCenter("Grains lost " + lost, 50, 1);
            plotString("Topplings " + topplings, 65, 1);
            plotString("Unstable sites " + unstableSites, 80, 1);
        }
    }

    Pile pile;
    PowerLaw powerLaw;
    Output output;
    Reader LReader, criticalSlopeReader, skipReader;
    Checkbox randomBox;
    int skip;

    public void init () {
        initial();
        add(pile = new Pile());
        add(powerLaw = new PowerLaw());
        add(output = new Output());
        add(LReader = new Reader("L = ", L));
        add(criticalSlopeReader = new Reader("Critical slope", criticalSlope));
        add(skipReader = new Reader("Skip steps", skip));
        add(randomBox = new Checkbox("Add random", random));
        randomBox.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent ie) {
                random = randomBox.getState();
            }
        });
        addControlPanel();
    }

    public void step () {
        for (int s = 0; s < skip; s++)
            timeStep();
        timeStep();
        pile.repaint();
        powerLaw.repaint();
        output.repaint();
    }

    public void reset () {
        L = LReader.readInt();
        criticalSlope = criticalSlopeReader.readInt();
        skip = skipReader.readInt();
        initial();
        pile.repaint();
        powerLaw.repaint();
        output.repaint();
    }

    Sandpile outer;
    public Sandpile () {
        super();
        outer = this;
    }

    public static void main (String[] args) {
        Sandpile sandpile = new Sandpile();
        sandpile.frame("One-dimensional sandpile", 650, 500);
    }
}


UB Physics Home Questions or comments: phygons@acsu.buffalo.edu