# 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 2 3 4 5 6 7 8 9 10 11 12 13  Circle { Radius = 0.5 GlobalPositionX = %(center)e ... } 

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 centerX, which serves as the -position of 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:

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import jcmwave # set problem parameter keys = { 'radius': 0.3, 'a': 1.0, 'n_rods': [3, 3], 'n_air': 1.0, 'n_glass': 1.52, 'lambda_0': 0.550, # in um 'polarization': 45 # in degree } # run the project results = jcmwave.solve('mie2D.jcmp', keys=keys) # get scattering cross section scattering_cross_section = results[1]['ElectromagneticFieldEnergyFlux'][0][0] print ('\nscattering cross section: %.8g\n' % scattering_cross_section.real ) # plot exported cartesian grid within python cfb = results[2] amplitude = cfb['field'][0] intensity = (amplitude.conj()*amplitude).sum(2).real from matplotlib.pyplot import * pcolormesh(cfb['X'], cfb['Y'], intensity, shading='gouraud') axis('tight') gca().set_aspect('equal') gca().xaxis.major.formatter.set_powerlimits((-1, 0)) gca().yaxis.major.formatter.set_powerlimits((-1, 0)) show() 

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 = {
'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 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58  Layout { UnitOfLength = 1e-6 MeshOptions { MaximumSidelength = 0.1 } # Computational domain Parallelogram { DomainId = 1 Width = %(computational_domain_X)e Height = %(computational_domain_Y)e # set transparent boundary conditions BoundarySegment { BoundaryClass = Transparent } } # Scatterer (rod) Circle { DomainId = 2 Radius = %(radius)e GlobalPosition = %(center)e RefineAll = 4 } } 

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).