PLaSK library
Loading...
Searching...
No Matches
fem_solver.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) 2023 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_COMMON_FEM_FEM_SOLVER_HPP
15#define PLASK_COMMON_FEM_FEM_SOLVER_HPP
16
17#include <plask/plask.hpp>
18#include "cholesky_matrix.hpp"
19#include "gauss_matrix.hpp"
20#include "iterative_matrix.hpp"
21
22namespace plask {
23
30
31template <typename SpaceT, typename MeshT> struct FemSolverWithMesh : public SolverWithMesh<SpaceT, MeshT> {
33
35
36 FemSolverWithMesh(const std::string& name = "") : SolverWithMesh<SpaceT, MeshT>(name) {}
37
38 bool parseFemConfiguration(XMLReader& reader, Manager& manager) {
39 if (reader.getNodeName() == "matrix") {
40 algorithm = reader.enumAttribute<FemMatrixAlgorithm>("algorithm")
41 .value("cholesky", ALGORITHM_CHOLESKY)
42 .value("gauss", ALGORITHM_GAUSS)
43 .value("iterative", ALGORITHM_ITERATIVE)
44 .get(algorithm);
45
46 if (reader.requireTagOrEnd("iterative")) {
95 iter_params.maxit = reader.getAttribute<int>("maxit", iter_params.maxit);
96 iter_params.maxerr = reader.getAttribute<double>("maxerr", iter_params.maxerr);
97 iter_params.nfact = reader.getAttribute<int>("nfact", iter_params.nfact);
98 iter_params.omega = reader.getAttribute<double>("omega", iter_params.omega);
99 iter_params.ndeg = reader.getAttribute<int>("ndeg", iter_params.ndeg);
100 iter_params.lvfill = reader.getAttribute<int>("lvfill", iter_params.lvfill);
101 iter_params.ltrunc = reader.getAttribute<int>("ltrunc", iter_params.ltrunc);
102 iter_params.ns1 = reader.getAttribute<int>("nsave", iter_params.ns1);
103 iter_params.ns2 = reader.getAttribute<int>("nrestart", iter_params.ns2);
104 reader.requireTagEnd(); // </iterative>
105 reader.requireTagEnd(); // </matrix>
106 }
107
108 return true;
109 }
110 return false;
111 }
112
114};
115
116template <typename SpaceT, typename MeshT> inline FemMatrix* FemSolverWithMesh<SpaceT, MeshT>::getMatrix() {
117 switch (algorithm) {
118 case ALGORITHM_CHOLESKY: return new DpbMatrix(this, this->mesh->size(), this->mesh->minorAxis()->size() + 1);
119 case ALGORITHM_GAUSS: return new DgbMatrix(this, this->mesh->size(), this->mesh->minorAxis()->size() + 1);
120 case ALGORITHM_ITERATIVE: return new SparseBandMatrix(this, this->mesh->size(), this->mesh->minorAxis()->size());
121 }
122 return nullptr;
123}
124
126 size_t band = this->mesh->minorAxis()->size() * (this->mesh->mediumAxis()->size() + 1) + 1;
127 switch (algorithm) {
128 case ALGORITHM_CHOLESKY: return new DpbMatrix(this, this->mesh->size(), band);
129 case ALGORITHM_GAUSS: return new DgbMatrix(this, this->mesh->size(), band);
131 return new SparseBandMatrix(this, this->mesh->size(), mesh->mediumAxis()->size() * mesh->minorAxis()->size(),
132 mesh->minorAxis()->size());
133 }
134 return nullptr;
135}
136
138
144
145template <typename SpaceT, typename MeshT> struct FemSolverWithMaskedMesh : public FemSolverWithMesh<SpaceT, MeshT> {
146 static_assert(std::is_base_of<RectangularMesh<MeshT::DIM>, MeshT>::value,
147 "FemSolverWithMaskedMesh only works with RectangularMesh");
148
149 FemSolverWithMaskedMesh(const std::string& name = "") : FemSolverWithMesh<SpaceT, MeshT>(name) {}
150
151 protected:
154
155 public:
160 empty_elements = val;
161 this->invalidate();
162 }
163
164 bool parseFemConfiguration(XMLReader& reader, Manager& manager) {
165 if (reader.getNodeName() == "mesh") {
166 if (reader.hasAttribute("include-empty")) {
167 this->writelog(LOG_WARNING, this->getId(), "Attribute 'include-empty' is deprecated, use 'empty-elements' instead");
168 empty_elements = reader.requireAttribute<bool>("include-empty") ? EMPTY_ELEMENTS_INCLUDED : EMPTY_ELEMENTS_EXCLUDED;
169 }
170 empty_elements = reader.enumAttribute<EmptyElementsHandling>("empty-elements")
171 .value("default", EMPTY_ELEMENTS_DEFAULT)
172 .value("exclude", EMPTY_ELEMENTS_EXCLUDED)
173 .value("include", EMPTY_ELEMENTS_INCLUDED)
174 .value("excluded", EMPTY_ELEMENTS_EXCLUDED)
175 .value("included", EMPTY_ELEMENTS_INCLUDED)
176 .get(empty_elements);
177 return false;
178 }
180 }
181
184 (this->algorithm == ALGORITHM_ITERATIVE && empty_elements == EMPTY_ELEMENTS_DEFAULT)) {
185 maskedMesh->selectAll(*this->mesh);
186 } else {
187 maskedMesh->reset(*this->mesh, *this->geometry, ~plask::Material::EMPTY);
188 }
189 }
190
192
194};
195
196template <typename SpaceT, typename MeshT> inline FemMatrix* FemSolverWithMaskedMesh<SpaceT, MeshT>::getMatrix() {
197 size_t band;
198 if (empty_elements == EMPTY_ELEMENTS_INCLUDED || this->algorithm == ALGORITHM_ITERATIVE) {
199 band = this->mesh->minorAxis()->size() + 1;
200 } else {
201 band = 0;
202 for (auto element : this->maskedMesh->elements()) {
203 size_t span = element.getUpUpIndex() - element.getLoLoIndex();
204 if (span > band) band = span;
205 }
206 }
207 switch (this->algorithm) {
208 case ALGORITHM_CHOLESKY: return new DpbMatrix(this, this->maskedMesh->size(), band);
209 case ALGORITHM_GAUSS: return new DgbMatrix(this, this->maskedMesh->size(), band);
211 if (empty_elements != EMPTY_ELEMENTS_EXCLUDED)
212 return new SparseBandMatrix(this, this->maskedMesh->size(), this->mesh->minorAxis()->size());
213 else
214 return new SparseFreeMatrix(this, this->maskedMesh->size(), this->maskedMesh->elements().size() * 10);
215 }
216 return nullptr;
217}
218
220 size_t band;
221 if (empty_elements || algorithm == ALGORITHM_ITERATIVE) {
222 band = this->mesh->minorAxis()->size() * (this->mesh->mediumAxis()->size() + 1) + 1;
223 } else {
224 band = 0;
225 for (auto element : this->maskedMesh->elements()) {
226 size_t span = element.getUpUpUpIndex() - element.getLoLoLoIndex();
227 if (span > band) band = span;
228 }
229 }
230 switch (algorithm) {
231 case ALGORITHM_CHOLESKY: return new DpbMatrix(this, this->maskedMesh->size(), band);
232 case ALGORITHM_GAUSS: return new DgbMatrix(this, this->maskedMesh->size(), band);
234 if (empty_elements != EMPTY_ELEMENTS_EXCLUDED)
235 return new SparseBandMatrix(this, this->maskedMesh->size(), mesh->mediumAxis()->size() * mesh->minorAxis()->size(),
236 mesh->minorAxis()->size());
237 else
238 return new SparseFreeMatrix(this, this->maskedMesh->size(), this->maskedMesh->elements().size() * 36);
239 }
240 return nullptr;
241}
242
243} // namespace plask
244
245#endif