週末はいつも晴れ

社会人5年目の日記です。プログラミングとか旅行とかラーメン。

TypeScript+CRA+Material-ui+redux-toolkit+Web Worker APIでReact App作成

注: 趣味グラマーです。
質は保証しかねます。

作りたいもの

既にTypescriptで作成済の重たい計算を行うライブラリがあります。
この計算の入力の作成、実行、出力の表示のすべてをフロントエンドで行えるPWAを作りたい・・・

以下のライブラリ等を利用して作成します。

情報ソース

TypeScript+Material UI v4

バージョン4の書き方のお手本
TypeScript + Material-UI v4 のスタイル付きコンポーネント作成ガイド - Qiita

redux-toolkit (Javascript)

reduxの基本からredux-toolkitの使い方まで
HookとRedux ToolkitでReact Reduxに入門する | Hypertext Candy

Typescript + redux-toolkit

redux-toolkit公式
Usage With TypeScript | Redux Toolkit

CRA+Web Worker

workerize-loaderを導入する方法です。
ejectしなくてもいけちゃいます。
Integration with Create React App · Issue #5 · developit/workerize-loader · GitHub

React + TypeScriptで開発するときのコツ

型が分からない問題の具体的な解決策など。
https://www.youtube.com/watch?v=Z5iWr6Srsj8

Redux関連で発生した問題と解決策

storeを作ってProviderで渡すところまでは、2つめの情報ソースでTypeScriptだろうと関係なくできました。

その後に発生した問題です。

useSelectorのところでstoreの型が不明

3つめ情報ソースであるredux-toolkit公式ドキュメントの一番上に書いてありました。

// sliceを定義しているファイル
const counterSlice = createSlice({
  name: "counter",
  initialState: 0,
  reducers: {
    // ...
  }
});
export default counterSlice;

// reducerを定義しているファイル
import counterSlice from '上のファイル';
const rootReducer = combineReducers({
  counter: counterSlice.reducer,
  // ...
});
export type RootState = ReturnType<typeof rootReducer>;

// useSelectorするファイル(comsumer)
import { RootState } from '上のファイル';

const YourComponent = () => {
  const count = useSelector((state: RootState) => state.counter);
  return <div>{count}</div>
}
独自定義型のstateを持つslicereducerコンパイルエラー

slice内でinitalStateをきちんと型定義しておくと、reducerではかなり型推論がきき、全く型を書く必要がなくなりました。

type Aaa = {
  bbb: number,
  ccc: string
}

const initalState = {
  bbb: 5,
  ccc: "f*ck"
}

const aaaSlice = {
  name: "aaa",
  initialState,
  reducers: {
    actionA: (state, action) => {
      return {...state, bbb: action.payload}
    }
  }  
}
actionの型をきちんと定義したい

独自の型のPayloadを渡すとき、コンパイルが通らなくなります。
PayloadAction型を使います。
こちらもredux-toolkit公式ドキュメントがソースです。

import { createSlice, PayloadAction } from "@reduxjs/toolkit";

type Aaa = {
  bbb: number,
  ccc: string
}

const initalState = {
  bbb: 5,
  ccc: "f*ck"
}

const aaaSlice = {
  name: "aaa",
  initialState,
  reducers: {
    setAll: (state, action: PayloadAction<Aaa>) => {
      return action.payload
    }
  }  
}

Web Worker関連

かなり大変でした。
CRAでworker-loaderは将来的にサポートされる予定ですが、どんどん先延ばしにされて行っています。
https://github.com/facebook/create-react-app/pull/5886

サポートされていない以上、CRAのお庭の外に出て(ejectして)戦うしかありません。
正直Webpackは勉強したくないし、事故ったっときに解決できる気がしないので、ejectは眼中にありませんでした。
水辺でパチャパチャしてるくらいが今の私には丁度いいのです。

そんな中で上記のソースをみつけ、一瞬で実装できました。
sampleWorker.worker.ts内のfooの下に自分が使う関数を定義しただけです。
使い方もComponent.tsxとほぼ同じです(async/awaitを使っただけ)。

