2024年12月13日金曜日

openEMSを再び(1)

 

以前ギブアップしていたopenEMSにもう一度チャレンジする。

以前、使ってみようとしてうまくいかんかったんだけど、もっかいチャレンジしてみる。この手のソフトって超絶高価すぎる売り物か、すごく限られたモデルしか解析できないフリーなものかのどっちかしかないと思う。openEMSは見た感じ、かなり自由に解析できるのにフリーってのが魅力なので、なんとか使えるようになりたい。
まずは、総本山(https://www.openems.de/)に行く。見た感じ、LinuxなやつはBuildせんかいってことになっている。"Linux Build instructions"をつつく。
そうすると、もうそのままやればいい感じに書いてあるが、ここで立ち止まる(そう考える人はまずいないと思う)。実はUbuntuはlibvtkのバージョンが違っているっぽくて、ここに書いているものそのままやればいいわけじゃない。もちろんSynapticで検索しながらやればlibvtk7じゃなくてlibvtk9いれればいいかな?ってところにたどり着く。が、じつはそういうのちゃんと書いてある。で、
で、
で、
ってなってるので、この通りに全部やる。といいたいが、liboctave-devはaptできないかもしれない。たぶんoctave-devで良いはず。
pythonライブラリのインストールはvenvに入れるってなると、
source ~/work_flash/venv1/bin/activate
ってして(activateがどこにいるかはそれぞれの環境による)から、
pip install numpy matplotlib cython3 python3-h5py
のほうがいいと思う。
で、やり切ったら、ページの最下部からNextを押す。
Clone, Build and Installってのが開く。ここはこの通りにやる。
で、pathを通すので~/.profileに
export PATH=”$HOME/opt/openEMS/bin:$PATH”
を追記して、
source ~/.profile
で反映。
で、octaveにもpath設定があるらしいので、
octave --gui
でoctaveを起動。
「編集」-->「Set Path」
で、
ってのを追加する。で、保存してreload。
で、tutorialをやってみるが、Documentationのページからだとpythonのtutorialしかなくて、今回はなぜかoctaveでやってみたいので、総本山のLegacy Wikiをつつく。
で、左のTutorialsをつつくと、そこそこ出てくるので、今回は、こちら
をやってみる。
コードはこちら
  1. close all
  2. clear
  3. clc
  4. %% Setup the physical constants and antenna parameters
  5. physical_constants;
  6. unit = 1e-3; % all length in mm
  7. % patch width in x-direction
  8. patch.width = 30; % resonant length
  9. % patch length in y-direction
  10. patch.length = 40;
  11. %substrate setup
  12. substrate.epsR = 3.38;
  13. substrate.kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;
  14. substrate.width = 60;
  15. substrate.length = 60;
  16. substrate.thickness = 1.524;
  17. substrate.cells = 4;
  18. %setup feeding
  19. feed.pos = -5.5; %feeding position in x-direction
  20. feed.width = 2; %feeding port width
  21. feed.R = 50; %feed resistance
  22. % size of the simulation box
  23. SimBox = [200 200 100];
  24. %% Setup FDTD parameters, excitation signals & boundary conditions
  25. f0 = 2e9; % center frequency
  26. fc = 1e9; % 20 dB corner frequency
  27. FDTD = InitFDTD('NrTS', 30000 );
  28. FDTD = SetGaussExcite( FDTD, f0, fc );
  29. BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % boundary conditions
  30. FDTD = SetBoundaryCond( FDTD, BC );
  31. %% Setup the CSXCAD mesh
  32. max_res = c0 / (f0+fc) / unit / 20; % cell size: lambda/20
  33. CSX = InitCSX();
  34. %create fixed lines for the simulation box, substrate and port
  35. mesh.x = [-SimBox(1)/2 SimBox(1)/2 -substrate.width/2 substrate.width/2 -patch.width/2 patch.width/2 feed.pos];
  36. mesh.x = SmoothMeshLines( mesh.x, max_res, 1.4); % create a smooth mesh between specified fixed mesh lines
  37. mesh.y = [-SimBox(2)/2 SimBox(2)/2 -substrate.length/2 substrate.length/2 -feed.width/2 feed.width/2 -patch.length/2 patch.length/2];
  38. mesh.y = SmoothMeshLines( mesh.y, max_res, 1.4 );
  39. %create fixed lines for the simulation box and given number of lines inside the substrate
  40. mesh.z = [-SimBox(3)/2 linspace(0,substrate.thickness,substrate.cells) SimBox(3)/2 ];
  41. mesh.z = SmoothMeshLines( mesh.z, max_res, 1.4 );
  42. CSX = DefineRectGrid( CSX, unit, mesh );
  43. %% Setup the geometry
  44. %% create patch
  45. CSX = AddMetal( CSX, 'patch' ); % create a perfect electric conductor (PEC)
  46. start = [-patch.width/2 -patch.length/2 substrate.thickness];
  47. stop = [ patch.width/2 patch.length/2 substrate.thickness];
  48. CSX = AddBox(CSX,'patch',10,start,stop); % add a box-primitive to the metal property 'patch'
  49. %% create substrate
  50. CSX = AddMaterial( CSX, 'substrate' );
  51. CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon', substrate.epsR, 'Kappa', substrate.kappa );
  52. start = [-substrate.width/2 -substrate.length/2 0];
  53. stop = [ substrate.width/2 substrate.length/2 substrate.thickness];
  54. CSX = AddBox( CSX, 'substrate', 0, start, stop );
  55. %% create ground (same size as substrate)
  56. CSX = AddMetal( CSX, 'gnd' ); % create a perfect electric conductor (PEC)
  57. start(3)=0;
  58. stop(3) =0;
  59. CSX = AddBox(CSX,'gnd',10,start,stop);
  60. %% Setup the feeding port as a lumped port with 50 Ohms
  61. start = [feed.pos-.1 -feed.width/2 0];
  62. stop = [feed.pos+.1 +feed.width/2 substrate.thickness];
  63. [CSX port] = AddLumpedPort(CSX, 5 ,1 ,feed.R, start, stop, [0 0 1], true);
  64. %% Add a nf2ff box
  65. SimBox = SimBox - max_res * 4; %reduced SimBox size for nf2ff box
  66. [CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', -SimBox/2, SimBox/2);
  67. %% Create simulation folder
  68. %% Write xml simulation file
  69. %% Visualize the Geometry using AppCSXCAD
  70. %% Run openEMS
  71. %% prepare simulation folder
  72. Sim_Path = 'tmp';
  73. Sim_CSX = 'patch_ant.xml';
  74. [status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
  75. [status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
  76. %% write openEMS compatible xml-file
  77. WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
  78. %% show the structure
  79. CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
  80. %% run openEMS
  81. RunOpenEMS( Sim_Path, Sim_CSX );
  82. %% Post-Processing
  83. %% Read in port voltages and currents
  84. %% postprocessing & do the plots
  85. freq = linspace( max([1e9,f0-fc]), f0+fc, 501 );
  86. port = calcPort(port, Sim_Path, freq);
  87. %% Calculate & plot antenna input-impedance
  88. Zin = port.uf.tot ./ port.if.tot;
  89. s11 = port.uf.ref ./ port.uf.inc;
  90. P_in = 0.5 * port.uf.inc .* conj( port.if.inc ); % antenna feed power
  91. % plot feed point impedance
  92. figure
  93. plot( freq/1e6, real(Zin), 'k-', 'Linewidth', 2 );
  94. hold on
  95. grid on
  96. plot( freq/1e6, imag(Zin), 'r--', 'Linewidth', 2 );
  97. title( 'feed point impedance' );
  98. xlabel( 'frequency f / MHz' );
  99. ylabel( 'impedance Z_{in} / Ohm' );
  100. legend( 'real', 'imag' );
  101. %% Calculate & Plot S-Parameter and accepted power
  102. % plot reflection coefficient S11
  103. figure
  104. plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
  105. grid on
  106. title( 'reflection coefficient S_{11}' );
  107. xlabel( 'frequency f / MHz' );
  108. ylabel( 'reflection coefficient |S_{11}|' );
  109. drawnow
  110. %% Calculate & Plot antenna parameter & radiation pattern
  111. %% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  112. %find resonance frequency from s11
  113. f_res_ind = find(s11==min(s11));
  114. f_res = freq(f_res_ind);
  115. % calculate the far field at phi=0 degrees and at phi=90 degrees
  116. disp( 'calculating far field at phi=[0 90] deg...' );
  117. nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, [-180:2:180]*pi/180, [0 90]*pi/180);
  118. % display power and directivity
  119. disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
  120. disp( ['directivity: Dmax = ' num2str(nf2ff.Dmax) ' (' num2str(10*log10(nf2ff.Dmax)) ' dBi)'] );
  121. disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./real(P_in(f_res_ind))) ' %']);
  122. % normalized directivity as polar plot
  123. figure
  124. polarFF(nf2ff,'xaxis','theta','param',[1 2],'normalize',1)
  125. % log-scale directivity plot
  126. figure
  127. plotFFdB(nf2ff,'xaxis','theta','param',[1 2])
  128. % conventional plot approach
  129. % plot( nf2ff.theta*180/pi, 20*log10(nf2ff.E_norm{1}/max(nf2ff.E_norm{1}(:)))+10*log10(nf2ff.Dmax));
  130. drawnow
  131. %%
  132. disp( 'calculating 3D far field pattern and dumping to vtk (use Paraview to visualize)...' );
  133. thetaRange = (0:2:180);
  134. phiRange = (0:2:360) - 180;
  135. nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180,'Verbose',1,'Outfile','3D_Pattern.h5');
  136. figure
  137. plotFF3D(nf2ff,'logscale',-20);
  138. E_far_normalized = nf2ff.E_norm{1} / max(nf2ff.E_norm{1}(:)) * nf2ff.Dmax;
  139. DumpFF2VTK([Sim_Path '/3D_Pattern.vtk'],E_far_normalized,thetaRange,phiRange,'scale',1e-3);
