Raspberry Pi 5
Raspberry Pi 5 は、N100 の半分程度の CPU 性能で 10 年位前の Intel i5 位の力があり、ストレスなく使えるとのことで、しばらくぶりに手を出してみることにしました。
Mac/Win の類からの Remote Desktop 接続による利用を前提として、Mathematica と gfortran + OpenCoarrays を設定する所までメモります。Free 版 Mathermatica は、シングルスレッド限定、最適化されていない、他言語と連携できない、バックエンド・サーバーに繋げない等々の機能限定版のようですが、ちょっと使う分には十分の模様です。Wolfram script を Jupyter のカーネルに使えばいいという話もありますが、ノートブックが直接読み書きできるものがあるに越したことはない気がします。
初期設定 Raspberry Pi Imager
Imager で micro SD Card に 64bit 版の Raspberry Pi OS を選択します。32bit 版でやったところ、Mathematica Ver.13 がライセンス・キーを要求してきましたが、64bit 版なら Ver.14.1 で問題なく起動しました。ネットの古い情報では 64bit 版はダメで 32bit OS なら大丈夫とありました、よく分かりませんが今は逆の状況のようです。
ヘッドレス運用のための初期値を聞かれますが、後でインストーラでやることにして飛ばします。
micro SD card を刺して起動、初回のインストーラが立ち上がります。
- 国:Japan、言語:Japanese、時間帯:Tokyo、Use English、Use US Keyboard
- User / Password: 適宜入力 なお User名 pi は、やめたほうがいいと警告されます。
- browser:chromium、個人情報売却する宣言で話題の FireFox も残しておきます。これらのブラウザは remote desktop を通すと GPU 加速を切らないと画面が崩れます。 *. WiFi 設定: 適宜入力
- update: skip して後で手動でやることにします。
- REBOOT
update
ターミナルを開いて、手動で行きます。full-upgrde 中に設定ファイルをどうするか聞かれますが、読まずに Yes, Yes と答えました。
sudo apt update sudo apt full-upgrade sudo apt autoremove
XRDP (Remote Desktop 被接続設定)
まず普通に設定しますが、この時点では音が出ません。音を出すためには、後で作業が必要になります。
- Wayland を無効化します。そうしないと画面が真っ黒になります。
sudo raspi-config
で、設定メニューを出した後、 6 Advanced Options --> A6 Wayland --> W1 X11 と X11 に設定します。
sudo reboot
再起動後 XRDP 関連をインストールします。
sudo apt install xrdp sudo systemctl enable xrdp sudo systemctl restart xrdp hostname -I sudo reboot
ここで ip address をメモっておいて、Remote Desktop 接続時に使います。
ここから先は Remote Desktop から作業します。
Chromium Browser 設定: Menu --> Internet --> Chromium Web Browse を右クリック、設定窓 File Properties が出るので Desktop Entry のタブ下の Command: の値に --disable-gpu を足します。/usr/bin/chromium --disable-gpu %U、OK クリック
音が出るようにします。
以下の記事を参考に作業します。
sudo apt install libpulse-dev dh-autoreconf git build-essential dpkg-dev git clone https://github.com/neutrinolabs/pulseaudio-module-xrdp.git cd pulseaudio-module-xrdp/ scripts/install_pulseaudio_sources_apt_wrapper.sh ./bootstrap && ./configure PULSE_DIR=~/pulseaudio.src make sudo make install sudo reboot
再起動後
sudo raspi-config
A6 Advanced options --> A7 audio config --> 1 pulse audio
sudo reboot
これで音が出るようになりますが、負荷が重いのかブツブツ途切れ気味に鳴ります。
Mathematica 14.1 (64bit OS)
sudo apt install wolfram-engine
メニューの programming の所に Mathematica が入るので起動すると、ライセンス認証なしに立ち上がります。Raasberry Pi OS 以外だとライセンス認証が求められるようです。32 bit 版でもライセンス認証を求められました。
OpenCoarrays
ソースからコンパイルします。MPI としては MPICH を選びます。apt install で gfortran 12.2, cmake 3.25, mpich 4.0.2 が入るので、コンパイルはすぐに終わります。
作業手順は、以下のページの Installation Script の Example script invocations の 2 番に従ってやります。
sudo apt install gfortran cmake mpich vim
git clone https://github.com/sourceryinstitute/OpenCoarrays.git
cd OpenCoarrays
./install.sh --prefix-root ${HOME}/software --num-threads 4 --yes-to-all
問題なく終わると思います。最後の方にパスを通すための source 云々という行が出るのでメモっておきます。
チェック、test.f90 を用意したとして・・・
source /home/p/software/opencoarrays/2.10.2/setup.sh caf test.f90 cafrun -np 8 ./a.out
fortran test
Mac 上の Windows App(MS 謹製 Remote Desktop Application)から点字プロットしてみました。