レタスの水耕栽培と徒長

はまっています。
IoTと組み合わせて遊んでます。
しかし、この時期のためか徒長(ひょろひょろ成長)してしまっています。

1. 徒長の原因

徒長の原因は4つあるそうです。
徒長の原因を知ることで、対策を練ることができます| PHYTOCHROME WEB Site HOME

  • 日当たり不足
  • 水遣り過多
  • 風の不足
  • 窒素肥料過多

以下でそれぞれの対策を考えていきます。

2. 日当たり不足対策

部屋内で育成しているため、これが主要因と思われます。
窓際に置いているので、日光だけではどうしようもない状態です。

そこで、人工光を与えることにしました。
人口光としては電気代が少なくて済むLEDライトを使用します。

では、LEDライトはどのように選べばいいのでしょう。
選択の条件(スペック)として、波長と消費電力があります。

2.1 LEDライトの波長

IoTされている方はArduino等でおなじみのLEDですが、赤色だけでなく様々な色があることをご存じでしょうか。
LED半導体の化合物組成によって、多様な発色が可能となっているようです。
LEDの発光原理 | LEDの基礎知識 | LED照明 | パナソニックのLED | 照明器具 | Panasonic

いくつかWebサイトを見ましたが、青色と赤色の可視光が植物の成長に重要なようです。
文部省の情報なのだし、自分で実験することもできないので鵜呑みにしてしまいます。

光合成にはクロロフィル葉緑素)という色素が関わっているが、これは図2に示すような吸収スペクトルを持っている。これを見ると、赤色(660nm近辺)と青色(450nm近辺)に二つの吸光合収ピークがあり、この波長が光合成に特に有効であることがわかる。白色光が葉に当たると赤と青が吸収されて、残りの光は緑が多くなるので葉は緑色に見えるのである。筆者らの実験によると植物の健全な生育にはこの赤色光と青色光がバランスよく配合されていることが大切で、後に述べる光量子束密度の単位でR/B比(赤と青の比率)が10:1あるいは5:1が適切なようである。

第2章 豊かなくらしに寄与する光 2 光と植物-植物工場:文部科学省

以上から、赤色LED(660nm)と青色LED(450nm)が10:1~5:1の範囲のものを検討することとします。

2.2 LEDライトの消費電力

2.2.1 植物に必要な光

植物に必要なものは照度[lx]で決まるようです。

  • 光合成で生成されるエネルギーは照度に比例するが、飽和する点(光飽和点)がある
  • (植物の成長に使われるエネルギー)=(光合成で生成されるエネルギー)ー(呼吸で消費されるエネルギー)
  • 植物の成長に使われるエネルギーが0となる照度が補償点と呼ばれている

植物工場の照明システム | 技術資料 | 岩崎電気

1969年のデータですが、レタスの光補償点は1.5~2[klx]、光飽和点は25[klx]です。

しかし、この値は自然光(太陽光)スペクトルをベースに算出されていることに注意しなければなりません。
上記の通り、LEDライトは植物の成長に抜群な波長の光のみを放出しています。
同じ照度[lx]でも、自然光とLEDでは成長の度合いは大きく異なることが予想されます。
つまり、LEDライトにおける光補償点、光飽和点は上記の値よりも小さくなります。

どのくらい小さくなるのか、はかなり難しい問題だと思います。
それぞれのスペクトルに対してエネルギー応答の重み及び葉緑素の応答の重みを乗じ、和をとって比とします。


 \frac{LED光補償点}{自然光光補償点} = \frac{\int S_{LED}(\lambda)M_{Energy}(\lambda)M_{Chloro}(\lambda) d\lambda}{\int S_{sun}(\lambda)M_{Energy}(\lambda)M_{Chloro}(\lambda) d\lambda}

