votca 2026-dev
Loading...
Searching...
No Matches
symmetric_tiles.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2026 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20// Standard includes
21#include <algorithm>
22#include <cstring>
23#include <stdexcept>
24
25// Local VOTCA includes
27
28namespace votca {
29namespace xtp {
30
32 if (n <= 0) {
33 return 0.0;
34 }
35 const Index nt = (n + tile - 1) / tile;
36 const double last = double(n - (nt - 1) * tile);
37 const double full = double(tile);
38 // full tiles of the strict lower triangle of the first nt-1 tile rows,
39 // the last tile row, and the diagonal tiles
40 const double nfull_lower = double(nt - 1) * double(nt - 2) / 2.0;
41 double elements = nfull_lower * full * full;
42 elements += double(nt - 1) * last * full; // last tile row
43 elements += double(nt - 1) * full * full + last * last; // diagonal tiles
44 return 8.0 * elements;
45}
46
48 Release();
49 if (tile <= 0) {
50 throw std::runtime_error("SymmetricTiles: tile size must be positive");
51 }
52 n_ = n;
53 tile_ = tile;
54 kind_ = kind;
55 ntiles_ = (n + tile - 1) / tile;
56 offset_.assign(std::size_t(ntiles_ * (ntiles_ + 1) / 2), 0);
57 std::size_t total = 0;
58 for (Index I = 0; I < ntiles_; ++I) {
59 for (Index J = 0; J <= I; ++J) {
60 offset_[std::size_t(I * (I + 1) / 2 + J)] = total;
61 total += std::size_t(TileSize(I) * TileSize(J));
62 }
63 }
64 // not value-initialised: the build writes every element (in parallel, so
65 // the pages are spread over the threads that use them)
66 data_.reset(new double[total]);
67}
68
70 data_.reset();
71 offset_.clear();
72 n_ = 0;
73 ntiles_ = 0;
74 built_ = false;
75}
76
77void SymmetricTiles::SetRowLower(Index r, const double* values) {
78 const Index I = r / tile_;
79 const Index local = r - TileStart(I);
80 for (Index J = 0; J <= I; ++J) {
81 const Index j0 = TileStart(J);
82 const Index len = (J < I) ? TileSize(J) : local + 1;
83 double* dest = TileData(I, J) + local * TileSize(J);
84 std::memcpy(dest, values + j0, std::size_t(len) * sizeof(double));
85 }
86}
87
89#pragma omp parallel for schedule(dynamic)
90 for (Index I = 0; I < ntiles_; ++I) {
92 T.triangularView<Eigen::StrictlyUpper>() = T.transpose();
93 }
94 built_ = true;
95}
96
97Eigen::MatrixXd SymmetricTiles::Multiply(const Eigen::MatrixXd& X,
98 double factor) const {
99 if (!built_) {
100 throw std::runtime_error("SymmetricTiles::Multiply: matrix not built");
101 }
102 if (X.rows() != n_) {
103 throw std::runtime_error("SymmetricTiles::Multiply: size mismatch");
104 }
105 Eigen::MatrixXd Y(n_, X.cols());
106 // each task owns one row block of Y: the tiles of tile row I and, for the
107 // part above the diagonal, the transposes of the tiles of tile column I
108#pragma omp parallel for schedule(dynamic)
109 for (Index I = 0; I < ntiles_; ++I) {
110 const Index i0 = TileStart(I);
111 const Index bi = TileSize(I);
112 auto Yi = Y.middleRows(i0, bi);
113 Yi.setZero();
114 for (Index J = 0; J <= I; ++J) {
115 ConstRowMajorMap T(TileData(I, J), bi, TileSize(J));
116 Yi.noalias() += T * X.middleRows(TileStart(J), TileSize(J));
117 }
118 for (Index J = I + 1; J < ntiles_; ++J) {
119 ConstRowMajorMap T(TileData(J, I), TileSize(J), bi);
120 Yi.noalias() += T.transpose() * X.middleRows(TileStart(J), TileSize(J));
121 }
122 if (factor != 1.0) {
123 Yi *= factor;
124 }
125 }
126 return Y;
127}
128
130 if (i < j) {
131 std::swap(i, j);
132 }
133 const Index I = i / tile_;
134 const Index J = j / tile_;
135 return TileData(I, J)[(i - TileStart(I)) * TileSize(J) + (j - TileStart(J))];
136}
137
138} // namespace xtp
139} // namespace votca
std::vector< std::size_t > offset_
void Allocate(Index n, Index kind, Index tile=DefaultTile)
Eigen::Map< const Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > > ConstRowMajorMap
Eigen::Map< Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > > RowMajorMap
double operator()(Index i, Index j) const
Element (i, j), for tests.
std::unique_ptr< double[]> data_
void FinishBuild()
Fills the upper halves of the diagonal tiles; marks the matrix built.
double * TileData(Index I, Index J) const
static double Bytes(Index n, Index tile=DefaultTile)
Bytes the tiles of an n x n matrix need.
Eigen::MatrixXd Multiply(const Eigen::MatrixXd &X, double factor=1.0) const
factor * S * X
void SetRowLower(Index r, const double *values)
Row r, columns 0..r (values[0..r]); rows may be set in parallel.
Index TileStart(Index I) const
Index TileSize(Index I) const
Charge transport classes.
Definition ERIs.h:28
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26