matthuszagh / pyems

High-level python interface to OpenEMS with automatic mesh generation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ModuleNotFoundError: No module named 'CSXCAD' (Ubuntu 20.04.4)

0xCoto opened this issue · comments

I have built OpenEMS successfully, and everything works fine from Octave on Ubuntu 20.04.4. However, when I try cloning:

git clone https://github.com/matthuszagh/pyems

and then running the horn_antenna.py example:

cd pyems/examples
cp horn_antenna.py .. # Moving one dir back so it identifies the pyems directory
cd ..
python3 horn_antenna.py

I get this error:

Traceback (most recent call last):
  File "horn_antenna.py", line 6, in <module>
    from pyems.utilities import print_table
  File "/home/apostolos/Desktop/oems_tests/pyems/pyems/utilities.py", line 5, in <module>
    from CSXCAD.CSXCAD import ContinuousStructure
ModuleNotFoundError: No module named 'CSXCAD'

Any ideas if I should try to install something in a different manner?

Thanks in advance!

That means the CSXCAD python bindings aren't installed (or at least not visible to python). Are you building csxcad in addition to openems?

FYI this and most other examples will run fine, but the microstrip to coax transition example requires a patch to csxcad, which has not yet been merged upstream.

@matthuszagh Thank you for your quick reply! Indeed, I had forgotten to add ./python3-openems*.deb to the build script. It now runs OK, but I'm facing a few other issues:

When I try to import STL files like so:

# Patch
patch = sim.csx.AddMetal("patch")
stl1 = patch.AddPolyhedronReader(
    filename=os.path.abspath("/home/apostolos/Desktop/Part__Feature001.stl")
)
stl1.ReadFile()

# Substrate
substrate = sim.csx.AddMaterial("substrate", epsilon=2.2, mue=1, kappa=0, sigma=0)
stl2 = substrate.AddPolyhedronReader(
    filename=os.path.abspath("/home/apostolos/Desktop/Part__Feature002.stl")
)
stl2.ReadFile()

# Ground
ground = sim.csx.AddMetal("ground")
stl3 = ground.AddPolyhedronReader(
    filename=os.path.abspath("/home/apostolos/Desktop/Part__Feature.stl")
)
stl3.ReadFile()

I get the following window popup:

An geometry read error occurred!!

Warning: Invalid primitive found in property: patch!
Warning: Invalid primitive found in property: substrate!
Warning: Invalid primitive found in property: ground!

As far as I know, this is often caused by the file not being found by the script, but I've specified the full path (which does work when being run from Octave). Any ideas? I couldn't find any other example (other than horn_antenna.py) that imports an STL.

Hm, I'm not able to reproduce this. As you mentioned, I was only able to see something similar when it wasn't able to find the file.

Do you get any stdout/stderr messages about the stl file not being found?

Is the stl file valid? If you share one I can test.

Here are the stl files in case you can manage to reproduce something: https://github.com/0xCoto/OpenEMS-Notes/tree/stl_files

They should be fine because Octave OpenEMS loads them up without issues, but for some reason pyems fails.

Full script (ignore the poor mesh/boundaries for now):

#!/usr/bin/env python3

import os
import sys
import numpy as np
from pyems.utilities import print_table
from pyems.port import DifferentialMicrostripPort
from pyems.simulation import Simulation
from pyems.field_dump import FieldDump
from pyems.structure import standard_waveguides
from pyems.coordinate import Coordinate3, Box3, Axis
from pyems.mesh import Mesh
from pyems.nf2ff import NF2FF

unit = 1e-3
freq = np.linspace(0e9, 3e9, 501)
sim = Simulation(freq=freq, unit=unit)

# Patch
patch = sim.csx.AddMetal("patch")
stl1 = patch.AddPolyhedronReader(
    filename=os.path.abspath("/home/apostolos/Desktop/Part__Feature001.stl")
)
stl1.ReadFile()

# Substrate
substrate = sim.csx.AddMaterial("substrate", epsilon=2.2, mue=1, kappa=0, sigma=0)
stl2 = substrate.AddPolyhedronReader(
    filename=os.path.abspath("/home/apostolos/Desktop/Part__Feature002.stl")
)
stl2.ReadFile()

# Ground
ground = sim.csx.AddMetal("ground")
stl3 = ground.AddPolyhedronReader(
    filename=os.path.abspath("/home/apostolos/Desktop/Part__Feature.stl")
)
stl3.ReadFile()