上記のうち、エネルギー応答だけは波長に反比例するので、簡単に求められます。
葉緑素の応答は上記リンクのグラフから読み取るしかなさそうです。
自然光スペクトルはどこかで手に入れることができるかもしれません。
LEDのスペクトルは・・・自分で測定するしかないですかね(-_-;)

2.2.2 LEDライトの照度

LED電球が広く使われるようになり、ルーメンの記載が義務付けられるようになったらしいので、ルーメンが分かっているものとします。

まず、ルクス[lx]とルーメン[lm]とカンデラ[cd]の定義を読みました。
ルクス - Wikipedia
ルーメン - Wikipedia
カンデラ - Wikipedia

用語 単位* 定義
光度 cd 単色光(540 THz)の光源からの放射強度が1/683[W/Sr]となる光度
光束 lm 1カンデラの光源から1ステラジアン内に放射される光束
照度 lx 1平方メートルの面が1ルーメンの光束で照らされるときの照度

光束[lm]が分かれば、位置関係から照度[lx]は求まりそうです。

 照度[lx] = 光束[lm] / 照射面積[m^2]

LED電球には指向性があるものとして、電球を中心とした下方向半球の範囲に光があたるとします。
電球とレタスが50cm離れていると、照射面積は
4 \times \pi \times 0.5^2 /2=1.5 [m^2 ]
となります。

さらに光が集中的にレタスに当たるようなLEDライトとすれば、照射面積は小さくなり、効率的になります(同じ光束でも照度が高くなります)。

2.3 自然光や時間を考慮する

自然光(太陽光)の照度は当然ですが時間的に変化しています。

LEDライトも私が部屋にいる間は付けたくないので、運転時間が決まっています。

このため、時間積分(または時間平均)を考慮した計算が必要となります。
パラメータを整理しておきます。

  • 自然光の時間積分(自然光の照度×時間)[lx h]
  • LEDライトの光束[lm]
  • LEDライトの照射面積[m2]
  • LEDライトの運転時間[h]
  • 植物の育成に必要な照度の時間積分[lx h]
2.3.1 LEDライトの計算

参考のため以下のライトを使用するとします(現時点で購入はしていません)。

本当かどうか分かりませんが、このライトの光束は1300~1500[lm]と記載されています。ここでは1500[lm]とします。
このライトは平板形ですが、先ほどの議論と同じように50cm離れた場所で下方向半球に光が広がるとします(若干厳しい仮定かも知れません)。
このとき、レタスの位置における照度は 1500[lm] / 1.5[m^2]=1000[lx] となります。

レタスの光飽和点25,000[lx]には遠く及ばないため、LEDライトの光が無駄になることはありません。

2.3.2 自然光の計算

簡単のため、太陽が出ている8時間の自然光が一定で2000[lx]であるとします。
その他の16時間はすべて暗闇で、0[lx]であるとします。
このとき、自然光の一日の時間積分は16,000[lx h]となります。

2.3.3 植物の育成に必要な照度の時間積分

補償点は2,000[lx]ですが、補償点では成長に回す栄養が無いので3,000[lx]必要であるとします。
一日で必要な照度の時間積分 24 \times 3000=72,000 [lx h] となります。

2.3.4 LEDライトの点灯時間

植物の育成に必要な照度時間積分から、自然光の照度時間積分を差し引きます。
この時間積分だけLEDライトを当てる必要があります。
 72,000 - 16,000 = 56,000 [lx h]

LEDライトの照度は1000[lx]なので、一日で必要な点灯時間は以下の通り求まります。
 56,000 / 1,000 = 56 時間

・・・

一日より長いじゃねえか!

ということで、ここまで一日あたりをベースに考えてきましたが、スパンを広げた時間積分を考える必要がありそうです。
極端に日照が少ない期間が含まれると危なさそうなこと、レタスの生育期間が半年程度であることを考えると、1週間や2週間を目安に照度の計算を行うべきでしょうか。・・・。分かりません。

