PLaSK library

Loading...
Searching...
No Matches
generator_rectangular.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__GENERATOR_RECTANGULAR_H
15#define PLASK__GENERATOR_RECTANGULAR_H
16
17#include "mesh.hpp"
18#include <plask/geometry/path.hpp>
19#include "rectangular.hpp"
20
21 namespace plask {
22
29 template <int dim>
30 PLASK_API shared_ptr<OrderedAxis> makeGeometryAxis(const shared_ptr<GeometryObjectD<dim>>& geometry,
31 Primitive<3>::Direction dir,
32 double split = 0.);
33
40 PLASK_API shared_ptr<OrderedAxis> makeGeometryGrid1D(const shared_ptr<GeometryObjectD<2>>& geometry, double split = 0.);
41
48 PLASK_API shared_ptr<RectangularMesh<2>> makeGeometryGrid(const shared_ptr<GeometryObjectD<2>>& geometry, double split = 0.);
49
56 PLASK_API shared_ptr<RectangularMesh<3>> makeGeometryGrid(const shared_ptr<GeometryObjectD<3>>& geometry, double split = 0.);
57
63 inline shared_ptr<OrderedAxis> makeGeometryGrid1D(const shared_ptr<GeometryD<2>>& geometry) {
64 return makeGeometryGrid1D(geometry->getChild());
65}
66
72 inline shared_ptr<RectangularMesh<2>> makeGeometryGrid(const shared_ptr<GeometryD<2>>& geometry) {
73 return makeGeometryGrid(geometry->getChild());
74}
75
81 inline shared_ptr<RectangularMesh<3>> makeGeometryGrid(const shared_ptr<GeometryD<3>>& geometry) {
82 return makeGeometryGrid(geometry->getChild());
83}
84
90 PLASK_API shared_ptr<OrderedAxis> refineAxis(const shared_ptr<MeshAxis>& axis, double spacing);
91
95 struct PLASK_API OrderedMesh1DSimpleGenerator : public MeshGeneratorD<1> {
96 protected:
97 bool split;
98
99 public:
101 OrderedMesh1DSimpleGenerator(bool split = false) : split(split) {}
102
103 shared_ptr<MeshD<1>> generate(const shared_ptr<GeometryObjectD<2>>& geometry) override;
104};
105
109 struct PLASK_API RectangularMesh2DSimpleGenerator : public MeshGeneratorD<2> {
110 protected:
111 bool split;
112
113 public:
115 RectangularMesh2DSimpleGenerator(bool split = false) : split(split) {}
116
117 shared_ptr<MeshD<2>> generate(const shared_ptr<GeometryObjectD<2>>& geometry) override;
118};
119
123 struct PLASK_API RectangularMesh3DSimpleGenerator : public MeshGeneratorD<3> {
124 protected:
125 bool split;
126
127 public:
129 RectangularMesh3DSimpleGenerator(bool split = false) : split(split) {}
130
131 shared_ptr<MeshD<3>> generate(const shared_ptr<GeometryObjectD<3>>& geometry) override;
132};
133
138 class PLASK_API OrderedMesh1DRegularGenerator : public OrderedMesh1DSimpleGenerator {
140 double spacing;
141
142 public:
147 OrderedMesh1DRegularGenerator(double spacing, bool split = false) : OrderedMesh1DSimpleGenerator(split), spacing(spacing) {}
148
149 shared_ptr<MeshD<1>> generate(const shared_ptr<GeometryObjectD<2>>& geometry) override;
150};
151
156 class PLASK_API RectangularMesh2DRegularGenerator : public RectangularMesh2DSimpleGenerator {
158 double spacing0, spacing1;
159
160 public:
165 RectangularMesh2DRegularGenerator(double spacing, bool split = false)
166 : RectangularMesh2DSimpleGenerator(split), spacing0(spacing), spacing1(spacing) {}
167
173 RectangularMesh2DRegularGenerator(double spacing0, double spacing1, bool split = false)
174 : RectangularMesh2DSimpleGenerator(split), spacing0(spacing0), spacing1(spacing1) {}
175
176 shared_ptr<MeshD<2>> generate(const shared_ptr<GeometryObjectD<2>>& geometry) override;
177};
178
183 struct PLASK_API RectangularMesh3DRegularGenerator : public RectangularMesh3DSimpleGenerator {
185 double spacing0, spacing1, spacing2;
186
187 public:
192 RectangularMesh3DRegularGenerator(double spacing, bool split = false)
193 : RectangularMesh3DSimpleGenerator(split), spacing0(spacing), spacing1(spacing), spacing2(spacing) {}
194
201 RectangularMesh3DRegularGenerator(double spacing0, double spacing1, double spacing2, bool split = false)
202 : RectangularMesh3DSimpleGenerator(split), spacing0(spacing0), spacing1(spacing1), spacing2(spacing2) {}
203
204 shared_ptr<MeshD<3>> generate(const shared_ptr<GeometryObjectD<3>>& geometry) override;
205};
206
210 class PLASK_API RectangularMesh2DFrom1DGenerator : public MeshGeneratorD<2> {
211 shared_ptr<MeshGeneratorD<1>> horizontal_generator;
212
213 public:
217 RectangularMesh2DFrom1DGenerator(const shared_ptr<MeshGeneratorD<1>>& source) : horizontal_generator(source) {}
218
219 shared_ptr<MeshD<2>> generate(const shared_ptr<GeometryObjectD<2>>& geometry) override;
220};
221
225 template <int dim> struct PLASK_API RectangularMeshRefinedGenerator : public MeshGeneratorD<dim> {
226 typedef typename Rectangular_t<dim>::Rectilinear GeneratedMeshType;
227 using MeshGeneratorD<dim>::DIM;
228
229 typedef std::map<std::pair<weak_ptr<const GeometryObjectD<DIM>>, PathHints>, std::set<double>> Refinements;
230
231 double aspect;
232
233 Refinements refinements[dim];
234
235 shared_ptr<OrderedAxis> getAxis(shared_ptr<OrderedAxis> axis, const shared_ptr<GeometryObjectD<DIM>>& geometry, size_t dir);
236
237 virtual shared_ptr<OrderedAxis> processAxis(shared_ptr<OrderedAxis> axis,
238 const shared_ptr<GeometryObjectD<DIM>>& geometry,
239 size_t dir) = 0;
240
241 virtual const char* name() = 0;
242
243 void fromXML(XMLReader&, Manager&);
244
245 std::pair<double, double> getMinMax(const shared_ptr<OrderedAxis>& axis);
246
247 void divideLargestSegment(shared_ptr<OrderedAxis> axis);
248
252 RectangularMeshRefinedGenerator() : aspect(0) {}
253
254 shared_ptr<MeshD<dim>> generate(const shared_ptr<GeometryObjectD<DIM>>& geometry) override;
255
257 double getAspect() const { return aspect; }
258
260 void setAspect(double value) {
261 if (value != 0. && value < 2.) throw BadInput("divideGenerator", "maximum aspect must be larger than 2");
262 aspect = value;
263 this->fireChanged();
264 }
265
268 const Refinements& getRefinements(typename Primitive<DIM>::Direction direction) const {
269 assert(size_t(direction) <= dim);
270 return refinements[size_t(direction)];
271 }
272
280 void addRefinement(typename Primitive<DIM>::Direction direction,
281 const weak_ptr<const GeometryObjectD<DIM>>& object,
282 const PathHints& path,
283 double position) {
284 auto key = std::make_pair(object, path);
285 assert(size_t(direction) <= dim);
286 refinements[size_t(direction)][key].insert(position);
287 this->fireChanged();
288 }
289
296 void addRefinement(typename Primitive<DIM>::Direction direction,
297 const weak_ptr<const GeometryObjectD<DIM>>& object,
298 double position) {
299 addRefinement(direction, object, PathHints(), position);
300 }
301
308 void addRefinement(typename Primitive<DIM>::Direction direction, const Path& path, double position) {
309 addRefinement(direction, dynamic_pointer_cast<const GeometryObjectD<DIM>>(path.back()), PathHints(path), position);
310 }
311
318 void addRefinement(typename Primitive<DIM>::Direction direction, const GeometryObject::Subtree& subtree, double position) {
319 auto path = subtree.getLastPath();
320 addRefinement(direction, dynamic_pointer_cast<const GeometryObjectD<DIM>>(path.back()), PathHints(path), position);
321 }
322
330 void removeRefinement(typename Primitive<DIM>::Direction direction,
331 const weak_ptr<const GeometryObjectD<DIM>>& object,
332 const PathHints& path,
333 double position) {
334 auto key = std::make_pair(object, path);
335 assert(size_t(direction) <= dim);
336 auto ref = refinements[size_t(direction)].find(key);
337 if (ref == refinements[size_t(direction)].end())
338 throw BadInput("RectangularMeshDivideGenerator", "there are no refinements for specified geometry object.");
339 auto oposition = ref->second.find(position);
340 if (oposition == ref->second.end())
341 throw BadInput("RectangularMeshDivideGenerator", "specified geometry object does not have refinements at {0}.",
342 *oposition);
343 ref->second.erase(oposition);
344 if (ref->second.empty()) refinements[size_t(direction)].erase(ref);
345 this->fireChanged();
346 }
347
354 void removeRefinement(typename Primitive<DIM>::Direction direction,
355 const weak_ptr<const GeometryObjectD<DIM>>& object,
356 double position) {
357 removeRefinement(direction, object, PathHints(), position);
358 }
359
366 void removeRefinement(typename Primitive<DIM>::Direction direction, const Path& path, double position) {
367 removeRefinement(direction, dynamic_pointer_cast<const GeometryObjectD<DIM>>(path.back()), PathHints(path), position);
368 }
369
376 void removeRefinement(typename Primitive<DIM>::Direction direction, const GeometryObject::Subtree& subtree, double position) {
377 auto path = subtree.getLastPath();
378 removeRefinement(direction, dynamic_pointer_cast<const GeometryObjectD<DIM>>(path.back()), PathHints(path), position);
379 }
380
386 void removeRefinements(const weak_ptr<const GeometryObjectD<DIM>>& object, const PathHints& path = PathHints()) {
387 auto key = std::make_pair(object, path);
388 bool found = false;
389 for (size_t i = 0; i != dim; ++i) {
390 auto ref = refinements[i].find(key);
391 if (ref != refinements[i].end()) {
392 found = true;
393 refinements[i].erase(ref);
394 }
395 }
396 if (found)
397 this->fireChanged();
398 else
399 writelog(LOG_WARNING, "RectangularMeshDivideGenerator: There are no refinements for specified geometry object");
400 }
401
405 void clearRefinements() {
406 refinements[0].clear();
407 refinements[1].clear();
408 this->fireChanged();
409 }
410
415 void removeRefinements(const Path& path) {
416 removeRefinements(dynamic_pointer_cast<const GeometryObjectD<DIM>>(path.back()), PathHints(path));
417 }
418
423 void removeRefinements(const GeometryObject::Subtree& subtree) {
424 auto path = subtree.getLastPath();
425 removeRefinements(dynamic_pointer_cast<const GeometryObjectD<DIM>>(path.back()), PathHints(path));
426 }
427};
428
429 template <>
430 shared_ptr<MeshD<1>> RectangularMeshRefinedGenerator<1>::generate(const boost::shared_ptr<plask::GeometryObjectD<2>>& geometry);
431 template <>
432 shared_ptr<MeshD<2>> RectangularMeshRefinedGenerator<2>::generate(const boost::shared_ptr<plask::GeometryObjectD<2>>& geometry);
433 template <>
434 shared_ptr<MeshD<3>> RectangularMeshRefinedGenerator<3>::generate(const boost::shared_ptr<plask::GeometryObjectD<3>>& geometry);
435
436 PLASK_API_EXTERN_TEMPLATE_STRUCT(RectangularMeshRefinedGenerator<1>)
437 PLASK_API_EXTERN_TEMPLATE_STRUCT(RectangularMeshRefinedGenerator<2>)
438 PLASK_API_EXTERN_TEMPLATE_STRUCT(RectangularMeshRefinedGenerator<3>)
439
440
443 template <int dim> struct PLASK_API RectangularMeshDivideGenerator : public RectangularMeshRefinedGenerator<dim> {
444 typedef typename Rectangular_t<dim>::Rectilinear GeneratedMeshType;
445 using MeshGeneratorD<dim>::DIM;
446
447 size_t pre_divisions[dim];
448 size_t post_divisions[dim];
449
450 unsigned char gradual;
451
452 shared_ptr<OrderedAxis> processAxis(shared_ptr<OrderedAxis> axis,
453 const shared_ptr<GeometryObjectD<DIM>>& geometry,
454 size_t dir) override;
455
456 const char* name() override { return "DivideGenerator"; }
457
458 template <int fd> friend shared_ptr<MeshGenerator> readRectangularDivideGenerator(XMLReader&, Manager&);
459
463 RectangularMeshDivideGenerator() : gradual(7) {
464 for (int i = 0; i != dim; ++i) {
465 pre_divisions[i] = 1;
466 post_divisions[i] = 1;
467 }
468 }
469
471 inline size_t getPreDivision(typename Primitive<DIM>::Direction direction) const {
472 assert(size_t(direction) <= dim);
473 return pre_divisions[size_t(direction)];
474 }
475
477 inline void setPreDivision(typename Primitive<DIM>::Direction direction, size_t div) {
478 assert(size_t(direction) <= dim);
479 pre_divisions[size_t(direction)] = div;
480 this->fireChanged();
481 }
482
484 inline size_t getPostDivision(typename Primitive<DIM>::Direction direction) const {
485 assert(size_t(direction) <= dim);
486 return post_divisions[size_t(direction)];
487 }
488
490 inline void setPostDivision(typename Primitive<DIM>::Direction direction, size_t div) {
491 assert(size_t(direction) <= dim);
492 post_divisions[size_t(direction)] = div;
493 this->fireChanged();
494 }
495
497 inline bool getGradual(size_t dir) const {
498 assert(dir <= dim);
499 return (gradual >> dir) & 1;
500 }
501
503 inline void setGradual(size_t dir, bool value) {
504 assert(dir <= dim);
505 gradual &= ~(1 << dir);
506 if (value) gradual |= 1 << dir;
507 this->fireChanged();
508 }
509
511 inline bool getGradual(typename Primitive<DIM>::Direction direction) const { return getGradual(size_t(direction)); }
512
514 inline void setGradual(typename Primitive<DIM>::Direction direction, bool value) { setGradual(size_t(direction), value); }
515};
516
517 PLASK_API_EXTERN_TEMPLATE_STRUCT(RectangularMeshDivideGenerator<1>)
518 PLASK_API_EXTERN_TEMPLATE_STRUCT(RectangularMeshDivideGenerator<2>)
519 PLASK_API_EXTERN_TEMPLATE_STRUCT(RectangularMeshDivideGenerator<3>)
520
521
524 template <int dim> struct PLASK_API RectangularMeshSmoothGenerator : public RectangularMeshRefinedGenerator<dim> {
525 typedef typename Rectangular_t<dim>::Rectilinear GeneratedMeshType;
526 using MeshGeneratorD<dim>::DIM;
527
528 double finestep[dim];
529 double maxstep[dim];
530 double factor[dim];
531
532 shared_ptr<OrderedAxis> processAxis(shared_ptr<OrderedAxis> axis,
533 const shared_ptr<GeometryObjectD<DIM>>& geometry,
534 size_t dir) override;
535
536 const char* name() override { return "SmoothGenerator"; }
537
538 template <int fd> friend shared_ptr<MeshGenerator> readRectangularSmoothGenerator(XMLReader&, Manager&);
539
541 RectangularMeshSmoothGenerator();
542
544 inline double getFineStep(typename Primitive<DIM>::Direction direction) const {
545 assert(size_t(direction) <= dim);
546 return finestep[size_t(direction)];
547 }
548
550 inline void setFineStep(typename Primitive<DIM>::Direction direction, double value) {
551 assert(size_t(direction) <= dim);
552 finestep[size_t(direction)] = value;
553 this->fireChanged();
554 }
555
557 inline double getMaxStep(typename Primitive<DIM>::Direction direction) const {
558 assert(size_t(direction) <= dim);
559 return maxstep[size_t(direction)];
560 }
561
563 inline void setMaxStep(typename Primitive<DIM>::Direction direction, double value) {
564 assert(size_t(direction) <= dim);
565 maxstep[size_t(direction)] = value;
566 this->fireChanged();
567 }
568
570 inline double getFactor(typename Primitive<DIM>::Direction direction) const {
571 assert(size_t(direction) <= dim);
572 return factor[size_t(direction)];
573 }
574
576 inline void setFactor(typename Primitive<DIM>::Direction direction, double value) {
577 assert(size_t(direction) <= dim);
578 if (value < 1.)
579 throw BadInput("SmoothGenerator", "increase factor for axis {:d} cannot be smaller than 1", size_t(direction));
580 factor[size_t(direction)] = value;
581 this->fireChanged();
582 }
583};
584
585 template <> RectangularMeshSmoothGenerator<1>::RectangularMeshSmoothGenerator();
586 template <> RectangularMeshSmoothGenerator<2>::RectangularMeshSmoothGenerator();
587 template <> RectangularMeshSmoothGenerator<3>::RectangularMeshSmoothGenerator();
588
589 PLASK_API_EXTERN_TEMPLATE_STRUCT(RectangularMeshSmoothGenerator<1>)
590 PLASK_API_EXTERN_TEMPLATE_STRUCT(RectangularMeshSmoothGenerator<2>)
591 PLASK_API_EXTERN_TEMPLATE_STRUCT(RectangularMeshSmoothGenerator<3>)
592
593} // namespace plask
594
595#endif // PLASK__GENERATOR_RECTANGULAR_H