@@ -531,6 +531,112 @@ int CeedVectorNorm(CeedVector vec, CeedNormType norm_type, CeedScalar *norm) {
531531 return CEED_ERROR_SUCCESS ;
532532}
533533
534+ /**
535+ @brief Compute y = alpha x + y
536+
537+ @param y[in,out] target vector for sum
538+ @param alpha[in] scaling factor
539+ @param x[in] second vector, must be different than y
540+
541+ @return An error code: 0 - success, otherwise - failure
542+
543+ @ref User
544+ **/
545+ int CeedVectorAXPY (CeedVector y , CeedScalar alpha , CeedVector x ) {
546+ int ierr ;
547+ CeedScalar * y_array ;
548+ CeedScalar const * x_array ;
549+ CeedInt n_x , n_y ;
550+
551+ ierr = CeedVectorGetLength (y , & n_y ); CeedChk (ierr );
552+ ierr = CeedVectorGetLength (x , & n_x ); CeedChk (ierr );
553+ if (n_x != n_y )
554+ // LCOV_EXCL_START
555+ return CeedError (y -> ceed , CEED_ERROR_UNSUPPORTED ,
556+ "Cannot add vector of different lengths" );
557+ // LCOV_EXCL_STOP
558+ if (x == y )
559+ // LCOV_EXCL_START
560+ return CeedError (y -> ceed , CEED_ERROR_UNSUPPORTED ,
561+ "Cannot use same vector for x and y in CeedVectorAXPY" );
562+ // LCOV_EXCL_STOP
563+
564+ // Backend implementation
565+ if (y -> AXPY )
566+ return y -> AXPY (y , alpha , x );
567+
568+ // Default implementation
569+ ierr = CeedVectorGetArray (y , CEED_MEM_HOST , & y_array ); CeedChk (ierr );
570+ ierr = CeedVectorGetArrayRead (x , CEED_MEM_HOST , & x_array ); CeedChk (ierr );
571+
572+ for (CeedInt i = 0 ; i < n_y ; i ++ )
573+ y_array [i ] += alpha * x_array [i ];
574+
575+ ierr = CeedVectorRestoreArray (y , & y_array ); CeedChk (ierr );
576+ ierr = CeedVectorRestoreArrayRead (x , & x_array ); CeedChk (ierr );
577+
578+ return CEED_ERROR_SUCCESS ;
579+ }
580+
581+ /**
582+ @brief Compute the pointwise multiplication w = x * y. Any
583+ subset of x, y, and w may be the same vector.
584+
585+ @param w[out] target vector for the product
586+ @param x[in] first vector for product
587+ @param y[in] second vector for the product
588+
589+ @return An error code: 0 - success, otherwise - failure
590+
591+ @ ref User
592+ **/
593+ int CeedVectorPointwiseMult (CeedVector w , CeedVector x , CeedVector y ) {
594+ int ierr ;
595+ CeedScalar * w_array ;
596+ CeedScalar const * x_array , * y_array ;
597+ CeedInt n_x , n_y , n_w ;
598+
599+ ierr = CeedVectorGetLength (w , & n_w ); CeedChk (ierr );
600+ ierr = CeedVectorGetLength (x , & n_x ); CeedChk (ierr );
601+ ierr = CeedVectorGetLength (y , & n_y ); CeedChk (ierr );
602+ if (n_w != n_x || n_w != n_y )
603+ // LCOV_EXCL_START
604+ return CeedError (w -> ceed , CEED_ERROR_UNSUPPORTED ,
605+ "Cannot multiply vectors of different lengths" );
606+ // LCOV_EXCL_STOP
607+
608+ // Backend implementation
609+ if (w -> PointwiseMult )
610+ return w -> PointwiseMult (w , x , y );
611+
612+ // Default implementation
613+ ierr = CeedVectorGetArray (w , CEED_MEM_HOST , & w_array ); CeedChk (ierr );
614+ if (x != w ) {
615+ ierr = CeedVectorGetArrayRead (x , CEED_MEM_HOST , & x_array ); CeedChk (ierr );
616+ } else {
617+ x_array = w_array ;
618+ }
619+ if (y != w && y != x ) {
620+ ierr = CeedVectorGetArrayRead (y , CEED_MEM_HOST , & y_array ); CeedChk (ierr );
621+ } else if (y != x ) {
622+ y_array = w_array ;
623+ } else {
624+ y_array = x_array ;
625+ }
626+
627+ for (CeedInt i = 0 ; i < n_w ; i ++ )
628+ w_array [i ] = x_array [i ] * y_array [i ];
629+
630+ if (y != w && y != x ) {
631+ ierr = CeedVectorRestoreArrayRead (y , & y_array ); CeedChk (ierr );
632+ }
633+ if (x != w ) {
634+ ierr = CeedVectorRestoreArrayRead (x , & x_array ); CeedChk (ierr );
635+ }
636+ ierr = CeedVectorRestoreArray (w , & w_array ); CeedChk (ierr );
637+ return CEED_ERROR_SUCCESS ;
638+ }
639+
534640/**
535641 @brief Take the reciprocal of a CeedVector.
536642
0 commit comments