PLaSK library

Loading...
Searching...
No Matches
diffusion1d.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#include <plask/plask.hpp>
15
16 namespace plask { namespace electrical { namespace diffusion1d {
17
18 template<typename Geometry2DType>
19 class PLASK_SOLVER_API DiffusionFem2DSolver: public SolverWithMesh<Geometry2DType, RegularMesh1D>
20{
21 public:
22 enum FemMethod {
23 FEM_LINEAR,
24 FEM_PARABOLIC
25 };
26
27 enum ComputationType {
28 COMPUTATION_INITIAL,
29 COMPUTATION_THRESHOLD,
30 COMPUTATION_OVERTHRESHOLD
31 };
32
33 ReceiverFor<CurrentDensity, Geometry2DType> inCurrentDensity;
34 ReceiverFor<Temperature, Geometry2DType> inTemperature;
35 ReceiverFor<Gain, Geometry2DType> inGain;
36 ReceiverFor<ModeWavelength> inWavelength;
37 ReceiverFor<ModeLightE, Geometry2DType> inLightE;
38
39 typename ProviderFor<CarriersConcentration, Geometry2DType>::Delegate outCarriersConcentration;
40
41 InterpolationMethod interpolation_method;
42 double relative_accuracy;
43 int max_mesh_changes;
44 int max_iterations;
45 FemMethod fem_method;
46 double minor_concentration;
47 bool do_initial;
48
49 DiffusionFem2DSolver<Geometry2DType>(const std::string& name=""):
50 SolverWithMesh<Geometry2DType,RegularMesh1D>(name),
51 outCarriersConcentration(this, &DiffusionFem2DSolver<Geometry2DType>::getConcentration),
52 interpolation_method(INTERPOLATION_SPLINE),
53 relative_accuracy(0.01),
54 max_mesh_changes(5),
55 max_iterations(20),
56 fem_method(FEM_PARABOLIC),
57 minor_concentration(5.0e+15),
58 do_initial(false),
59 mesh2(new RectangularMesh<2>())
60 {
61 inTemperature = 300.;
62 }
63
64 virtual ~DiffusionFem2DSolver<Geometry2DType>()
65 {
66 }
67
68 std::string getClassName() const override;
69
70 void loadConfiguration(XMLReader&, Manager&) override;
71
72 void compute(ComputationType type);
73 void compute_initial();
74 void compute_threshold();
75 void compute_overthreshold();
76
77 shared_ptr<MeshAxis> current_mesh_ptr()
78 {
79 return mesh2->axis[0];
80 }
81
82 RegularAxis& current_mesh()
83 {
84 return *static_cast<RegularAxis*>(mesh2->axis[0].get());
85 }
86
87 double burning_integral(void); // całka strat nadprogu
88
89 std::vector<double> modesP; // Integral for overthreshold computations summed for each mode
90
91 protected:
92
93 shared_ptr<RectangularMesh<2>> mesh2;
94
95 static constexpr double hk = phys::h_J/plask::PI; // stala plancka/2pi
96
97 shared_ptr<Material> QW_material;
98
99 double z; // z coordinate of active region
100
101 bool initial_computation;
102 bool threshold_computation;
103 bool overthreshold_computation;
104
105 double global_QW_width; // sumaryczna grubosc studni kwantowych [cm];
106 int iterations;
107
108 double jacobian(double r);
109
110 std::vector<Box2D> detected_QW;
111
112 LazyData<Vec<2>> j_on_the_mesh; // current density vector provided by inCurrentDensity reciever
113 LazyData<double> T_on_the_mesh; // temperature vector provided by inTemperature reciever
114
115 DataVector<double> PM; // Factor for overthreshold computations summed for all modes
116 DataVector<double> overthreshold_dgdn; // Factor for overthreshold computations summed for all modes
117
118 DataVector<double> n_previous; // concentration computed in n-1 -th step vector
119 DataVector<double> n_present; // concentration computed in n -th step vector
120
121 /**********************************************************************/
122
123 // Methods for solving equation
124 // K*n" - E*n = -F
125
126 void createMatrices(DataVector<double> A_matrix, DataVector<double> B_vector);
127
128 double K(int i);
129 double E(int i); // E dla rozkladu poczatkowego i progowego
130 double F(int i); // F dla rozkladu poczatkowego i progowego
131
132 double leftSide(std::size_t i); // lewa strona rownania dla rozkladu poczatkowego
133 double rightSide(std::size_t i); // prawa strona rownania dla rozkladu poczatkowego i progowego
134 double nSecondDeriv(std::size_t i); // druga pochodna n po r
135
136 bool MatrixFEM();
137 void determineQwWidth();
138
139 std::vector<Box2D> detectQuantumWells();
140 double getZQWCoordinate();
141 std::vector<double> getZQWCoordinates();
142
143 DataVector<const Tensor2<double>> averageLi(LazyData<Vec<3,dcomplex>> initLi, const RectangularMesh<2>& mesh_Li);
144
145 void onInitialize() override;
146 void onInvalidate() override;
147
148 struct ConcentrationDataImpl: public LazyDataImpl<double>
149 {
150 const DiffusionFem2DSolver* solver;
151 shared_ptr<const MeshD<2>> destination_mesh;
152 InterpolationFlags interpolationFlags;
153 LazyData<double> concentration;
154 ConcentrationDataImpl(const DiffusionFem2DSolver* solver,
155 shared_ptr<const MeshD<2>> dest_mesh,
156 InterpolationMethod interp);
157 double at(size_t i) const override;
158 size_t size() const override { return destination_mesh->size(); }
159 };
160
162 const LazyData<double> getConcentration(CarriersConcentration::EnumType what, shared_ptr<const MeshD<2>> dest_mesh,
163 InterpolationMethod interpolation=INTERPOLATION_DEFAULT ) const;
164
165}; // class DiffusionFem2DSolver
166
167 template <> inline
168 double DiffusionFem2DSolver<Geometry2DCartesian>::jacobian(double) {
169 return 1;
170}
171
172 template <> inline
173 double DiffusionFem2DSolver<Geometry2DCylindrical>::jacobian(double r) {
174 return 2*plask::PI * r;
175} // 2*PI from integral over full angle,
176
177}}} //namespace electrical::diffusion1d