PLaSK library
Loading...
Searching...
No Matches
solver.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#ifndef PLASK__SOLVER_OPTICAL_MODAL_SOLVER_H
15#define PLASK__SOLVER_OPTICAL_MODAL_SOLVER_H
16
17#include <plask/plask.hpp>
18#include "expansion.hpp"
19#include "rootdigger.hpp"
20#include "solverbase.hpp"
21#include "transfer.hpp"
22
23#undef interface
24
25namespace plask { namespace optical { namespace modal {
26
30template <typename BaseT> class PLASK_SOLVER_API ModalSolver : public BaseT, public ModalBase {
32 void onInputChanged(ReceiverBase&, ReceiverBase::ChangeReason) {
33 this->clearModes();
34 this->recompute_integrals = true;
35 }
36
38 void onGainChanged(ReceiverBase&, ReceiverBase::ChangeReason reason) {
39 if (reason == ReceiverBase::ChangeReason::REASON_VALUE) {
40 this->clearModes();
41 this->recompute_gain_integrals = true;
42 } else {
43 this->invalidate();
44 }
45 }
46
47 protected:
48 void onInitialize() override { setupLayers(); }
49
50 void onGeometryChange(const Geometry::Event& evt) override {
51 BaseT::onGeometryChange(evt);
52 if (this->geometry) {
53 if (evt.flags() == 0) {
54 auto objects = this->geometry->getObjectsWithRole("interface");
55 if (objects.size() > 1) {
56 Solver::writelog(LOG_WARNING, "More than one object with 'interface' role: interface not set");
57 } else if (objects.size() == 1) {
58 setInterfaceOn(objects[0]);
59 }
60 }
61 } else {
62 vbounds->clear();
63 }
64 }
65
67 void parseCommonModalConfiguration(XMLReader& reader, Manager& manager);
68
70 void setupLayers();
71
73 double smooth;
74
75 public:
78
81
84
87
90
93
96
99
102
105
108
111
114
117
118 ModalSolver(const std::string& name = "");
119
120 ~ModalSolver();
121
123 double getSmooth() const { return smooth; }
124
126 void setSmooth(double value) {
127 bool changed = smooth != value;
128 smooth = value;
129 if (changed) this->invalidate();
130 }
131
133 Transfer::Method getTransferMethod() const { return transfer_method; }
134
137 if (method != transfer_method) this->invalidate();
138 transfer_method = method;
139 }
140
142 bool getGroupLayers() const { return group_layers; }
143
145 void setGroupLayers(bool value) {
146 bool changed = group_layers != value;
147 group_layers = value;
148 if (changed) this->invalidate();
149 }
150
152 double getMaxTempDiff() const { return max_temp_diff; }
153
155 void setMaxTempDiff(double value) {
156 bool changed = max_temp_diff != value;
157 max_temp_diff = value;
158 if (changed) this->invalidate();
159 }
160
162 double getTempDist() const { return temp_dist; }
163
165 void setTempDist(double value) {
166 bool changed = temp_dist != value;
167 temp_dist = value;
168 if (changed) this->invalidate();
169 }
170
172 double getTempLayer() const { return temp_layer; }
173
175 void setTempLayer(double value) {
176 bool changed = temp_layer != value;
177 temp_layer = value;
178 if (changed) this->invalidate();
179 }
180
181 std::string getId() const override { return Solver::getId(); }
182
183 bool initCalculation() override { return Solver::initCalculation(); }
184
189 inline size_t getInterface() {
190 Solver::initCalculation();
191 return interface;
192 }
193
198 inline void setInterfaceAt(double pos) {
199 if (pos != interface_position) {
200 this->invalidate();
201 interface_position = pos;
202 Solver::writelog(LOG_DEBUG, "Setting interface at position {:g}um", interface_position);
203 }
204 }
205
211 void setInterfaceOn(const shared_ptr<const GeometryObject>& object, const PathHints* path = nullptr) {
212 auto boxes = this->geometry->getObjectBoundingBoxes(object, path);
213 if (boxes.size() != 1) throw NotUniqueObjectException();
214 if (interface_position != boxes[0].lower.vert()) {
215 this->invalidate();
216 interface_position = boxes[0].lower.vert();
217 Solver::writelog(LOG_DEBUG, "Setting interface on an object at position {:g}um", interface_position);
218 }
219 }
220
226 void setInterfaceOn(const shared_ptr<const GeometryObject>& object, const PathHints& path) { setInterfaceOn(object, &path); }
227
229 dcomplex getDeterminant() {
230 initCalculation();
231 ensureInterface();
232 if (!transfer) initTransfer(getExpansion(), false);
233 return transfer->determinant();
234 }
235
237 const shared_ptr<MeshD<BaseT::SpaceType::DIM>>& mesh,
238 dcomplex lam,
239 dcomplex glam) {
240 expansion->temperature = inTemperature(mesh);
241 expansion->gain_connected = inGain.hasProvider();
242 expansion->epsilon_connected = inEpsilon.hasProvider();
243 if (expansion->gain_connected) {
244 if (isnan(glam)) glam = lam;
245 expansion->gain = inGain(mesh, real(glam));
246 }
247 if (expansion->epsilon_connected) {
248 if (isnan(glam)) glam = lam;
249 expansion->epsilons = inEpsilon(mesh, glam);
250 }
251 expansion->carriers = inCarriersConcentration.hasProvider() ? inCarriersConcentration(CarriersConcentration::MAJORITY, mesh)
252 : LazyData<double>(mesh->size(), 0.);
253 }
254
262 cvector incidentVector(Transfer::IncidentDirection side, size_t idx, dcomplex lam = NAN);
263
271 cvector incidentVector(Transfer::IncidentDirection side, const cvector& incident, dcomplex lam = NAN);
272
273 protected:
274 // Initialize the incident field vector
275 size_t initIncidence(Transfer::IncidentDirection side, dcomplex lam = NAN);
276
278 void scaleIncidentVector(cvector& incident, size_t layer);
279
283 virtual size_t nummodes() const = 0;
284
289 virtual double applyMode(size_t n) = 0;
290
296 DataVector<const Tensor3<dcomplex>> getEpsilonProfile(const shared_ptr<const MeshD<BaseT::SpaceType::DIM>>& dst_mesh,
297 dcomplex lam,
298 InterpolationMethod interp = INTERPOLATION_DEFAULT);
299
305 LazyData<dcomplex> getRefractiveIndex(RefractiveIndex::EnumType component,
306 const shared_ptr<const MeshD<BaseT::SpaceType::DIM>>& dst_mesh,
307 dcomplex lam,
308 InterpolationMethod interp = INTERPOLATION_DEFAULT);
309
316 template <PropagationDirection part = PROPAGATION_TOTAL>
317 LazyData<Vec<3, dcomplex>> getLightE(size_t num,
318 shared_ptr<const MeshD<BaseT::SpaceType::DIM>> dst_mesh,
319 InterpolationMethod method);
320
327 template <PropagationDirection part = PROPAGATION_TOTAL>
328 LazyData<Vec<3, dcomplex>> getLightH(size_t num,
329 shared_ptr<const MeshD<BaseT::SpaceType::DIM>> dst_mesh,
330 InterpolationMethod method);
331
338 LazyData<double> getLightMagnitude(size_t num,
339 shared_ptr<const MeshD<BaseT::SpaceType::DIM>> dst_mesh,
340 InterpolationMethod method);
341
346 virtual double getWavelength(size_t n) = 0;
347};
348
349}}} // namespace plask::optical::modal
350
351#endif // PLASK__SOLVER_OPTICAL_MODAL_SOLVER_H