port = DifferentialMicrostripPort(
    sim=sim,
    box=Box3(
        Coordinate3(-1, -75 / 2, -1.6),
        Coordinate3(-1, -75 / 2, 0),
    ),
    excitation_axis=Axis("z"),
    propagation_axis=Axis("y"),
    excite=True,
    number=1,
    gap=1.6,
    thickness=0,
)
# port.add_metal_shell(thickness=5)


# Mesh
mesh = Mesh(
    sim=sim,
    metal_res=1 / 20,
    nonmetal_res=1 / 10,
    # smooth=(1.5, 1.5, 1.5),
    min_lines=5,
    expand_bounds=((16, 16), (16, 16), (8, 24)),
)

# 100, 100, 25


# Post processing
field_dump = FieldDump(sim=sim, box=mesh.sim_box(include_pml=False))
nf2ff = NF2FF(sim=sim)

if os.getenv("_PYEMS_PYTEST"):
    sys.exit(0)

sim.run()
sim.view_field()

s11 = sim.s_param(1, 1)
print_table(
    np.concatenate(([sim.freq / 1e9], [s11])),
    col_names=["freq", "s11"],
    prec=[4, 4],
)

theta = np.arange(-90, 90, 1)
phi = np.arange(0, 360, 1)

nf2ff.calc(theta=theta, phi=phi)

horn_width = 109.9e-3
horn_height = 80e-3
effective_aperture = horn_height * horn_width
print(nf2ff.directivity(effective_aperture))
print("gain: {:.2f} dB".format(nf2ff.gain()))

rad_phi0 = nf2ff.radiation_pattern(phi=0)
rad_phi90 = nf2ff.radiation_pattern(phi=90)

print("phi0")
print_table(
    np.concatenate(([theta], [rad_phi0])),
    col_names=["theta", "gain"],
    prec=[4, 4],
)

print("phi90")
print_table(
    np.concatenate(([theta], [rad_phi90])),
    col_names=["theta", "gain"],
    prec=[4, 4],
)

Output:

apostolos@apostolos-VirtualBox:~/Desktop/oems_tests/pyems$ python3 horn_antenna.py 
/home/apostolos/.local/lib/python3.8/site-packages/scipy/optimize/_minpack_py.py:175: RuntimeWarning: The iteration is not making good progress, as measured by the 
  improvement from the last ten iterations.
  warnings.warn(msg, RuntimeWarning)
