|
11 | 11 | #include <convert.h> |
12 | 12 | #include <clover_field.h> |
13 | 13 | #include <complex_quda.h> |
| 14 | +#include <index_helper.cuh> |
14 | 15 | #include <quda_matrix.h> |
15 | 16 | #include <color_spinor.h> |
16 | 17 | #include <load_store.h> |
@@ -614,7 +615,11 @@ namespace quda { |
614 | 615 | errorQuda("Accessor reconstruct = %d does not match field reconstruct %d", enable_reconstruct, |
615 | 616 | clover.Reconstruct()); |
616 | 617 | if (clover.max_element(is_inverse) == 0.0 && isFixed<Float>::value) |
| 618 | +#ifdef BUILD_OPENQCD_INTERFACE |
| 619 | + warningQuda("%p max_element(%d) appears unset", &clover, is_inverse); /* ignore if the SW-field is zero */ |
| 620 | +#else |
617 | 621 | errorQuda("%p max_element(%d) appears unset", &clover, is_inverse); |
| 622 | +#endif |
618 | 623 | if (clover.Diagonal() == 0.0 && clover.Reconstruct()) errorQuda("%p diagonal appears unset", &clover); |
619 | 624 | this->clover = clover_ ? clover_ : clover.data<Float *>(is_inverse); |
620 | 625 | } |
@@ -983,6 +988,97 @@ namespace quda { |
983 | 988 | size_t Bytes() const { return length*sizeof(Float); } |
984 | 989 | }; |
985 | 990 |
|
| 991 | + /** |
| 992 | + * OpenQCD ordering for clover fields |
| 993 | + */ |
| 994 | + template <typename Float, int length = 72> struct OpenQCDOrder { |
| 995 | + static constexpr bool enable_reconstruct = false; |
| 996 | + typedef typename mapper<Float>::type RegType; |
| 997 | + Float *clover; |
| 998 | + const int volumeCB; |
| 999 | + const QudaTwistFlavorType twist_flavor; |
| 1000 | + const Float mu2; |
| 1001 | + const Float epsilon2; |
| 1002 | + const double coeff; |
| 1003 | + const double csw; |
| 1004 | + const double kappa; |
| 1005 | + const int dim[4]; // xyzt convention |
| 1006 | + const int L[4]; // txyz convention |
| 1007 | + |
| 1008 | + OpenQCDOrder(const CloverField &clover, bool inverse, Float *clover_ = nullptr, void * = nullptr) : |
| 1009 | + volumeCB(clover.Stride()), |
| 1010 | + twist_flavor(clover.TwistFlavor()), |
| 1011 | + mu2(clover.Mu2()), |
| 1012 | + epsilon2(clover.Epsilon2()), |
| 1013 | + coeff(clover.Coeff()), |
| 1014 | + csw(clover.Csw()), |
| 1015 | + kappa(clover.Coeff() / clover.Csw()), |
| 1016 | + dim {clover.X()[0], clover.X()[1], clover.X()[2], clover.X()[3]}, // *local* lattice dimensions, xyzt |
| 1017 | + L {clover.X()[3], clover.X()[0], clover.X()[1], clover.X()[2]} // *local* lattice dimensions, txyz |
| 1018 | + { |
| 1019 | + if (clover.Order() != QUDA_OPENQCD_CLOVER_ORDER) { |
| 1020 | + errorQuda("Invalid clover order %d for this accessor", clover.Order()); |
| 1021 | + } |
| 1022 | + this->clover = clover_ ? clover_ : clover.data<Float *>(inverse); |
| 1023 | + if (clover.Coeff() == 0.0 || clover.Csw() == 0.0) { errorQuda("Neither coeff nor csw may be zero!"); } |
| 1024 | + } |
| 1025 | + |
| 1026 | + QudaTwistFlavorType TwistFlavor() const { return twist_flavor; } |
| 1027 | + Float Mu2() const { return mu2; } |
| 1028 | + Float Epsilon2() const { return epsilon2; } |
| 1029 | + |
| 1030 | + /** |
| 1031 | + * @brief Gets the offset in Floats from the openQCD base pointer to |
| 1032 | + * the spinor field. |
| 1033 | + * |
| 1034 | + * @param[in] x_cb Checkerboard index coming from quda |
| 1035 | + * @param[in] parity The parity coming from quda |
| 1036 | + * |
| 1037 | + * @return The offset. |
| 1038 | + */ |
| 1039 | + __device__ __host__ inline int getCloverOffset(int x_cb, int parity) const |
| 1040 | + { |
| 1041 | + int x_quda[4], x[4]; |
| 1042 | + getCoords(x_quda, x_cb, dim, parity); // x_quda contains xyzt local Carthesian corrdinates |
| 1043 | + openqcd::rotate_coords(x_quda, x); // xyzt -> txyz, x = openQCD local Carthesian lattice coordinate |
| 1044 | + return openqcd::ipt(x, L) * length; |
| 1045 | + } |
| 1046 | + |
| 1047 | + /** |
| 1048 | + * @brief Load a clover field at lattice point x_cb |
| 1049 | + * |
| 1050 | + * @param v The output clover matrix in QUDA order |
| 1051 | + * @param x_cb The checkerboarded lattice site |
| 1052 | + * @param parity The parity of the lattice site |
| 1053 | + */ |
| 1054 | + __device__ __host__ inline void load(RegType v[length], int x_cb, int parity) const |
| 1055 | + { |
| 1056 | + int sign[36] = {-1, -1, -1, -1, -1, -1, // diagonals (idx 0-5) |
| 1057 | + -1, +1, -1, +1, -1, -1, -1, -1, -1, -1, // column 0 (idx 6-15) |
| 1058 | + -1, +1, -1, -1, -1, -1, -1, -1, // column 1 (idx 16-23) |
| 1059 | + -1, -1, -1, -1, -1, -1, // column 2 (idx 24-29) |
| 1060 | + -1, +1, -1, +1, // column 3 (idx 30-33) |
| 1061 | + -1, +1}; // column 4 (idx 34-35) |
| 1062 | + int map[36] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18, 19, 24, 25, 16, 17, |
| 1063 | + 12, 13, 20, 21, 26, 27, 14, 15, 22, 23, 28, 29, 30, 31, 32, 33, 34, 35}; |
| 1064 | + const int M = length / 2; |
| 1065 | + int offset = getCloverOffset(x_cb, parity); |
| 1066 | + auto Ap = &clover[offset]; // A_+ |
| 1067 | + auto Am = &clover[offset + M]; // A_- |
| 1068 | + |
| 1069 | +#pragma unroll |
| 1070 | + for (int i = 0; i < M; i++) { |
| 1071 | + v[i] = sign[i] * (kappa * Am[map[i]] - (i < 6)); |
| 1072 | + v[M + i] = sign[i] * (kappa * Ap[map[i]] - (i < 6)); |
| 1073 | + } |
| 1074 | + } |
| 1075 | + |
| 1076 | + // FIXME implement the save routine for OpenQCD ordered fields |
| 1077 | + __device__ __host__ inline void save(RegType[length], int, int) const { } |
| 1078 | + |
| 1079 | + size_t Bytes() const { return length * sizeof(Float); } |
| 1080 | + }; |
| 1081 | + |
986 | 1082 | } // namespace clover |
987 | 1083 |
|
988 | 1084 | // Use traits to reduce the template explosion |
|
0 commit comments