で、このまま実行すると、とまった?って思うけど、コマンドウィンドウでyes/noを入力しないと進まないようになっている。で、yesってして、
こういうの出るので、
ざっくり見て、閉じる(閉じないと先に進まない)
そすっと計算を進めている風になって、その後、こういうの
が出る。で、裏ではこのまま計算が進むんだけど、
まぁ、こんな感じで止まっちゃう。何かがないので何かを生成しようとしているっぽいけど失敗している感じ。
/home/hoge/opt/openEMS/share/openEMS/matlab/setup.m
に何やろうちしているか書いてある。
mkoctfile("h5readatt_octave.cc", ["-L" hdf5lib_dir], ["-I" hdf5inc_dir], "-lhdf5") これをやりたいらしい。ならば先にやって差し上げておこう。hdf5lib_dirとhdf5inc_dirはエラーメッセージから読み取ると、両方とも/usr/lib/x86_64-linux-gnu/hdf5/serialらしい。
なので、
cd /home/hoge/opt/openEMS/share/openEMS/matlab
mkoctfile h5readatt_octave.cc -L/usr/lib/x86_64-linux-gnu/hdf5/serial -I/usr/include/hdf5/serial -lhdf5
ってする。そすっと完了して、h5readatt_octave.octってのができる。で、再び実行してみると、最後までやりきって、こういう感じ
になる。たぶんうまくいった。
よし、何かに使ってみる、、、実物で検証できないテーマだな、、、家では狭すぎるし、田舎の誰もいない公園でも、法に触れることはやっちゃいかんし、、、

てかひさびさの更新!約2ヶ月!あれもこれもと思っているうちに時間がたってしまった。そして、考えていたうちのどれでもないテーマで書いてしまった、、、挙動不審の極み。認知症に足首くらいまで入ってるな。

0 件のコメント:

コメントを投稿