# Working with Shapes and Regions

I’ve introduced an easy-to-use high-level interface for working with shapes and regions. There are a number of built-in elementary shapes (rectangle, disk, triangle, ellipsoid, torus, pyramid, tetrahedron, cone) which can be combined to form composite shapes. These shapes can then be used as 1) physical objects in meshes, 2) as masks to set magnetization directions, and 3) as regions to set material parameter values. The shapes also have transformation functions, including scaling, translation, rotation, array generation.

Shapes can be used directly with console commands, however the best way to use them is with the high-level Python interface now provided through the NetSocks.py module. Let’s have a look at some examples.

First let’s take a simple example with two objects: a torus and a disk.

 `from NetSocks import NSClientfrom NetSocks import Shapens = NSClient('localhost', serverport = 1542)ns.configure(True)########################################l, w, t = 800e-9, 800e-9, 100e-9ns.meshrect([l, w, t])ns.delrect()tor = Shape.torus([l, w, t])disk = Shape.disk([l/2, w/2, t])#set disk centredns.shape_set(disk.move([l/2, w/2, t/2]))#set torus centredns.shape_set(tor.move([l/2, w/2, t/2]))#set magnetization angles of defined shapesns.shape_setangle(disk, [180, 0])ns.shape_setangle(tor, [90, 90])`

The Shape class contains all the elementary shapes, which can be combined using simple operators (+, -) into composite shapes. Once a shape is define it can be physically set in the mesh using the shape_set function. The shapes can also be used as masks to set magnetization angle using the shape_setangle function. The above example produces the following mesh structure and magnetization direction: Finally the shapes can be used to define regions with different material parameters, set using the shape_setparam function.

 `#set material parameter values of regions defined by shapesns.setparam(ns.meshfocus(), 'Ms', 1)ns.shape_setparam('Ms', disk, 600e3)ns.shape_setparam('Ms', tor, 1200e3)`

If we look at the Ms material parameter spatial variation we have the following: All material parameters in Boris may be assigned a spatial variation with the same resolution as the mesh discretization, and there are a number of built-in spatial variation generators as described in the manual. Internally this is handled efficiently (in terms of code reuse and maintainability, as well as execution time) using a variadic template function to check material parameters spatial, temporal, and temperature dependences.

Let’s have a look at a more advanced example. First let’s set a hollow half-torus, and set its left and right sides to different magnetization directions, using the following script:

 `from NetSocks import NSClientfrom NetSocks import Shapens = NSClient('localhost', serverport = 1542)ns.configure(True)########################################l, w, t = 800e-9, 800e-9, 200e-9ns.meshrect([l, w, t])ns.cellsize([2.5e-9, 2.5e-9, 2.5e-9])ns.delrect()#define hollow half-torustor1 = Shape.torus([l, w, t])tor2 = Shape.torus([l - t/2 + t*0.75/2, w - t/2 + t*0.75/2, t*0.75])htor = tor1 - tor2 - Shape.rect([l, w/2, t]).move([0, -w/4, 0])#define masks for left and right sides of half-torusleft = htor - Shape.rect([l/2, w/2, t]).move([l/4, w/4, 0])right = htor - Shape.rect([l/2, w/2, t]).move([-l/4, w/4, 0])#set shape and magnetization directions for left and right sidesns.shape_set(htor.move([l/2, w/2, t/2]))ns.shape_setangle(left.move([l/2, w/2, t/2]), [90, 90])ns.shape_setangle(right.move([l/2, w/2, t/2]), [90, 270])`

This produces the following: Let’s take it a step further and introduce more shapes, also showing how rotations and array generation can be used:

 `#rectangular basebase = Shape.rect([l * 0.6, w*0.5, 10e-9])ns.shape_set(base.move([l/2, w/4, t/3]))#repeated tetrahedrad = 40e-9tetra = Shape.tetrahedron([d, d, d])tetra.setrepetitions([1, w / (4*d), 1], [0, d * 2, 0])ns.shape_set(tetra.move([l * 0.2 + d, d, t/3 + d/2]))ns.shape_setangle(tetra, [90, 0])#repeated pyramidspyramid = Shape.pyramid([d, d, d])pyramid.setrepetitions([1, w / (4*d), 1], [0, d * 2, 0])ns.shape_set(pyramid.move([l * 0.2 + 3*d, d, t/3 + d/2]))ns.shape_setangle(pyramid, [0, 0])#repeated rotated trianglestriangle = Shape.triangle([d, d, d])triangle.setrepetitions([1, w / (4*d), 1], [0, d * 2, 0])triangle.rotate([0, 90, 45])ns.shape_set(triangle.move([l * 0.2 + 5*d, d, t/3 + d/2]))ns.shape_setangle(triangle, [180, 0])#repeated rotated excentric tubestube = Shape.disk([d, d, d]) - Shape.disk([d/2, d/2, d]).move([d/5, 0, 0])tube.setrepetitions([1, w / (4*d), 1], [0, d * 2, 0])tube.rotate([-30, 45, 45])ns.shape_set(tube.move([l * 0.2 + 7*d, d, t/3 + d/2]))ns.shape_setangle(tube, [90, 90])#repeated ellipsoidsellipsoid = Shape.ellipsoid([d/2, d*1.5, d*0.75])ellipsoid.setrepetitions([1, w / (4*d), 1], [0, d * 2, 0])ns.shape_set(ellipsoid.move([l * 0.2 + 9*d, d, t/3 + d/2]))ns.shape_setangle(ellipsoid, [90, 270])#repeated conescone = Shape.cone([d, d, d])cone.setrepetitions([1, w / (4*d), 1], [0, d * 2, 0])ns.shape_set(cone.move([l * 0.2 + 11*d, d, t/3 + d/2]))ns.shape_setangle(cone, [45, 45])`

This now produces the following: Finally let’s relax the magnetization so it looks a bit more interesting (why not!): This functionality will be available in v3.0, which I’m hoping to release this Friday.