また、ここではLEDライトスペクトルの優位性を考慮していませんでした。
太陽光スペクトルに比べ、2倍、3倍効率的であれば、必要な点灯時間は1/2、1/3となりますので、現実的になるかもしれません。

農家の方が天気に苦労される理由が少しわかった気がします。

3. その他対策

3.1 水やり過多

いろいろな水耕栽培Webサイトの推奨水位を守っているので問題なし。

3.2 風の不足

屋内なんですよね。
毎日息を吹きかけてあげよう笑

3.3 窒素肥料過多

ちゃんとハイポニカの指定の濃度を守っているから問題なし。

ポケモンGO iPhone 歩行自動化(idevicelocation, 脱獄なし)

※すべて自己責任のもと実施のこと
※ちなみに私はやり過ぎてストライク1を食らっています。

結構ハードルが高いですが、ポケモンGoの歩行自動化方法を紹介します。

はじめに

前提条件

流れ

  1. XCodeとhomebrewのインストール
  2. ideviceloationのインストール
  3. 歩行自動化

XCodeとhomebrewのインストール

最も簡単です。以下等を参考にインストールしてください。
qiita.com
XCodeでは空のアプリケーションを作成する等で、usbケーブル接続中のiPhoneにアクセスできる状態にしておく必要があります(結構重要)。

idevicelocationのインストール

少し大変です。以下等を参考にインストールします。
以下のリンクだけでは情報が足りないので、後日補足説明を加えます。
qiita.com

歩行自動化

idevicelocationの使い方

idevicelocationはusbケーブルを通して接続されたiOSバイス(iPhone等)の位置情報を変更することができます。
idevicelocationには以下の2つの情報を渡す必要があります。

位置情報は【ポケモンGO】みんポケ等で決めてあげてください。
iOSバイスのIDは`idevice_id`というコマンドで取得します。

$ idevice_id -l

上記のコマンドでは接続されているすべてのiOSバイスの一覧が表示されます。
通常は1台しか接続しないと思いますので、上記のコマンドをそのままidevicelocationにわたすことにします。

$ idevicelocation 経度座標 緯度座標 -u $(idevice_id -l)

これによってポケモンGoを含むGPSを使用するアプリケーションすべてにおいて、
位置座標が変更されていることが確認できます。

変更後は位置座標が固定されてしまいます。
元の状態に戻すには、以下のコマンドを使用します。

$ idevicelocation -s -u $(idevice_id -l)

pythonスクリプト

歩行を自動化するには、連続的に位置情報をidevicelocationで与え続ける必要があります。
書きかけ

注意事項

テレポートによるソフトBAN

瞬時に座標が変更されると、以下のように一定時間の間ポケストップが回せなくなり、ポケモンが一投目で逃げるソフトBANが発生します。
高速移動ペナルティ(ソフトBAN)対策 – PokemonGO Hacks
このため、座標を現実的な速度で移動させる等の工夫が必要になります。

移動速度

私のTry & Errorでは、2.6m/sあたりを境に歩行距離がカウントされなくなり、卵が孵化しなくなりました。
また、10m/sあたりを境にポケストップを回せなくなりました。

その他

さらにgotchaやauto catchのようなデバイスを使うと、
歩行だけでなくポケモン収集やアイテム収集も自動化されます。

Rasberry Pi 3 Model B+

用途

買ったもの

Raspberry Pi 3 Model B+ スターターセット BASIC

Raspberry Pi 3 Model B+ スターターセット BASIC

Raspberry Pi用電源セット(5V 3.0A)?Pi3フル負荷検証済

Raspberry Pi用電源セット(5V 3.0A)?Pi3フル負荷検証済

既にあるもの

SSH接続できるようになるまで

qiita.com

OpenMC dockerfile

作りましたのでぜひご利用ください。
CentOS7 ベースです。

dockerfile

OpenMC dockerfile · GitHub

私の環境ではNNDCから断面積ファイルを落とすのに
2時間くらいかかりました。
海外サーバーですからね。

ファイルサイズは合計で6GBくらいになります。

