StatusCode Xtbmv<T>::DoTbmv(const Layout layout, const Triangle triangle, const Transpose a_transpose, const Diagonal diagonal, const size_t n, const size_t k, const Buffer<T> &a_buffer, const size_t a_offset, const size_t a_ld, const Buffer<T> &x_buffer, const size_t x_offset, const size_t x_inc) { // Creates a copy of X: a temporary scratch buffer auto scratch_buffer = Buffer<T>(context_, n*x_inc + x_offset); try { x_buffer.CopyTo(queue_, n*x_inc + x_offset, scratch_buffer); } catch (...) { } // Continues: error-code is returned in MatVec // The data is either in the upper or lower triangle size_t is_upper = ((triangle == Triangle::kUpper && layout != Layout::kRowMajor) || (triangle == Triangle::kLower && layout == Layout::kRowMajor)); // Adds '2' to the parameter if the diagonal is unit auto parameter = (diagonal == Diagonal::kUnit) ? is_upper + 2 : is_upper; // Runs the generic matrix-vector multiplication, disabling the use of fast vectorized kernels. // The specific triangular banded matrix-accesses are implemented in the kernel guarded by the // ROUTINE_TBMV define. auto fast_kernels = false; auto status = MatVec(layout, a_transpose, n, n, static_cast<T>(1), a_buffer, a_offset, a_ld, scratch_buffer, x_offset, x_inc, static_cast<T>(0), x_buffer, x_offset, x_inc, fast_kernels, fast_kernels, parameter, false, k, 0); // Returns the proper error code (renames vector Y to X) switch(status) { case StatusCode::kInvalidVectorY: return StatusCode::kInvalidVectorX; case StatusCode::kInvalidIncrementY: return StatusCode::kInvalidIncrementX; case StatusCode::kInsufficientMemoryY: return StatusCode::kInsufficientMemoryX; default: return status; } }
void Xspmv<T>::DoSpmv(const Layout layout, const Triangle triangle, const size_t n, const T alpha, const Buffer<T> &ap_buffer, const size_t ap_offset, const Buffer<T> &x_buffer, const size_t x_offset, const size_t x_inc, const T beta, const Buffer<T> &y_buffer, const size_t y_offset, const size_t y_inc) { // The data is either in the upper or lower triangle size_t is_upper = ((triangle == Triangle::kUpper && layout != Layout::kRowMajor) || (triangle == Triangle::kLower && layout == Layout::kRowMajor)); // Runs the generic matrix-vector multiplication, disabling the use of fast vectorized kernels. // The specific symmetric packed matrix-accesses are implemented in the kernel guarded by the // ROUTINE_SPMV define. bool fast_kernels = false; MatVec(layout, Transpose::kNo, n, n, alpha, ap_buffer, ap_offset, n, x_buffer, x_offset, x_inc, beta, y_buffer, y_offset, y_inc, fast_kernels, fast_kernels, is_upper, true, 0, 0); }
PetscErrorCode FiberFieldInitLocalFiber( FiberField fibers, int numVerticies, PetscReal l0, FiberTypeID vertexType, FiberTypeID edgeType, FiberTypeID bendingEdgeType ) { int i; int flen = numVerticies; Array fiber = fibers->fiber; Vertex v0; Vertex v1; Vertex v2; PetscRandom rnd = fibers->rnd; PetscBool hitBoundary; Coor rndSphere; Coor n; Coor r; Coor s; Coor d; Coor lmin = fibers->localBounds.min; Coor lmax = fibers->localBounds.max; PetscReal NORTH_HEMISPHERE = 0.65; const PetscReal WHOLE_SPHERE = 0.0; const PetscReal DELTA = PETSC_SMALL; PetscErrorCode ierr; PetscFunctionBegin; ierr = ArraySetSize(fiber, 0); CHKERRQ(ierr); ierr = ArraySetMaxSize( fibers->verts, flen + ArrayLength(fibers->verts) ); CHKERRQ(ierr); // add small delta lmin.x += DELTA; lmin.y += DELTA; lmin.z += DELTA; lmax.x -= DELTA; lmax.y -= DELTA; lmax.z -= DELTA; ierr = PetscOptionsGetReal(0,"-fiber_bend",&NORTH_HEMISPHERE,0); CHKERRQ(ierr); // Initialize v0 anywhere in the local bbox ierr = FiberFieldAddVertex( fibers, vertexType, &v0); CHKERRQ(ierr); ierr = ArrayAppendPtr( fiber, v0); CHKERRQ(ierr); PetscRandomGetValue(rnd,&v0->X.x); // [0,1] PetscRandomGetValue(rnd,&v0->X.y); // [0,1] PetscRandomGetValue(rnd,&v0->X.z); // [0,1] // map [0, 1] to local bbox [lmin, lmax] v0->X.x = (1-v0->X.x) * lmin.x + v0->X.x * lmax.x; v0->X.y = (1-v0->X.y) * lmin.y + v0->X.y * lmax.y; v0->X.z = (1-v0->X.z) * lmin.z + v0->X.z * lmax.z; // Initialize v1 anywhere spherically from v0 ierr = FiberFieldAddVertex( fibers, vertexType, &v1); CHKERRQ(ierr); ierr = ArrayAppendPtr( fiber, v1); CHKERRQ(ierr); SphericalDistribution(rnd, WHOLE_SPHERE, &d); v1->X.x = v0->X.x + l0*d.x; v1->X.y = v0->X.y + l0*d.y; v1->X.z = v0->X.z + l0*d.z; BoundaryCheck( lmin, lmax, &v1->X, &hitBoundary ); if (hitBoundary) { ierr = FiberFieldAddEdge( fibers, v0, v1, edgeType, l0 ); CHKERRQ(ierr); PetscFunctionReturn(0); } for (i = 1; i < flen-1; i++ ) { ierr = FiberFieldAddVertex( fibers, vertexType, &v2); CHKERRQ(ierr); ierr = ArrayAppendPtr( fiber, v2); CHKERRQ(ierr); SphericalDistribution(rnd, NORTH_HEMISPHERE, &rndSphere); Rotation(v0->X,v1->X,&n,&r,&s); MatVec(&n,&r,&s,&rndSphere, &d); v2->X.x = v1->X.x + l0*d.x; v2->X.y = v1->X.y + l0*d.y; v2->X.z = v1->X.z + l0*d.z; BoundaryCheck( lmin, lmax, &v2->X, &hitBoundary ); if (hitBoundary) { break; } v0 = v1; v1 = v2; } flen = ArrayLength( fiber ); Vertex *v = ArrayGetData( fiber ); // Link fiber edges: v_i -- v_i+1 for (i = 0; i < flen-1; i++) { ierr = FiberFieldAddEdge( fibers, v[i], v[i+1], edgeType, l0 ); CHKERRQ(ierr); } // Link bending edges: v_i-1 -- v_i+1 for (i = 1; i < flen-1; i++) { ierr = FiberFieldAddEdge( fibers, v[i-1], v[i+1], bendingEdgeType, 2*l0 ); CHKERRQ(ierr); } PetscFunctionReturn(0); }