ソース・プログラム
絶対座標と相対座標部分を別のモジュールに分けました。
module uniplot0 implicit none private public :: fig0_t type :: fig0_t private integer, public :: nx, ny integer, allocatable :: array(:, :) contains procedure :: init0 procedure :: show procedure :: text0 procedure :: point0 procedure :: line0 end type fig0_t contains subroutine init0(fig, nx, ny) class(fig0_t), intent(out) :: fig integer, intent(in) :: nx, ny fig%nx = nx fig%ny = ny allocate(fig%array(0:(nx+1)/2, 0:(ny+3)/4), source = 0) end subroutine init0 ! Braille 2 * 4 dots ! ix !iy 0 1 : 0 8 ! 1 : 2 16 ! 2 : 4 32 ! 3 : 64 128 ! + 0x2800 Unicode : offset : 0x2800 = 0010_1000 0000_0000 -> 4,6,6bits -> 0010, 100000, 000000 ! ! Unicode to UTF-8 : 1110_0000, 1000_0000, 1000_0000 ! 1110..., 1000...., 1000...., ! 0010, 10_0000, 00_0000 ! 0x2800 ! icode : 00_00xx, xx_xxxx ! 1110_0010, 1010_00xx, 10xx_xxxx ! subroutine show(fig) class(fig0_t), intent(in) :: fig integer :: iy do iy = 0, ubound(fig%array, 2) print '(*(a))', reverse_endian(to_utf8(fig%array(:, iy))) ! little endian end do end subroutine show pure elemental integer function icode(kx, ky) integer, intent(in) :: kx, ky if (ky == 3) then icode = 64 + 64 * kx else ! 0, 1, 2 icode = 2**(ky + 3*kx) end if end function icode pure elemental integer function to_utf8(i) integer, intent(in) :: i integer, parameter :: n_unicode = 10240 ! 0x2800 ! 0010_1000 0000_0000 integer, parameter :: n_offset= 14712960 ! 0xE08080 ! 1110_0000 1000_0000 1000_0000 integer :: k if (i >= 0) then ! Braille k = i + n_unicode to_utf8 = n_offset + 256 * (256 * mod(k/4096, 16) + mod(k/64, 64)) + mod(k, 64) else ! ascii to_utf8 = -i ! ascii passed as a negative number end if end function to_utf8 pure elemental character(len = 4) function reverse_endian(i) integer, intent(in) :: i character:: tmp(4) tmp = transfer(i, ' ', size = 4) reverse_endian = transfer(tmp(4:1:-1), ' ') !array 4 to len 4 characters end function reverse_endian subroutine text0(fig, ix, iy, txt) class(fig0_t), intent(in out) :: fig integer, intent(in) :: ix, iy character(len = *), intent(in) :: txt integer :: i, iax, iay iax = ix / 2 iay = iy / 4 do i = 1, len_trim(txt) ! clipping if (0<=i+iax .and. i+iax-1<=ubound(fig%array,1) .and. 0<=iay .and. iay<=ubound(fig%array,2)) then fig%array(i + iax - 1, iay) = -iachar(txt(i:i)) ! ascii chars passed as a negative number end if end do end subroutine text0 subroutine point0(fig, ix, iy) class(fig0_t), intent(in out) :: fig integer, intent(in) :: ix, iy integer :: iax, iay iax = ix / 2 iay = iy / 4 ! clipping if (0<=ix .and. ix<=fig%nx .and. 0<=iy .and. iy<=fig%ny) then if (fig%array(iax, iay) >= 0) & ! don't overwrite text & fig%array(iax, iay) = ior(fig%array(iax, iay), icode(mod(ix, 2), mod(iy, 4))) end if end subroutine point0 subroutine line0(fig, ix0, iy0, ix1, iy1) class(fig0_t), intent(in out) :: fig integer, intent(in) :: ix0, iy0, ix1, iy1 integer :: i, ix, iy, nx, ny real :: d nx = ix1 - ix0 ny = iy1 - iy0 if (nx == 0 .and. ny ==0) then ix = ix0 iy = iy0 call fig%point0(ix, iy) else if (abs(nx) < abs(ny)) then d = nx / real(ny) do i = 0, abs(ny) ix = nint(ix0 + d * sign(i, ny)) iy = iy0 + sign(i, ny) call fig%point0(ix, iy) end do else d = ny / real(nx) do i = 0, abs(nx) iy = nint(iy0 + d * sign(i, nx)) ix = ix0 + sign(i, nx) call fig%point0(ix, iy) end do end if end subroutine line0 end module uniplot0
module uniplot use uniplot0 implicit none private public :: fig_t type, extends(fig0_t) :: fig_t private real :: x0 = -1.0, y0 = -1.0, x1 = 1.0, y1 = 1.0 contains procedure :: init procedure :: text procedure :: point procedure :: line end type fig_t contains subroutine init(fig, nx, ny, x0, y0, x1, y1) class(fig_t), intent(out) :: fig integer, intent(in) :: nx, ny real, intent(in), optional :: x0, y0, x1, y1 call fig%init0(nx, ny) if (present(x0)) fig%x0 = x0 if (present(y0)) fig%y0 = y0 if (present(x1)) fig%x1 = x1 if (present(y1)) fig%y1 = y1 end subroutine init subroutine text(fig, x, y, txt) class(fig_t), intent(in out) :: fig real, intent(in) :: x, y character(len = *), intent(in) :: txt integer :: ix, iy, iax, iay ix = nint( (x - fig%x0) / (fig%x1 - fig%x0) * fig%nx) iy = nint(fig%ny - (y - fig%y0) / (fig%y1 - fig%y0) * fig%ny) call fig%text0(ix, iy, txt) end subroutine text subroutine point(fig, x, y) class(fig_t), intent(in out) :: fig real, intent(in) :: x, y integer :: ix, iy, iax, iay ix = nint( (x - fig%x0) / (fig%x1 - fig%x0) * fig%nx) iy = nint(fig%ny - (y - fig%y0) / (fig%y1 - fig%y0) * fig%ny) call fig%point0(ix, iy) end subroutine point subroutine line(fig, x, y, ipen) class(fig_t), intent(in out) :: fig real, intent(in) :: x, y integer, intent(in) :: ipen integer, save :: ix0 = 0, iy0 = 0 integer :: ix, iy ix = nint( (x - fig%x0) / (fig%x1 - fig%x0) * fig%nx) iy = nint(fig%ny - (y - fig%y0) / (fig%y1 - fig%y0) * fig%ny) if (ipen == 1) call fig%line0(ix0, iy0, ix, iy) ix0 = ix iy0 = iy end subroutine line end module uniplot
program uniplot_main implicit none ! !windows_cmd: block ! for Windows CMD prompt ! use, intrinsic :: iso_fortran_env, only: output_unit ! open(unit=output_unit, encoding='utf-8') ! call execute_command_line('CHCP 65001 > nul') ! UTF-8: CHCP 65001, JP: CHCP 432, US: CHCP 437 ! end block windows_cmd fig_1: block use :: uniplot real, allocatable :: x(:), y(:) type(fig_t) :: fig integer :: nx, ny integer :: n n = 10**3 allocate(x(n), y(n)) rand: block call random_seed() call random_number(x) call random_number(y) end block rand nx = 140 ny = nx print * print *, repeat(' ', 14), 'Monte Carlo: estimated pi =', 4.0 * count(x**2 + y**2 < 1.0) / n call fig%init(nx, ny, -0.1, -0.1, 1.05, 1.05) ! draw box call fig%line(0.0, 0.0, 0) call fig%line(0.0, 1.0, 1) call fig%line(1.0, 1.0, 1) call fig%line(1.0, 0.0, 1) call fig%line(0.0, 0.0, 1) call fig%text(-0.06, 0.0, '0.0') call fig%text(-0.06, 1.0, '1.0') call fig%text(-0.005, -0.05, '0.0') call fig%text( 0.985, -0.05, '1.0') ! draw 1/4 circle circle: block integer :: i real :: x, y call fig%line(0.0, 1.0, 0) do i = 0, nx x = i / real(nx) y = sqrt(1.0 - x**2) call fig%line(x, y, 1) end do end block circle ! plot random dots random_dots: block integer :: i do i = 1, n call fig%point(x(i), y(i)) end do end block random_dots call fig%show() end block fig_1 fig_2: block ! Sin curve use :: uniplot type(fig_t) :: fig real, parameter :: pi = 4 * atan(1.0) integer :: nx, ny nx = 100 ny = nx print * print *, repeat(' ', 20), 'Sin curve' call fig%init(nx, ny, -1.7, -1.1, 1.7, 1.1) ! draw axes call fig%line(-1.6, 0.0, 0) call fig%line( 1.6, 0.0, 1) call fig%line( 0.0, -1.1, 0) call fig%line( 0.0, 1.1, 1) call fig%line( 0.0, 1.0, 0) call fig%line( 0.1, 1.0, 1) call fig%line( 0.0, -1.0, 0) call fig%line( 0.1, -1.0, 1) call fig%text(-0.05, -0.05, '0.0') call fig%text(-0.05, 1.05, '1.0') call fig%text(-0.10, -1.05, '-1.0') call fig%line(-1.57, 0.0 , 0) call fig%line(-1.57, 0.05, 1) call fig%line( 1.57, 0.0 , 0) call fig%line( 1.57, 0.05, 1) call fig%text( 1.40, -0.05, ' pi/2') call fig%text(-1.65, -0.05, '-pi/2') ! draw Sin curve sine: block integer :: i real :: x, y call fig%line(-pi/2, -1.0, 0) do i = 0, nx x = -pi/2 + i * pi / nx y = sin(x) call fig%line(x, y, 1) end do end block sine call fig%show() end block fig_2 end program uniplot_main






