23 void ssyevd_(
char* jobz,
char* uplo,
int* n,
float* a,
int* lda,
float* w,
24 float* work,
int* lwork,
int* iwork,
int* liwork,
int* info);
25 void dsyevd_(
char* jobz,
char* uplo,
int* n,
double* a,
int* lda,
double* w,
26 double* work,
int* lwork,
int* iwork,
int* liwork,
int* info);
28 void sgesv_(
int* N,
int* NRHS,
float* A,
int* LDA,
int* IPIV,
float* B,
30 void dgesv_(
int* N,
int* NRHS,
double* A,
int* LDA,
int* IPIV,
double* B,
33 void sgemm_(
char* transa,
char* transb,
int* m,
int* n,
int* k,
float* alpha,
34 float* a,
int* lda,
float* b,
int* ldb,
float* beta,
float* c,
36 void dgemm_(
char* transa,
char* transb,
int* m,
int* n,
int* k,
double* alpha,
37 double* a,
int* lda,
double* b,
int* ldb,
double* beta,
double* c,
40 int sgetrf_(
const int* m,
const int* n,
float* a,
const int* lda,
int* lpiv,
42 int dgetrf_(
const int* m,
const int* n,
double* a,
const int* lda,
int* lpiv,
63template <std::
floating_po
int T>
64void dot_blas(std::span<const T>
A, std::array<std::size_t, 2>
Ashape,
65 std::span<const T>
B, std::array<std::size_t, 2>
Bshape,
68 static_assert(std::is_same_v<T, float>
or std::is_same_v<T, double>);
81 if constexpr (std::is_same_v<T, float>)
86 else if constexpr (std::is_same_v<T, double>)
99template <
typename U,
typename V>
100std::pair<std::vector<typename U::value_type>, std::array<std::size_t, 2>>
103 std::vector<typename U::value_type>
result(
u.size() *
v.size());
104 for (std::size_t
i = 0;
i <
u.size(); ++
i)
105 for (std::size_t
j = 0;
j <
v.size(); ++
j)
107 return {std::move(
result), {
u.size(),
v.size()}};
114template <
typename U,
typename V>
115std::array<typename U::value_type, 3>
cross(
const U&
u,
const V&
v)
119 return {
u[1] *
v[2] -
u[2] *
v[1],
u[2] *
v[0] -
u[0] *
v[2],
120 u[0] *
v[1] -
u[1] *
v[0]};
130template <std::
floating_po
int T>
131std::pair<std::vector<T>, std::vector<T>>
eigh(std::span<const T>
A,
135 std::vector<T> M(
A.begin(),
A.end());
138 std::vector<T>
w(
n, 0);
147 std::vector<T>
work(1);
148 std::vector<int>
iwork(1);
151 if constexpr (std::is_same_v<T, float>)
156 else if constexpr (std::is_same_v<T, double>)
163 throw std::runtime_error(
"Could not find workspace size for syevd.");
170 if constexpr (std::is_same_v<T, float>)
175 else if constexpr (std::is_same_v<T, double>)
181 throw std::runtime_error(
"Eigenvalue computation did not converge.");
183 return {std::move(
w), std::move(M)};
190template <std::
floating_po
int T>
191std::vector<T>
solve(md::mdspan<
const T, md::dextents<std::size_t, 2>>
A,
192 md::mdspan<
const T, md::dextents<std::size_t, 2>>
B)
195 mdex::mdarray<T, md::dextents<std::size_t, 2>, md::layout_left>
_A(
198 for (std::size_t
i = 0;
i <
A.extent(0); ++
i)
199 for (std::size_t
j = 0;
j <
A.extent(1); ++
j)
201 for (std::size_t
i = 0;
i <
B.extent(0); ++
i)
202 for (std::size_t
j = 0;
j <
B.extent(1); ++
j)
205 int N =
_A.extent(0);
207 int lda =
_A.extent(0);
208 int ldb =
_B.extent(0);
211 std::vector<int>
piv(
N);
213 if constexpr (std::is_same_v<T, float>)
215 else if constexpr (std::is_same_v<T, double>)
218 throw std::runtime_error(
"Call to dgesv failed: " + std::to_string(
info));
221 std::vector<T>
rb(
_B.extent(0) *
_B.extent(1));
222 md::mdspan<T, md::dextents<std::size_t, 2>>
r(
rb.data(),
_B.extents());
223 for (std::size_t
i = 0;
i <
_B.extent(0); ++
i)
224 for (std::size_t
j = 0;
j <
_B.extent(1); ++
j)
233template <std::
floating_po
int T>
237 mdex::mdarray<T, md::dextents<std::size_t, 2>, md::layout_left>
_A(
239 for (std::size_t
i = 0;
i <
A.extent(0); ++
i)
240 for (std::size_t
j = 0;
j <
A.extent(1); ++
j)
243 std::vector<T>
B(
A.extent(1), 1);
244 int N =
_A.extent(0);
246 int lda =
_A.extent(0);
250 std::vector<int>
piv(
N);
252 if constexpr (std::is_same_v<T, float>)
254 else if constexpr (std::is_same_v<T, double>)
259 throw std::runtime_error(
"dgesv failed due to invalid value: "
260 + std::to_string(
info));
273template <std::
floating_po
int T>
274std::vector<std::size_t>
277 std::size_t dim =
A.second[0];
284 if constexpr (std::is_same_v<T, float>)
286 else if constexpr (std::is_same_v<T, double>)
291 throw std::runtime_error(
"LU decomposition failed: "
292 + std::to_string(
info));
295 std::vector<std::size_t>
perm(dim);
296 for (std::size_t
i = 0;
i < dim; ++
i)
309template <
typename U,
typename V,
typename W>
311 typename std::decay_t<U>::value_type
alpha = 1,
312 typename std::decay_t<U>::value_type
beta = 0)
314 using T =
typename std::decay_t<U>::value_type;
319 if (
A.extent(0) *
B.extent(1) *
A.extent(1) < 256)
321 for (std::size_t
i = 0;
i <
A.extent(0); ++
i)
323 for (std::size_t
j = 0;
j <
B.extent(1); ++
j)
328 for (std::size_t
k = 0;
k <
A.extent(1); ++
k)
336 static_assert(std::is_same_v<typename std::decay_t<U>::layout_type,
338 static_assert(std::is_same_v<typename std::decay_t<V>::layout_type,
340 static_assert(std::is_same_v<typename std::decay_t<W>::layout_type,
342 static_assert(std::is_same_v<typename std::decay_t<V>::value_type,
T>);
343 static_assert(std::is_same_v<typename std::decay_t<W>::value_type,
T>);
345 std::span(
A.data_handle(),
A.size()), {A.extent(0), A.extent(1)},
346 std::span(
B.data_handle(),
B.size()), {B.extent(0), B.extent(1)},
347 std::span(
C.data_handle(),
C.size()),
alpha,
beta);
354template <std::
floating_po
int T>
355std::vector<T>
eye(std::size_t
n)
357 std::vector<T>
I(
n *
n, 0);
358 md::mdspan<T, md::dextents<std::size_t, 2>>
Iview(
I.data(),
n,
n);
359 for (std::size_t
i = 0;
i <
n; ++
i)
368template <std::
floating_po
int T>
370 std::size_t
start = 0)
372 using mdspan2_t = md::mdspan<T, md::dextents<std::size_t, 2>>;
373 using cmdspan2_t = md::mdspan<const T, md::dextents<std::size_t, 2>>;
375 const std::size_t
ndofs = wcoeffs.extent(0);
376 const std::size_t
psize = wcoeffs.extent(1);
383 std::vector<T>
a_vec;
388 for (std::size_t
k = 0;
k <
psize; ++
k)
389 norm += wcoeffs(
i,
k) * wcoeffs(
i,
k);
392 if (
norm < 2 * std::numeric_limits<T>::epsilon())
394 throw std::runtime_error(
"Cannot orthogonalise the rows of a matrix "
395 "with incomplete row rank");
398 for (std::size_t
k = 0;
k <
psize; ++
k)
423 for (std::size_t
j = 0;
j <
nrem; ++
j)
424 for (std::size_t
k = 0;
k <
psize; ++
k)
A finite element.
Definition finite-element.h:138
Mathematical functions.
Definition math.h:51
bool is_singular(md::mdspan< const T, md::dextents< std::size_t, 2 > > A)
Check if A is a singular matrix.
Definition math.h:234
std::array< typename U::value_type, 3 > cross(const U &u, const V &v)
Compute the cross product u x v.
Definition math.h:115
std::vector< std::size_t > transpose_lu(std::pair< std::vector< T >, std::array< std::size_t, 2 > > &A)
Compute the LU decomposition of the transpose of a square matrix A.
Definition math.h:275
void orthogonalise(md::mdspan< T, md::dextents< std::size_t, 2 > > wcoeffs, std::size_t start=0)
Orthonormalise the rows of a matrix (in place).
Definition math.h:369
std::vector< T > solve(md::mdspan< const T, md::dextents< std::size_t, 2 > > A, md::mdspan< const T, md::dextents< std::size_t, 2 > > B)
Solve A X = B.
Definition math.h:191
void dot(const U &A, const V &B, W &&C, typename std::decay_t< U >::value_type alpha=1, typename std::decay_t< U >::value_type beta=0)
Compute C = alpha A * B + beta C.
Definition math.h:310
std::pair< std::vector< T >, std::vector< T > > eigh(std::span< const T > A, std::size_t n)
Compute the eigenvalues and eigenvectors of a square symmetric matrix A.
Definition math.h:131
std::vector< T > eye(std::size_t n)
Build an identity matrix.
Definition math.h:355
std::pair< std::vector< typename U::value_type >, std::array< std::size_t, 2 > > outer(const U &u, const V &v)
Compute the outer product of vectors u and v.
Definition math.h:101