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
27 namespace plask {
28
34 struct PLASK_API MaterialsDB {
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>
90 struct RegisterUnderName {
91 RegisterUnderName(const std::string& name) { getDefault().add<MaterialType>(name); }
92 };
93
98 struct PLASK_API MaterialConstructor {
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
124 virtual ~MaterialConstructor() {}
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
138 struct PLASK_API MixedCompositionFactory {
139
140 protected:
141
142 shared_ptr<const MaterialConstructor> constructor;
143
144 public:
149 MixedCompositionFactory(shared_ptr<const MaterialConstructor> constructor): constructor(constructor) {}
150
151 virtual ~MixedCompositionFactory() {}
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
176 Material::Composition material1composition, material2composition;
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
214 struct PLASK_API MixedCompositionAndDopantFactory: public MixedCompositionOnlyFactory {
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
250 struct PLASK_API MixedDopantFactory: public MixedCompositionFactory {
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
283 struct PLASK_API DummyMixedCompositionFactory: public MixedCompositionFactory {
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
325 public:
326
328 MaterialInfo::DB info;
329
331 typedef boost::transform_iterator<iter_val, constructors_map_t::const_iterator> iterator;
332
334 typedef iterator const_iterator;
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 >
377 struct DelegateMaterialConstructor;
378
379 template <typename MaterialType>
380 struct DelegateMaterialConstructor<MaterialType, true, true>: public MaterialConstructor {
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>
393 struct DelegateMaterialConstructor<MaterialType, true, false>: public MaterialConstructor {
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>
407 struct DelegateMaterialConstructor<MaterialType, false, true>: public MaterialConstructor {
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);
413 return plask::make_shared<MaterialType>(doping);
414 }
415
416 bool isAlloy() const override { return false; }
417 };
418
419 template <typename MaterialType>
420 struct DelegateMaterialConstructor<MaterialType, false, false>: public MaterialConstructor {
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);
427 return plask::make_shared<MaterialType>();
428 }
429
430 bool isAlloy() const override { return false; }
431 };
432
436 class PLASK_API ProxyMaterialConstructor: public MaterialConstructor {
437 shared_ptr<Material> material;
438 shared_ptr<const MaterialsDB::MaterialConstructor> constructor;
439 Material::Composition composition;
440 double doping;
441
442 public:
443 ProxyMaterialConstructor();
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
464 shared_ptr<Material> get(const Material::Composition& composition, const std::string& label, const std::string& dopant_name, double doping) const;
465
475 shared_ptr<Material> get(const Material::Composition& composition, const std::string& dopant_name, double doping) const {
476 return get(composition, "", dopant_name, doping);
477 }
478
487 shared_ptr<Material> get(const Material::Composition& composition, const std::string& label = "") const {
488 return get(composition, label, "", 0.);
489 }
490
498 shared_ptr<Material> get(const std::string& name_with_dopant, double doping) const;
499
500 /*
501 * Create material object.
502 * @param name_with_components objects composition in format object1(amount1)...objectN(amountN), where some amounts are optional for example: "Al(0.7)GaN"
503 * @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"
504 * @return constructed material
505 * @throw NoSuchMaterial if database doesn't know material with name @p parsed_name_with_donor
506 * @throw MaterialParseException if can't parse @p name_with_components or @p doping_descr
507 */
508 //shared_ptr<Material> get(const std::string& name_with_components, const std::string& doping_descr) const;
509
516 shared_ptr<const MaterialConstructor> getConstructor(const std::string& name_without_composition) const;
517
518 shared_ptr<Material> get(const Material::Parameters& param) const;
519
527 shared_ptr<Material> get(const std::string& full_name) const;
528
536 shared_ptr<MixedCompositionFactory> getFactory(const std::string& material1_fullname, const std::string& material2_fullname, double shape=1.) const;
537
538 /*
539 * Add simple material (which does snot require composition parsing) to DB. Replace existing material if there is one already in DB.
540 * @param constructor object which can create material instance; must be created by operator new and material DB will call delete for it
541 */
542 // void addSimple(const MaterialConstructor* constructor);
543
548 void addSimple(shared_ptr<MaterialConstructor> constructor);
549
550 /*
551 * Add alloy material (which require composition parsing) to DB. Replace existing material if there is one already in DB.
552 * @param constructor object which can create material instance; must be created by operator new and material DB will call delete for it
553 */
554 //void addAlloy(const MaterialConstructor* constructor);
555
560 void addAlloy(shared_ptr<MaterialConstructor> constructor);
561
569 template <typename MaterialType, bool requireComposition, bool requireDopant>
570 void add(const std::string& name) {
571 if (requireComposition)
572 addAlloy(plask::make_shared< DelegateMaterialConstructor<MaterialType, requireComposition, requireDopant> >(name));
573 else
574 addSimple(plask::make_shared< DelegateMaterialConstructor<MaterialType, requireComposition, requireDopant> >(name));
575 }
576
584 template <typename MaterialType>
585 void add(const std::string& name) {
586 add<MaterialType, Material::is_with_composition<MaterialType>::value, Material::is_with_dopant<MaterialType>::value>(name);
587 }
588
596 template <typename MaterialType>
597 void add() { add<MaterialType>(MaterialType::NAME); }
598
605 void remove(const std::string& name);
606
613 bool isAlloy(const std::string& material_name) const;
614
615 /*
616 * Get alloy material constructor object.
617 * @param composition objects composition
618 * @param dopant_name name of dopant (if any)
619 */
620 shared_ptr<const MaterialConstructor> getConstructor(const Material::Composition& composition, const std::string& label = "", const std::string& dopant_name = "") const;
621
622 shared_ptr<const MaterialConstructor> getConstructor(const Material::Parameters& material, bool allow_alloy_without_composition = false) const;
623
624 private:
625
632 shared_ptr<const MaterialConstructor> getConstructor(const std::string& dbKey, const Material::Composition& composition, bool allow_alloy_without_composition = false) const;
633
643 shared_ptr<Material> get(const std::string& dbKey, const Material::Composition& composition, double doping = 0.0) const;
644
645};
646
647 struct PLASK_API MaterialsDB::TemporaryReplaceDefault {
648 MaterialsDB toRevert;
649
650 TemporaryReplaceDefault(const TemporaryReplaceDefault&) = delete;
651 TemporaryReplaceDefault& operator=(const TemporaryReplaceDefault&) = delete;
652 TemporaryReplaceDefault(TemporaryReplaceDefault&&) = delete;
653 TemporaryReplaceDefault& operator=(TemporaryReplaceDefault&&) = delete;
654
659 TemporaryReplaceDefault(MaterialsDB temporaryValue = MaterialsDB()): toRevert(std::move(getDefault())) {
660 getDefault() = std::move(temporaryValue);
661 }
662
663 ~TemporaryReplaceDefault() {
664 MaterialsDB::getDefault() = std::move(toRevert);
665 }
666};
667
668} // namespace plask
669
670#endif // PLASK__MATERIAL_DB_H