Parametric Surfaces - All About

This document describes how parametric surfaces are implemented in OSCARS.

A parametric surface in OSCARS is represented by a python class. This class must contain the variables u and v, start and stop points ustart, ustop, vstart, vstop, and the number of points in each dimension nu, nv. Later in this notebook we develop a custom surface. First we start with surfaces in OSCARS.

In [1]:
# matplotlib plots inline
%matplotlib inline

# Import the OSCARS SR module
import oscars.sr

# Import OSCARS 3D tools (matplotlib)
from oscars.plots3d_mpl import *

# Import OSCARS parametric surfaces
from oscars.parametric_surfaces import *
OSCARS v2.1.8 - Open Source Code for Advanced Radiation Simulation
Brookhaven National Laboratory, Upton NY, USA
http://oscars.bnl.gov
oscars@bnl.gov
In [2]:
# Plot the rectangle
rectangle = PSRectangle(L=0.01, W=0.01, nu=51, nv=51)
plot_surface(rectangle)
In [3]:
# Plot the sphere
sphere = PSSphere(R=0.010, nu=51, nv=51)
plot_surface(sphere)
In [4]:
# Plot the cylinder
cylinder = PSCylinder(R=0.010, L=0.1, nu=51, nv=51)
plot_surface(cylinder)
In [5]:
# Plot the torus
torus = PSTorus(R=0.010, r=0.005, nu=51, nv=51)
plot_surface(torus)

Eample - Custom Parametric Surface in OSCARS

The example that follows shows how to create a custom parametric surface. The parametric surface is created in a simple python class. OSCARS requires the class to have the following defined:

Functions: position(u, v), normal(u, v) which each return a 3-element list [x, y, z]

Integers: nu, nv

Floats: ustart, ustop, vstart, vstop

At the moment you must provide the normal. You can use the following recipe for the components of the normal:

In the following, let x = x(u, v) = position(u, v)[0], and so on

$$ N_x = \frac{\partial y}{\partial u}\frac{\partial z}{\partial v} - \frac{\partial z}{\partial u}\frac{\partial y}{\partial v}\\ N_y = \frac{\partial z}{\partial u}\frac{\partial x}{\partial v} - \frac{\partial x}{\partial u}\frac{\partial z}{\partial v}\\ N_y = \frac{\partial x}{\partial u}\frac{\partial y}{\partial v} - \frac{\partial y}{\partial u}\frac{\partial x}{\partial v} $$

You need to decide if you want to invert this or not since it's not clear which is the front and back side. It is also a good idea to normalize this.

The position in this example is given by the following: $$ x = u \sin(v)\\ y = u \cos(v)\\ z = A \sin( 2 \pi u / \lambda ) $$

which gives a normal of: $$ N_x = 2 A \pi u \cos(2 \pi u / \lambda) \sin(v) / \lambda\\ N_y = 2 A \pi u \cos(2 \pi u / \lambda) \cos(v) / \lambda\\ N_z = -u $$ and in this example I did have to invert the normal vector

In [6]:
from math import sin, cos, pi, sqrt, exp
class PSWavyDisk:
    """A Parametric surface - wavy disk with a hole in the center"""

    # This shape specific parameters
    R1 = 0.001
    R2 = 0.005
    A = 0.001
    Lambda = 0.01

    # Required for all PS shapes
    # Start, stop, and number of points for the u and v parameters
    # All PSShapes must have these defined
    ustart = R1
    ustop  = R2
    vstart = 0
    vstop  = 2 * pi
    nu = 21
    nv = 21

    def __init__ (self, R1=0.001, R2=0.005, nu=21, nv=21):
        self.R1 = R1
        self.R2 = R2
        self.ustart = R1
        self.ustop  = R2
        self.nu = nu
        self.vstart = 0
        self.vstop = 2.*pi
        self.nv = nv


    def position (self, u, v):
        """Return the position in 3D at this u and v"""

        x = u * sin(v)
        y = u * cos(v)
        z = self.A * sin( 2. * pi * u / self.Lambda )

        return [x, y, z]


    def normal (self, u, v):
        """Return a unit normal in 3D at this u and v position"""

        xn = -2. * self.A * pi * u * cos(2. * pi * u / self.Lambda) * sin(v) / self.Lambda
        yn = -2. * self.A * pi * u * cos(2. * pi * u / self.Lambda) * cos(v) / self.Lambda
        zn = u

        mag = sqrt(xn*xn + yn*yn + zn*zn)

        return [xn / mag, yn / mag, zn / mag]
In [7]:
# Create a parametric shape and plot it
wavydisk = PSWavyDisk(R1=0.01, R2=0.04, nu=51, nv=101)
plot_surface(wavydisk, zlim=[-0.01, 0.01])