画1维光栅能带的Python拓展
最近因为无法忍受Python运行效率的低下,但又不想放弃Python,于是用C语言写了一个Python画一维光栅能带和薄膜干涉的拓展。
代码
改了很多遍,终于改出了自己想要的编程风格,等以后自己编程风格变了,再回来把它改了。
plotBand.h
/**********************************************************************************************************************
* File Name : plotBand.h
* Copyright : 2020-2025 Fudan University, All Rights Reserved.
* Module Name : plotBand
*
* CPU : 16 Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
* OS : Ubuntu
*
* Create Date : 2020/11/23
* Author/Corporation : Lingjie Fan/Fudan University
*
* Abstract Description : Some declarations of struct and function used to plot band of grating are contained
* in this file.
*
*--------------------------------------------------------------------------------------------------------------------
* Revision History
* No Version Date Revised By Item Description
* 1 V1.0.0 2020/11/23 Lingjie Fan Header File Header Section Description and record are added
* 2 V1.0.0 2020/11/23 Lingjie Fan Macro Define Section Macro EPSILON is defined
* 3 V1.0.0 2020/11/23 Lingjie Fan Prototype Declare Section Two private function is moved from
* header file to source file
* 4 V1.0.0 2020/11/25 Lingjie Fan Structure Define Section "typedef" is used for simplify
* 5 V2.0.0 2020/11/25 Lingjie Fan Structure Define Section In order to calculate the band with
* dispersion, Two struct and function
* is added
* 6 V2.0.0 2020/11/26 Lingjie Fan Structure Define Section struct _Band and _Interference is delete
*
***********************************************************************************************************************/
#ifndef _PLOT_BAND_H_
#define _PLOT_BAND_H_
#define PI 3.1415926
#define NO_SOLUTION -100.
#define EPSILON 1E-3
typedef struct _Grating
{
float a; /*Period of grating*/
float d; /*Thickness of grating*/
float f; /*Duty cycle of grating*/
float n1; /*Refractive index of Air*/
float n2; /*Refractive index of Grating*/
float n3; /*Refractive index of Substrate*/
}Grating;
typedef struct _BandAtOmega
{
float *k;
float omega;
float *Z;
int size;
int isTE;
int order;
}BandAtOmega;
typedef struct _InterferenceAtOmega
{
float k;
float omega;
int order;
}InterferenceAtOmega;
extern void solveFilmAtOmega(Grating *pGrating, InterferenceAtOmega *pInterferenceAtOmega);
extern void solveBandAtOmega(Grating *pGrating, BandAtOmega *pBandAtOmega);
#endif /*_PLOT_BAND_H_*/
plotBand.c
/**********************************************************************************************************************
* File
* File Name : plotBand.c
* Copyright : 2020-2025 Fudan University, All Rights Reserved.
* Module Name : plotBand
*
* CPU : 16 Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
* OS : Ubuntu
*
* Create Date : 2020/11/23
* Author/Corporation : Lingjie Fan/Fudan University
*
* Abstract Description : Some functions used to plot band of grating are implemented in this file.
*
*----------------------------------------------------------------------------------------------------------------------
* Function
* Function1 Name : solveFilm
* Create Time : 2020/11/23
* Description : Calculate the extreme point of the film interference, change the property omega
* in struct _Interference
* Param : pGrating: the pointer of struct _Grating
* pInterference: the pointer of struct _Interference
* Return Code : void: only change the property omega in struct _Interference
* Global Variable : None
* File Static Variable : None
* Function Static Variable : None
*
* Function2 Name : bandEquation
* Create Time : 2020/11/23
* Description : Calculate the band at point (omega, k)
* Param : pGrating: the pointer of struct _Grating
* k: the wave vector
* omega: the angular frequency
* isTE: whether the band is TE, 0 for TM, 1 for TE.
* order: the order of the band
* Return Code : creal(l1+l2+l3): if the point (omega, k) is at the band
* NO_SOLUTION: if the point is out of the band
* Global Variable : None
* File Static Variable : None
* Function Static Variable : None
*
* Function3 Name : solveBand
* Create Time : 2020/11/23
* Description : Calculate the band of the 1D grating
* Param : pGrating: the pointer of struct _Grating
* pBand: the pointer of struct _Band
* Return Code : void: only change the property Z in struct _Band
* Global Variable : None
* File Static Variable : None
* Function Static Variable : None
*
* Function4 Name : solveFilmAtOmega
* Create Time : 2020/11/25
* Description : Calculate the film interference of the 1D grating at a omega
* Param : pGrating: the pointer of struct _Grating
* pInterferenceAtOmega: the pointer of struct _InterferenceAtOmega
* Return Code : void: only change the property k in struct _InterferenceAtOmega
* Global Variable : None
* File Static Variable : None
* Function Static Variable : None
*
* Function5 Name : solveBandAtOmega
* Create Time : 2020/11/25
* Description : Calculate the band of the 1D grating at a omega
* Param : pGrating: the pointer of struct _Grating
* pBandAtOmega: the pointer of struct _BandAtOmega
* Return Code : void: only change the property k in struct _BandAtOmega
* Global Variable : None
* File Static Variable : None
* Function Static Variable : None
*
*---------------------------------------------------------------------------------------------------------------------
* Revision History
* No Version Date Revised By Item Description
* 1 V1.0.0 2020/11/23 Lingjie Fan Source File Header Section Description and record are added
* 2 V1.0.0 2020/11/23 Lingjie Fan Function Define Section Word "register" is used for loop vars
* 3 V1.0.0 2020/11/23 Lingjie Fan Prototype Define Section Two private functions are moved from
* header file to source file
* 4 V1.0.0 2020/11/24 Lingjie Fan Macro Define Section Function nEff is replaced by Macro NEFF
* 5 V1.0.0 2020/11/24 Lingjie Fan Function Define Section In order to become faster, "pow(,2)" is
* replace by "*"
* 6 V1.0.0 2020/11/25 Lingjie Fan Function Define Section In order to become faster, function fabs
* is replaced by Macro FABS.
* 7 V2.0.0 2020/11/25 Lingjie Fan Function Define Section Two function is added to consider the
* dispersion of material.
*
***********************************************************************************************************************/
#include "plotBand.h"
#include <math.h>
#include <complex.h>
#define NEFF(n1, n2, f) sqrt(((n1) * (n1) * (1-(f))) + ((n2) * (n2) * (f)))
#define FABS(x) (((x)>=0.0)? (x) : -(x))
extern float bandEquation(Grating *pGrating, float k, float omega, int isTE, int order);
void solveFilmAtOmega(Grating *pGrating, InterferenceAtOmega *pInterferenceAtOmega)
{
float neff;
float complex k;
neff = NEFF(pGrating->n1, pGrating->n2, pGrating->f);
k = csqrt(neff * neff * pInterferenceAtOmega->omega * pInterferenceAtOmega->omega - pInterferenceAtOmega->order *\
pInterferenceAtOmega->order * pGrating->a * pGrating->a / (4 * 4 * pGrating->d * pGrating->d));
if(creal(k) < pInterferenceAtOmega->omega)
{
pInterferenceAtOmega->k = creal(k);
}
else
{
pInterferenceAtOmega->k = NO_SOLUTION;
}
}
float bandEquation(Grating *pGrating, float k, float omega, int isTE, int order)
{
float neff;
float complex l1, l2, l3;
neff = NEFF(pGrating->n1, pGrating->n2, pGrating->f);
if(isTE)
{
l1 = -I * clog((I * csqrt(k * k - pGrating->n1 * pGrating->n1 * omega * omega) - csqrt(-k * k + \
neff * neff * omega * omega)) / (I * csqrt(k * k - pGrating->n1 * pGrating->n1 * omega * omega) + \
csqrt(-k * k + neff * neff * omega * omega)));
l2 = carg((csqrt(-k * k + neff * neff * omega * omega) - csqrt(-k * k + pGrating->n3 * pGrating->n3 * omega * \
omega)) / (csqrt(-k * k + neff * neff * omega * omega) + csqrt(-k * k + pGrating->n3 * pGrating->n3 * \
omega * omega)));
}
else
{
l1 = -I * clog((I * neff * neff * csqrt(k * k - pGrating->n1 * pGrating->n1 * omega * omega) - \
pGrating->n1 * pGrating->n1 * csqrt(-k * k + neff * neff * omega * omega))/(I * neff * neff * \
csqrt(k * k - pGrating->n1 * pGrating->n1 * pGrating->n1 * pGrating->n1 * omega * omega) + \
pGrating->n1 * pGrating->n1 * csqrt(-k * k + neff * neff * omega * omega)));
l2 = carg((pGrating->n1 * pGrating->n1 * csqrt(-k * k + neff * neff * omega * omega) - \
neff * neff * csqrt(-k * k + pGrating->n3 * pGrating->n3 * omega * omega))/(neff * neff * csqrt(-k * k + \
neff * neff * omega * omega) + pGrating->n1 * pGrating->n1 * csqrt(-k * k + pGrating->n3 * pGrating->n3 * \
omega * omega)));
}
l3 = - (2. * order + 1. - 2. * csqrt(-k * k + neff * neff * omega * omega) * 2 * pGrating->d / pGrating->a) * PI;
if(FABS(cimag(l1+l2+l3)) < EPSILON)
return creal(l1+l2+l3);
else
return NO_SOLUTION;
}
void solveBandAtOmega(Grating *pGrating, BandAtOmega *pBandAtOmega)
{
register int i;
for(i=0; i<pBandAtOmega->size; i++)
{
*(pBandAtOmega->Z + i) = bandEquation(pGrating, *(pBandAtOmega->k + i), pBandAtOmega->omega, \
pBandAtOmega->isTE, pBandAtOmega->order);
}
}
PyplotBand.c
/**********************************************************************************************************************
* File
* File Name : PyplotBand.c
* Copyright : 2020-2025 Fudan University, All Rights Reserved.
* Module Name : plotBand
*
* CPU : 16 Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
* OS : Ubuntu
*
* Create Date : 2020/11/23
* Author/Corporation : Lingjie Fan/Fudan University
*
* Abstract Description : This file is used to package function in C into the function in python.
*
*----------------------------------------------------------------------------------------------------------------------
* Function
* Function1 Name : plotBand_solveFilm
* Create Time : 2020/11/23
* Description : Package C function solveFilm into python function plotBand.solveFilm
* Param : self: Unknown
* args: The parameters received from python function in python Object which need to
* transform into var in C
* Return Code : pList: a python list contained the information of omega in struct Interference
* Global Variable : None
* File Static Variable : None
* Function Static Variable : None
*
* Function2 Name : plotBand_solveBand
* Create Time : 2020/11/23
* Description : Package C function solveBand into python function plotBand.solveBand
* Param : self: Unknown
* args: The parameters received from python function in python Object which need to
* transform into var in C
* Return Code : matrix: A python 2D list contained the information of Z in struct Band
* Global Variable : None
* File Static Variable : None
* Function Static Variable : None
*
* Function3 Name : plotBand_solveDispFilm
* Create Time : 2020/11/25
* Description : Package C function solveFilmAtOmega into python function plotBand.solveDispFilm
* Param : self: Unknown
* args: The parameters received from python function in python Object which need to
* transform into var in C
* Return Code : pList: a python list contained the information of omega in struct Interference
* Global Variable : None
* File Static Variable : None
* Function Static Variable : None
*
* Function4 Name : plotBand_solveDispBand
* Create Time : 2020/11/26
* Description : Package C function solveBandAtOmega into python function plotBand.solveDispBand
* Param : self: Unknown
* args: The parameters received from python function in python Object which need to
* transform into var in C
* Return Code : matrix: A python 2D list contained the information of Z in struct Band
* Global Variable : None
* File Static Variable : None
* Function Static Variable : None
*--------------------------------------------------------------------------------------------------------------------
* Revision History
* No Version Date Revised By Item Description
* 1 V1.0.0 2020/11/23 Lingjie Fan Source File Header Section Description and record are added
* 2 V1.0.0 2020/11/23 Lingjie Fan Function Define Section Word "register" is used for loop vars
* 3 V2.0.0 2020/11/25 Lingjie Fan Function Define Section Function plotBand_solveDispFilm is
* added
* 4 V2.0.0 2020/11/26 Lingjie Fan Function Define Section Function plotBand_solveDisBand is added
***********************************************************************************************************************/
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <stdio.h>
#include "plotBand.h"
static PyObject *plotBand_solveFilm(PyObject *self, PyObject *args)
{
register int i;
int size, order;
float a, d, f, omegaMin, omegaMax;
PyObject *Pyn1, *Pyn2, *Pyn3;
if(!PyArg_ParseTuple(args,"(fffOOO)(ffii)",&a, &d, &f, &Pyn1, &Pyn2, &Pyn3, &omegaMin, &omegaMax, &size, &order))
{
return NULL;
}
float k, omega, n1, n2, n3, step;
PyObject *pList = PyList_New(size);
assert(PyList_Check(pList));
assert(PyList_Check(Pyn1));
assert(PyList_Check(Pyn2));
assert(PyList_Check(Pyn3));
step = (omegaMax - omegaMin) / size;
for(i=0;i<size;i++)
{
k = 0.0;
omega = omegaMin + step * i;
n1 = PyFloat_AsDouble(PyList_GetItem(Pyn1, i));
n2 = PyFloat_AsDouble(PyList_GetItem(Pyn2, i));
n3 = PyFloat_AsDouble(PyList_GetItem(Pyn3, i));
Grating grating={a, d, f, n1, n2, n3};
InterferenceAtOmega interferenceAtOmega={k, omega, order};
solveFilmAtOmega(&grating, &interferenceAtOmega);
if(interferenceAtOmega.k != NO_SOLUTION)
{
PyList_SetItem(pList, i, Py_BuildValue("f", interferenceAtOmega.k));
}
else
{
Py_INCREF(Py_None);
PyList_SetItem(pList, i, Py_None);
}
}
return pList;
}
static PyObject *plotBand_solveBand(PyObject *self, PyObject *args)
{
register int i, j;
int kSize, omegaSize, isTE, order;
float a, d, f, n1, n2, n3;
float omega, omegaMax, omegaMin, kMax, kMin, kStep, omegaStep;
PyObject *Pyn1, *Pyn2, *Pyn3;
if(!PyArg_ParseTuple(args, "(fffOOO)(ffffiiii)", &a, &d, &f, &Pyn1, &Pyn2, &Pyn3, &kMin, &kMax, &omegaMin, \
&omegaMax, &kSize, &omegaSize, &isTE, &order))
{
return NULL;
}
float k[kSize], Z[kSize];
PyObject *matrix = PyList_New(omegaSize);
assert(PyList_Check(matrix));
assert(PyList_Check(Pyn1));
assert(PyList_Check(Pyn2));
assert(PyList_Check(Pyn3));
kStep = (kMax - kMin) / kSize;
omegaStep = (omegaMax - omegaMin) / omegaSize;
for(i=0;i<kSize;i++)
{
k[i] = kMin + kStep * i;
}
for(j=0;j<omegaSize;j++)
{
omega = omegaMin + omegaStep * j;
n1 = PyFloat_AsDouble(PyList_GetItem(Pyn1, j));
n2 = PyFloat_AsDouble(PyList_GetItem(Pyn2, j));
n3 = PyFloat_AsDouble(PyList_GetItem(Pyn3, j));
Grating grating = {a, d, f, n1, n2, n3};
BandAtOmega bandAtOmega = {k, omega, Z, kSize, isTE, order};
solveBandAtOmega(&grating, &bandAtOmega);
PyObject *rowList = PyList_New(kSize);
assert(PyList_Check(rowList));
for(i=0;i<kSize;i++)
{
if(*(bandAtOmega.Z+i) != NO_SOLUTION)
{
PyList_SetItem(rowList, i, Py_BuildValue("f", *(bandAtOmega.Z+i)));
}
else
{
Py_INCREF(Py_None);
PyList_SetItem(rowList, i, Py_None);
}
}
PyList_SetItem(matrix,j,rowList);
}
return matrix;
}
static PyMethodDef PlotBandMethods[] =
{
{"solveFilm", plotBand_solveFilm, METH_VARARGS, "Calculate interference of film"},
{"solveBand", plotBand_solveBand, METH_VARARGS, "Calculate band of grating"},
{NULL,NULL,0,NULL}
};
static PyModuleDef plotBand =
{
PyModuleDef_HEAD_INIT,
"plotBand",
NULL,
-1,
PlotBandMethods
};
PyMODINIT_FUNC PyInit_plotBand(void)
{
return PyModule_Create(&plotBand);
}
setup.py
from distutils.core import setup, Extension
def main():
setup(name="plotBand",
version="1.0.0",
description="Python interface for plotBand",
author="lingjie",
author_email="20210190044@fudan.edu.cn",
ext_modules=[Extension("plotBand", ["PyplotBand.c", "plotBand.c"])])
if __name__ == "__main__":
main()
test.py
"""
//
/
/plotBand 接口:
/ 1.色散关系设置: n1(list), n2(list), n3(list);
/ 类型:list 、自变量 omega,因变量 n1,n2,n3
/
/ 2.光栅设置: grating
/ 类型:元组、(周期、高度、占空比、空气折射率(list)、光栅材料折射率(list)、衬底折射率(list))
/
/ 3.干涉设置: interference
/ 类型:元组、(omegaMin, omegaMax, omegaSize, 干涉级次)
/
/ 4.能带: band
/ 类型:元组、(kMin,kMax,omegaMin,omegaMax,kSize,omegaSize,TE/TM: 1 for TE, 0 for TM, 级次(order))
/
/ 5.显示设置
/
/ 6.文件
/ w_a_h w/a
/ 第1列 1/lamda
/ 第2列-第52列 p
/ 第52列-103列 s
/ k: k_give * a / (2 * pi) k_give range(0,2*pi/(0.4*sin(65)),51)
/ omega: omega_give * a omega_give range(1/0.9,1/0.4,301)
/ 光线以下是-1
/
//
"""
import warnings
import plotBand as pltbd
import matplotlib.pyplot as plt
import numpy as np
warnings.filterwarnings("ignore")
# Range Setting
omegaMin = 0.5
omegaMax = 2.0
omegaSize = 150
kMin = 0.0
kMax = 2.0
kSize = 200
# Grating Setting
period = 500
thickness = 300
f = 0.5
n1 = list(np.linspace(1, 1, omegaSize))
n2 = list(np.linspace(1.4, 1.4, omegaSize))
n3 = list(np.linspace(3.4, 6, omegaSize))
# Show Setting
kMinShow = 0.0
kMaxShow = 2.0
omegaMinShow = 0.5
omegaMaxShow = 2.0
k = np.linspace(kMin, kMax-(kMax-kMin)/kSize, kSize)
omega = np.linspace(omegaMin, omegaMax-(omegaMax-omegaMin)/omegaSize, omegaSize)
grating = (period, thickness, f, n1, n2, n3)
interference1 = (omegaMin, omegaMax, omegaSize, 1)
interference2 = (omegaMin, omegaMax, omegaSize, 2)
interference3 = (omegaMin, omegaMax, omegaSize, 3)
interference4 = (omegaMin, omegaMax, omegaSize, 4)
interference5 = (omegaMin, omegaMax, omegaSize, 5)
TEband1 = (kMin,kMax,omegaMin,omegaMax,kSize,omegaSize, 1, 1)
TEband2 = (kMin,kMax,omegaMin,omegaMax,kSize,omegaSize, 1, 2)
TMband1 = (kMin,kMax,omegaMin,omegaMax,kSize,omegaSize, 0, 1)
TMband2 = (kMin,kMax,omegaMin,omegaMax,kSize,omegaSize, 0, 2)
iResult1 = pltbd.solveFilm(grating, interference1)
iResult2 = pltbd.solveFilm(grating, interference2)
iResult3 = pltbd.solveFilm(grating, interference3)
iResult4 = pltbd.solveFilm(grating, interference4)
iResult5 = pltbd.solveFilm(grating, interference5)
bResult1 = pltbd.solveBand(grating, TEband1)
bResult2 = pltbd.solveBand(grating, TEband2)
bResult3 = pltbd.solveBand(grating, TMband1)
bResult4 = pltbd.solveBand(grating, TMband2)
#light line
plt.plot(omega,omega,color="black")
plt.plot(1-omega,omega,color="black")
plt.plot(omega-1,omega,color="black")
plt.plot(2-omega,omega,color="black")
plt.plot(omega-2,omega,color="black")
plt.plot(3-omega,omega,color="black")
#interference
plt.plot(iResult1,omega)
plt.plot(iResult2,omega)
plt.plot(iResult3,omega)
plt.plot(iResult4,omega)
plt.plot(iResult5,omega)
#band
plt.contour(k,omega,bResult1,[0],colors="red")
plt.contour(k,omega,bResult2,[0],colors="red")
plt.contour(k,omega,bResult3,[0],colors="blue")
plt.contour(k,omega,bResult4,[0],colors="blue")
plt.contour(1-k,omega,bResult1,[0],colors="red")
plt.contour(1-k,omega,bResult2,[0],colors="red")
plt.contour(1-k,omega,bResult3,[0],colors="blue")
plt.contour(1-k,omega,bResult4,[0],colors="blue")
plt.contour(k-1,omega,bResult1,[0],colors="red")
plt.contour(k-1,omega,bResult2,[0],colors="red")
plt.contour(k-1,omega,bResult3,[0],colors="blue")
plt.contour(k-1,omega,bResult4,[0],colors="blue")
plt.contour(2-k,omega,bResult1,[0],colors="red")
plt.contour(2-k,omega,bResult2,[0],colors="red")
plt.contour(2-k,omega,bResult3,[0],colors="blue")
plt.contour(2-k,omega,bResult4,[0],colors="blue")
plt.contour(3-k,omega,bResult1,[0],colors="red")
plt.contour(3-k,omega,bResult2,[0],colors="red")
plt.contour(3-k,omega,bResult3,[0],colors="blue")
plt.contour(3-k,omega,bResult4,[0],colors="blue")
plt.xlim(kMinShow, kMaxShow)
plt.ylim(omegaMinShow, omegaMaxShow)
plt.show()
安装
linux系统上,在该目录下
$ sudo python3 setup.py install
这个程序 Windows 上安装会提示不能用变量作为数组的长度,但是按照C99标准明明可以这么做。不管了只要linux上的 gcc 不报错就行了。
运行
之后就可以运行 test.py这个测试程序了。