/home/apostolos/.local/lib/python3.8/site-packages/scipy/optimize/_minpack_py.py:175: RuntimeWarning: The iteration is not making good progress, as measured by the 
  improvement from the last five Jacobian evaluations.
  warnings.warn(msg, RuntimeWarning)
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos -36.1667 for dimension 0 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.28. For convenience the last three lines are: -39.9626, -37.8333 and -36.1667.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos -28.9655 for dimension 0 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.32. For convenience the last three lines are: -32.8333, -31.1667 and -28.9655.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos -18.5536 for dimension 0 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 2.21. For convenience the last three lines are: -24.9656, -22.9658 and -18.5536.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos 2.4187 for dimension 0 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.28. For convenience the last three lines are: -5.3742, -1.0000 and 2.4187.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos 30.8333 for dimension 0 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.27. For convenience the last three lines are: 27.0472, 29.1667 and 30.8333.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos 37.9626 for dimension 0 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.28. For convenience the last three lines are: 34.1667, 35.8333 and 37.9626.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos -32.8167 for dimension 1 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.41. For convenience the last three lines are: -40.8117, -37.5000 and -32.8167.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos -9.4004 for dimension 1 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 843932831515.30. For convenience the last three lines are: -14.0837, -9.4004 and -9.4004.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos -4.9081 for dimension 1 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 809510081404.04. For convenience the last three lines are: -9.4004, -9.4004 and -4.9081.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos 26.3958 for dimension 1 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.21. For convenience the last three lines are: 17.8831, 22.5417 and 26.3958.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos 42.7753 for dimension 1 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.25. For convenience the last three lines are: 34.1042, 37.9583 and 42.7753.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos 100.6774 for dimension 1 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.20. For convenience the last three lines are: 84.5697, 91.8899 and 100.6774.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos -1.6000 for dimension 2 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.28. For convenience the last three lines are: -1.6000, -1.6000 and -1.6000.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos 0.0000 for dimension 2 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.50. For convenience the last three lines are: -0.0157, -0.0063 and 0.0000.
  warn(
/home/apostolos/Desktop/oems_tests/pyems/pyems/mesh.py:664: UserWarning: Mesh line at pos 0.0080 for dimension 2 violates smoothness. Smoothness was set to 1.20 but this line creates a spacing with factor 1.27. For convenience the last three lines are: -0.0063, 0.0000 and 0.0080.
  warn(
CSPrimPolyhedronReader::ReadFromXML: Error, can't read filename!
CSPrimPolyhedronReader::ReadFromXML: Error, can't read filename!
CSPrimPolyhedronReader::ReadFromXML: Error, can't read filename!
VTKPrimitives::AddCube: Warning, can't draw a Point Box... skipping
VTKPrimitives::AddCube: Warning, can't draw a Point Box... skipping
VTKPrimitives::AddCube: Warning, can't draw a Point Box... skipping
VTKPrimitives::AddCube: Warning, can't draw a Point Box... skipping
VTKPrimitives::AddCube: Warning, can't draw a Point Box... skipping
VTKPrimitives::AddCube: Warning, can't draw a Point Box... skipping
Continue simulation (y/n)? n
Terminating simulation.

Edit: And here's the Octave script that does load the stls without issues:

%
% EXAMPLE / antennas / patch antenna
%
% This example demonstrates how to:
%  - calculate the reflection coefficient of a patch antenna
% 
%
% Tested with
%  - Matlab 2009b
%  - Octave 3.3.52
%  - openEMS v0.0.23
%
% (C) 2010,2011 Thorsten Liebig <thorsten.liebig@uni-due.de>

close all
clear
clc
addpath('~/opt/openEMS/share/openEMS/matlab');
addpath('~/opt/openEMS/share/CSXCAD/matlab');


%% switches & options...
postprocessing_only = 0;
draw_3d_pattern = 0; % this may take a while...
use_pml = 1;         % use pml boundaries instead of mur
openEMS_opts = '';

%% setup the simulation
physical_constants;
unit = 1e-3; % all length in mm

% width in x-direction
% length in y-direction
% main radiation in z-direction
patch.width  = 59; % resonant length
patch.length = 40;

substrate.epsR   = 2.2;
substrate.kappa  = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;
substrate.width  = 77;
substrate.length = 75;
substrate.thickness = 1.6;
substrate.cells = 64;

feed.pos = -1;
feed.width = 5;
feed.R = 50; % feed resistance

% size of the simulation box
SimBox = [100 100 25];

%% prepare simulation folder
Sim_Path = 'tmp';
Sim_CSX = 'patch_ant.xml';
if (postprocessing_only==0)
    [status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
    [status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
end

%% setup FDTD parameter & excitation function
max_timesteps = 30000;
min_decrement = 1e-5; % equivalent to -50 dB
f0 = 0e9; % center frequency
fc = 3e9; % 20 dB corner frequency (in this case 0 Hz - 3e9 Hz)
FDTD = InitFDTD( 'NrTS', max_timesteps, 'EndCriteria', min_decrement );
FDTD = SetGaussExcite( FDTD, f0, fc );
BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % boundary conditions
if (use_pml>0)
    BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'}; % use pml instead of mur
end
FDTD = SetBoundaryCond( FDTD, BC );

%% setup CSXCAD geometry & mesh
% currently, openEMS cannot automatically generate a mesh
max_res = c0 / (f0+fc) / unit / 120; % cell size: lambda/20
CSX = InitCSX();
mesh.x = [-SimBox(1)/2 SimBox(1)/2 -substrate.width/2 substrate.width/2 feed.pos];
% add patch mesh with 2/3 - 1/3 rule
mesh.x = [mesh.x -patch.width/2-max_res/2*0.66 -patch.width/2+max_res/2*0.33 patch.width/2+max_res/2*0.66 patch.width/2-max_res/2*0.33];
mesh.x = SmoothMeshLines( mesh.x, max_res, 1.4); % create a smooth mesh between specified mesh lines
mesh.y = [-SimBox(2)/2 SimBox(2)/2 -substrate.length/2 substrate.length/2 -feed.width/2 feed.width/2];
% add patch mesh with 2/3 - 1/3 rule
mesh.y = [mesh.y -patch.length/2-max_res/2*0.66 -patch.length/2+max_res/2*0.33 patch.length/2+max_res/2*0.66 patch.length/2-max_res/2*0.33];
mesh.y = SmoothMeshLines( mesh.y, max_res, 1.4 );
mesh.z = [-SimBox(3)/2 linspace(-substrate.thickness-0.035,0.035,substrate.cells) SimBox(3) ];
mesh.z = SmoothMeshLines( mesh.z, max_res, 1.4 );
mesh = AddPML( mesh, [8 8 8 8 8 8] ); % add equidistant cells (air around the structure)
CSX = DefineRectGrid( CSX, unit, mesh );

# Add cad geometry 
CSX = AddMetal(CSX, 'patch'); # Declare PEC
CSX = ImportSTL(CSX, 'patch',1,'/home/apostolos/Desktop/Part__Feature001.stl'); # Import geometry; make sure you use the absolute path!

CSX = AddMaterial(CSX,'substrate');
CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon', substrate.epsR, 'Kappa', substrate.kappa );
CSX = ImportSTL(CSX, 'substrate',10, '/home/apostolos/Desktop/Part__Feature002.stl','Transform',{'Scale', 1});

CSX = AddMetal(CSX, 'ground'); # Declare PEC
CSX = ImportSTL(CSX, 'ground',1,'/home/apostolos/Desktop/Part__Feature.stl'); # Import geometry; make sure you use the absolute path!

start = [feed.pos-0 -substrate.length/2 -substrate.thickness];
stop  = [feed.pos+0 -substrate.length/2 0];
[CSX] = AddLumpedPort(CSX, 5 ,1 ,feed.R, start, stop, [0 0 1], true);

%% dump magnetic field over the patch antenna
CSX = AddDump( CSX, 'Ht_', 'DumpType', 1, 'DumpMode', 2); % cell interpolated
start = [-patch.width -patch.length substrate.thickness+1];
stop  = [ patch.width  patch.length substrate.thickness+1];
CSX = AddBox( CSX, 'Ht_', 0, start, stop );

%%nf2ff calc
[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', -SimBox/2, SimBox/2);

if (postprocessing_only==0)
    %% write openEMS compatible xml-file
    WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );

    %% show the structure
    CSXGeomPlot( [Sim_Path '/' Sim_CSX] );

    %% run openEMS
    RunOpenEMS( Sim_Path, Sim_CSX, openEMS_opts );
end

%% postprocessing & do the plots
freq = linspace( max([1e9,f0-fc]), f0+fc, 501 );
U = ReadUI( {'port_ut1','et'}, 'tmp/', freq ); % time domain/freq domain voltage
I = ReadUI( 'port_it1', 'tmp/', freq ); % time domain/freq domain current (half time step is corrected)

% plot time domain voltage
figure
[ax,h1,h2] = plotyy( U.TD{1}.t/1e-9, U.TD{1}.val, U.TD{2}.t/1e-9, U.TD{2}.val );
set( h1, 'Linewidth', 2 );
set( h1, 'Color', [1 0 0] );
set( h2, 'Linewidth', 2 );
set( h2, 'Color', [0 0 0] );
grid on
title( 'time domain voltage' );
xlabel( 'time t / ns' );
ylabel( ax(1), 'voltage ut1 / V' );
ylabel( ax(2), 'voltage et / V' );
% now make the y-axis symmetric to y=0 (align zeros of y1 and y2)
y1 = ylim(ax(1));
y2 = ylim(ax(2));
ylim( ax(1), [-max(abs(y1)) max(abs(y1))] );
ylim( ax(2), [-max(abs(y2)) max(abs(y2))] );

% plot feed point impedance
figure
Zin = U.FD{1}.val ./ I.FD{1}.val;
plot( freq/1e6, real(Zin), 'k-', 'Linewidth', 2 );
hold on
grid on
plot( freq/1e6, imag(Zin), 'r--', 'Linewidth', 2 );
title( 'feed point impedance' );
xlabel( 'frequency f / MHz' );
ylabel( 'impedance Z_{in} / Ohm' );
legend( 'real', 'imag' );

% plot reflection coefficient S11
s_fig = figure;
uf_inc = 0.5*(U.FD{1}.val + I.FD{1}.val * 50);
if_inc = 0.5*(I.FD{1}.val - U.FD{1}.val / 50);
uf_ref = U.FD{1}.val - uf_inc;
if_ref = I.FD{1}.val - if_inc;
s11 = uf_ref ./ uf_inc;
plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
grid on
title( 'reflection coefficient S_{11}' );
print(s_fig,'MySavedPlot','-dpng')
xlabel( 'frequency f / MHz' );
ylabel( 'reflection coefficient |S_{11}|' );

P_in = 0.5*U.FD{1}.val .* conj( I.FD{1}.val );

%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
f_res_ind = find(s11==min(s11));
f_res = freq(f_res_ind);

% calculate the far field at phi=0 degrees and at phi=90 degrees
thetaRange = (0:2:359) - 180;
phiRange = [0 90];
disp( 'calculating far field at phi=[0 90] deg...' );
nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180);

Dlog=10*log10(nf2ff.Dmax);

% display power and directivity
disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
disp( ['directivity: Dmax = ' num2str(Dlog) ' dBi'] );
disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./real(P_in(f_res_ind))) ' %']);

