Source code for tidy3d.plugins.dispersion.fit_fast
"""Fit PoleResidue Dispersion models to optical NK data"""from__future__importannotationsfromtypingimportTupleimportnumpyasnpfrompydantic.v1importNonNegativeFloat,PositiveIntfrom...components.dispersion_fitterimportAdvancedFastFitterParam,fitfrom...components.mediumimportPoleResiduefrom...constantsimportC_0,HBARfrom.fitimportDispersionFitter# numerical tolerance for pole relocation for fast fitterTOL=1e-8# numerical cutoff for passivity testingCUTOFF=np.finfo(np.float32).eps# parameters for passivity optimizationPASSIVITY_NUM_ITERS_DEFAULT=50SLSQP_CONSTRAINT_SCALE_DEFAULT=1e35# min value of the rms for default weights calculated based on Re[eps], Im[eps]RMS_MIN=0.1DEFAULT_MAX_POLES=5DEFAULT_NUM_ITERS=20DEFAULT_TOLERANCE_RMS=1e-5# this avoids divide by zero errors with lossless polesSCALE_FACTOR=1.01# when poles are close to omega, can cause invalid response function, and we reject modelOMEGA_POLE_CLOSE_ATOL=1e-10
[docs]classFastDispersionFitter(DispersionFitter):"""Tool for fitting refractive index data to get a dispersive medium described by :class:`.PoleResidue` model."""
[docs]deffit(self,min_num_poles:PositiveInt=1,max_num_poles:PositiveInt=DEFAULT_MAX_POLES,eps_inf:float=None,tolerance_rms:NonNegativeFloat=DEFAULT_TOLERANCE_RMS,advanced_param:AdvancedFastFitterParam=None,)->Tuple[PoleResidue,float]:"""Fit data using a fast fitting algorithm. Note ---- The algorithm is described in:: B. Gustavsen and A. Semlyen, "Rational approximation of frequency domain responses by vector fitting," IEEE Trans. Power. Deliv. 14, 3 (1999). B. Gustavsen, "Improving the pole relocation properties of vector fitting," IEEE Trans. Power Deliv. 21, 3 (2006). B. Gustavsen, "Enforcing Passivity for Admittance Matrices Approximated by Rational Functions," IEEE Trans. Power Syst. 16, 1 (2001). Note ---- The fit is performed after weighting the real and imaginary parts, so the RMS error is also weighted accordingly. By default, the weights are chosen based on typical values of the data. To change this behavior, use 'AdvancedFastFitterParam.weights'. Parameters ---------- min_num_poles: PositiveInt, optional Minimum number of poles in the model. max_num_poles: PositiveInt, optional Maximum number of poles in the model. eps_inf : float, optional Value of eps_inf to use in fit. If None, then eps_inf is also fit. Note: fitting eps_inf is not guaranteed to yield a global optimum, so the result may occasionally be better with a fixed value of eps_inf. tolerance_rms : float, optional Weighted RMS error below which the fit is successful and the result is returned. advanced_param : :class:`AdvancedFastFitterParam`, optional Advanced parameters for fitting. Returns ------- Tuple[:class:`.PoleResidue`, float] Best fitting result: (dispersive medium, weighted RMS error). """omega_data=PoleResidue.Hz_to_angular_freq(self.freqs)eps_data=self.eps_datascale_factor=HBARparams,error=fit(omega_data=omega_data,resp_data=eps_data,min_num_poles=min_num_poles,max_num_poles=max_num_poles,resp_inf=eps_inf,tolerance_rms=tolerance_rms,advanced_param=advanced_param,scale_factor=scale_factor,)eps_inf,poles,residues=paramsmedium=PoleResidue(eps_inf=eps_inf,poles=list(zip(poles,residues)))returnmedium,error
[docs]@classmethoddefconstant_loss_tangent_model(cls,eps_real:float,loss_tangent:float,frequency_range:Tuple[float,float],max_num_poles:PositiveInt=DEFAULT_MAX_POLES,number_sampling_frequency:PositiveInt=10,tolerance_rms:NonNegativeFloat=DEFAULT_TOLERANCE_RMS,)->PoleResidue:"""Fit a constant loss tangent material model. Parameters ---------- eps_real : float Real part of permittivity loss_tangent : float Loss tangent. frequency_range : Tuple[float, float] Freqquency range for the material to exhibit constant loss tangent response. max_num_poles : PositiveInt, optional Maximum number of poles in the model. number_sampling_frequency : PositiveInt, optional Number of sampling frequencies to compute RMS error for fitting. tolerance_rms : float, optional Weighted RMS error below which the fit is successful and the result is returned. Returns ------- :class:`.PoleResidue Best results of multiple fits. """ifnumber_sampling_frequency<2:frequencies=np.array([np.mean(frequency_range)])else:frequencies=np.linspace(frequency_range[0],frequency_range[1],number_sampling_frequency)wvl_um=C_0/frequencieseps_real_array=np.ones_like(frequencies)*eps_realloss_tangent_array=np.ones_like(frequencies)*loss_tangentfitter=cls.from_loss_tangent(wvl_um,eps_real_array,loss_tangent_array)material,_=fitter.fit(max_num_poles=max_num_poles,tolerance_rms=tolerance_rms)returnmaterial