コンパイルの条件

  • コンパイラ: mpif90とmpicc
  • HDF5もmpiで並列化
  • optimize有効
  • pythonはminicondaを使用してインストール
  • python関連ライブラリについては、silo以外をインストール済(Python3非対応のため)

github.com

OpenMC

日本語の情報が無いのでメモ。

The OpenMC Monte Carlo Code — OpenMC Documentation

OpenMCとは

OpenMCは粒子のモンテカルロ輸送計算コードで、臨界計算に重きを置いています。
2次曲面を含む3次元モデルのジオメトリーでシミュレーションできます。
OpenMCでは連続エネルギーと多群計算の両方をサポートしています。
連続エネルギーの粒子の相互作用データはHDF5フォーマットに基づいています。
HDF5フォーマットはMCNPやSerpentといったモンテカルロコードで使用されているACEフォーマットから生成することも可能です。

HDF5フォーマットとは
HDF5フォーマットに関するメモ書き - たまに書きます。

ACEフォーマットとか、わざわざ独自仕様にするのは本当にやめて欲しいですよね
ENDF/B形式も然りです。そろそろ現代的なものに見直そうと思わないのでしょうか?

OpenMC本体のインストール

linuxはapt-getでバイナリを落としてくることもできます。
macはソースからインストールするしかありません。
windowsは知りません。

以下はソースコードからインストールする方法

git clone https://github.com/mit-crpg/openmc.git
cd openmc
mkdir build
cd build
cmake .. # オプション指定できます
make
make install

以下はcmakeオプションのおすすめです。

cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local\
      -DCMAKE_CXX_COMPILER=/usr/local/bin/g++-7\
      -Openmp=on\
      -Optimize=on ..

macxcodeで入るclangにopenmpを通すのは面倒だし、
brewでインストールしたgccを使っています。hdf5もbrewでインストールしました。
以下では上記のcmakeオプションを使用したと仮定して進めます。

インストールが完了するとCMAKE_INSTALL_PREFIXで指定したディレクトリは以下のようになります。

$ tree .local/ -L 2
.local/
├── bin
│   ├── openmc
│   ├── openmc-ace-to-hdf5
│   ├── openmc-convert-mcnp70-data
│   ├── openmc-convert-mcnp71-data
│   ├── openmc-get-jeff-data
│   ├── openmc-get-multipole-data
│   ├── openmc-get-nndc-data
│   ├── openmc-plot-mesh-tally
│   ├── openmc-track-to-vtk
│   ├── openmc-update-inputs
│   ├── openmc-update-mgxs
│   ├── openmc-validate-xml
│   └── openmc-voxel-to-silovtk
├── include
│   └── python3.5m
├── lib
│   ├── libopenmc.dylib
│   └── python3.5
└── share
    ├── doc
    ├── man
    └── openmc

9 directories, 14 files

思いっきりPythonを使うみたいですね。素晴らしい。
日本の開発はここら辺がすっごく遅いです。
私の場合は環境のPythonが使われるように設定されたようです。

断面積のダウンロード

binフォルダにあるopenmc-get-nndc-dataを使うと
ENDF/B-VII.1の断面積をNNDCからダウロードできます。

$ cd ~/.local
$ mkdir data
$ cd data
$ ~/.local/bin/openmc-get-nndc-data
Downloading ENDF-B-VII.1-neutron-293.6K.tar.gz... ^P^P^P^A^Eb 501910959  [100.00%]
Downloading ENDF-B-VII.1-tsl.tar.gz...   17925081  [100.00%]
Verifying MD5 checksums...
Extracting ENDF-B-VII.1-neutron-293.6K.tar.gz...
Extracting ENDF-B-VII.1-tsl.tar.gz...
Fixing ZAIDs for S(a,b) tables
Delete *.tar.gz files? ([y]/n) y
Converting 89225.71c (ACE) to Ac225 (HDF5)
Converting 89226.71c (ACE) to Ac226 (HDF5)
Converting 89227.71c (ACE) to Ac227 (HDF5)
〜省略〜
Converting paraD.71t (ACE) to c_para_D (HDF5)
Converting paraH.71t (ACE) to c_para_H (HDF5)
Converting sCH4.71t (ACE) to c_H_in_CH4_solid (HDF5)
Converting UUO2.71t (ACE) to c_U_in_UO2 (HDF5)
Converting ZrZrH.71t (ACE) to c_Zr_in_ZrH (HDF5)

