// this actually applies the preconditioned dslash, e.g., D_ee^{-1} D_eo or D_oo^{-1} D_oe void wil_dslash(void *out, void **gauge, void *in, int oddBit, int daggerBit, QudaPrecision precision, QudaGaugeParam &gauge_param) { #ifndef MULTI_GPU if (precision == QUDA_DOUBLE_PRECISION) dslashReference((double*)out, (double**)gauge, (double*)in, oddBit, daggerBit); else dslashReference((float*)out, (float**)gauge, (float*)in, oddBit, daggerBit); #else GaugeFieldParam gauge_field_param(gauge, gauge_param); cpuGaugeField cpu(gauge_field_param); cpu.exchangeGhost(); void **ghostGauge = (void**)cpu.Ghost(); // Get spinor ghost fields // First wrap the input spinor into a ColorSpinorField ColorSpinorParam csParam; csParam.v = in; csParam.fieldLocation = QUDA_CPU_FIELD_LOCATION; csParam.nColor = 3; csParam.nSpin = 4; csParam.nDim = 4; for (int d=0; d<4; d++) csParam.x[d] = Z[d]; csParam.precision = precision; csParam.pad = 0; csParam.siteSubset = QUDA_PARITY_SITE_SUBSET; csParam.x[0] /= 2; csParam.siteOrder = QUDA_EVEN_ODD_SITE_ORDER; csParam.fieldOrder = QUDA_SPACE_SPIN_COLOR_FIELD_ORDER; csParam.gammaBasis = QUDA_DEGRAND_ROSSI_GAMMA_BASIS; csParam.create = QUDA_REFERENCE_FIELD_CREATE; cpuColorSpinorField inField(csParam); { // Now do the exchange QudaParity otherParity = QUDA_INVALID_PARITY; if (oddBit == QUDA_EVEN_PARITY) otherParity = QUDA_ODD_PARITY; else if (oddBit == QUDA_ODD_PARITY) otherParity = QUDA_EVEN_PARITY; else errorQuda("ERROR: full parity not supported in function %s", __FUNCTION__); int nFace = 1; FaceBuffer faceBuf(Z, 4, mySpinorSiteSize, nFace, precision); faceBuf.exchangeCpuSpinor(inField, otherParity, daggerBit); } void** fwd_nbr_spinor = inField.fwdGhostFaceBuffer; void** back_nbr_spinor = inField.backGhostFaceBuffer; if (precision == QUDA_DOUBLE_PRECISION) { dslashReference((double*)out, (double**)gauge, (double**)ghostGauge, (double*)in, (double**)fwd_nbr_spinor, (double**)back_nbr_spinor, oddBit, daggerBit); } else{ dslashReference((float*)out, (float**)gauge, (float**)ghostGauge, (float*)in, (float**)fwd_nbr_spinor, (float**)back_nbr_spinor, oddBit, daggerBit); } #endif }
// Apply the even-odd preconditioned Dirac operator void MatPCDag(float *outEven, float **gauge, float *inEven, float kappa) { float *tmpOdd = (float*)malloc(Nh*spinorSiteSize*sizeof(float)); // full dslash operator dslashReference(tmpOdd, gauge, inEven, 1, 1); dslashReference(outEven, gauge, tmpOdd, 0, 1); float kappa2 = -kappa*kappa; xpay(inEven, kappa2, outEven, Nh*spinorSiteSize); free(tmpOdd); }
void MatDag(float *out, float **gauge, float *in, float kappa) { float *inEven = in; float *inOdd = in + Nh*spinorSiteSize; float *outEven = out; float *outOdd = out + Nh*spinorSiteSize; // full dslash operator dslashReference(outOdd, gauge, inEven, 1, 1); dslashReference(outEven, gauge, inOdd, 0, 1); // lastly apply the kappa term xpay(in, -kappa, out, N*spinorSiteSize); }
void cgTest() { float mass = 0.01; float kappa = 1.0 / (2.0*(4 + mass)); float *gauge[4]; for (int dir = 0; dir < 4; dir++) { gauge[dir] = (float*)malloc(N*gaugeSiteSize*sizeof(float)); } //constructGaugeField(gauge); constructUnitGaugeField(gauge); float *spinorIn = (float*)malloc(N*spinorSiteSize*sizeof(float)); float *spinorOut = (float*)malloc(N*spinorSiteSize*sizeof(float)); #ifdef EVEN_ODD float *source = (float *)malloc(Nh*spinorSiteSize*sizeof(float)); float *tmp = (float *)malloc(Nh*spinorSiteSize*sizeof(float)); #else float *source = (float *)malloc(N*spinorSiteSize*sizeof(float)); #endif int i0 = 0; int s0 = 0; int c0 = 0; constructPointSpinorField(spinorIn, i0, s0, c0); //constructSpinorField(spinorIn); // Prepare the source term ax(2*kappa, spinorIn, N*spinorSiteSize); // see output element // Mat(source, gauge, spinorIn, kappa); // printSpinorElement(source, 0); #ifdef EVEN_ODD float *spinorInOdd = spinorIn + Nh*spinorSiteSize; dslashReference(tmp, gauge, spinorInOdd, 0, 0); xpay(spinorIn, kappa, tmp, Nh*spinorSiteSize); MatPCDag(source, gauge, tmp, kappa); #else MatDag(source, gauge, spinorIn, kappa); #endif cgCuda(spinorOut, gauge, source, kappa, 1e-7); // cg_reference(spinorOut, gauge, source, kappa, 1e-7); // Reconstruct the full inverse #ifdef EVEN_ODD float *spinorOutOdd = spinorOut + Nh*spinorSiteSize; dslashReference(spinorOutOdd, gauge, spinorOut, 1, 0); xpay(spinorInOdd, kappa, spinorOutOdd, Nh*spinorSiteSize); #endif printf("Result norm = %e\n", norm(spinorOut, N*spinorSiteSize)); // release memory for (int dir = 0; dir < 4; dir++) free(gauge[dir]); free(source); #ifdef EVEN_ODD free(tmp); #endif free(spinorIn); free(spinorOut); }