Моделирование планеты маргариток +25


Моделирование планеты маргариток


  1. Лирика
  2. Описание интерфейса
  3. Декомпозиция
  4. Модель
  5. Логика

1. Лирика


Давным-давно, не помню где, я узнал об одном удивительном эксперименте, начало описания было такое: Представьте себе планету, примерно такую, как Земля, которая вращается вокруг звезды примерно такой, как Солнце. На планете есть жизнь, но не очень разнообразная — всего два вида маргариток — черные и белые. Представили? Какой заход! Автор красавчик, почти Экзюпери.

Далее описывался эксперимент: В начальной точке маргаритки есть только в виде семян, а планета настолько холодна, что на экваторе температура на грани выживания. Тем не менее прорастает несколько маргариток черных и белых, и они даже начинают цвести. Белая маргаритка, из-за своей большой отражательной способности отражает больше света, чем зеленые листики и коричневая земля, в этом месте локально становится холодней, и она замерзает. Вокруг черной маргаритки, наоборот возникает небольшая прогретая зона, так как она поглощает больше энергии от звезды. Маргаритка начинает чувствовать себя лучше, цветет, а потом, в прогретую землю бросает свои семена. Из этих семян прорастают еще несколько черных маргариток (потому что родитель у них черный), цветение этих маргариток прогревает еще больший участок, на котором может расти еще больше маргариток, и они тоже будут черными, потому что здесь оставляют семена только черные маргаритки.

Таким образом, потепление, вызванное цветением черных маргариток, провоцирует еще большее распространение черных маргариток, которые в свою очередь прогревают больше площади вокруг себя, и так по кругу. Таким образом черные маргаритки захватывают экваториальную область, но дальше распространяться не могут — там слишком холодно.

Однако такое бурное цветение черных маргариток уменьшает отражательную способность всей планеты (альбедо), это повлияет на баланс поглощенной/отраженной энергии в планетарном масштабе, что приводит к повышению эффективной температуры планеты, то есть на всей планете становится теплей. После этого черные маргаритки еще немного расширяют свои территории на юг и на север, что в свою очередь приводит к еще большему глобальному потеплению. Таким образом черные маргаритки пробираются к полюсам, а планета разогревается.

Но не нужно забывать — на планете стало теплее, и теперь есть все условия для роста и белых маргариток тоже. Более того, по мере прогрева, на экваторе становится все жарче, а черные маргаритки еще сильнее утепляют землю вокруг себя, и в этом районе им становится все более некомфортно. Не то, что белым маргариткам, которые отражают больше энергии, и создают вокруг себя приятную прохладную зону, в которой им хорошо расти, и туда же отбрасывать семена. Ну вы поняли — белые теснят с экватора черных. Но тут сюрприз — альбедо планеты снова увеличивается из-за больших площадей белых маргариток, планета холодеет и в конечном итоге наступает некоторое равновесие.

Далее автор не намерен оставлять планету в этом унылом для него, и комфортном для маргариток состоянии. Происходит вот что — Звезда, как у них это обычно бывает, начинает светиться ярче, и на планету падает больше энергии. Реакция планеты — увеличение площади распространения белых маргариток, увеличение альбедо — и снижение эффективной температуры, переход в новое равновесное состояние. Почти то же самое происходит при снижении светимости звезды, только появляется больше черных маргариток.

Вывод, который делает автор — биосфера сама себе создает комфортные температурные условия на планете в широких диапазонах светимости звезды. Авторов этого замечательного эксперимента зовут Джеймс Лавлок и Эндрю Уотсон. Кому интересны все выводы и более подробное описание см. Википедия — Маргаритковый мир, там написано больше и лучше. Смысл этого долгого вступления не пересказать статью из вики, а подвести к самому интересному — непосредственно проведению эксперимента. Автор статьи, описывающей эксперимент, задавал риторический вопрос: Рассуждения выглядят логично, но как провести такой эксперимент, где взять планету со звездой, с подходящими условиями, и как доставить туда семена маргариток? Даже если кому-то взбредет в голову использовать для этого Марс то у него ничего не получиться. Я был очень опечален таким поворотом потому, что большой фанат терраформирования и крутых экспериментов. Но автор, к моей большой радости, сказал, что такой эксперимент возможен с помощью компьютерного моделирования.

