画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这个测试程序了。
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值