751 Solver for threshold search of semiconductor laser.
753 This solver performs thermo-electrical computations followed by
754 determination ot threshold current and optical analysis in order to
755 determine the threshold of a semiconductor laser. The search is
756 performed by ``scipy`` root finding algorithm in order to determine
757 the voltage and electric current ensuring no optical loss in the
760 The computations can be executed using `compute` method, after which
761 the results may be save to the HDF5 file with `save` or presented visually
762 using ``plot_...`` methods. If ``save`` parameter of the :meth:`compute` method
763 is *True* the fields are saved automatically after the computations.
764 The file name is based on the name of the executed script with suffix denoting
765 either the launch time or the identifier of a batch job if a batch system
766 (like SLURM, OpenPBS, or SGE) is used.
769 _Thermal = thermal.static.StaticCyl
770 _Electrical = electrical.shockley.ShockleyCyl
771 _Diffusion = electrical.diffusion.DiffusionCyl
772 _Gain = gain.freecarrier.FreeCarrierCyl
774 _OPTICAL_ROOTS = {
'optical-root':
'root',
'optical-stripe-root':
'stripe_root'}
776 outTemperature = property(
lambda self: self.
thermalthermal.outTemperature, doc=_Thermal.outTemperature.__doc__)
777 outHeatFlux = property(
lambda self: self.
thermalthermal.outHeatFlux, doc=_Thermal.outHeatFlux.__doc__)
779 outThermalConductivity = property(
lambda self: self.
thermalthermal.outThermalConductivity,
780 doc=_Thermal.outThermalConductivity.__doc__)
783 doc=_Electrical.outCurrentDensity.__doc__)
785 outConductivity = property(
lambda self: self.
electricalelectrical.outConductivity, doc=_Electrical.outConductivity.__doc__)
787 doc=_Diffusion.outCarriersConcentration.__doc__)
788 outGain = property(
lambda self: self.
gaingain.outGain, doc=_Gain.outGain.__doc__)
789 outLightMagnitude = property(
lambda self: self.
opticaloptical.outLightMagnitude, doc=_doc.outLightMagnitude)
791 outWavelength = property(
lambda self: self.
opticaloptical.outWavelength, doc=_doc.outWavelength)
792 outRefractiveIndex = property(
lambda self: self.
opticaloptical.outRefractiveIndex, doc=_doc.outRefractiveIndex)
793 outLightE = property(
lambda self: self.
opticaloptical.outLightE, doc=_doc.outLightE)
796 ":class:`thermal.static.StaticCyl` solver used for thermal calculations."
799 ":class:`electrical.shockley.ShockleyCyl` solver used for electrical calculations."
802 ":class:`electrical.diffusion.DiffusionCyl` solver used for electrical calculations."
805 ":class:`gain.freecarrier.FreeCarrierCyl` solver used for gain calculations."
808 ":class:`optical.effective.EffectiveFrequencyCyl` solver used for optical calculations."
812 Number of electrical iterations per single thermal step.
814 As temperature tends to converge faster, it is reasonable to repeat thermal
815 solution less frequently.
820 Minimum voltage to search threshold for.
822 It should be below the threshold.
827 Maximum voltage to search threshold for.
829 It should be above the threshold.
833 "Tolerance on voltage in the root search."
836 "Maximum number of root finding iterations."
839 "Maximum wavelength considered for the optical mode search."
845 Step, by which the wavelength is swept while searching for the approximate mode.
850 Angular mode number $m$.
852 0Â for LP0x, 1Â for LP1x, etc.
857 Radial mode number $n$.
859 1Â for LPx1, 2Â for LPx2, etc.
862 optical_resolution = (800, 600)
864 Number of points along the horizontal and vertical axes for the saved
865 and plotted optical field.
870 Skip thermal computations.
872 The structure is assumed to have a constant temperature.
873 This can be used to look for the threshold under pulse laser operation.
887 Get approximate wavelength for optical computations.
889 This method returns approximate wavelength for optical computations.
890 By default if browses the wavelength range starting from :attr:`maxlam`,
891 decreasing it by :attr:`dlam` until radial mode :attr:`lpn` is found.
893 You can override this method or set it to a a fixed value to use custom
897 >>> solver = ThresholdSearchCyl()
898 >>> solver.get_lam = 980.
906 while n < self.
lpnlpn and lam.real > 0.:
908 if decr
and curr > prev:
915 raise ValueError(
"Approximation of mode LP{0.lpm}{0.lpn} not found".format(self))
918 return dict(m=self.
lpmlpm)
926 maxlam = tag.get(
'maxlam')
927 if maxlam
is not None:
931 raise plask.XMLError(
"{}: attribute maxlam has illegal value '{}'".format(tag, maxlam))
936 if tag ==
'optical-root':
942 Function computing ‘vertical determinant’ of the optical solver.
945 vlam (float or array): ‘Vertical wavelength’ to compute the vertical
946 determinant for (nm).
949 float or array: Optical vertical determinant.
961 Function plotting ‘vertical determinant’ of the optical solver.
964 vlams (array): ‘Vertical wavelengths’ to plot the determinant for (nm).
966 **kwargs: Keyword arguments passed to the plot function.
969 plask.plot(vlams, abs(vals))
971 plask.xlabel(
"Vertical Wavelength (nm)")
972 plask.ylabel(
"Determinant [ar.u.]")
982 Solver for threshold search of semiconductor laser with vector optical solver.
984 This solver performs thermo-electrical computations followed by
985 determination ot threshold current and optical analysis in order to
986 determine the threshold of a semiconductor laser. The search is
987 performed by ``scipy`` root finding algorithm in order to determine
988 the voltage and electric current ensuring no optical loss in the
991 This solver uses vector optical solver :class:`~plask.optical.modal.BesselCyl`.
993 The computations can be executed using `compute` method, after which
994 the results may be save to the HDF5 file with `save` or presented visually
995 using ``plot_...`` methods. If ``save`` parameter of the :meth:`compute` method
996 is *True* the fields are saved automatically after the computations.
997 The file name is based on the name of the executed script with suffix denoting
998 either the launch time or the identifier of a batch job if a batch system
999 (like SLURM, OpenPBS, or SGE) is used.
1002 _Thermal = thermal.static.StaticCyl
1003 _Electrical = electrical.shockley.ShockleyCyl
1004 _Diffusion = electrical.diffusion.DiffusionCyl
1005 _Gain = gain.freecarrier.FreeCarrierCyl
1007 _OPTICAL_ROOTS = {
'optical-root':
'root'}
1009 outTemperature = property(
lambda self: self.
thermalthermal.outTemperature, doc=_Thermal.outTemperature.__doc__)
1010 outHeatFlux = property(
lambda self: self.
thermalthermal.outHeatFlux, doc=_Thermal.outHeatFlux.__doc__)
1012 outThermalConductivity = property(
lambda self: self.
thermalthermal.outThermalConductivity,
1013 doc=_Thermal.outThermalConductivity.__doc__)
1016 doc=_Electrical.outCurrentDensity.__doc__)
1018 outConductivity = property(
lambda self: self.
electricalelectrical.outConductivity, doc=_Electrical.outConductivity.__doc__)
1020 doc=_Diffusion.outCarriersConcentration.__doc__)
1021 outGain = property(
lambda self: self.
gaingain.outGain, doc=_Gain.outGain.__doc__)
1022 outLightMagnitude = property(
lambda self: self.
opticaloptical.outLightMagnitude, doc=_doc.outLightMagnitude)
1024 outWavelength = property(
lambda self: self.
opticaloptical.outWavelength, doc=_doc.outWavelength)
1025 outEpsilon = property(
lambda self: self.
opticaloptical.outEpsilon, doc=_doc.outEpsilon)
1029 ":class:`thermal.static.StaticCyl` solver used for thermal calculations."
1032 ":class:`electrical.shockley.ShockleyCyl` solver used for electrical calculations."
1035 ":class:`electrical.diffusion.DiffusionCyl` solver used for electrical calculations."
1038 ":class:`gain.freecarrier.FreeCarrierCyl` solver used for gain calculations."
1041 ":class:`optical.modal.BesselFrequencyCyl` solver used for optical calculations."
1045 Number of electrical iterations per single thermal step.
1047 As temperature tends to converge faster, it is reasonable to repeat thermal
1048 solution less frequently.
1053 Minimum voltage to search threshold for.
1055 It should be below the threshold.
1060 Maximum voltage to search threshold for.
1062 It should be above the threshold.
1066 "Tolerance on voltage in the root search."
1069 "Maximum number of root finding iterations."
1072 "Maximum wavelength considered for the optical mode search."
1078 Step, by which the wavelength is swept while searching for the approximate mode.
1083 Angular mode number $m$.
1085 1Â for HE1x, 2Â for HE2x, etc.
1090 Radial mode number $n$.
1092 1Â for HEx1, 2Â for HEx2, etc.
1097 Initial wavelength for optical search.
1099 If this value is set, the computations are started from this value. If this
1100 value is set, the radial mode number :attr:`hen` is ignored.
1102 Note that it is safer to leave this empty and allow the solver to look for it
1103 automatically, however, it may increase the time of optical computations.
1106 optical_resolution = (800, 600)
1108 Number of points along the horizontal and vertical axes for the saved
1109 and plotted optical field.
1112 skip_thermal =
False
1114 Skip thermal computations.
1116 The structure is assumed to have a constant temperature.
1117 This can be used to look for the threshold under pulse laser operation.
1134 Get approximate wavelength for optical computations.
1136 This method returns approximate wavelength for optical computations.
1137 By default if browses the wavelength range starting from :attr:`maxlam`,
1138 decreasing it by :attr:`dlam` until radial mode :attr:`hen` is found.
1140 You can override this method or set it to a a fixed value to use custom
1144 >>> solver = ThresholdSearchBesselCyl()
1145 >>> solver.get_lam = 980.
1146 >>> solver.compute()
1149 if self.
lam is not None:
1156 while n < self.
henhen and lam.real > 0.:
1158 if decr
and curr > prev:
1165 raise ValueError(
"Approximation of mode HE{0.hem}{0.hen} not found".format(self))
1168 return dict(m=self.
hemhem)
1171 if tag ==
'optical':
1181 maxlam = tag.get(
'maxlam')
1182 if maxlam
is not None:
1186 raise plask.XMLError(
"{}: attribute maxlam has illegal value '{}'".format(tag, maxlam))
1188 self.
lam = tag.get(
'lam', self.
lam)
1192 elif tag ==
'optical-interface':
1193 attrs = {key: val
for (key, val)
in ((key, tag.get(key))
for key
in (
'position',
'object',
'path'))
1195 if len(attrs) > 1
and (len(attrs) > 2
or 'position' in attrs):
1196 raise plask.XMLError(
"{}: conflicting attributes '{}'".format(tag,
"' and '".join(attrs.keys())))
1197 elif 'position' in attrs:
1199 elif 'object' in attrs:
1200 path = attrs.get(
'path')
1201 if path
is not None:
1202 self.
opticaloptical.set_interface(manager.geo[attrs[
'object']], manager.pth[path])
1205 elif tag ==
'optical-vpml':
1209 elif tag ==
'optical-pml':
1225 Solver for threshold search of semiconductor laser.
1227 This solver performs thermo-electrical computations followed by
1228 determination ot threshold current and optical analysis in order to
1229 determine the threshold of a semiconductor laser. The search is
1230 performed by ``scipy`` root finding algorithm in order to determine
1231 the voltage and electric current ensuring no optical loss in the
1234 The computations can be executed using `compute` method, after which
1235 the results may be save to the HDF5 file with `save` or presented visually
1236 using ``plot_...`` methods. If ``save`` parameter of the :meth:`compute` method
1237 is *True* the fields are saved automatically after the computations.
1238 The file name is based on the name of the executed script with suffix denoting
1239 either the launch time or the identifier of a batch job if a batch system
1240 (like SLURM, OpenPBS, or SGE) is used.
1244 _lam0 =
'wavelength'
1246 _Thermal = thermal.static.Static2D
1247 _Electrical = electrical.shockley.Shockley2D
1248 _Diffusion = electrical.diffusion.Diffusion2D
1249 _Gain = gain.freecarrier.FreeCarrier2D
1251 _OPTICAL_ROOTS = {
'optical-root':
'root',
'optical-stripe-root':
'stripe_root'}
1253 outTemperature = property(
lambda self: self.
thermalthermal.outTemperature, doc=_Thermal.outTemperature.__doc__)
1254 outHeatFlux = property(
lambda self: self.
thermalthermal.outHeatFlux, doc=_Thermal.outHeatFlux.__doc__)
1256 outThermalConductivity = property(
lambda self: self.
thermalthermal.outThermalConductivity,
1257 doc=_Thermal.outThermalConductivity.__doc__)
1260 doc=_Electrical.outCurrentDensity.__doc__)
1262 outConductivity = property(
lambda self: self.
electricalelectrical.outConductivity, doc=_Electrical.outConductivity.__doc__)
1264 doc=_Diffusion.outCarriersConcentration.__doc__)
1265 outGain = property(
lambda self: self.
gaingain.outGain, doc=_Gain.outGain.__doc__)
1266 outLightMagnitude = property(
lambda self: self.
opticaloptical.outLightMagnitude, doc=_doc.outLightMagnitude)
1269 outRefractiveIndex = property(
lambda self: self.
opticaloptical.outRefractiveIndex, doc=_doc.outRefractiveIndex)
1273 ":class:`thermal.static.Static2D` solver used for thermal calculations."
1276 ":class:`electrical.shockley.Shockley2D` solver used for electrical calculations."
1279 ":class:`electrical.diffusion.Diffusion2D` solver used for electrical calculations."
1282 ":class:`gain.freecarrier.FreeCarrier2D` solver used for gain calculations."
1285 ":class:`optical.effective.EffectiveIndex2D` solver used for optical calculations."
1289 Number of electrical iterations per single thermal step.
1291 As temperature tends to converge faster, it is reasonable to repeat thermal
1292 solution less frequently.
1297 Minimum voltage to search threshold for.
1299 It should be below the threshold.
1304 Maximum voltage to search threshold for.
1306 It should be above the threshold.
1310 "Tolerance on voltage in the root search."
1313 "Maximum number of root finding iterations."
1316 "Emission wavelength (nm)."
1320 Effective index step.
1322 Step, by which the effective index is swept while searching for the approximate mode.
1327 Lateral mode number $n$.
1330 optical_resolution = (800, 600)
1332 Number of points along the horizontal and vertical axes for the saved
1333 and plotted optical field.
1336 skip_thermal =
False
1338 Skip thermal computations.
1340 The structure is assumed to have a constant temperature.
1341 This can be used to look for the threshold under pulse laser operation.
1351 points = plask.mesh.Rectangular2D.SimpleGenerator()(self.
opticaloptical.geometry).elements.mesh
1353 for point
in points)
1357 Get approximate effective index for optical computations.
1359 This method returns approximate wavelength for optical computations.
1360 By default if browses the wavelength range starting from :attr:`maxneff`,
1361 decreasing it by :attr:`dneff` until lateral mode :attr:`mn` is found.
1363 You can override this method to use custom mode approximation.
1366 >>> solver = ThresholdSearch2D()
1367 >>> solver.get_nng = lambda: 3.5
1368 >>> solver.compute()
1375 while n < self.
mnmn and neff.real > 0.:
1377 if decr
and curr > prev:
1384 raise ValueError(
"Mode approximation not found")
1387 if tag ==
'optical':
1396 if tag ==
'optical-root':
1402 Function computing determinant of the optical solver.
1405 neff (float or array): Effective index to compute the determinant for.
1408 float or array: Optical determinant.
1420 Function plotting determinant of the optical solver.
1423 neffs (array): Array of effective indices to plot the determinant for.
1425 **kwargs: Keyword arguments passed to the plot function.
1428 plask.plot(neffs, abs(vals))
1430 plask.xlabel(
"Effective Index")
1431 plask.ylabel(
"Determinant [ar.u.]")
1435 Function computing ‘vertical determinant’ of the optical solver.
1438 vneff (float or array): Effective index to compute the vertical
1442 float or array: Optical determinant.
1454 Function plotting ‘vertical determinant’ of the optical solver.
1457 vneffs (array): Array of effective indices to plot the vertical
1460 **kwargs: Keyword arguments passed to the plot function.
1463 plask.plot(vneffs, abs(vals))
1465 plask.xlabel(
"Vertical Effective Index")
1466 plask.ylabel(
"Determinant [ar.u.]")
1476 Solver for threshold search of semiconductor laser.
1478 This solver performs thermo-electrical computations followed by
1479 determination ot threshold current and optical analysis in order to
1480 determine the threshold of a semiconductor laser. The search is
1481 performed by ``scipy`` root finding algorithm in order to determine
1482 the voltage and electric current ensuring no optical loss in the
1485 This solver uses vector optical solver :class:`~plask.optical.modal.Fourier2D`.
1487 The computations can be executed using `compute` method, after which
1488 the results may be save to the HDF5 file with `save` or presented visually
1489 using ``plot_...`` methods. If ``save`` parameter of the :meth:`compute` method
1490 is *True* the fields are saved automatically after the computations.
1491 The file name is based on the name of the executed script with suffix denoting
1492 either the launch time or the identifier of a batch job if a batch system
1493 (like SLURM, OpenPBS, or SGE) is used.
1499 _Thermal = thermal.static.Static2D
1500 _Electrical = electrical.shockley.Shockley2D
1501 _Diffusion = electrical.diffusion.Diffusion2D
1502 _Gain = gain.freecarrier.FreeCarrier2D
1504 _OPTICAL_ROOTS = {
'optical-root':
'root'}
1506 outTemperature = property(
lambda self: self.
thermalthermal.outTemperature, doc=_Thermal.outTemperature.__doc__)
1507 outHeatFlux = property(
lambda self: self.
thermalthermal.outHeatFlux, doc=_Thermal.outHeatFlux.__doc__)
1509 outThermalConductivity = property(
lambda self: self.
thermalthermal.outThermalConductivity,
1510 doc=_Thermal.outThermalConductivity.__doc__)
1513 doc=_Electrical.outCurrentDensity.__doc__)
1515 outConductivity = property(
lambda self: self.
electricalelectrical.outConductivity, doc=_Electrical.outConductivity.__doc__)
1517 doc=_Diffusion.outCarriersConcentration.__doc__)
1518 outGain = property(
lambda self: self.
gaingain.outGain, doc=_Gain.outGain.__doc__)
1519 outLightMagnitude = property(
lambda self: self.
opticaloptical.outLightMagnitude, doc=_doc.outLightMagnitude)
1521 outEpsilon = property(
lambda self: self.
opticaloptical.outEpsilon, doc=_doc.outEpsilon)
1525 ":class:`thermal.static.Static2D` solver used for thermal calculations."
1528 ":class:`electrical.shockley.Shockley2D` solver used for electrical calculations."
1531 ":class:`electrical.diffusion.Diffusion2D` solver used for electrical calculations."
1534 ":class:`gain.freecarrier.FreeCarrier2D` solver used for gain calculations."
1537 ":class:`optical.modal.Fourier2D` solver used for optical calculations."
1541 Number of electrical iterations per single thermal step.
1543 As temperature tends to converge faster, it is reasonable to repeat thermal
1544 solution less frequently.
1549 Minimum voltage to search threshold for.
1551 It should be below the threshold.
1556 Maximum voltage to search threshold for.
1558 It should be above the threshold.
1562 "Tolerance on voltage in the root search."
1565 "Maximum number of root finding iterations."
1568 "Emission wavelength (nm)."
1572 Effective index step.
1574 Step, by which the effective index is swept while searching for the approximate mode.
1579 Lateral mode number $n$.
1582 optical_resolution = (800, 600)
1584 Number of points along the horizontal and vertical axes for the saved
1585 and plotted optical field.
1588 skip_thermal =
False
1590 Skip thermal computations.
1592 The structure is assumed to have a constant temperature.
1593 This can be used to look for the threshold under pulse laser operation.
1603 points = plask.mesh.Rectangular2D.SimpleGenerator()(self.
opticaloptical.geometry).elements.mesh
1605 for point
in points)
1609 Get approximate effective index for optical computations.
1611 This method returns approximate wavelength for optical computations.
1612 By default if browses the wavelength range starting from :attr:`maxneff`,
1613 decreasing it by :attr:`dneff` until lateral mode :attr:`mn` is found.
1615 You can override this method to use custom mode approximation.
1618 >>> solver = ThresholdSearchFourier2D()
1619 >>> solver.get_nng = lambda: 3.5
1620 >>> solver.compute()
1627 while n < self.
mnmn and neff.real > 0.:
1629 if decr
and curr > prev:
1636 raise ValueError(
"Mode approximation not found")
1639 if tag ==
'optical':
1649 elif tag ==
'optical-interface':
1650 attrs = {key: val
for (key, val)
in ((key, tag.get(key))
for key
in (
'position',
'object',
'path'))
1652 if len(attrs) > 1
and (len(attrs) > 2
or 'position' in attrs):
1653 raise plask.XMLError(
"{}: conflicting attributes '{}'".format(tag,
"' and '".join(attrs.keys())))
1654 elif 'position' in attrs:
1656 elif 'object' in attrs:
1657 path = attrs.get(
'path')
1658 if path
is not None:
1659 self.
opticaloptical.set_interface(manager.geo[attrs[
'object']], manager.pth[path])
1662 elif tag ==
'optical-vpml':
1666 elif tag ==
'optical-pml':
1676 Function computing determinant of the optical solver.
1679 neff (float or array): Effective index to compute the determinant for.
1682 float or array: Optical determinant.
1694 Function plotting determinant of the optical solver.
1697 neffs (array): Array of effective indices to plot the determinant for.
1699 **kwargs: Keyword arguments passed to the plot function.
1702 plask.plot(neffs, abs(vals))
1704 plask.xlabel(
"Effective Index")
1705 plask.ylabel(
"Determinant [ar.u.]")
1709 Function plotting ‘vertical determinant’ of the optical solver.
1712 vneffs (array): Array of effective indices to plot the vertical
1715 **kwargs: Keyword arguments passed to the plot function.
1717 vals = self.get_vert_optical_determinant(vneffs)
1718 plask.plot(vneffs, abs(vals))
1720 plask.xlabel(
"Vertical Effective Index")
1721 plask.ylabel(
"Determinant [ar.u.]")