ACEファイルがダウンロードされて、自動的にHDF5フォーマットに書き換えているようです。
私の環境ではGe76, Eu152, Mo100の変換時に怒られました。

次に断面積リストのxmlファイルcross_sections.xml環境変数に登録します。

echo "OPENMC_CROSS_SECTIONS=$HOME/.local/data/nndc_hdf5/cross_sections.xml" >> .bashrc

以上でインストールは完了です。
あとは以下のipython notebookを追えば、入門できます。
やっぱりI/O周りが素晴らしいですね
Modeling a Pin-Cell — OpenMC Documentation

MCNPのI/Oはゴミ過ぎで進歩しない。
SCALEは多少マシになったようですが、これからはPython APIが無いと若者はついて行かないです。
MCNPもAPIは無理だけど、wrapperを誰か書いてくれないものでしょうか。
あのインプットファイルとかジオメトリ可視化機能はありえない笑
ユーザーの切なる願いです。

dockerで使う方法

新らしい技術は積極的に取り入れましょう。
我々の業界は時代遅れすぎます。
「docker 使い方」とか「docker 仕組み」でググってください。

ergsさんが一番良さそうなのでお借りします。

docker pull ergs/ergs-openmc

すぐに使えるようなります。

OpenFOAMメモ

あんまりこの形式でインストールする人はいないと思います。
私用のメモ

vagrant

まずvagrantをインストールした。
イメージはCentOS7を使う。以下のVagrantFileを使用する。
Vagrant box centos/7 - Vagrant Cloud
paraviewを使うのでX11の設定を書き込む

config.ssh.forward_x11 = true

Trueにしてたせいで5分悩んだ。
コピペは積極的にすべきと再認識。

vagrantを起動

vagrant init
vagrant up

vagrantゲストのシャットダウン

vagrant halt

docker

OpenFOAMがdockerで配布されているのでdocker ceをインストールする。
vagrantssh接続してdockerをインストールした。

vagrant ssh
sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce

そのほか、X windowyumでgroupinstallした。

OpenFOAM

ここで結構めんどくさかった。

まず前提としてvagrantゲストのエディタ・ParaViewからOpenFOAMの入出力にさわりたい。
なぜならdocker上にコンパイラとかエディタを入れるのは難しいから(OpenFOAMのdockerのrootパスワードがわからない)。
また、vagrantのホストからvagrantを飛び越えてdockerのファイルにアクセスする設定をするのは面倒臭そうだから。

面倒ごとを回避しようとしても、結局面倒な問題を1つは解決しないといけない問題に衝突するんですけどね。
今回も同じ。

dockerをsudo無しで実行できるようにする

vagrantにはvagrantさんで入る。
いちいちsudoするのがめんどくさいし、sudoでdocker runしたファイルはvagarntさんがいじれなくなる。
Dockerコマンドをsudoなしで実行する方法 - Qiita

OpenFOAMをインストールする

まずはdockerのdaemonを立ち上げる

sudo systemctl start docker

OpenFOAMのdockerスクリプトをダウンロード

wget --trust-server-names https://sourceforge.net/projects/openfoamplus/files/v1706/installOpenFOAM
wget --trust-server-names https://sourceforge.net/projects/openfoamplus/files/v1706/startOpenFOAM

それぞれ実行権限を与える。

chmod +x installOpenFOAM
chmod +x startOpenFOAM

dockerのワークディレクトリをvagrantゲストのどのディレクトリに割り当てるか、installOpenFOAMのhome変数で指定する。

書きかけ