PLaSK library
Loading...
Searching...
No Matches
db.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__MATERIAL_DB_H
15#define PLASK__MATERIAL_DB_H
16
17#include <functional>
18#include "material.hpp"
19#include "const_material.hpp"
20
21#include <boost/iterator/transform_iterator.hpp>
22#include "../utils/system.hpp"
23#include "../utils/warnings.hpp"
24
25#include "info.hpp"
26
27namespace plask {
28
35
40 static MaterialsDB& getDefault();
41
43 struct TemporaryReplaceDefault;
44 typedef TemporaryReplaceDefault TemporaryClearDefault;
45
50 static void loadToDefault(const std::string& fileName_mainpart);
51
56 static void loadAllToDefault(const std::string& dir = plaskMaterialsPath());
57
61 void clear() {
62 constructors.clear();
63 info.clear();
64 }
65
70 void update(const MaterialsDB& src) {
71 for (const auto& item: src.constructors) {
72 constructors[item.first] = item.second;
73 }
74 info.update(src.info);
75 }
76
82 template <typename MaterialType>
83 struct Register {
84 Register(const std::string& name) { getDefault().add<MaterialType>(name); }
85 Register() { getDefault().add<MaterialType>(); }
86 };
87
89 template <typename MaterialType>
91 RegisterUnderName(const std::string& name) { getDefault().add<MaterialType>(name); }
92 };
93
99
103 std::string materialName;
104
109 MaterialConstructor(const std::string& materialName): materialName(materialName) {}
110
117 virtual shared_ptr<Material> operator()(const Material::Composition& composition, double doping) const = 0;
118
122 virtual bool isAlloy() const = 0;
123
125
126 void ensureCompositionIsEmpty(const Material::Composition& composition) const {
127 if (!composition.empty()) throw Exception("redundant composition given for material '{0}'", materialName);
128 }
129
130 void ensureNoDoping(double doping) const {
131 if (!isnan(doping) && doping != 0.) throw Exception("redundant doping given for material '{0}'", materialName);
132 }
133 };
134
139
140 protected:
141
142 shared_ptr<const MaterialConstructor> constructor;
143
144 public:
149 MixedCompositionFactory(shared_ptr<const MaterialConstructor> constructor): constructor(constructor) {}
150
152
158 virtual shared_ptr<Material> operator()(double m1_weight) const = 0;
159
164 virtual shared_ptr<Material> singleMaterial() const = 0;
165
166 };
167
171 //TODO cache: double -> constructed material
172 struct PLASK_API MixedCompositionOnlyFactory: public MixedCompositionFactory { //TODO nonlinear mixing with functor double [0.0, 1.0] -> double [0.0, 1.0]
173
174 protected:
175
177
178 double shape;
179
185 Material::Composition mixedComposition(double m1_weight) const;
186
187 public:
195 MixedCompositionOnlyFactory(shared_ptr<const MaterialConstructor> constructor, const Material::Composition& material1composition, const Material::Composition& material2composition, double shape=1.);
196
202 shared_ptr<Material> operator()(double m1_weight) const override {
203 return (*constructor)(mixedComposition(m1_weight), NAN);
204 }
205
206 shared_ptr<Material> singleMaterial() const override {
207 return material1composition == material2composition ? (*constructor)(material1composition, NAN) : shared_ptr<Material>();
208 }
209 };
210
215 protected:
216 double m1DopAmount, m2DopAmount;
217
218 public:
227 MixedCompositionAndDopantFactory(shared_ptr<const MaterialConstructor> constructor, const Material::Composition& material1composition, const Material::Composition& material2composition,
228 double m1DopAmount, double m2DopAmount, double shape=1.)
229 : MixedCompositionOnlyFactory(constructor, material1composition, material2composition, shape), m1DopAmount(m1DopAmount), m2DopAmount(m2DopAmount) {}
230
236 shared_ptr<Material> operator()(double m1_weight) const override {
237 return (*constructor)(mixedComposition(m1_weight),
238 m1DopAmount * pow(m1_weight, shape) + m2DopAmount * (1.0 - pow(m1_weight, shape)));
239 }
240
241 shared_ptr<Material> singleMaterial() const override {
242 return (material1composition == material2composition) && (m1DopAmount == m2DopAmount) ?
243 (*constructor)(material1composition, m1DopAmount) : shared_ptr<Material>();
244 }
245 };
246
251 protected:
252 double m1DopAmount, m2DopAmount;
253
254 double shape;
255
256 public:
263 MixedDopantFactory(shared_ptr<const MaterialConstructor> constructor, double m1DopAmount, double m2DopAmount, double shape=1.)
264 : MixedCompositionFactory(constructor), m1DopAmount(m1DopAmount), m2DopAmount(m2DopAmount), shape(shape) {}
265
271 shared_ptr<Material> operator()(double m1_weight) const override {
272 return (*constructor)(Material::Composition(), m1DopAmount * pow(m1_weight, shape) + m2DopAmount * (1.0 - pow(m1_weight, shape)));
273 }
274
275 shared_ptr<Material> singleMaterial() const override {
276 return m1DopAmount == m2DopAmount ? (*constructor)(Material::Composition(), m1DopAmount) : shared_ptr<Material>();
277 }
278 };
279
284 protected:
285 std::string full_name;
286
287 public:
295 DummyMixedCompositionFactory(const std::string& name1, const std::string& name2)
296 : MixedCompositionFactory(shared_ptr<const MaterialConstructor>()), full_name(name1 + "..." + name2) {}
297
303 shared_ptr<Material> operator()(double PLASK_UNUSED(m1_weight)) const override {
304 return plask::make_shared<DummyMaterial>(full_name);
305 }
306
307 shared_ptr<Material> singleMaterial() const override {
308 return plask::make_shared<DummyMaterial>(full_name);
309 }
310 };
311
312 private:
313
315 typedef std::map<std::string, shared_ptr<const MaterialConstructor> > constructors_map_t;
316
318 constructors_map_t constructors;
319
320 // Static const constructors_map_t::mapped_type& iter_val(const constructors_map_t::value_type &pair) { return pair.second; }
321 struct iter_val: public std::function<const constructors_map_t::mapped_type&(const constructors_map_t::value_type&)> {
322 const constructors_map_t::mapped_type& operator()(const constructors_map_t::value_type &pair) const { return pair.second; }
323 };
324
325public:
326
329
331 typedef boost::transform_iterator<iter_val, constructors_map_t::const_iterator> iterator;
332
335
340 const_iterator begin() const { return iterator(constructors.begin()); }
341
346 const_iterator end() const { return iterator(constructors.end()); }
347
355 size_t size() const {
356 return constructors.size();
357 }
358
363 static void ensureCompositionIsNotEmpty(const Material::Composition& composition);
364
374 template <typename MaterialType,
375 bool requireComposition = Material::is_with_composition<MaterialType>::value,
376 bool requireDopant = Material::is_with_dopant<MaterialType>::value >
378
379 template <typename MaterialType>
381
382 DelegateMaterialConstructor(const std::string& material_name): MaterialConstructor(material_name) {}
383
384 shared_ptr<Material> operator()(const Material::Composition& composition, double doping) const override {
385 ensureCompositionIsNotEmpty(composition);
386 return plask::make_shared<MaterialType>(Material::completeComposition(composition), doping);
387 }
388
389 bool isAlloy() const override { return true; } // == ! requireComposition
390 };
391
392 template <typename MaterialType>
394
395 DelegateMaterialConstructor(const std::string& material_name): MaterialConstructor(material_name) {}
396
397 shared_ptr<Material> operator()(const Material::Composition& composition, double doping) const override {
398 ensureCompositionIsNotEmpty(composition);
399 ensureNoDoping(doping);
400 return plask::make_shared<MaterialType>(Material::completeComposition(composition));
401 }
402
403 bool isAlloy() const override { return true; }
404 };
405
406 template <typename MaterialType>
408
409 DelegateMaterialConstructor(const std::string& material_name): MaterialConstructor(material_name) {}
410
411 shared_ptr<Material> operator()(const Material::Composition& composition, double doping) const override {
412 ensureCompositionIsEmpty(composition);
414 }
415
416 bool isAlloy() const override { return false; }
417 };
418
419 template <typename MaterialType>
421
422 DelegateMaterialConstructor(const std::string& material_name): MaterialConstructor(material_name) {}
423
424 shared_ptr<Material> operator()(const Material::Composition& composition, double doping) const override {
425 ensureCompositionIsEmpty(composition);
426 ensureNoDoping(doping);
428 }
429
430 bool isAlloy() const override { return false; }
431 };
432
437 shared_ptr<Material> material;
438 shared_ptr<const MaterialsDB::MaterialConstructor> constructor;
439 Material::Composition composition;
440 double doping;
441
442 public:
444
445 ProxyMaterialConstructor(const std::string& name, const MaterialsDB& db=MaterialsDB::getDefault());
446
447 ProxyMaterialConstructor(const shared_ptr<Material>& material);
448
449 shared_ptr<Material> operator()(const Material::Composition& comp, double dop) const override;
450
451 bool isAlloy() const override;
452 };
453
463 shared_ptr<Material> get(const Material::Composition& composition, const std::string& label, const std::string& dopant_name = "", double doping = 0.0) const;
464
473 //shared_ptr<Material> get(const std::string& parsed_name_with_dopant, const std::vector<double>& composition, double doping = 0.) const;
474
482 shared_ptr<Material> get(const std::string& name_with_dopant, double doping) const;
483
484 /*
485 * Create material object.
486 * @param name_with_components objects composition in format object1(amount1)...objectN(amountN), where some amounts are optional for example: "Al(0.7)GaN"
487 * @param doping_descr empty string if there is no doping or description of dopant in format objectname=amount or objectname p/n=amount, for example: "Mg=7e18" or "Mg p=7e18"
488 * @return constructed material
489 * @throw NoSuchMaterial if database doesn't know material with name @p parsed_name_with_donor
490 * @throw MaterialParseException if can't parse @p name_with_components or @p doping_descr
491 */
492 //shared_ptr<Material> get(const std::string& name_with_components, const std::string& doping_descr) const;
493
500 shared_ptr<const MaterialConstructor> getConstructor(const std::string& name_without_composition) const;
501
503
511 shared_ptr<Material> get(const std::string& full_name) const;
512
520 shared_ptr<MixedCompositionFactory> getFactory(const std::string& material1_fullname, const std::string& material2_fullname, double shape=1.) const;
521
522 /*
523 * Add simple material (which does snot require composition parsing) to DB. Replace existing material if there is one already in DB.
524 * @param constructor object which can create material instance; must be created by operator new and material DB will call delete for it
525 */
526 // void addSimple(const MaterialConstructor* constructor);
527
532 void addSimple(shared_ptr<MaterialConstructor> constructor);
533
534 /*
535 * Add alloy material (which require composition parsing) to DB. Replace existing material if there is one already in DB.
536 * @param constructor object which can create material instance; must be created by operator new and material DB will call delete for it
537 */
538 //void addAlloy(const MaterialConstructor* constructor);
539
544 void addAlloy(shared_ptr<MaterialConstructor> constructor);
545
553 template <typename MaterialType, bool requireComposition, bool requireDopant>
554 void add(const std::string& name) {
557 else
559 }
560
568 template <typename MaterialType>
569 void add(const std::string& name) {
570 add<MaterialType, Material::is_with_composition<MaterialType>::value, Material::is_with_dopant<MaterialType>::value>(name);
571 }
572
580 template <typename MaterialType>
581 void add() { add<MaterialType>(MaterialType::NAME); }
582
589 void remove(const std::string& name);
590
597 bool isAlloy(const std::string& material_name) const;
598
599 /*
600 * Get alloy material constructor object.
601 * @param composition objects composition
602 * @param dopant_name name of dopant (if any)
603 */
604 shared_ptr<const MaterialConstructor> getConstructor(const Material::Composition& composition, const std::string& label = "", const std::string& dopant_name = "") const;
605
606 shared_ptr<const MaterialConstructor> getConstructor(const Material::Parameters& material, bool allow_alloy_without_composition = false) const;
607
608private:
609
610 // * @param dopant_name name of dopant (if any), use for error messages
617 shared_ptr<const MaterialConstructor> getConstructor(const std::string& dbKey, const Material::Composition& composition, bool allow_alloy_without_composition = false) const;
618
619 // * @param dopant_name name of dopant (if any)
629 shared_ptr<Material> get(const std::string& dbKey, const Material::Composition& composition, double doping = 0.0) const;
630
631};
632
633struct PLASK_API MaterialsDB::TemporaryReplaceDefault {
635
636 TemporaryReplaceDefault(const TemporaryReplaceDefault&) = delete;
637 TemporaryReplaceDefault& operator=(const TemporaryReplaceDefault&) = delete;
638 TemporaryReplaceDefault(TemporaryReplaceDefault&&) = delete;
639 TemporaryReplaceDefault& operator=(TemporaryReplaceDefault&&) = delete;
640
646 getDefault() = std::move(temporaryValue);
647 }
648
650 MaterialsDB::getDefault() = std::move(toRevert);
651 }
652};
653
654} // namespace plask
655
656#endif // PLASK__MATERIAL_DB_H