Loops¶
In this section we show how to exploit loops (for, while) within Python code snippets to define complicated geometries or project setups in a few number of script lines.
Loops within an embedded Python code block (cf. previous section Python Code Snippets) may extend over several blocks:
1<?
2for centerX in range(0, 10):
3 keys['center'] = [centerX, 0.0]
4 ?>
5
6Circle {
7 Radius = 0.5
8 GlobalPosition = %(center)e
9 ...
10}
11
12 <? # closes for loop
13?>
Here, a for-loop starts in line 2 within the first Python block. As a convention the <?, ?> starting and closing tags follow the Python indentation rules. Hence the for-loop is not closed in line 4, but in line 13 after a .jcm code block (lines 6-10).
Line 3 dynamically sets the value for key center, which serves as the circle’s center in line 8. This way, we have defined ten circles, equally spaced in
-direction.
To see how this works in practice, we want to compute the light scattering off multiple rods aligned on a hexagonal lattice. Figure “Multiple rod geometry” shows the setup.
Multiple rod geometry¶
and
are called grid vectors. For a hexagonal alignment we have

with a lattice parameter
, which is passed as a further parameter in the driver script:
1import jcmwave
2
3# set problem parameter
4keys = {
5 'radius': 0.3,
6 'a': 1.0,
7 'n_rods': [3, 3],
8 'n_air': 1.0,
9 'n_glass': 1.52,
10 'lambda_0': 0.550, # in um
11 'polarization': 45 # in degree
12}
13
14# run the project
15results = jcmwave.solve('mie2D.jcmp', keys=keys)
16
17# get scattering cross section
18scattering_cross_section = results[1]['ElectromagneticFieldEnergyFlux'][0][0]
19print ('\nscattering cross section: %.8g\n' % scattering_cross_section.real )
20
21# plot exported cartesian grid within python
22cfb = results[2]
23amplitude = cfb['field'][0]
24intensity = (amplitude.conj()*amplitude).sum(2).real
25
26from matplotlib.pyplot import *
27pcolormesh(cfb['X'], cfb['Y'], intensity, shading='gouraud')
28axis('tight')
29gca().set_aspect('equal')
30gca().xaxis.major.formatter.set_powerlimits((-1, 0))
31gca().yaxis.major.formatter.set_powerlimits((-1, 0))
32show()
In line 7 we set the number of rods in
- and
- direction. Figure “Intensity” shows the computed intensity of the electric field.
Intensity¶
Pseudo-color intensity plot as produced by the driver run.py.
For this problem you again find a driver run_geo.py which only runs the mesh generation:
import jcmwave
# set geometry parameter
keys = {
'radius': 0.3,
'a': 1.0,
'n_rods': [3, 3]
}
# generate mesh file only
jcmwave.geo('.', keys)
# open grid.jcm in JCMview
jcmwave.view('grid.jcm')
You can use this script to “play” with the geometry parameters and to watch how the geometry is updated.
In the following we want to discuss the updated layout file:
1<?
2# compute grid vectors for hexagonal grid
3
4from math import sin, cos, pi
5from numpy import array
6
7gv1 = array([0.0, keys['a']])
8gv2 = array([sin(60./180*pi), cos(60./180*pi)])*keys['a']
9
10# compute computational domain enclosing all scatterer
11maxX = (keys['n_rods'][0]-1)*gv2[0]
12maxY = (keys['n_rods'][1]-1)*gv1[1]
13
14keys['computational_domain_X'] = maxX+2*keys['radius']+2
15keys['computational_domain_Y'] = maxY+2*keys['radius']+2
16?>
17
18
19Layout2D {
20 UnitOfLength = 1e-6
21
22 MeshOptions {
23 MaximumSideLength = 0.1
24 CurvilinearDegree = 2
25 }
26
27 Objects {
28 # Computational domain
29 Parallelogram {
30 DomainId = 1
31 Width = %(computational_domain_X)e
32 Height = %(computational_domain_Y)e
33
34 # set transparent boundary conditions
35 Boundary{
36 Class = Transparent
37 }
38 }
39
40<?
41center_array = array([maxX/2, maxY/2])
42for iX in range(0, keys['n_rods'][0]):
43 col_start = array([iX*gv2[0], (iX % 2)*gv2[1]])
44 for iY in range(0, keys['n_rods'][1]-(iX % 2)):
45 keys['center'] = col_start+iY*gv1-center_array
46 ?>
47 # Scatterer (rod)
48 Circle {
49 DomainId = 2
50 Radius = %(radius)e
51 GlobalPosition = %(center)e
52 }
53
54<? # closes for loops
55?>
56 }
57}
58
59
60
The first Python block computes the grid vectors
(lines 7-8), and adapts the computational domain size to enclose all rods (lines 10-15). There, maxX and maxY are the dimensions of the array of rods in
and
.
The Python block from lines 38-46 defines two for loops over the number of rods in
and
. Line 43 sets the center of the current rod, which is used in line 51 in the enclosed .jcm block (center_array is used to shift the center of the array of rods to the origin). The for loops are closed in the last Python block (lines 56-57).