% display phi
figure
plotFFdB(nf2ff,'xaxis','theta','param',[1 2]);
drawnow

if (draw_3d_pattern==0)
    return
end

%% calculate 3D pattern
phiRange = 0:2:360;
thetaRange = 0:2:180;
disp( 'calculating 3D far field...' );
nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180, 'Verbose',2,'Outfile','nf2ff_3D.h5');
figure
plotFF3D(nf2ff);

I can't reproduce this either; works fine on my computer. The only difference in my test is that I put the STL files in /tmp.

The specific error you're triggering is here. QueryStringAttribute is a tinyxml function. You can download a tarball of the sources for that here. Here is some relevant code from that:

	int QueryStringAttribute( const char* name, std::string* _value ) const {
		const char* cstr = Attribute( name );
		if ( cstr ) {
			*_value = std::string( cstr );
			return TIXML_SUCCESS;
		}
		return TIXML_NO_ATTRIBUTE;
	}
const char* TiXmlElement::Attribute( const char* name ) const
{
	const TiXmlAttribute* node = attributeSet.Find( name );
	if ( node )
		return node->Value();
	return 0;
}

Anyway, Attribute seems to be returning a null pointer in your case. Unfortunately I'm not really familiar with the tinyxml codebase. The strange thing is it seems to be complaining about "Filename", not the actual file name. My first guess was that you'd used invalid characters in the file name but that doesn't seem to be the case. I'd dig through that tinyxml code if I were you and I'd double-check the installation, in particular with respect to tinyxml.

