From 457232255349215789c493da80c89118d4809b1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ne=C4=8Dada?= Date: Sun, 11 Aug 2019 19:06:50 +0300 Subject: [PATCH] Experimental support for custom python-defined material functions. Former-commit-id: acf19bb2537505922110d7de46cee52e76811637 --- qpms/cymaterials.pyx | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/qpms/cymaterials.pyx b/qpms/cymaterials.pyx index 2769f5e..f79f683 100644 --- a/qpms/cymaterials.pyx +++ b/qpms/cymaterials.pyx @@ -12,10 +12,11 @@ import os from scipy.constants import e as eV, hbar from libc.stdlib cimport malloc, free, calloc, abort -class EpsMuGeneratorType(enum.IntEnum): +class EpsMuGeneratorType(enum.Enum): CONSTANT = 1 PERMITTIVITY_INTERPOLATOR = 2 LORENTZ_DRUDE = 3 + PYTHON_CALLABLE = 4 cdef class EpsMu: def __init__(self, *args ,**kwargs): @@ -74,6 +75,12 @@ lorentz_drude = { (0.053*eh, 3.886*eh, 0.452*eh,0.065*eh, 0.916*eh, 2.419*eh)), } +cdef qpms_epsmu_t python_epsmu_generator(cdouble omega, const void *params): + object fun = params + cdef qpms_epsmu_t em + em.eps, em.mu = fun(omega) + return em + cdef class EpsMuGenerator: def __init__(self, what): if isinstance(what, EpsMu): @@ -88,8 +95,16 @@ cdef class EpsMuGenerator: self.holder = what self.g.function = qpms_permittivity_interpolator_epsmu_g self.g.params = (self.holder).rawpointer() + elif isinstance(what, EpsMuGenerator): # Copy constructor + self.holder = what.holder + self.g = what.g + elif callable(what): + warnings.warn("Custom python (eps,mu) generators are an experimental feature") + self.holder = what + self.g.function = python_epsmu_generator + self.g.params = what else: - raise ValueError("Must be constructed from EpsMu, LorentzDrudeModel or MaterialInterpolator") + raise ValueError("Must be constructed from EpsMu, LorentzDrudeModel or MaterialInterpolator, or a python callable object that returns an (epsilon, mu) tuple.") property typ: def __get__(self): @@ -99,6 +114,8 @@ cdef class EpsMuGenerator: return EpsMuGeneratorType.LORENTZ_DRUDE elif(self.g.function == qpms_permittivity_interpolator_epsmu_g): return EpsMuGeneratorType.PERMITTIVITY_INTERPOLATOR + elif(self.g.function == python_epsmu_generator): + return EpsMuGeneratorType.PYTHON_CALLABLE else: raise ValueError("Damn, this is a bug.") @@ -109,7 +126,8 @@ cdef class EpsMuGenerator: if(omega < i[0] or omega > i[1]): raise ValueError("Input frequency %g is outside the interpolator domain (%g, %g)." % (omega, i[0], i[1])) - em = self.g.function(omega, self.g.params) + with nogil: + em = self.g.function(omega, self.g.params) return EpsMu(em.eps, em.mu) cdef qpms_epsmu_generator_t raw(self):