PLaSK library
Loading...
Searching...
No Matches
complex_gauss_matrix.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) 2026 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 SOLVERS_ELECTRICAL_CAPACITANCE_COMPLEX_GAUSS_MATRIX_HPP
15#define SOLVERS_ELECTRICAL_CAPACITANCE_COMPLEX_GAUSS_MATRIX_HPP
16
17#include <cstddef>
18
20#include <plask/math.hpp>
21
22using plask::dcomplex;
23
24// BLAS routine to multiply matrix by vector
25#define zgbmv F77_GLOBAL(zgbmv, ZGBMV)
26F77SUB zgbmv(const char& trans,
27 const int& m,
28 const int& n,
29 const int& kl,
30 const int& ku,
31 const dcomplex& alpha,
32 dcomplex* a,
33 const int& lda,
34 const dcomplex* x,
35 int incx,
36 const dcomplex& beta,
37 dcomplex* y,
38 int incy);
39
40// LAPACK routines to solve set of linear equations
41#define zgbtrf F77_GLOBAL(zgbtrf, DGBTRF)
42F77SUB zgbtrf(const int& m, const int& n, const int& kl, const int& ku, dcomplex* ab, const int& ldab, int* ipiv, int& info);
43
44#define zgbtrs F77_GLOBAL(zgbtrs, DGBTRS)
45F77SUB zgbtrs(const char& trans,
46 const int& n,
47 const int& kl,
48 const int& ku,
49 const int& nrhs,
50 dcomplex* ab,
51 const int& ldab,
52 int* ipiv,
53 dcomplex* b,
54 const int& ldb,
55 int& info);
56
57namespace plask { namespace electrical { namespace capacitance {
58
63struct ZgbMatrix : BandMatrix<dcomplex> {
64 const size_t shift;
65
67
73 ZgbMatrix(const Solver* solver, size_t rank, size_t band)
74 : BandMatrix<dcomplex>(solver, rank, band, ((3 * band + 1 + (15 / sizeof(double))) & ~size_t(15 / sizeof(double))) - 1),
75 shift(2 * band) {}
76
77 ZgbMatrix(const ZgbMatrix&) = delete;
78
79 size_t index(size_t r, size_t c) {
80 assert(r < rank && c < rank);
81 if (r < c) {
82 assert(c - r <= kd);
83 // AB(kl+ku+1+i-j,j) = A(i,j)
84 return shift + r + ld * c;
85 } else {
86 assert(r - c <= kd);
87 return shift + c + ld * r;
88 }
89 }
90
91 dcomplex& operator()(size_t r, size_t c) override { return data[index(r, c)]; }
92
93 void factorize() override {
94 solver->writelog(LOG_DETAIL, "Factorizing system");
95
96 int info = 0;
98
99 mirror();
100
101 // Factorize matrix
102 zgbtrf(int(rank), int(rank), int(kd), int(kd), data, int(ld + 1), ipiv.get(), info);
103 if (info < 0) {
104 throw CriticalException("{0}: Argument {1} of `zgbtrf` has illegal value", solver->getId(), -info);
105 } else if (info > 0) {
106 throw ComputationError(solver->getId(), "matrix is singular (at {0})", info);
107 }
108 }
109
111 solver->writelog(LOG_DETAIL, "Solving matrix system");
112
113 int info = 0;
114 zgbtrs('N', int(rank), int(kd), int(kd), 1, data, int(ld + 1), ipiv.get(), B.data(), int(B.size()), info);
115 if (info < 0) throw CriticalException("{0}: Argument {1} of `zgbtrs` has illegal value", solver->getId(), -info);
116
117 std::swap(B, X);
118 }
119
126 mirror();
127 zgbmv('N', int(rank), int(rank), int(kd), int(kd), 1.0, data, int(ld) + 1, vector.data(), 1, 0.0, result.data(), 1);
128 }
129
136 mirror();
137 zgbmv('N', int(rank), int(rank), int(kd), int(kd), 1.0, data, int(ld) + 1, vector.data(), 1, 1.0, result.data(), 1);
138 }
139
140 private:
142 void mirror() {
143 for (size_t i = 0; i < rank; ++i) {
144 size_t ldi = shift + (ld + 1) * i;
145 size_t knd = min(kd, rank - 1 - i);
146 for (size_t j = 1; j <= knd; ++j) data[ldi + j] = data[ldi + ld * j];
147 }
148 }
149};
150
151}}} // namespace plask::electrical::capacitance
152
153#endif // PLASK_COMMON_FEM_GAUSS_MATRIX_H