@@ -531,6 +531,132 @@ 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+ Ceed ceed_parent_x , ceed_parent_y ;
565+ ierr = CeedGetParent (x -> ceed , & ceed_parent_x ); CeedChk (ierr );
566+ ierr = CeedGetParent (y -> ceed , & ceed_parent_y ); CeedChk (ierr );
567+ if (ceed_parent_x != ceed_parent_y )
568+ // LCOV_EXCL_START
569+ return CeedError (y -> ceed , CEED_ERROR_INCOMPATIBLE ,
570+ "Vectors x and y must be created by the same Ceed context" );
571+ // LCOV_EXCL_STOP
572+
573+ // Backend implementation
574+ if (y -> AXPY )
575+ return y -> AXPY (y , alpha , x );
576+
577+ // Default implementation
578+ ierr = CeedVectorGetArray (y , CEED_MEM_HOST , & y_array ); CeedChk (ierr );
579+ ierr = CeedVectorGetArrayRead (x , CEED_MEM_HOST , & x_array ); CeedChk (ierr );
580+
581+ for (CeedInt i = 0 ; i < n_y ; i ++ )
582+ y_array [i ] += alpha * x_array [i ];
583+
584+ ierr = CeedVectorRestoreArray (y , & y_array ); CeedChk (ierr );
585+ ierr = CeedVectorRestoreArrayRead (x , & x_array ); CeedChk (ierr );
586+
587+ return CEED_ERROR_SUCCESS ;
588+ }
589+
590+ /**
591+ @brief Compute the pointwise multiplication w = x * y. Any
592+ subset of x, y, and w may be the same vector.
593+
594+ @param w[out] target vector for the product
595+ @param x[in] first vector for product
596+ @param y[in] second vector for the product
597+
598+ @return An error code: 0 - success, otherwise - failure
599+
600+ @ ref User
601+ **/
602+ int CeedVectorPointwiseMult (CeedVector w , CeedVector x , CeedVector y ) {
603+ int ierr ;
604+ CeedScalar * w_array ;
605+ CeedScalar const * x_array , * y_array ;
606+ CeedInt n_w , n_x , n_y ;
607+
608+ ierr = CeedVectorGetLength (w , & n_w ); CeedChk (ierr );
609+ ierr = CeedVectorGetLength (x , & n_x ); CeedChk (ierr );
610+ ierr = CeedVectorGetLength (y , & n_y ); CeedChk (ierr );
611+ if (n_w != n_x || n_w != n_y )
612+ // LCOV_EXCL_START
613+ return CeedError (w -> ceed , CEED_ERROR_UNSUPPORTED ,
614+ "Cannot multiply vectors of different lengths" );
615+ // LCOV_EXCL_STOP
616+
617+ Ceed ceed_parent_w , ceed_parent_x , ceed_parent_y ;
618+ ierr = CeedGetParent (w -> ceed , & ceed_parent_w ); CeedChk (ierr );
619+ ierr = CeedGetParent (x -> ceed , & ceed_parent_x ); CeedChk (ierr );
620+ ierr = CeedGetParent (y -> ceed , & ceed_parent_y ); CeedChk (ierr );
621+ if ((ceed_parent_w != ceed_parent_y ) ||
622+ (ceed_parent_w != ceed_parent_y ))
623+ // LCOV_EXCL_START
624+ return CeedError (w -> ceed , CEED_ERROR_INCOMPATIBLE ,
625+ "Vectors w, x, and y must be created by the same Ceed context" );
626+ // LCOV_EXCL_STOP
627+
628+ // Backend implementation
629+ if (w -> PointwiseMult )
630+ return w -> PointwiseMult (w , x , y );
631+
632+ // Default implementation
633+ ierr = CeedVectorGetArray (w , CEED_MEM_HOST , & w_array ); CeedChk (ierr );
634+ if (x != w ) {
635+ ierr = CeedVectorGetArrayRead (x , CEED_MEM_HOST , & x_array ); CeedChk (ierr );
636+ } else {
637+ x_array = w_array ;
638+ }
639+ if (y != w && y != x ) {
640+ ierr = CeedVectorGetArrayRead (y , CEED_MEM_HOST , & y_array ); CeedChk (ierr );
641+ } else if (y != x ) {
642+ y_array = w_array ;
643+ } else {
644+ y_array = x_array ;
645+ }
646+
647+ for (CeedInt i = 0 ; i < n_w ; i ++ )
648+ w_array [i ] = x_array [i ] * y_array [i ];
649+
650+ if (y != w && y != x ) {
651+ ierr = CeedVectorRestoreArrayRead (y , & y_array ); CeedChk (ierr );
652+ }
653+ if (x != w ) {
654+ ierr = CeedVectorRestoreArrayRead (x , & x_array ); CeedChk (ierr );
655+ }
656+ ierr = CeedVectorRestoreArray (w , & w_array ); CeedChk (ierr );
657+ return CEED_ERROR_SUCCESS ;
658+ }
659+
534660/**
535661 @brief Take the reciprocal of a CeedVector.
536662
0 commit comments