Actual source code: veccomp0.h
slepc-3.22.2 2024-12-02
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
7: SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9: */
11: #include <petsc/private/vecimpl.h>
13: #if defined(__WITH_MPI__)
15: #else
17: #endif
22: static PetscErrorCode __SUF__(VecDot_Comp)(Vec a,Vec b,PetscScalar *z)
23: {
24: PetscScalar sum = 0.0,work;
25: PetscInt i;
26: Vec_Comp *as = (Vec_Comp*)a->data,*bs = (Vec_Comp*)b->data;
28: PetscFunctionBegin;
29: SlepcValidVecComp(a,1);
30: SlepcValidVecComp(b,2);
31: if (as->x[0]->ops->dot_local) {
32: for (i=0,sum=0.0;i<as->n->n;i++) {
33: PetscUseTypeMethod(as->x[i],dot_local,bs->x[i],&work);
34: sum += work;
35: }
36: #if defined(__WITH_MPI__)
37: work = sum;
38: PetscCallMPI(MPIU_Allreduce(&work,&sum,1,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)a)));
39: #endif
40: } else {
41: for (i=0,sum=0.0;i<as->n->n;i++) {
42: PetscCall(VecDot(as->x[i],bs->x[i],&work));
43: sum += work;
44: }
45: }
46: *z = sum;
47: PetscFunctionReturn(PETSC_SUCCESS);
48: }
50: static PetscErrorCode __SUF__(VecMDot_Comp)(Vec a,PetscInt n,const Vec b[],PetscScalar *z)
51: {
52: PetscScalar *work,*work0,*r;
53: Vec_Comp *as = (Vec_Comp*)a->data;
54: Vec *bx;
55: PetscInt i,j;
57: PetscFunctionBegin;
58: SlepcValidVecComp(a,1);
59: for (i=0;i<n;i++) SlepcValidVecComp(b[i],3);
61: if (as->n->n == 0) {
62: *z = 0;
63: PetscFunctionReturn(PETSC_SUCCESS);
64: }
66: PetscCall(PetscMalloc2(n,&work0,n,&bx));
68: #if defined(__WITH_MPI__)
69: if (as->x[0]->ops->mdot_local) {
70: r = work0; work = z;
71: } else
72: #endif
73: {
74: r = z; work = work0;
75: }
77: /* z[i] <- a.x' * b[i].x */
78: for (i=0;i<n;i++) r[i] = 0.0;
79: for (j=0;j<as->n->n;j++) {
80: for (i=0;i<n;i++) bx[i] = ((Vec_Comp*)b[i]->data)->x[j];
81: if (as->x[0]->ops->mdot_local) PetscUseTypeMethod(as->x[j],mdot_local,n,bx,work);
82: else PetscCall(VecMDot(as->x[j],n,bx,work));
83: for (i=0;i<n;i++) r[i] += work[i];
84: }
86: /* If def(__WITH_MPI__) and exists mdot_local */
87: #if defined(__WITH_MPI__)
88: if (as->x[0]->ops->mdot_local) {
89: /* z[i] <- Allreduce(work[i]) */
90: PetscCallMPI(MPIU_Allreduce(r,z,n,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)a)));
91: }
92: #endif
94: PetscCall(PetscFree2(work0,bx));
95: PetscFunctionReturn(PETSC_SUCCESS);
96: }
98: static PetscErrorCode __SUF__(VecTDot_Comp)(Vec a,Vec b,PetscScalar *z)
99: {
100: PetscScalar sum = 0.0,work;
101: PetscInt i;
102: Vec_Comp *as = (Vec_Comp*)a->data,*bs = (Vec_Comp*)b->data;
104: PetscFunctionBegin;
105: SlepcValidVecComp(a,1);
106: SlepcValidVecComp(b,2);
107: if (as->x[0]->ops->tdot_local) {
108: for (i=0,sum=0.0;i<as->n->n;i++) {
109: PetscUseTypeMethod(as->x[i],tdot_local,bs->x[i],&work);
110: sum += work;
111: }
112: #if defined(__WITH_MPI__)
113: work = sum;
114: PetscCallMPI(MPIU_Allreduce(&work,&sum,1,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)a)));
115: #endif
116: } else {
117: for (i=0,sum=0.0;i<as->n->n;i++) {
118: PetscCall(VecTDot(as->x[i],bs->x[i],&work));
119: sum += work;
120: }
121: }
122: *z = sum;
123: PetscFunctionReturn(PETSC_SUCCESS);
124: }
126: static PetscErrorCode __SUF__(VecMTDot_Comp)(Vec a,PetscInt n,const Vec b[],PetscScalar *z)
127: {
128: PetscScalar *work,*work0,*r;
129: Vec_Comp *as = (Vec_Comp*)a->data;
130: Vec *bx;
131: PetscInt i,j;
133: PetscFunctionBegin;
134: SlepcValidVecComp(a,1);
135: for (i=0;i<n;i++) SlepcValidVecComp(b[i],3);
137: if (as->n->n == 0) {
138: *z = 0;
139: PetscFunctionReturn(PETSC_SUCCESS);
140: }
142: PetscCall(PetscMalloc2(n,&work0,n,&bx));
144: #if defined(__WITH_MPI__)
145: if (as->x[0]->ops->mtdot_local) {
146: r = work0; work = z;
147: } else
148: #endif
149: {
150: r = z; work = work0;
151: }
153: /* z[i] <- a.x' * b[i].x */
154: for (i=0;i<n;i++) r[i] = 0.0;
155: for (j=0;j<as->n->n;j++) {
156: for (i=0;i<n;i++) bx[i] = ((Vec_Comp*)b[i]->data)->x[j];
157: if (as->x[0]->ops->mtdot_local) PetscUseTypeMethod(as->x[j],mtdot_local,n,bx,work);
158: else PetscCall(VecMTDot(as->x[j],n,bx,work));
159: for (i=0;i<n;i++) r[i] += work[i];
160: }
162: /* If def(__WITH_MPI__) and exists mtdot_local */
163: #if defined(__WITH_MPI__)
164: if (as->x[0]->ops->mtdot_local) {
165: /* z[i] <- Allreduce(work[i]) */
166: PetscCallMPI(MPIU_Allreduce(r,z,n,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)a)));
167: }
168: #endif
170: PetscCall(PetscFree2(work0,bx));
171: PetscFunctionReturn(PETSC_SUCCESS);
172: }
174: static PetscErrorCode __SUF__(VecNorm_Comp)(Vec a,NormType t,PetscReal *norm)
175: {
176: PetscReal work[3],s=0.0;
177: Vec_Comp *as = (Vec_Comp*)a->data;
178: PetscInt i;
180: PetscFunctionBegin;
181: SlepcValidVecComp(a,1);
182: /* Initialize norm */
183: switch (t) {
184: case NORM_1: case NORM_INFINITY: *norm = 0.0; break;
185: case NORM_2: case NORM_FROBENIUS: *norm = 1.0; s = 0.0; break;
186: case NORM_1_AND_2: norm[0] = 0.0; norm[1] = 1.0; s = 0.0; break;
187: }
188: for (i=0;i<as->n->n;i++) {
189: if (as->x[0]->ops->norm_local) PetscUseTypeMethod(as->x[i],norm_local,t,work);
190: else PetscCall(VecNorm(as->x[i],t,work));
191: /* norm+= work */
192: switch (t) {
193: case NORM_1: *norm+= *work; break;
194: case NORM_2: case NORM_FROBENIUS: AddNorm2(norm,&s,*work); break;
195: case NORM_1_AND_2: norm[0]+= work[0]; AddNorm2(&norm[1],&s,work[1]); break;
196: case NORM_INFINITY: *norm = PetscMax(*norm,*work); break;
197: }
198: }
200: /* If def(__WITH_MPI__) and exists norm_local */
201: #if defined(__WITH_MPI__)
202: if (as->x[0]->ops->norm_local) {
203: PetscReal work0[3];
204: /* norm <- Allreduce(work) */
205: switch (t) {
206: case NORM_1:
207: work[0] = *norm;
208: PetscCallMPI(MPIU_Allreduce(work,norm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)a)));
209: break;
210: case NORM_2: case NORM_FROBENIUS:
211: work[0] = *norm; work[1] = s;
212: PetscCallMPI(MPIU_Allreduce(work,work0,1,MPIU_NORM2,MPIU_NORM2_SUM,PetscObjectComm((PetscObject)a)));
213: *norm = GetNorm2(work0[0],work0[1]);
214: break;
215: case NORM_1_AND_2:
216: work[0] = norm[0]; work[1] = norm[1]; work[2] = s;
217: PetscCallMPI(MPIU_Allreduce(work,work0,1,MPIU_NORM1_AND_2,MPIU_NORM2_SUM,PetscObjectComm((PetscObject)a)));
218: norm[0] = work0[0];
219: norm[1] = GetNorm2(work0[1],work0[2]);
220: break;
221: case NORM_INFINITY:
222: work[0] = *norm;
223: PetscCallMPI(MPIU_Allreduce(work,norm,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)a)));
224: break;
225: }
226: }
227: #else
228: /* Norm correction */
229: switch (t) {
230: case NORM_2: case NORM_FROBENIUS: *norm = GetNorm2(*norm,s); break;
231: case NORM_1_AND_2: norm[1] = GetNorm2(norm[1],s); break;
232: default: ;
233: }
234: #endif
235: PetscFunctionReturn(PETSC_SUCCESS);
236: }
238: PetscErrorCode __SUF__(VecDotNorm2_Comp)(Vec v,Vec w,PetscScalar *dp,PetscScalar *nm)
239: {
240: PetscScalar dp0=0.0,nm0=0.0,dp1=0.0,nm1=0.0;
241: const PetscScalar *vx,*wx;
242: Vec_Comp *vs = (Vec_Comp*)v->data,*ws = (Vec_Comp*)w->data;
243: PetscInt i,n;
244: PetscBool t0,t1;
245: #if defined(__WITH_MPI__)
246: PetscScalar work[4];
247: #endif
249: PetscFunctionBegin;
250: /* Compute recursively the local part */
251: PetscCall(PetscObjectTypeCompare((PetscObject)v,VECCOMP,&t0));
252: PetscCall(PetscObjectTypeCompare((PetscObject)w,VECCOMP,&t1));
253: if (t0 && t1) {
254: SlepcValidVecComp(v,1);
255: SlepcValidVecComp(w,2);
256: for (i=0;i<vs->n->n;i++) {
257: PetscCall(VecDotNorm2_Comp_Seq(vs->x[i],ws->x[i],&dp1,&nm1));
258: dp0 += dp1;
259: nm0 += nm1;
260: }
261: } else if (!t0 && !t1) {
262: PetscCall(VecGetLocalSize(v,&n));
263: PetscCall(VecGetArrayRead(v,&vx));
264: PetscCall(VecGetArrayRead(w,&wx));
265: for (i=0;i<n;i++) {
266: dp0 += vx[i]*PetscConj(wx[i]);
267: nm0 += wx[i]*PetscConj(wx[i]);
268: }
269: PetscCall(VecRestoreArrayRead(v,&vx));
270: PetscCall(VecRestoreArrayRead(w,&wx));
271: } else SETERRQ(PetscObjectComm((PetscObject)v),PETSC_ERR_ARG_INCOMP,"Incompatible vector types");
273: #if defined(__WITH_MPI__)
274: /* [dp, nm] <- Allreduce([dp0, nm0]) */
275: work[0] = dp0; work[1] = nm0;
276: PetscCallMPI(MPIU_Allreduce(work,&work[2],2,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)v)));
277: *dp = work[2]; *nm = work[3];
278: #else
279: *dp = dp0; *nm = nm0;
280: #endif
281: PetscFunctionReturn(PETSC_SUCCESS);
282: }