PLaSK library

Loading...
Searching...
No Matches
diffusion.cpp
Go to the documentation of this file.
1
4#include <cmath>
5#include <plask/common/fem/python.hpp>
6#include <plask/python.hpp>
7 using namespace plask;
8 using namespace plask::python;
9
10#include "../diffusion2d.hpp"
11#include "../diffusion3d.hpp"
12 using namespace plask::electrical::diffusion;
13
14 template <typename SolverT>
15 static double DiffusionSolver_compute(SolverT* solver, unsigned loops, bool shb, const py::object& pact) {
16 if (pact.is_none()) {
17 return solver->compute(loops, shb);
18 } else {
19 int act = py::extract<int>(pact);
20 if (act < 0) act = solver->activeRegionsCount() + act;
21 return solver->compute(loops, shb, act);
22 }
23}
24
25 static void DiffusionSolver2D_compute_threshold(Diffusion2DSolver<Geometry2DCartesian>* solver) {
26 writelog(LOG_WARNING, u8"DiffusionSolver2D.compute_threshold() is deprecated. Use DiffusionSolver2D.compute() instead.");
27 solver->compute(0, false);
28}
29
30 static void DiffusionSolver2D_compute_overthreshold(Diffusion2DSolver<Geometry2DCartesian>* solver) {
31 writelog(LOG_WARNING,
32 u8"DiffusionSolver2D.compute_overthreshold() is deprecated. Use DiffusionSolver2D.compute(shb=True) instead.");
33 solver->compute(0, true);
34}
35
36 static void DiffusionSolverCyl_compute_threshold(Diffusion2DSolver<Geometry2DCylindrical>* solver) {
37 writelog(LOG_WARNING, u8"DiffusionSolverCyl.compute_threshold() is deprecated. Use DiffusionSolverCyl.compute() instead.");
38 solver->compute(0, false);
39}
40
41 static void DiffusionSolverCyl_compute_overthreshold(Diffusion2DSolver<Geometry2DCylindrical>* solver) {
42 writelog(LOG_WARNING,
43 u8"DiffusionSolverCyl.compute_overthreshold() is deprecated. Use DiffusionSolverCyl.compute(shb=True) instead.");
44 solver->compute(0, true);
45}
46
47 template <typename SolverT> static double DiffusionSolver_get_burning_for_mode(SolverT* solver, int mode) {
48 if (mode < 0) mode = solver->inLightE.size() + mode;
49 return solver->get_burning_integral_for_mode(mode);
50}
51
52 template <typename GeometryT> struct ExportedDiffusion2DSolverDefaultDefs {
53 static void Solver_setMesh(Diffusion2DSolver<GeometryT>& self, py::object mesh) {
54 if (mesh.is_none()) {
55 self.setMesh(shared_ptr<RectangularMesh<2>>());
56 return;
57 }
58
59 py::extract<shared_ptr<RectangularMesh<2>>> mesh2d(mesh);
60 if (mesh2d.check()) {
61 self.setMesh(mesh2d());
62 return;
63 }
64
65 py::extract<shared_ptr<MeshGeneratorD<2>>> generator2d(mesh);
66 if (generator2d.check()) {
67 self.setMesh(generator2d());
68 return;
69 }
70
71 py::extract<shared_ptr<MeshD<1>>> mesh1d(mesh);
72 if (mesh1d.check()) {
73 self.setMesh(mesh1d());
74 return;
75 }
76
77 py::extract<shared_ptr<MeshGeneratorD<1>>> generator1d(mesh);
78 if (generator1d.check()) {
79 self.setMesh(generator1d());
80 return;
81 }
82
83 if (PySequence_Check(mesh.ptr())) {
84 py::stl_input_iterator<double> begin(mesh), end;
85 shared_ptr<OrderedAxis> ordered_axis(new OrderedAxis(std::vector<double>(begin, end)));
86 self.setMesh(static_pointer_cast<MeshD<1>>(ordered_axis));
87 return;
88 }
89
90 throw TypeError(u8"cannot convert argument to proper mesh type");
91 }
92
93 template <typename PySolver> static auto init(PySolver& solver) -> PySolver& {
94 solver.add_property("geometry", &Diffusion2DSolver<GeometryT>::getGeometry, &Diffusion2DSolver<GeometryT>::setGeometry,
95 u8"Geometry provided to the solver");
96 solver.add_property("mesh", &Diffusion2DSolver<GeometryT>::getMesh, &Solver_setMesh, u8"Mesh provided to the solver");
97 return solver;
98 }
99};
100
101 namespace plask { namespace python { namespace detail {
102
103 template <>
104 struct ExportedSolverDefaultDefs<Diffusion2DSolver<Geometry2DCylindrical>, void, void>
105 : ExportedDiffusion2DSolverDefaultDefs<Geometry2DCylindrical> {};
106
107 template <>
108 struct ExportedSolverDefaultDefs<Diffusion2DSolver<Geometry2DCartesian>, void, void>
109 : ExportedDiffusion2DSolverDefaultDefs<Geometry2DCartesian> {};
110
111}}} // namespace plask::python::detail
112
119 BOOST_PYTHON_MODULE(diffusion) {
120 {
121 CLASS(Diffusion2DSolver<Geometry2DCylindrical>, "DiffusionCyl",
122 u8"Calculates carrier pairs concentration in active region using FEM in two-dimensional cylindrical space")
123 solver.def("compute", &DiffusionSolver_compute<__Class__>,
124 u8"Run diffusion calculations\n\n"
125 u8"Args:\n"
126 u8" loops (int): Number of iterations to perform. If 0, the solver will run\n"
127 u8" until the convergence.\n"
128 u8" shb (bool): If True, the solver will use take into account the spatial hole\n"
129 u8" burning effect.\n"
130 u8" reg (int or None): Index of the active region to compute. If None, perform\n"
131 u8" computations for all the active regions.",
132 (py::arg("loops") = 0, py::arg("shb") = false, py::arg("reg") = py::object()));
133 RW_FIELD(maxerr, u8"Maximum relative residual error (%)");
134 RECEIVER(inCurrentDensity, u8"");
135 RECEIVER(inTemperature, u8"");
136 RECEIVER(inGain, u8"It is required only for the SHB computations.");
137 RECEIVER(inWavelength, u8"It is required only for the SHB computations.");
138 RECEIVER(inLightE, u8"It is required only for the SHB computations.");
139 PROVIDER(outCarriersConcentration, u8"");
140 METHOD(get_total_burning, get_burning_integral, u8"Get total power burned over threshold [mW].");
141 solver.def("get_burning_for_mode", DiffusionSolver_get_burning_for_mode<__Class__>,
142 u8"Get power burned over threshold by specified mode [mW].", py::arg("mode"));
143 registerFemSolver(solver);
144
145 // TODO remove some day
146 solver.def("compute_threshold", &DiffusionSolverCyl_compute_threshold, u8"Deprecated method. Use compute() instead.");
147 solver.def("compute_overthreshold", &DiffusionSolverCyl_compute_overthreshold,
148 u8"Deprecated method. Use compute(shb=True) instead.");
149 }
150
151 {
152 CLASS(Diffusion2DSolver<Geometry2DCartesian>, "Diffusion2D",
153 u8"Calculates carrier pairs concentration in active region using FEM in two-dimensional Cartesian space")
154 solver.def("compute", &DiffusionSolver_compute<__Class__>,
155 u8"Run diffusion calculations\n\n"
156 u8"Args:\n"
157 u8" loops (int): Number of iterations to perform. If 0, the solver will run\n"
158 u8" until the convergence.\n"
159 u8" shb (bool): If True, the solver will use take into account the spatial hole\n"
160 u8" burning effect.\n"
161 u8" reg (int or None): Index of the active region to compute. If None, perform\n"
162 u8" computations for all the active regions.",
163 (py::arg("loops") = 0, py::arg("shb") = false, py::arg("reg") = py::object()));
164 RW_FIELD(maxerr, u8"Maximum relative residual error (%)");
165 RECEIVER(inCurrentDensity, u8"");
166 RECEIVER(inTemperature, u8"");
167 RECEIVER(inGain, u8"It is required only for the SHB computations.");
168 RECEIVER(inWavelength, u8"It is required only for the SHB computations.");
169 RECEIVER(inLightE, u8"It is required only for the SHB computations.");
170 PROVIDER(outCarriersConcentration, u8"");
171 METHOD(get_total_burning, get_burning_integral, u8"Get total power burned over threshold [mW].");
172 solver.def("get_burning_for_mode", DiffusionSolver_get_burning_for_mode<__Class__>,
173 u8"Get power burned over threshold by specified mode [mW].", py::arg("mode"));
174 registerFemSolver(solver);
175
176 // TODO remove some day
177 solver.def("compute_threshold", &DiffusionSolver2D_compute_threshold, u8"Deprecated method. Use compute() instead.");
178 solver.def("compute_overthreshold", &DiffusionSolver2D_compute_overthreshold,
179 u8"Deprecated method. Use compute(shb=True) instead.");
180 }
181
182 {
183 CLASS(Diffusion3DSolver, "Diffusion3D",
184 u8"Calculates carrier pairs concentration in active region using FEM in three-dimensional space")
185 solver.def("compute", &DiffusionSolver_compute<__Class__>,
186 u8"Run diffusion calculations\n\n"
187 u8"Args:\n"
188 u8" loops (int): Number of iterations to perform. If 0, the solver will run\n"
189 u8" until the convergence.\n"
190 u8" shb (bool): If True, the solver will use take into account the spatial hole\n"
191 u8" burning effect.\n"
192 u8" reg (int or None): Index of the active region to compute. If None, perform\n"
193 u8" computations for all the active regions.",
194 (py::arg("loops") = 0, py::arg("shb") = false, py::arg("reg") = py::object()));
195 RW_FIELD(maxerr, u8"Maximum relative residual error (%)");
196 RECEIVER(inCurrentDensity, u8"");
197 RECEIVER(inTemperature, u8"");
198 RECEIVER(inGain, u8"It is required only for the SHB computations.");
199 RECEIVER(inWavelength, u8"It is required only for the SHB computations.");
200 RECEIVER(inLightE, u8"It is required only for the SHB computations.");
201 PROVIDER(outCarriersConcentration, u8"");
202 METHOD(get_total_burning, get_burning_integral, u8"Get total power burned over threshold [mW].");
203 solver.def("get_burning_for_mode", DiffusionSolver_get_burning_for_mode<__Class__>,
204 u8"Get power burned over threshold by specified mode [mW].", py::arg("mode"));
205 registerFemSolver(solver);
206 }
207}