xref: /petsc/src/mat/impls/h2opus/cuda/math2opusutils.cu (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
1f17f7ee2SSatish Balay #include <petsc/private/matimpl.h>
2f17f7ee2SSatish Balay #include <petsc/private/vecimpl.h>
3f17f7ee2SSatish Balay #include <petscsf.h>
4f17f7ee2SSatish Balay #if defined(PETSC_HAVE_CUDA)
5f17f7ee2SSatish Balay   #include <thrust/for_each.h>
6f17f7ee2SSatish Balay   #include <thrust/device_vector.h>
7f17f7ee2SSatish Balay   #include <thrust/execution_policy.h>
8f17f7ee2SSatish Balay #endif
9f17f7ee2SSatish Balay 
10*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscSFGetVectorSF(PetscSF sf, PetscInt nv, PetscInt ldr, PetscInt ldl, PetscSF *vsf)
11*d71ae5a4SJacob Faibussowitsch {
12f17f7ee2SSatish Balay   PetscSF            rankssf;
13f17f7ee2SSatish Balay   const PetscSFNode *iremote;
14f17f7ee2SSatish Balay   PetscSFNode       *viremote, *rremotes;
15f17f7ee2SSatish Balay   const PetscInt    *ilocal;
16f17f7ee2SSatish Balay   PetscInt          *vilocal = NULL, *ldrs;
17f17f7ee2SSatish Balay   const PetscMPIInt *ranks;
18f17f7ee2SSatish Balay   PetscMPIInt       *sranks;
19f17f7ee2SSatish Balay   PetscInt           nranks, nr, nl, vnr, vnl, i, v, j, maxl;
20f17f7ee2SSatish Balay   MPI_Comm           comm;
21f17f7ee2SSatish Balay 
22f17f7ee2SSatish Balay   PetscFunctionBegin;
23f17f7ee2SSatish Balay   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
24f17f7ee2SSatish Balay   PetscValidLogicalCollectiveInt(sf, nv, 2);
25f17f7ee2SSatish Balay   PetscValidPointer(vsf, 5);
26f17f7ee2SSatish Balay   if (nv == 1) {
27f17f7ee2SSatish Balay     PetscCall(PetscObjectReference((PetscObject)sf));
28f17f7ee2SSatish Balay     *vsf = sf;
29f17f7ee2SSatish Balay     PetscFunctionReturn(0);
30f17f7ee2SSatish Balay   }
31f17f7ee2SSatish Balay   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
32f17f7ee2SSatish Balay   PetscCall(PetscSFGetGraph(sf, &nr, &nl, &ilocal, &iremote));
33f17f7ee2SSatish Balay   PetscCall(PetscSFGetLeafRange(sf, NULL, &maxl));
34f17f7ee2SSatish Balay   maxl += 1;
35f17f7ee2SSatish Balay   if (ldl == PETSC_DECIDE) ldl = maxl;
36f17f7ee2SSatish Balay   if (ldr == PETSC_DECIDE) ldr = nr;
37f17f7ee2SSatish Balay   PetscCheck(ldr >= nr, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid leading dimension %" PetscInt_FMT " < %" PetscInt_FMT, ldr, nr);
38f17f7ee2SSatish Balay   PetscCheck(ldl >= maxl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid leading dimension %" PetscInt_FMT " < %" PetscInt_FMT, ldl, maxl);
39f17f7ee2SSatish Balay   vnr = nr * nv;
40f17f7ee2SSatish Balay   vnl = nl * nv;
41f17f7ee2SSatish Balay   PetscCall(PetscMalloc1(vnl, &viremote));
42f17f7ee2SSatish Balay   if (ilocal) PetscCall(PetscMalloc1(vnl, &vilocal));
43f17f7ee2SSatish Balay 
44f17f7ee2SSatish Balay   /* TODO: Should this special SF be available, e.g.
45f17f7ee2SSatish Balay      PetscSFGetRanksSF or similar? */
46f17f7ee2SSatish Balay   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL));
47f17f7ee2SSatish Balay   PetscCall(PetscMalloc1(nranks, &sranks));
48f17f7ee2SSatish Balay   PetscCall(PetscArraycpy(sranks, ranks, nranks));
49f17f7ee2SSatish Balay   PetscCall(PetscSortMPIInt(nranks, sranks));
50f17f7ee2SSatish Balay   PetscCall(PetscMalloc1(nranks, &rremotes));
51f17f7ee2SSatish Balay   for (i = 0; i < nranks; i++) {
52f17f7ee2SSatish Balay     rremotes[i].rank  = sranks[i];
53f17f7ee2SSatish Balay     rremotes[i].index = 0;
54f17f7ee2SSatish Balay   }
55f17f7ee2SSatish Balay   PetscCall(PetscSFDuplicate(sf, PETSCSF_DUPLICATE_CONFONLY, &rankssf));
56f17f7ee2SSatish Balay   PetscCall(PetscSFSetGraph(rankssf, 1, nranks, NULL, PETSC_OWN_POINTER, rremotes, PETSC_OWN_POINTER));
57f17f7ee2SSatish Balay   PetscCall(PetscMalloc1(nranks, &ldrs));
58f17f7ee2SSatish Balay   PetscCall(PetscSFBcastBegin(rankssf, MPIU_INT, &ldr, ldrs, MPI_REPLACE));
59f17f7ee2SSatish Balay   PetscCall(PetscSFBcastEnd(rankssf, MPIU_INT, &ldr, ldrs, MPI_REPLACE));
60f17f7ee2SSatish Balay   PetscCall(PetscSFDestroy(&rankssf));
61f17f7ee2SSatish Balay 
62f17f7ee2SSatish Balay   j = -1;
63f17f7ee2SSatish Balay   for (i = 0; i < nl; i++) {
64f17f7ee2SSatish Balay     const PetscInt r  = iremote[i].rank;
65f17f7ee2SSatish Balay     const PetscInt ii = iremote[i].index;
66f17f7ee2SSatish Balay 
6748a46eb9SPierre Jolivet     if (j < 0 || sranks[j] != r) PetscCall(PetscFindMPIInt(r, nranks, sranks, &j));
68f17f7ee2SSatish Balay     PetscCheck(j >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unable to locate neighbor rank %" PetscInt_FMT, r);
69f17f7ee2SSatish Balay     for (v = 0; v < nv; v++) {
70f17f7ee2SSatish Balay       viremote[v * nl + i].rank  = r;
71f17f7ee2SSatish Balay       viremote[v * nl + i].index = v * ldrs[j] + ii;
72f17f7ee2SSatish Balay       if (ilocal) vilocal[v * nl + i] = v * ldl + ilocal[i];
73f17f7ee2SSatish Balay     }
74f17f7ee2SSatish Balay   }
75f17f7ee2SSatish Balay   PetscCall(PetscFree(sranks));
76f17f7ee2SSatish Balay   PetscCall(PetscFree(ldrs));
77f17f7ee2SSatish Balay   PetscCall(PetscSFCreate(comm, vsf));
78f17f7ee2SSatish Balay   PetscCall(PetscSFSetGraph(*vsf, vnr, vnl, vilocal, PETSC_OWN_POINTER, viremote, PETSC_OWN_POINTER));
79f17f7ee2SSatish Balay   PetscFunctionReturn(0);
80f17f7ee2SSatish Balay }
81f17f7ee2SSatish Balay 
82*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatDenseGetH2OpusVectorSF(Mat A, PetscSF h2sf, PetscSF *osf)
83*d71ae5a4SJacob Faibussowitsch {
84f17f7ee2SSatish Balay   PetscSF asf;
85f17f7ee2SSatish Balay 
86f17f7ee2SSatish Balay   PetscFunctionBegin;
87f17f7ee2SSatish Balay   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
88f17f7ee2SSatish Balay   PetscValidHeaderSpecific(h2sf, PETSCSF_CLASSID, 2);
89f17f7ee2SSatish Balay   PetscValidPointer(osf, 3);
90f17f7ee2SSatish Balay   PetscCall(PetscObjectQuery((PetscObject)A, "_math2opus_vectorsf", (PetscObject *)&asf));
91f17f7ee2SSatish Balay   if (!asf) {
92f17f7ee2SSatish Balay     PetscInt lda;
93f17f7ee2SSatish Balay 
94f17f7ee2SSatish Balay     PetscCall(MatDenseGetLDA(A, &lda));
95f17f7ee2SSatish Balay     PetscCall(PetscSFGetVectorSF(h2sf, A->cmap->N, lda, PETSC_DECIDE, &asf));
96f17f7ee2SSatish Balay     PetscCall(PetscObjectCompose((PetscObject)A, "_math2opus_vectorsf", (PetscObject)asf));
97f17f7ee2SSatish Balay     PetscCall(PetscObjectDereference((PetscObject)asf));
98f17f7ee2SSatish Balay   }
99f17f7ee2SSatish Balay   *osf = asf;
100f17f7ee2SSatish Balay   PetscFunctionReturn(0);
101f17f7ee2SSatish Balay }
102f17f7ee2SSatish Balay 
103f17f7ee2SSatish Balay #if defined(PETSC_HAVE_CUDA)
1049371c9d4SSatish Balay struct SignVector_Functor {
105f17f7ee2SSatish Balay   const PetscScalar *v;
106f17f7ee2SSatish Balay   PetscScalar       *s;
107f17f7ee2SSatish Balay   SignVector_Functor(const PetscScalar *_v, PetscScalar *_s) : v(_v), s(_s) { }
108f17f7ee2SSatish Balay 
1099371c9d4SSatish Balay   __host__ __device__ void operator()(PetscInt i) { s[i] = (v[i] < 0 ? -1 : 1); }
110f17f7ee2SSatish Balay };
111f17f7ee2SSatish Balay #endif
112f17f7ee2SSatish Balay 
113*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode VecSign(Vec v, Vec s)
114*d71ae5a4SJacob Faibussowitsch {
115f17f7ee2SSatish Balay   const PetscScalar *av;
116f17f7ee2SSatish Balay   PetscScalar       *as;
117f17f7ee2SSatish Balay   PetscInt           i, n;
118f17f7ee2SSatish Balay #if defined(PETSC_HAVE_CUDA)
119f17f7ee2SSatish Balay   PetscBool viscuda, siscuda;
120f17f7ee2SSatish Balay #endif
121f17f7ee2SSatish Balay 
122f17f7ee2SSatish Balay   PetscFunctionBegin;
123f17f7ee2SSatish Balay   PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
124f17f7ee2SSatish Balay   PetscValidHeaderSpecific(s, VEC_CLASSID, 2);
125f17f7ee2SSatish Balay   PetscCall(VecGetLocalSize(s, &n));
126f17f7ee2SSatish Balay   PetscCall(VecGetLocalSize(v, &i));
127f17f7ee2SSatish Balay   PetscCheck(i == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Invalid local sizes %" PetscInt_FMT " != %" PetscInt_FMT, i, n);
128f17f7ee2SSatish Balay #if defined(PETSC_HAVE_CUDA)
129f17f7ee2SSatish Balay   PetscCall(PetscObjectTypeCompareAny((PetscObject)v, &viscuda, VECSEQCUDA, VECMPICUDA, ""));
130f17f7ee2SSatish Balay   PetscCall(PetscObjectTypeCompareAny((PetscObject)s, &siscuda, VECSEQCUDA, VECMPICUDA, ""));
131f17f7ee2SSatish Balay   viscuda = (PetscBool)(viscuda && !v->boundtocpu);
132f17f7ee2SSatish Balay   siscuda = (PetscBool)(siscuda && !s->boundtocpu);
133f17f7ee2SSatish Balay   if (viscuda && siscuda) {
134f17f7ee2SSatish Balay     PetscCall(VecCUDAGetArrayRead(v, &av));
135f17f7ee2SSatish Balay     PetscCall(VecCUDAGetArrayWrite(s, &as));
136f17f7ee2SSatish Balay     SignVector_Functor sign_vector(av, as);
1379371c9d4SSatish Balay     thrust::for_each(thrust::device, thrust::counting_iterator<PetscInt>(0), thrust::counting_iterator<PetscInt>(n), sign_vector);
138f17f7ee2SSatish Balay     PetscCall(VecCUDARestoreArrayWrite(s, &as));
139f17f7ee2SSatish Balay     PetscCall(VecCUDARestoreArrayRead(v, &av));
140f17f7ee2SSatish Balay   } else
141f17f7ee2SSatish Balay #endif
142f17f7ee2SSatish Balay   {
143f17f7ee2SSatish Balay     PetscCall(VecGetArrayRead(v, &av));
144f17f7ee2SSatish Balay     PetscCall(VecGetArrayWrite(s, &as));
145f17f7ee2SSatish Balay     for (i = 0; i < n; i++) as[i] = PetscAbsScalar(av[i]) < 0 ? -1. : 1.;
146f17f7ee2SSatish Balay     PetscCall(VecRestoreArrayWrite(s, &as));
147f17f7ee2SSatish Balay     PetscCall(VecRestoreArrayRead(v, &av));
148f17f7ee2SSatish Balay   }
149f17f7ee2SSatish Balay   PetscFunctionReturn(0);
150f17f7ee2SSatish Balay }
151f17f7ee2SSatish Balay 
152f17f7ee2SSatish Balay #if defined(PETSC_HAVE_CUDA)
1539371c9d4SSatish Balay struct StandardBasis_Functor {
154f17f7ee2SSatish Balay   PetscScalar *v;
155f17f7ee2SSatish Balay   PetscInt     j;
156f17f7ee2SSatish Balay 
157f17f7ee2SSatish Balay   StandardBasis_Functor(PetscScalar *_v, PetscInt _j) : v(_v), j(_j) { }
1589371c9d4SSatish Balay   __host__ __device__ void operator()(PetscInt i) { v[i] = (i == j ? 1 : 0); }
159f17f7ee2SSatish Balay };
160f17f7ee2SSatish Balay #endif
161f17f7ee2SSatish Balay 
162*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode VecSetDelta(Vec x, PetscInt i)
163*d71ae5a4SJacob Faibussowitsch {
164f17f7ee2SSatish Balay #if defined(PETSC_HAVE_CUDA)
165f17f7ee2SSatish Balay   PetscBool iscuda;
166f17f7ee2SSatish Balay #endif
167f17f7ee2SSatish Balay   PetscInt st, en;
168f17f7ee2SSatish Balay 
169f17f7ee2SSatish Balay   PetscFunctionBegin;
170f17f7ee2SSatish Balay   PetscCall(VecGetOwnershipRange(x, &st, &en));
171f17f7ee2SSatish Balay #if defined(PETSC_HAVE_CUDA)
172f17f7ee2SSatish Balay   PetscCall(PetscObjectTypeCompareAny((PetscObject)x, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
173f17f7ee2SSatish Balay   iscuda = (PetscBool)(iscuda && !x->boundtocpu);
174f17f7ee2SSatish Balay   if (iscuda) {
175f17f7ee2SSatish Balay     PetscScalar *ax;
176f17f7ee2SSatish Balay     PetscCall(VecCUDAGetArrayWrite(x, &ax));
177f17f7ee2SSatish Balay     StandardBasis_Functor delta(ax, i - st);
1789371c9d4SSatish Balay     thrust::for_each(thrust::device, thrust::counting_iterator<PetscInt>(0), thrust::counting_iterator<PetscInt>(en - st), delta);
179f17f7ee2SSatish Balay     PetscCall(VecCUDARestoreArrayWrite(x, &ax));
180f17f7ee2SSatish Balay   } else
181f17f7ee2SSatish Balay #endif
182f17f7ee2SSatish Balay   {
183f17f7ee2SSatish Balay     PetscCall(VecSet(x, 0.));
18448a46eb9SPierre Jolivet     if (st <= i && i < en) PetscCall(VecSetValue(x, i, 1.0, INSERT_VALUES));
185f17f7ee2SSatish Balay     PetscCall(VecAssemblyBegin(x));
186f17f7ee2SSatish Balay     PetscCall(VecAssemblyEnd(x));
187f17f7ee2SSatish Balay   }
188f17f7ee2SSatish Balay   PetscFunctionReturn(0);
189f17f7ee2SSatish Balay }
190f17f7ee2SSatish Balay 
191f17f7ee2SSatish Balay /* these are approximate norms */
192f17f7ee2SSatish Balay /* NORM_2: Estimating the matrix p-norm Nicholas J. Higham
193f17f7ee2SSatish Balay    NORM_1/NORM_INFINITY: A block algorithm for matrix 1-norm estimation, with an application to 1-norm pseudospectra Higham, Nicholas J. and Tisseur, Francoise */
194*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatApproximateNorm_Private(Mat A, NormType normtype, PetscInt normsamples, PetscReal *n)
195*d71ae5a4SJacob Faibussowitsch {
196f17f7ee2SSatish Balay   Vec         x, y, w, z;
197f17f7ee2SSatish Balay   PetscReal   normz, adot;
198f17f7ee2SSatish Balay   PetscScalar dot;
199f17f7ee2SSatish Balay   PetscInt    i, j, N, jold = -1;
200f17f7ee2SSatish Balay   PetscBool   boundtocpu = PETSC_TRUE;
201f17f7ee2SSatish Balay 
202f17f7ee2SSatish Balay   PetscFunctionBegin;
203f17f7ee2SSatish Balay #if defined(PETSC_HAVE_DEVICE)
204f17f7ee2SSatish Balay   boundtocpu = A->boundtocpu;
205f17f7ee2SSatish Balay #endif
206f17f7ee2SSatish Balay   switch (normtype) {
207f17f7ee2SSatish Balay   case NORM_INFINITY:
208f17f7ee2SSatish Balay   case NORM_1:
209f17f7ee2SSatish Balay     if (normsamples < 0) normsamples = 10; /* pure guess */
210f17f7ee2SSatish Balay     if (normtype == NORM_INFINITY) {
211f17f7ee2SSatish Balay       Mat B;
212f17f7ee2SSatish Balay       PetscCall(MatCreateTranspose(A, &B));
213f17f7ee2SSatish Balay       A = B;
214f17f7ee2SSatish Balay     } else {
215f17f7ee2SSatish Balay       PetscCall(PetscObjectReference((PetscObject)A));
216f17f7ee2SSatish Balay     }
217f17f7ee2SSatish Balay     PetscCall(MatCreateVecs(A, &x, &y));
218f17f7ee2SSatish Balay     PetscCall(MatCreateVecs(A, &z, &w));
219f17f7ee2SSatish Balay     PetscCall(VecBindToCPU(x, boundtocpu));
220f17f7ee2SSatish Balay     PetscCall(VecBindToCPU(y, boundtocpu));
221f17f7ee2SSatish Balay     PetscCall(VecBindToCPU(z, boundtocpu));
222f17f7ee2SSatish Balay     PetscCall(VecBindToCPU(w, boundtocpu));
223f17f7ee2SSatish Balay     PetscCall(VecGetSize(x, &N));
224f17f7ee2SSatish Balay     PetscCall(VecSet(x, 1. / N));
225f17f7ee2SSatish Balay     *n = 0.0;
226f17f7ee2SSatish Balay     for (i = 0; i < normsamples; i++) {
227f17f7ee2SSatish Balay       PetscCall(MatMult(A, x, y));
228f17f7ee2SSatish Balay       PetscCall(VecSign(y, w));
229f17f7ee2SSatish Balay       PetscCall(MatMultTranspose(A, w, z));
230f17f7ee2SSatish Balay       PetscCall(VecNorm(z, NORM_INFINITY, &normz));
231f17f7ee2SSatish Balay       PetscCall(VecDot(x, z, &dot));
232f17f7ee2SSatish Balay       adot = PetscAbsScalar(dot);
233f17f7ee2SSatish Balay       PetscCall(PetscInfo(A, "%s norm it %" PetscInt_FMT " -> (%g %g)\n", NormTypes[normtype], i, (double)normz, (double)adot));
234f17f7ee2SSatish Balay       if (normz <= adot && i > 0) {
235f17f7ee2SSatish Balay         PetscCall(VecNorm(y, NORM_1, n));
236f17f7ee2SSatish Balay         break;
237f17f7ee2SSatish Balay       }
238f17f7ee2SSatish Balay       PetscCall(VecMax(z, &j, &normz));
239f17f7ee2SSatish Balay       if (j == jold) {
240f17f7ee2SSatish Balay         PetscCall(VecNorm(y, NORM_1, n));
241f17f7ee2SSatish Balay         PetscCall(PetscInfo(A, "%s norm it %" PetscInt_FMT " -> breakdown (j==jold)\n", NormTypes[normtype], i));
242f17f7ee2SSatish Balay         break;
243f17f7ee2SSatish Balay       }
244f17f7ee2SSatish Balay       jold = j;
245f17f7ee2SSatish Balay       PetscCall(VecSetDelta(x, j));
246f17f7ee2SSatish Balay     }
247f17f7ee2SSatish Balay     PetscCall(MatDestroy(&A));
248f17f7ee2SSatish Balay     PetscCall(VecDestroy(&x));
249f17f7ee2SSatish Balay     PetscCall(VecDestroy(&w));
250f17f7ee2SSatish Balay     PetscCall(VecDestroy(&y));
251f17f7ee2SSatish Balay     PetscCall(VecDestroy(&z));
252f17f7ee2SSatish Balay     break;
253f17f7ee2SSatish Balay   case NORM_2:
254f17f7ee2SSatish Balay     if (normsamples < 0) normsamples = 20; /* pure guess */
255f17f7ee2SSatish Balay     PetscCall(MatCreateVecs(A, &x, &y));
256f17f7ee2SSatish Balay     PetscCall(MatCreateVecs(A, &z, NULL));
257f17f7ee2SSatish Balay     PetscCall(VecBindToCPU(x, boundtocpu));
258f17f7ee2SSatish Balay     PetscCall(VecBindToCPU(y, boundtocpu));
259f17f7ee2SSatish Balay     PetscCall(VecBindToCPU(z, boundtocpu));
260f17f7ee2SSatish Balay     PetscCall(VecSetRandom(x, NULL));
261f17f7ee2SSatish Balay     PetscCall(VecNormalize(x, NULL));
262f17f7ee2SSatish Balay     *n = 0.0;
263f17f7ee2SSatish Balay     for (i = 0; i < normsamples; i++) {
264f17f7ee2SSatish Balay       PetscCall(MatMult(A, x, y));
265f17f7ee2SSatish Balay       PetscCall(VecNormalize(y, n));
266f17f7ee2SSatish Balay       PetscCall(MatMultTranspose(A, y, z));
267f17f7ee2SSatish Balay       PetscCall(VecNorm(z, NORM_2, &normz));
268f17f7ee2SSatish Balay       PetscCall(VecDot(x, z, &dot));
269f17f7ee2SSatish Balay       adot = PetscAbsScalar(dot);
270f17f7ee2SSatish Balay       PetscCall(PetscInfo(A, "%s norm it %" PetscInt_FMT " -> %g (%g %g)\n", NormTypes[normtype], i, (double)*n, (double)normz, (double)adot));
271f17f7ee2SSatish Balay       if (normz <= adot) break;
272f17f7ee2SSatish Balay       if (i < normsamples - 1) {
273f17f7ee2SSatish Balay         Vec t;
274f17f7ee2SSatish Balay 
275f17f7ee2SSatish Balay         PetscCall(VecNormalize(z, NULL));
276f17f7ee2SSatish Balay         t = x;
277f17f7ee2SSatish Balay         x = z;
278f17f7ee2SSatish Balay         z = t;
279f17f7ee2SSatish Balay       }
280f17f7ee2SSatish Balay     }
281f17f7ee2SSatish Balay     PetscCall(VecDestroy(&x));
282f17f7ee2SSatish Balay     PetscCall(VecDestroy(&y));
283f17f7ee2SSatish Balay     PetscCall(VecDestroy(&z));
284f17f7ee2SSatish Balay     break;
285*d71ae5a4SJacob Faibussowitsch   default:
286*d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "%s norm not supported", NormTypes[normtype]);
287f17f7ee2SSatish Balay   }
288f17f7ee2SSatish Balay   PetscCall(PetscInfo(A, "%s norm %g computed in %" PetscInt_FMT " iterations\n", NormTypes[normtype], (double)*n, i));
289f17f7ee2SSatish Balay   PetscFunctionReturn(0);
290f17f7ee2SSatish Balay }
291