Does my horn-antenna example work for you? Are you able to run other simulations that don't use the stl reader? It would be a bit strange if tinyxml failed in this specific case but was otherwise able to write XML files fine.

Hmm, looks like I'm getting the same error with the horn example. I'll double-check the installation; perhaps we might have missed something in the build script.

Couldn't it be related to this? In which case the cause of your problem would be the Debian OpenEMS packages we use that are not up to date (2019/01/03).

Couldn't it be related to this? In which case the cause of your problem would be the Debian OpenEMS packages we use that are not up to date (2019/01/03).

Yep, I'd completely forgotten about that. Could definitely be it.

@thomaslepoix Is there a good reason to use the outdated Debian package at all? Could you update the build script so it grabs the latest version from git, and also takes care of the ./python3-openems*.deb install? I tried to install the latest version using:

sudo apt-get install build-essential cmake git libhdf5-dev libvtk7-dev libboost-all-dev libcgal-dev libtinyxml-dev qtbase5-dev libvtk7-qt-dev
sudo apt-get install octave liboctave-dev
sudo pip3 install matplotlib cython h5py
git clone --recursive https://github.com/thliebig/openEMS-Project.git
cd openEMS-Project
./update_openEMS.sh ~/opt/openEMS
./update_openEMS.sh ~/opt/openEMS --python

but got the initial error again after trying pyems: No module named 'CSXCAD'. I'm guessing we have to insert something along the lines of sudo apt install python3-openems*.deb like we did last time, but for the latest version?

You can't really mix manual and APT based installation.

  • If you want it immediately, I would suggest to follow the procedure you spotted here.

  • Using the .deb is IMHO better because of the usual benefits of APT and because the package contains patches about various oddities. I could try a script that updates on the fly the existing package before regenerating it. Will also submit my patch about build flags and request an update from Debian maintainer.

I could try a script that updates on the fly the existing package before regenerating it.

That would be perfect, thanks! We're currently investigating some methods of achieving speedup in the FDTD code, so being able to update from a git repository whenever needed would be ideal.

Solved - Thomas also helped built a convenient script for installing openEMS on fresh debian installations. The relevant PR for CSXCAD fixed the problem. It's also important to make sure the submodules are up-to-date; we cloned using --recursive --remote-submodules to ensure the submodules are updated in case Thorsten has forgotten to link them to the latest commits (e.g. the CSXCAD submodule is not currently linked to the latest commit).

Will open another issue for pyems usage questions, cheers!