PLaSK library

Loading...
Searching...
No Matches
ordered1d.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 "ordered1d.hpp"
15
16#include "../utils/stl.hpp"
17#include "../log/log.hpp"
18
19 namespace plask {
20
21 void OrderedAxis::sortPointsAndRemoveNonUnique(double min_dist)
22{
23 std::sort(this->points.begin(), this->points.end());
24 auto almost_equal = [min_dist](const double& x, const double& y) -> bool { return std::abs(x-y) < min_dist; };
25 this->points.erase(std::unique(this->points.begin(), this->points.end(), almost_equal), this->points.end());
26}
27
28 OrderedAxis::OrderedAxis(std::initializer_list<PointType> points, double min_dist): points(points), warn_too_close(true) {
29 sortPointsAndRemoveNonUnique(min_dist);
30}
31
32 OrderedAxis::OrderedAxis(const std::vector<PointType>& points, double min_dist): points(points), warn_too_close(true) {
33 sortPointsAndRemoveNonUnique(min_dist);
34}
35
36 OrderedAxis::OrderedAxis(std::vector<PointType>&& points, double min_dist): points(std::move(points)), warn_too_close(true) {
37 sortPointsAndRemoveNonUnique(min_dist);
38}
39
40 bool OrderedAxis::operator==(const plask::OrderedAxis& to_compare) const {
41 return points == to_compare.points;
42}
43
44 void OrderedAxis::writeXML(XMLElement &object) const {
45 object.attr("type", "ordered");
46 //object.indent();
47 for (auto x: this->points) {
48 object.writeText(x);
49 object.writeText(" ");
50 }
51 //object.writeText("\n");
52}
53
54
55
56 OrderedAxis::native_const_iterator OrderedAxis::find(double to_find) const {
57 return std::lower_bound(points.begin(), points.end(), to_find);
58}
59
60 OrderedAxis::native_const_iterator OrderedAxis::findUp(double to_find) const {
61 return std::upper_bound(points.begin(), points.end(), to_find);
62}
63
64 OrderedAxis::native_const_iterator OrderedAxis::findNearest(double to_find) const {
65 return find_nearest_binary(points.begin(), points.end(), to_find);
66}
67
68 OrderedAxis &OrderedAxis::operator=(const MeshAxis &src) {
69 bool resized = size() != src.size();
70 points.clear();
71 points.reserve(src.size());
72 for (auto i: src) points.push_back(i);
73 std::sort(points.begin(), points.end());
74 if (resized) fireResized(); else fireChanged();
75 return *this;
76}
77
78 OrderedAxis &OrderedAxis::operator=(OrderedAxis &&src) {
79 bool resized = size() != src.size();
80 this->points = std::move(src.points);
81 if (resized) fireResized(); else fireChanged();
82 return *this;
83}
84
85 OrderedAxis &OrderedAxis::operator=(const OrderedAxis &src) {
86 bool resized = size() != src.size();
87 points = src.points;
88 if (resized) fireResized(); else fireChanged();
89 return *this;
90}
91
92 bool OrderedAxis::addPoint(double new_node_cord, double min_dist) {
93 auto where = std::lower_bound(points.begin(), points.end(), new_node_cord);
94 if (where == points.end()) {
95 if (points.size() == 0 || new_node_cord - points.back() > min_dist) {
96 points.push_back(new_node_cord);
97 fireResized();
98 return true;
99 }
100 } else {
101 if (*where - new_node_cord > min_dist && (where == points.begin() || new_node_cord - *(where-1) > min_dist)) {
102 points.insert(where, new_node_cord);
103 fireResized();
104 return true;
105 }
106 }
107 if (warn_too_close) writelog(LOG_WARNING, "Points in ordered mesh too close, skipping point at {0}", new_node_cord);
108 return false;
109}
110
111 void OrderedAxis::addPointsLinear(double first, double last, std::size_t points_count) {
112 if (points_count == 0) return;
113 --points_count;
114 const double len = last - first;
115 auto get_el = [&](std::size_t i) { return first + double(i) * len / double(points_count); };
116 addOrderedPoints(makeFunctorIndexedIterator(get_el, 0), makeFunctorIndexedIterator(get_el, points_count+1), points_count+1);
117 fireResized();
118}
119
120 void OrderedAxis::removePoint(std::size_t index) {
121 points.erase(points.begin() + index);
122 fireResized();
123}
124
125 void OrderedAxis::removePoints(std::size_t start, std::size_t stop) {
126 points.erase(points.begin() + start, points.begin() + stop);
127 fireResized();
128}
129
130 void OrderedAxis::removePoints(std::size_t start, std::size_t stop, std::ptrdiff_t step) {
131 if (step > 0) {
132 if (stop < start) return;
133 if (step == 1)
134 points.erase(points.begin() + start, points.begin() + stop);
135 else
136 for (std::size_t i = start; i < stop; i += step) {
137 points.erase(points.begin() + (i--));
138 stop--;
139 }
140 } else
141 if (stop > start) return;
142 if (step == -1)
143 points.erase(points.begin() + stop, points.begin() + start);
144 else if (step == 0)
145 throw Exception("orderedAxis: step cannot be zero");
146 else
147 for (std::size_t i = start; i > stop; i += step)
148 points.erase(points.begin() + i);
149 fireResized();
150}
151
152
153 void OrderedAxis::clear() {
154 points.clear();
155 fireResized();
156}
157
158shared_ptr<MeshAxis> OrderedAxis::clone() const {
159 return plask::make_shared<OrderedAxis>(*this);
160}
161
162 shared_ptr<OrderedMesh1D> readRectilinearMeshAxis(XMLReader& reader) {
163 auto result = plask::make_shared<OrderedMesh1D>();
164 if (reader.hasAttribute("start")) {
165 double start = reader.requireAttribute<double>("start");
166 double stop = reader.requireAttribute<double>("stop");
167 size_t count = reader.requireAttribute<size_t>("num");
168 result->addPointsLinear(start, stop, count);
169 reader.requireTagEnd();
170 } else {
171 std::string data = reader.requireTextInCurrentTag();
172 for (auto point: boost::tokenizer<boost::char_separator<char>>(data, boost::char_separator<char>(" ,;\t\n"))) {
173 try {
174 double val = boost::lexical_cast<double>(point);
175 result->addPoint(val);
176 } catch (boost::bad_lexical_cast&) {
177 throw XMLException(reader, format("value '{0}' cannot be converted to float", point));
178 }
179 }
180 }
181 return result;
182}
183
184 shared_ptr<OrderedMesh1D> readOrderedMesh1D(XMLReader& reader) {
185 reader.requireTag("axis");
186 auto result = readRectilinearMeshAxis(reader);
187 reader.requireTagEnd();
188 return result;
189}
190
191 static RegisterMeshReader rectilinearmesh_reader("ordered", readOrderedMesh1D);
192
193
194// obsolete:
195
196 shared_ptr<OrderedMesh1D> readOrderedMesh1D_obsolete(XMLReader& reader) {
197 writelog(LOG_WARNING, "Mesh type \"{0}\" is obsolete, use \"ordered\" instead.", reader.requireAttribute("type"));
198 return readOrderedMesh1D(reader);
199}
200 RegisterMeshReader rectilinearmesh1d_reader("rectilinear1d", readOrderedMesh1D_obsolete);
201
202
203
204
205} // namespace plask