2D Cylindrical Wave
Simulate a 2D cylindrical wave radiating from an off-centre point source, using five nested cylindrical sub-grids to prevent azimuthal over-sampling near the axis while keeping the domain large enough to observe far-field behaviour.
This tutorial covers:
Cylindrical coordinate system (
CoordSystem=1) in openEMSNested cylindrical sub-grids (
MultiGrid) that double azimuthal resolution at each boundary towards the axisCombined VTK (time-domain) and HDF5 (frequency-domain) field dumps
Phase animation of the complex E_z phasor in Octave
Octave/Matlab Script
Setup the Simulation
Define the simulation domain radius, mesh resolution, and five nested cylindrical sub-grids whose boundaries progressively double the azimuthal cell count, preventing over-sampling of the fields near the axis.
physical_constants
mesh_res = 10; %desired mesh resolution
radius = 2560; %simulation domain radius
split = ['80,160,320,640,1280']; %radii to split the mesh into sub-grids
split_N = 5; %number of nested sub-grids
heigth = mesh_res*4;
f0 = 1e9;
exite_offset = 1300;
excite_angle = 45;
FDTD Parameters and Excitation
CoordSystem=1 selects cylindrical coordinates; MultiGrid activates
the nested sub-grid engine. A PML on the outer radial face absorbs the
outgoing cylindrical wave; all other boundaries default to PEC.
FDTD = InitFDTD('NrTS', 100000, 'EndCriteria', 1e-4, 'CoordSystem', 1, 'MultiGrid', split);
FDTD = SetGaussExcite(FDTD,f0,f0/2);
BC = [0 3 0 0 0 0]; % pml in positive r-direction
FDTD = SetBoundaryCond(FDTD,BC);
CSXCAD Geometry and Mesh
The outermost sub-domain carries 50 x 2^5 = 1600 azimuthal lines; each
inner sub-grid halves this count so angular resolution scales with cell
size. SmoothMeshLines distributes radial and axial lines uniformly.
% 50 mesh lines for the inner most mesh
% increase the total number of meshlines in alpha direcion for all sub-grids
N_alpha = 50 * 2^split_N + 1;
CSX = InitCSX('CoordSystem',1);
mesh.r = SmoothMeshLines([0 radius],mesh_res);
mesh.a = linspace(-pi,pi,N_alpha);
mesh.z = SmoothMeshLines([-heigth/2 0 heigth/2],mesh_res);
CSX = DefineRectGrid(CSX, 1e-3,mesh);
Dipole Excitation
A z-directed electric-current source placed off-centre at 1300 mm radius and 45 degree azimuth launches an asymmetric cylindrical wave, exercising the multigrid across its full radial extent.
start = [exite_offset excite_angle/180*pi-0.001 -20];
stop = [exite_offset excite_angle/180*pi+0.001 20];
if (exite_offset==0)
start(2) = mesh.a(1);
stop(2) = mesh.a(1);
end
CSX = AddExcitation(CSX,'excite',1,[0 0 1]);
CSX = AddBox(CSX,'excite',0 ,start,stop);
Field Dump Boxes
Two overlapping dump regions cover the full r-alpha plane at z = 0. The time-domain VTK dump is sub-sampled for Paraview; the frequency-domain HDF5 dump stores the complex E-field phasor at f0 for post-processing.
start = [mesh.r(1) mesh.a(1) 0];
stop = [mesh.r(end-8) mesh.a(end) 0];
% time domain vtk dump
CSX = AddDump(CSX,'Et_ra','DumpType',0,'FileType',0,'SubSampling','4,10,1');
CSX = AddBox(CSX,'Et_ra',0 , start,stop);
% frequency domain hdf5 dump
CSX = AddDump(CSX,'Ef_ra','DumpType',10,'FileType',1,'SubSampling','2,2,2','Frequency',f0);
CSX = AddBox(CSX,'Ef_ra',0 , start,stop);
Write and Run
Serialize the simulation model to XML and invoke the openEMS solver.
CleanupSimPath removes stale results from any previous run.
Sim_Path = 'tmp';
Sim_CSX = '2D_CC_Wave.xml';
CleanupSimPath(Sim_Path);
WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
RunOpenEMS(Sim_Path, Sim_CSX);
Paraview Visualization
The time-domain VTK dump can be opened in Paraview to animate the propagating wave front directly on the cylindrical mesh.
disp('use Paraview to visualize the vtk field dump...');
Post-processing and Phase Animation
Read the frequency-domain HDF5 dump, convert the cylindrical mesh to Cartesian coordinates, then animate the E_z phasor over 0-360 degrees to visualise the full cylindrical wave pattern.
[field mesh_h5] = ReadHDF5Dump([Sim_Path '/Ef_ra.h5']);
r = mesh_h5.lines{1};
a = mesh_h5.lines{2};
a(end+1) = a(1); %closeup mesh for visualization
[R A] = ndgrid(r,a);
X = R.*cos(A);
Y = R.*sin(A);
Ez = squeeze(field.FD.values{1}(:,:,1,3));
Ez(:,end+1) = Ez(:,1); %closeup mesh for visualization
E_max = max(max(abs(Ez))); %get maximum E_z amplitude
while 1
for ph = linspace(0,360,41) %animate phase from 0..360 degree
surf(X,Y,real(Ez*exp(1j*ph*pi/180)),'EdgeColor','none')
caxis([-E_max E_max]/10)
zlim([-E_max E_max])
pause(0.3)
end
end
Notes
Sub-grid azimuthal resolution: the outermost sub-domain carries 50 × 25 = 1600 azimuthal lines; each inner sub-grid halves this count, so the angular cell size scales with radius and avoids the extreme over-sampling that a uniform mesh would produce near the axis.
AppCSXCAD limitation: CSXGeomPlot does not render the sub-grid
structure — it displays the finest azimuthal mesh at all radii instead.
The actual multi-resolution grid only becomes visible in the field-dump output.
Images
Phase animation of the E_z field showing the asymmetric cylindrical wave propagating outward from the off-centre source