|
14 | 14 |
|
15 | 15 | namespace module_tddft |
16 | 16 | { |
| 17 | +//------------------------ Utility function ------------------------// |
| 18 | +#ifdef __MPI |
| 19 | +inline int globalIndex(int localindex, int nblk, int nprocs, int myproc) |
| 20 | +{ |
| 21 | + int iblock, gIndex; |
| 22 | + iblock = localindex / nblk; |
| 23 | + gIndex = (iblock * nprocs + myproc) * nblk + localindex % nblk; |
| 24 | + return gIndex; |
| 25 | +} |
| 26 | +#endif // __MPI |
| 27 | + |
| 28 | +// Auxiliary function: process non-complex types, return value 1.0 |
| 29 | +template <typename T> |
| 30 | +inline T init_value(typename std::enable_if<!std::is_same<T, std::complex<float>>::value |
| 31 | + && !std::is_same<T, std::complex<double>>::value>::type* = nullptr) |
| 32 | +{ |
| 33 | + return T(1.0); |
| 34 | +} |
| 35 | + |
| 36 | +// Auxiliary function: process complex types, return value 1.0 + 0.0i |
| 37 | +template <typename T> |
| 38 | +inline T init_value(typename std::enable_if<std::is_same<T, std::complex<float>>::value |
| 39 | + || std::is_same<T, std::complex<double>>::value>::type* = nullptr) |
| 40 | +{ |
| 41 | + return T(1.0, 0.0); |
| 42 | +} |
| 43 | + |
| 44 | +// Create an identity matrix of size n×n |
| 45 | +template <typename T> |
| 46 | +ct::Tensor create_identity_matrix(const int n, ct::DeviceType device = ct::DeviceType::CpuDevice) |
| 47 | +{ |
| 48 | + // Choose the data type of the Tensor |
| 49 | + ct::DataType data_type; |
| 50 | + if (std::is_same<T, float>::value) |
| 51 | + { |
| 52 | + data_type = ct::DataType::DT_FLOAT; |
| 53 | + } |
| 54 | + else if (std::is_same<T, double>::value) |
| 55 | + { |
| 56 | + data_type = ct::DataType::DT_DOUBLE; |
| 57 | + } |
| 58 | + else if (std::is_same<T, std::complex<float>>::value) |
| 59 | + { |
| 60 | + data_type = ct::DataType::DT_COMPLEX; |
| 61 | + } |
| 62 | + else if (std::is_same<T, std::complex<double>>::value) |
| 63 | + { |
| 64 | + data_type = ct::DataType::DT_COMPLEX_DOUBLE; |
| 65 | + } |
| 66 | + else |
| 67 | + { |
| 68 | + static_assert(std::is_same<T, float>::value || std::is_same<T, double>::value |
| 69 | + || std::is_same<T, std::complex<float>>::value |
| 70 | + || std::is_same<T, std::complex<double>>::value, |
| 71 | + "Unsupported data type!"); |
| 72 | + } |
| 73 | + |
| 74 | + ct::Tensor tensor(data_type, device, ct::TensorShape({n, n})); |
| 75 | + tensor.zero(); |
| 76 | + |
| 77 | + // Set the diagonal elements to 1 |
| 78 | + if (device == ct::DeviceType::CpuDevice) |
| 79 | + { |
| 80 | + // For CPU, we can directly access the data |
| 81 | + T* data_ptr = tensor.data<T>(); |
| 82 | + for (int i = 0; i < n; ++i) |
| 83 | + { |
| 84 | + data_ptr[i * n + i] = init_value<T>(); |
| 85 | + } |
| 86 | + } |
| 87 | + else if (device == ct::DeviceType::GpuDevice) |
| 88 | + { |
| 89 | + // For GPU, we need to use a kernel to set the diagonal elements |
| 90 | + T* data_ptr = tensor.data<T>(); |
| 91 | + for (int i = 0; i < n; ++i) |
| 92 | + { |
| 93 | + T value = init_value<T>(); |
| 94 | + ct::kernels::set_memory<T, ct::DEVICE_GPU>()(data_ptr + i * n + i, value, 1); |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + return tensor; |
| 99 | +} |
| 100 | +//------------------------ Utility function ------------------------// |
| 101 | + |
17 | 102 | class Propagator |
18 | 103 | { |
19 | 104 | public: |
|
0 commit comments