PLaSK library

Loading...
Searching...
No Matches
rectangular2d.cpp
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 "rectangular2d.hpp"
15
16#include "regular1d.hpp"
17#include "ordered1d.hpp"
18
19 namespace plask {
20
21 static std::size_t normal_index(const RectangularMesh2D* mesh, std::size_t index0, std::size_t index1) {
22 return index0 + mesh->axis[0]->size() * index1;
23}
24 static std::size_t normal_index0(const RectangularMesh2D* mesh, std::size_t mesh_index) {
25 return mesh_index % mesh->axis[0]->size();
26}
27 static std::size_t normal_index1(const RectangularMesh2D* mesh, std::size_t mesh_index) {
28 return mesh_index / mesh->axis[0]->size();
29}
30
31 static std::size_t transposed_index(const RectangularMesh2D* mesh, std::size_t index0, std::size_t index1) {
32 return mesh->axis[1]->size() * index0 + index1;
33}
34 static std::size_t transposed_index0(const RectangularMesh2D* mesh, std::size_t mesh_index) {
35 return mesh_index / mesh->axis[1]->size();
36}
37 static std::size_t transposed_index1(const RectangularMesh2D* mesh, std::size_t mesh_index) {
38 return mesh_index % mesh->axis[1]->size();
39}
40
41 void RectangularMesh2D::setIterationOrder(IterationOrder iterationOrder) {
42 if (iterationOrder == ORDER_01) {
43 index_f = transposed_index;
44 index0_f = transposed_index0;
45 index1_f = transposed_index1;
46 minor_axis = &axis[1];
47 major_axis = &axis[0];
48 } else {
49 index_f = normal_index;
50 index0_f = normal_index0;
51 index1_f = normal_index1;
52 minor_axis = &axis[0];
53 major_axis = &axis[1];
54 }
55 this->fireChanged();
56}
57
58 typename RectangularMesh2D::IterationOrder RectangularMesh2D::getIterationOrder() const {
59 return (index_f == &transposed_index)? ORDER_01 : ORDER_10;
60}
61
62 void RectangularMesh2D::onAxisChanged(Mesh::Event &e) {
63 assert(!e.isDelete());
64 this->fireChanged(e.flags());
65}
66
67 RectangularMesh2D::RectangularMesh2D(IterationOrder iterationOrder)
68 : axis{ plask::make_shared<OrderedAxis>(), plask::make_shared<OrderedAxis>() } {
69 setIterationOrder(iterationOrder);
70 setChangeSignal(this->axis[0]);
71 setChangeSignal(this->axis[1]);
72}
73
74 RectangularMesh2D::RectangularMesh2D(shared_ptr<MeshAxis> axis0, shared_ptr<MeshAxis> axis1, IterationOrder iterationOrder)
75 : axis{ std::move(axis0), std::move(axis1) } {
76 setIterationOrder(iterationOrder);
77 setChangeSignal(this->axis[0]);
78 setChangeSignal(this->axis[1]);
79}
80
81 void RectangularMesh2D::reset(shared_ptr<MeshAxis> axis0, shared_ptr<MeshAxis> axis1, RectangularMesh2D::IterationOrder iterationOrder) {
82 setAxis(0, std::move(axis0), false);
83 setAxis(1, std::move(axis1), false);
84 setIterationOrder(iterationOrder);
85}
86
87 RectangularMesh2D::RectangularMesh2D(const RectangularMesh2D &src, bool clone_axes):
88 RectangularMeshBase2D(src),
89 axis {clone_axes ? src.axis[0]->clone() : src.axis[0],
90 clone_axes ? src.axis[1]->clone() : src.axis[1]}
91{
92 setIterationOrder(src.getIterationOrder());
93 setChangeSignal(this->axis[0]);
94 setChangeSignal(this->axis[1]);
95}
96
97 void RectangularMesh2D::reset(const RectangularMesh2D &src, bool clone_axes) {
98 if (clone_axes)
99 reset(src.axis[0]->clone(), src.axis[1]->clone(), src.getIterationOrder());
100 else
101 reset(src.axis[0], src.axis[1], src.getIterationOrder());
102}
103
104 RectangularMesh2D::~RectangularMesh2D() {
105 unsetChangeSignal(this->axis[0]);
106 unsetChangeSignal(this->axis[1]);
107}
108
109 void RectangularMesh2D::setAxis(std::size_t axis_nr, shared_ptr<MeshAxis> new_val, bool fireResized)
110{
111 if (axis[axis_nr] == new_val) return;
112 unsetChangeSignal(axis[axis_nr]);
113 const_cast<shared_ptr<MeshAxis>&>(axis[axis_nr]) = new_val;
114 setChangeSignal(axis[axis_nr]);
115 if (fireResized) this->fireResized();
116}
117
118 shared_ptr<RectangularMesh2D::ElementMesh> RectangularMesh2D::getElementMesh() const {
119 return plask::make_shared<RectangularMesh2D::ElementMesh>(this, axis[0]->getMidpointAxis(), axis[1]->getMidpointAxis(), getIterationOrder());
120}
121
122 bool RectangularMesh2D::hasSameNodes(const MeshD<2> &to_compare) const {
123 if (const RectangularMesh2D* c = dynamic_cast<const RectangularMesh2D*>(&to_compare))
124 return *this == *c; // this will call == operator from RectangularMesh2D
125 return RectangularMeshBase2D::hasSameNodes(to_compare);
126}
127
128 BoundaryNodeSet RectangularMesh2D::createVerticalBoundaryAtLine(std::size_t line_nr_axis0) const {
129 return new VerticalBoundary(*this, line_nr_axis0);
130}
131
132 BoundaryNodeSet RectangularMesh2D::createVerticalBoundaryAtLine(std::size_t line_nr_axis0, std::size_t indexBegin, std::size_t indexEnd) const {
133 return new VerticalBoundaryInRange(*this, line_nr_axis0, indexBegin, indexEnd);
134}
135
136 BoundaryNodeSet RectangularMesh2D::createVerticalBoundaryNear(double axis0_coord) const {
137 return new VerticalBoundary(*this, axis[0]->findNearestIndex(axis0_coord));
138}
139
140 BoundaryNodeSet RectangularMesh2D::createVerticalBoundaryNear(double axis0_coord, double from, double to) const {
141 std::size_t begInd, endInd;
142 if (!details::getIndexesInBoundsExt(begInd, endInd, *axis[1], from, to))
143 return new EmptyBoundaryImpl();
144 return new VerticalBoundaryInRange(*this, axis[0]->findNearestIndex(axis0_coord), begInd, endInd);
145}
146
147 BoundaryNodeSet RectangularMesh2D::createLeftBoundary() const {
148 return new VerticalBoundary(*this, 0);
149}
150
151 BoundaryNodeSet RectangularMesh2D::createRightBoundary() const {
152 return new VerticalBoundary(*this, axis[0]->size()-1);
153}
154
155 BoundaryNodeSet RectangularMesh2D::createLeftOfBoundary(const Box2D &box) const {
156 std::size_t line, begInd, endInd;
157 if (details::getLineLo(line, *axis[0], box.lower.c0, box.upper.c0) &&
158 details::getIndexesInBounds(begInd, endInd, *axis[1], box.lower.c1, box.upper.c1))
159 return new VerticalBoundaryInRange(*this, line, begInd, endInd);
160 else
161 return new EmptyBoundaryImpl();
162}
163
164 BoundaryNodeSet RectangularMesh2D::createRightOfBoundary(const Box2D &box) const {
165 std::size_t line, begInd, endInd;
166 if (details::getLineHi(line, *axis[0], box.lower.c0, box.upper.c0) &&
167 details::getIndexesInBounds(begInd, endInd, *axis[1], box.lower.c1, box.upper.c1))
168 return new VerticalBoundaryInRange(*this, line, begInd, endInd);
169 else
170 return new EmptyBoundaryImpl();
171}
172
173 BoundaryNodeSet RectangularMesh2D::createBottomOfBoundary(const Box2D &box) const {
174 std::size_t line, begInd, endInd;
175 if (details::getLineLo(line, *axis[1], box.lower.c1, box.upper.c1) &&
176 details::getIndexesInBounds(begInd, endInd, *axis[0], box.lower.c0, box.upper.c0))
177 return new HorizontalBoundaryInRange(*this, line, begInd, endInd);
178 else
179 return new EmptyBoundaryImpl();
180}
181
182 BoundaryNodeSet RectangularMesh2D::createTopOfBoundary(const Box2D &box) const {
183 std::size_t line, begInd, endInd;
184 if (details::getLineHi(line, *axis[1], box.lower.c1, box.upper.c1) &&
185 details::getIndexesInBounds(begInd, endInd, *axis[0], box.lower.c0, box.upper.c0))
186 return new HorizontalBoundaryInRange(*this, line, begInd, endInd);
187 else
188 return new EmptyBoundaryImpl();
189}
190
191 BoundaryNodeSet RectangularMesh2D::createHorizontalBoundaryAtLine(std::size_t line_nr_axis1) const {
192 return new HorizontalBoundary(*this, line_nr_axis1);
193}
194
195 BoundaryNodeSet RectangularMesh2D::createHorizontalBoundaryAtLine(std::size_t line_nr_axis1, std::size_t indexBegin, std::size_t indexEnd) const {
196 return new HorizontalBoundaryInRange(*this, line_nr_axis1, indexBegin, indexEnd);
197}
198
199 BoundaryNodeSet RectangularMesh2D::createHorizontalBoundaryNear(double axis1_coord) const {
200 return new HorizontalBoundary(*this, axis[1]->findNearestIndex(axis1_coord));
201}
202
203 BoundaryNodeSet RectangularMesh2D::createHorizontalBoundaryNear(double axis1_coord, double from, double to) const {
204 std::size_t begInd, endInd;
205 if (!details::getIndexesInBoundsExt(begInd, endInd, *axis[0], from, to))
206 return new EmptyBoundaryImpl();
207 return new HorizontalBoundaryInRange(*this, axis[1]->findNearestIndex(axis1_coord), begInd, endInd);
208}
209
210 BoundaryNodeSet RectangularMesh2D::createTopBoundary() const {
211 return new HorizontalBoundary(*this, axis[1]->size()-1);
212}
213
214 BoundaryNodeSet RectangularMesh2D::createBottomBoundary() const {
215 return new HorizontalBoundary(*this, 0);
216}
217
218 void RectangularMesh2D::writeXML(XMLElement& object) const {
219 object.attr("type", "rectangular2d");
220 { auto a = object.addTag("axis0"); axis[0]->writeXML(a); }
221 { auto a = object.addTag("axis1"); axis[1]->writeXML(a); }
222}
223
224 shared_ptr<RectangularMesh2D > make_rectangular_mesh(const RectangularMesh2D &to_copy) {
225 return plask::make_shared<RectangularMesh2D>(plask::make_shared<OrderedAxis>(*to_copy.axis[0]), plask::make_shared<OrderedAxis>(*to_copy.axis[1]), to_copy.getIterationOrder());
226}
227
228 static shared_ptr<Mesh> readRectangularMesh2D(XMLReader& reader) {
229 shared_ptr<MeshAxis> axis[2];
230 XMLReader::CheckTagDuplication dub_check;
231 for (int i = 0; i < 2; ++i) {
232 reader.requireTag();
233 std::string node = reader.getNodeName();
234 if (node != "axis0" && node != "axis1") throw XMLUnexpectedElementException(reader, "<axis0> or <axis1>");
235 dub_check(std::string("<mesh>"), node);
236 axis[node[4]-'0'] = readMeshAxis(reader);
237 }
238 reader.requireTagEnd();
239 return plask::make_shared<RectangularMesh2D>(std::move(axis[0]), std::move(axis[1]));
240}
241
242 static RegisterMeshReader rectangular2d_reader("rectangular2d", readRectangularMesh2D);
243
244// obsolete:
245 static shared_ptr<Mesh> readRectangularMesh2D_obsolete(XMLReader& reader) {
246 writelog(LOG_WARNING, "Mesh type \"{0}\" is obsolete (will not work in future versions of PLaSK), use \"rectangular2d\" instead.", reader.requireAttribute("type"));
247 return readRectangularMesh2D(reader);
248}
249 static RegisterMeshReader regularmesh2d_reader("regular2d", readRectangularMesh2D_obsolete);
250 static RegisterMeshReader rectilinear2d_reader("rectilinear2d", readRectangularMesh2D_obsolete);
251
252 bool RectangularMesh2D::ElementMesh::hasSameNodes(const MeshD<2> &to_compare) const {
253 if (const RectangularMesh2D::ElementMesh* c = dynamic_cast<const RectangularMesh2D::ElementMesh*>(&to_compare))
254 if (this->originalMesh == c->originalMesh) return true;
255 return RectangularMesh2D::hasSameNodes(to_compare);
256}
257
258} // namespace plask
259
260
261
262
263
264
265
266
267