Ну конечно!!! Этот эксперимент, как бы собственно для компьютерного моделирования и был придуман, и даже достиг своей цели (ну то есть посрамил каких-то там двух мудрецов, см. вики). На этом отрезке повествования об эксперименте у меня прям сперло дыхание, потому что я подумал о счастливчиках, которые смотря на это описание, каким-то образом, превращают идею во что-то наглядное, доступное для того, чтобы посмотреть в реальном времени, «потрогать руками». При том, интересен был как сам процесс моделирования, так и проведение экспериментов. Прочитать эксперимент и подивиться выводам это одно, а «поиграть» с этой планетой, поэкспериментировать с разными условиями, это совсем другое. Но тогда я еще не мог программировать :(, но настали нынешние времена, к счастью, и поэтому предлагаю перейти от длинной и скучной лирики, к содержательной части. Кто просто хочет поиграть с планетой может переходить к описанию интерфейса, кого увлекает процесс моделирования к части под названием Декомпозиция и далее.

2. Описание интерфейса




В левой части расположено два блока Populator и Updater, в центральной части визуальное отображение планеты и некоторых параметров, в правой части графики изменения эффективной температуры и Звездной постоянной.

Управление осуществляется в блоках Populator и Updater.

В блоке Populator можно задать соотношение белых маргариток, черных маргариток и пустых ячеек, после нажатия кнопки Populate, планета будет заселена соответствующим образом. Заселить планету можно как в начале эксперимента, так и в любой другой момент, если понадобится.

Блок Updater отвечает за обновление модели планеты, в нем можно задать количество обновлений за раз, а также значение (допускаются отрицательные) и периодичность инкрементирования звездной постоянной (например, обновить 100 раз, при этом увеличивать звездную постоянную на 1 каждые две итерации).

Визуальное отображение планеты:

Белые кружочки — это районы с белыми маргаритками, черные — с черными, оливковые — пустые ячейки.

В левом верхнем углу текущие значения эффективной температуры по кельвину, звездной постоянной, альбедо и номер итерации.

Справа от планеты две цветовые шкалы: левая — для черных маргариток, правая для белых. Каждая точка шкалы соответствует температуре расположенного напротив пояса планеты. Легенда такая: Синий — слишком холодно для жизни, Желтый — жить можно, Зеленый — жить не только можно, но и комфортно, Красный — слишком жарко для жизни.

3. Декомпозиция


В приложении использован паттерн MVC, хотя в JavaFX, как известно вью и контролер немного слиплись, зато границы модели очерчены совершенно отчетливо.

Модель, в свою очередь, также разбита на часть, отвечающую за состояние, и часть, отвечающую за поведение, в лучших традициях, так сказать. Еще есть часть, отвечающая за сохранение результатов в БД, работает вроде нормально, но в интерфейс и в настройки не стал выносить за ненадобностью. Вид и слой персистентности описывать не буду, ниже все про модель и поведение.

4. Модель


Модель представлена шестью обычными классами Planet, Starr, Zone, Conditions, BlackDaizy, WhiteDaizy, NoDaizy, одним абстрактным Daizy, и одним перечислением Type. Хотя можно было и меньшим числом классов, я подумал, что звезда настолько крупная и важная вещь, что оставлять ее без класса было бы некрасиво. А для маргариток, в программе под названием «Планета Маргариток» была выстроена целая небольшая иерархия классов, и даже введено перечисление. Таким образом, основные классы, определяющие состояние это, Planet, Conditions и Zone.

Planet — является основным агрегирующим классом, экземпляр этого класса в приложении играет роль модели, из него контроллеры получают состояние для вью, а классы, отвечающие за поведение, получают ссылку на экземпляр Planet для изменения состояния.
Класс Planet содержит поля, характеризующие состояние планеты: это

/** Отражающая способность, характеризуется отношением отраженного света к падающему*/
    private double albedo = 0;

  /** Эффективная температура: зависит от поглощаемой энергии,
     * вычисляется как температура абсолютно черного тела по закону Стефана-Больцмана*/
    private double temperature = 0;

  /** Да планета имеет размер*/
    private double radius = Conditions.getInstance().radius;

/** количество поясов на которое разбито одно полушарие, локальная температура вычисляется для каждого пояса, на всей площади одного пояса — одинаковая температура*/
    private int halfZonation = Conditions.getInstance().halfZonation;

  /** фрагментация пояса: максимальное количество маргариток на пояс,
     на всех поясах - количество маргариток одинаковое, это не ограничение программы, а геометрический закон, ибо пояса с одинаковой высотой имеют одинаковую площадь,
     * так - то*/
    private long daiziesPerZone = Conditions.getInstance().daiziesPerZone;

/** эффективная площадь - проекция планеты на плоскость перпендикулярную направлению излучения идущему от звезды к планете, используется для расчета альбедо  */
    private double effectiveArea;

    /**  площадь пояса. у всех поясов area - одинаковая
      S = 2?rh,
      r – радиус сферы,
      h – высота сферического пояса.
     */
    private double zoneArea;
    /** условная площадь одной маргаритки, справочный параметр*/
    private double daisyArea;

Кроме того, класс Planet содержит ссылку на звезду Starr, массив экземпляров класса Zone, каждый элемент которого характеризует отдельный пояс, счетчик апдейтов, признак inhabited ну, то есть обитаемая ли планета. А также ссылки на классы, отвечающие за поведение

 PopulatorImpl populator = new PopulatorImpl();
    AlbedoCalculator albedoCalculator = new AlbedoCalculatorImpl();

о которых речь пойдет ниже.

Второй важный класс — это Conditions, в нем собраны все константы. Вот некоторые

public double Kelvin = -273.15;

// Planet constants
    public double radius = 1000.0;
    public int halfZonation = 90;
    public long daiziesPerZone = 100;
/**
 эмпирическая отсебятина: разница температур на экваторе и на полюсах, если вычислять в зависимости от широты
 то на полисе окажется нулевая по кельвину, что противоречит здравому смыслу
 величина должна зависеть от теплопроводности планеты, миграции тепла по атмосфере, и т.п.
 к тому же температура на поверхности должна быть выше расчетной из-за того, что поверхность первой прогревается,
 и из-за парникового эффекта, если, конечно, есть подходящая атмосфера
 */
public double planetDeltaTemper = 70.0;


/* используются для вычисления большого альбедо*/
public double blackDaisyAlbedo = 0.1;
public double whiteDaisyAlbedo = 0.9;
public double noDaisyAlbedo = 0.5;
  /* Значение комфортной температуры для жизни маргариток
Собственно, реализация прогрева и охлаждения почвы вокруг маргариток,
  */
public double blackComfortableTemper = 18 + (-Kelvin);
public double whiteComfortableTemper = 22 + (-Kelvin);
/**Звездная постоянная - суммарная мощность излучения звезды, проходящего через единичную площадку,
 * ориентированную перпендикулярно потоку, на расстоянии одной астрономической единицы от Звезды
 * для Солнца и Земли равняется 1367 Вт/м?*/
public double StarConstant = 1367.0;
	/** Значение постоянной Стефана-Больцмана
 * */
public double StephanBoltsmanConst = 5.67e-8;
И третий важный, но не большой класс модели Zone:

/** высота границы ближайшей к экватору */
private double latitude;
/** эффективная площадь - проекция половины шарового слоя на плоскость,
 *  используется для расчета альбедо  */
private double effectiveArea;
/** высота шарового слоя*/
private double height;
/** температура на поверхности в данной zone*/
private double localTemperature;

//    количество маргариток
private long numBlackDaisies;
private long numWhiteDaisies;
private long numEmptyCells;

Обратите внимание на метод установки локальной температуры вычисляет температуру, как описано выше:

public void setLocalTemperature(double globalTemperature) {
    this.localTemperature = globalTemperature + Conditions.getInstance().planetDeltaTemper*Math.cos(latitude);
}

В классе нет методов, вычисляющих состояние, значение всех полей передается в параметрах конструктора, либо устанавливаются сеттерами.

5. Логика


Почти всё поведение собрано в паке logic, и представлено следующими классами:

ZoneMaker — класс используется для создания всего массива зон планеты, с учетом того, что у разной планеты может быть разная фрагментация (количество зон), а у каждой зоны своя уникальная широта, соответствующая индексу в массиве

AlbedoCalculator — интерфейс, единственный метод
 double calcAlbedo(Zone[] zones); 
его реализации используются для вычисления альбедо всей планеты в зависимости от соотношения черных и белых маргариток и незанятого пространства, а также внимание, их расположения — так как маргаритки, растущие на разных широтах, вносят разный вклад в общее альбедо.

StephanBoltsman — класс для расчета эффективной температуры планеты.

Populator — интерфейс, отвечающий за заселения планеты маргариткам.

Метод

void populate(Zone zone,  int whiteExpectance, int blackExpectance, int noneExpectance);

предназначен для заполнения одной, переданной в параметре, зоны, параметры

int whiteExpectance, int blackExpectance, int noneExpectance 

что-то вроде математических ожиданий, в зависимости от их соотношения, в случайном порядке по зоне будут посажены белые и черные маргаритки, или будет сделан пропуск, но общее число ячеек для маргариток в зоне всегда постоянно, и зависит от начальных настроек (задается Conditions.daiziesPerZone).

Этот метод используется в двух других методах, которые заполняют уже все зоны на планете:

void populateInitial(Zone[] zones, int whiteExpectance, int blackExpectance, int noneExpectance);

Заполняет все зоны с одинаковым соотношением. В конструкторе планеты стоят параметры 0,0,1. То-есть планета создается необитаемой.

Метод

void rePopulate(Planet planet);

является реализацией механизма вытеснения маргаритками маргариток, и заполнения пустого пространства. Он используется для перераспределения маргариток на планете, в зависимости от сложившихся на Планете условий. Метод работает приблизительно следующим образом: в нем определены три переменные, в первую очередь они устанавливаются в значения количества белых, черных маргариток и пустых ячеек очередной зоны.

Далее, если температура для какого-либо вида маргариток не соответствует жизненным условиям, соответствующий параметр обнуляется. Если соответствует жизненным условиям, то значение остается неизменным. Если температура находится в интервале комфорта, то значение удваивается. В случае, если температура впервые стала пригодна для жизни, для какого-либо вида маргариток, то соответствующий параметр устанавливается в среднее арифметическое от количества соответствующих маргариток из смежных зон.

И наконец, нужно описать метод update() класса Planet, который отвечает за жизненный цикл каждой итерации:

public void update() {
    albedo = albedoCalculator.calcAlbedo(zones);
    temperature = StephanBoltsman.countTemperature(albedo,star.getStarConstant());
    updateLocalTempers();
    populator.rePopulate(this);
    iterationId++;
}

В первую очередь вычисляется альбедо планеты, исходя из количества и расположения маргариток. Затем вычисляется эффективная температура планеты используя только что найденное альбедо и звездную постоянную (значение которой также может измениться). Затем обновляются значения локальных температур в зонах исходя из найденной эффективной температуры. И в конце, используя новые данные локальных температур, осуществляется перераспределения маргариток.

Ссылка на гит. Сборка: gradlew build




К сожалению, не доступен сервер mySQL