1
2 #include <petsc/private/dmimpl.h>
3 #include <petscdm.h> /*I "petscdm.h" I*/
4 #include <petscdmplex.h> /*I "petscdmplex.h" I*/
5 #include <petscksp.h> /*I "petscksp.h" I*/
6 #include <petscblaslapack.h>
7
8 typedef struct _projectConstraintsCtx
9 {
10 DM dm;
11 Vec mask;
12 }
13 projectConstraintsCtx;
14
MatMult_GlobalToLocalNormal(Mat CtC,Vec x,Vec y)15 PetscErrorCode MatMult_GlobalToLocalNormal(Mat CtC, Vec x, Vec y)
16 {
17 DM dm;
18 Vec local, mask;
19 projectConstraintsCtx *ctx;
20 PetscErrorCode ierr;
21
22 PetscFunctionBegin;
23 ierr = MatShellGetContext(CtC,&ctx);CHKERRQ(ierr);
24 dm = ctx->dm;
25 mask = ctx->mask;
26 ierr = DMGetLocalVector(dm,&local);CHKERRQ(ierr);
27 ierr = DMGlobalToLocalBegin(dm,x,INSERT_VALUES,local);CHKERRQ(ierr);
28 ierr = DMGlobalToLocalEnd(dm,x,INSERT_VALUES,local);CHKERRQ(ierr);
29 if (mask) {ierr = VecPointwiseMult(local,mask,local);CHKERRQ(ierr);}
30 ierr = VecSet(y,0.);CHKERRQ(ierr);
31 ierr = DMLocalToGlobalBegin(dm,local,ADD_VALUES,y);CHKERRQ(ierr);
32 ierr = DMLocalToGlobalEnd(dm,local,ADD_VALUES,y);CHKERRQ(ierr);
33 ierr = DMRestoreLocalVector(dm,&local);CHKERRQ(ierr);
34 PetscFunctionReturn(0);
35 }
36
DMGlobalToLocalSolve_project1(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nf,PetscScalar u[],void * ctx)37 static PetscErrorCode DMGlobalToLocalSolve_project1 (PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx)
38 {
39 PetscInt f;
40
41 PetscFunctionBegin;
42 for (f = 0; f < Nf; f++) {
43 u[f] = 1.;
44 }
45 PetscFunctionReturn(0);
46 }
47
48 /*@
49 DMGlobalToLocalSolve - Solve for the global vector that is mapped to a given local vector by DMGlobalToLocalBegin()/DMGlobalToLocalEnd() with mode
50 = INSERT_VALUES. It is assumed that the sum of all the local vector sizes is greater than or equal to the global vector size, so the solution is
51 a least-squares solution. It is also assumed that DMLocalToGlobalBegin()/DMLocalToGlobalEnd() with mode = ADD_VALUES is the adjoint of the
52 global-to-local map, so that the least-squares solution may be found by the normal equations.
53
54 collective
55
56 Input Parameters:
57 + dm - The DM object
58 . x - The local vector
59 - y - The global vector: the input value of globalVec is used as an initial guess
60
61 Output Parameters:
62 . y - The least-squares solution
63
64 Level: advanced
65
66 Note: If the DM is of type DMPLEX, then y is the solution of L' * D * L * y = L' * D * x, where D is a diagonal mask that is 1 for every point in
67 the union of the closures of the local cells and 0 otherwise. This difference is only relevant if there are anchor points that are not in the
68 closure of any local cell (see DMPlexGetAnchors()/DMPlexSetAnchors()).
69
70 .seealso: DMGlobalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd(), DMPlexGetAnchors(), DMPlexSetAnchors()
71 @*/
DMGlobalToLocalSolve(DM dm,Vec x,Vec y)72 PetscErrorCode DMGlobalToLocalSolve(DM dm, Vec x, Vec y)
73 {
74 Mat CtC;
75 PetscInt n, N, cStart, cEnd, c;
76 PetscBool isPlex;
77 KSP ksp;
78 PC pc;
79 Vec global, mask=NULL;
80 projectConstraintsCtx ctx;
81 PetscErrorCode ierr;
82
83 PetscFunctionBegin;
84 ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isPlex);CHKERRQ(ierr);
85 if (isPlex) {
86 /* mark points in the closure */
87 ierr = DMCreateLocalVector(dm,&mask);CHKERRQ(ierr);
88 ierr = VecSet(mask,0.0);CHKERRQ(ierr);
89 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr);
90 if (cEnd > cStart) {
91 PetscScalar *ones;
92 PetscInt numValues, i;
93
94 ierr = DMPlexVecGetClosure(dm,NULL,mask,cStart,&numValues,NULL);CHKERRQ(ierr);
95 ierr = PetscMalloc1(numValues,&ones);CHKERRQ(ierr);
96 for (i = 0; i < numValues; i++) {
97 ones[i] = 1.;
98 }
99 for (c = cStart; c < cEnd; c++) {
100 ierr = DMPlexVecSetClosure(dm,NULL,mask,c,ones,INSERT_VALUES);CHKERRQ(ierr);
101 }
102 ierr = PetscFree(ones);CHKERRQ(ierr);
103 }
104 }
105 else {
106 PetscBool hasMask;
107
108 ierr = DMHasNamedLocalVector(dm, "_DMGlobalToLocalSolve_mask", &hasMask);CHKERRQ(ierr);
109 if (!hasMask) {
110 PetscErrorCode (**func) (PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx);
111 void **ctx;
112 PetscInt Nf, f;
113
114 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
115 ierr = PetscMalloc2(Nf, &func, Nf, &ctx);CHKERRQ(ierr);
116 for (f = 0; f < Nf; ++f) {
117 func[f] = DMGlobalToLocalSolve_project1;
118 ctx[f] = NULL;
119 }
120 ierr = DMGetNamedLocalVector(dm, "_DMGlobalToLocalSolve_mask", &mask);CHKERRQ(ierr);
121 ierr = DMProjectFunctionLocal(dm,0.0,func,ctx,INSERT_ALL_VALUES,mask);CHKERRQ(ierr);
122 ierr = DMRestoreNamedLocalVector(dm, "_DMGlobalToLocalSolve_mask", &mask);CHKERRQ(ierr);
123 ierr = PetscFree2(func, ctx);CHKERRQ(ierr);
124 }
125 ierr = DMGetNamedLocalVector(dm, "_DMGlobalToLocalSolve_mask", &mask);CHKERRQ(ierr);
126 }
127 ctx.dm = dm;
128 ctx.mask = mask;
129 ierr = VecGetSize(y,&N);CHKERRQ(ierr);
130 ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
131 ierr = MatCreate(PetscObjectComm((PetscObject)dm),&CtC);CHKERRQ(ierr);
132 ierr = MatSetSizes(CtC,n,n,N,N);CHKERRQ(ierr);
133 ierr = MatSetType(CtC,MATSHELL);CHKERRQ(ierr);
134 ierr = MatSetUp(CtC);CHKERRQ(ierr);
135 ierr = MatShellSetContext(CtC,&ctx);CHKERRQ(ierr);
136 ierr = MatShellSetOperation(CtC,MATOP_MULT,(void(*)(void))MatMult_GlobalToLocalNormal);CHKERRQ(ierr);
137 ierr = KSPCreate(PetscObjectComm((PetscObject)dm),&ksp);CHKERRQ(ierr);
138 ierr = KSPSetOperators(ksp,CtC,CtC);CHKERRQ(ierr);
139 ierr = KSPSetType(ksp,KSPCG);CHKERRQ(ierr);
140 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
141 ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
142 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
143 ierr = KSPSetUp(ksp);CHKERRQ(ierr);
144 ierr = DMGetGlobalVector(dm,&global);CHKERRQ(ierr);
145 ierr = VecSet(global,0.);CHKERRQ(ierr);
146 if (mask) {ierr = VecPointwiseMult(x,mask,x);CHKERRQ(ierr);}
147 ierr = DMLocalToGlobalBegin(dm,x,ADD_VALUES,global);CHKERRQ(ierr);
148 ierr = DMLocalToGlobalEnd(dm,x,ADD_VALUES,global);CHKERRQ(ierr);
149 ierr = KSPSolve(ksp,global,y);CHKERRQ(ierr);
150 ierr = DMRestoreGlobalVector(dm,&global);CHKERRQ(ierr);
151 /* clean up */
152 ierr = KSPDestroy(&ksp);CHKERRQ(ierr);
153 ierr = MatDestroy(&CtC);CHKERRQ(ierr);
154 if (isPlex) {
155 ierr = VecDestroy(&mask);CHKERRQ(ierr);
156 }
157 else {
158 ierr = DMRestoreNamedLocalVector(dm, "_DMGlobalToLocalSolve_mask", &mask);CHKERRQ(ierr);
159 }
160
161 PetscFunctionReturn(0);
162 }
163
164 /*@C
165 DMProjectField - This projects the given function of the input fields into the function space provided, putting the coefficients in a global vector.
166
167 Collective on DM
168
169 Input Parameters:
170 + dm - The DM
171 . time - The time
172 . U - The input field vector
173 . funcs - The functions to evaluate, one per field
174 - mode - The insertion mode for values
175
176 Output Parameter:
177 . X - The output vector
178
179 Calling sequence of func:
180 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
181 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
182 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
183 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
184
185 + dim - The spatial dimension
186 . Nf - The number of input fields
187 . NfAux - The number of input auxiliary fields
188 . uOff - The offset of each field in u[]
189 . uOff_x - The offset of each field in u_x[]
190 . u - The field values at this point in space
191 . u_t - The field time derivative at this point in space (or NULL)
192 . u_x - The field derivatives at this point in space
193 . aOff - The offset of each auxiliary field in u[]
194 . aOff_x - The offset of each auxiliary field in u_x[]
195 . a - The auxiliary field values at this point in space
196 . a_t - The auxiliary field time derivative at this point in space (or NULL)
197 . a_x - The auxiliary field derivatives at this point in space
198 . t - The current time
199 . x - The coordinates of this point
200 . numConstants - The number of constants
201 . constants - The value of each constant
202 - f - The value of the function at this point in space
203
204 Note: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs.
205 The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
206 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the
207 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
208
209 Level: intermediate
210
211 .seealso: DMProjectFieldLocal(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff()
212 @*/
DMProjectField(DM dm,PetscReal time,Vec U,void (** funcs)(PetscInt,PetscInt,PetscInt,const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],PetscReal,const PetscReal[],PetscInt,const PetscScalar[],PetscScalar[]),InsertMode mode,Vec X)213 PetscErrorCode DMProjectField(DM dm, PetscReal time, Vec U,
214 void (**funcs)(PetscInt, PetscInt, PetscInt,
215 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
216 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
217 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
218 InsertMode mode, Vec X)
219 {
220 Vec localX, localU;
221 PetscErrorCode ierr;
222
223 PetscFunctionBegin;
224 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
225 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
226 /* We currently check whether locU == locX to see if we need to apply BC */
227 if (U != X) {ierr = DMGetLocalVector(dm, &localU);CHKERRQ(ierr);}
228 else {localU = localX;}
229 ierr = DMGlobalToLocalBegin(dm, U, INSERT_VALUES, localU);CHKERRQ(ierr);
230 ierr = DMGlobalToLocalEnd(dm, U, INSERT_VALUES, localU);CHKERRQ(ierr);
231 ierr = DMProjectFieldLocal(dm, time, localU, funcs, mode, localX);CHKERRQ(ierr);
232 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr);
233 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr);
234 if (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES) {
235 Mat cMat;
236
237 ierr = DMGetDefaultConstraints(dm, NULL, &cMat);CHKERRQ(ierr);
238 if (cMat) {
239 ierr = DMGlobalToLocalSolve(dm, localX, X);CHKERRQ(ierr);
240 }
241 }
242 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
243 if (U != X) {ierr = DMRestoreLocalVector(dm, &localU);CHKERRQ(ierr);}
244 PetscFunctionReturn(0);
245 }
246
247 /********************* Adaptive Interpolation **************************/
248
249 /* See the discussion of Adaptive Interpolation in manual/high_level_mg.rst */
DMAdaptInterpolator(DM dmc,DM dmf,Mat In,KSP smoother,PetscInt Nc,Vec vf[],Vec vc[],Mat * InAdapt,void * user)250 PetscErrorCode DMAdaptInterpolator(DM dmc, DM dmf, Mat In, KSP smoother, PetscInt Nc, Vec vf[], Vec vc[], Mat *InAdapt, void *user)
251 {
252 Mat globalA;
253 Vec tmp, tmp2;
254 PetscScalar *A, *b, *x, *workscalar;
255 PetscReal *w, *sing, *workreal, rcond = PETSC_SMALL;
256 PetscBLASInt M, N, one = 1, irank, lwrk, info;
257 PetscInt debug = 0, rStart, rEnd, r, maxcols = 0, k;
258 PetscBool allocVc = PETSC_FALSE;
259 PetscErrorCode ierr;
260
261 PetscFunctionBegin;
262 ierr = PetscLogEventBegin(DM_AdaptInterpolator,dmc,dmf,0,0);CHKERRQ(ierr);
263 ierr = PetscOptionsGetInt(NULL, NULL, "-dm_interpolator_adapt_debug", &debug, NULL);CHKERRQ(ierr);
264 ierr = MatDuplicate(In, MAT_SHARE_NONZERO_PATTERN, InAdapt);CHKERRQ(ierr);
265 ierr = MatGetOwnershipRange(In, &rStart, &rEnd);CHKERRQ(ierr);
266 #if 0
267 ierr = MatGetMaxRowLen(In, &maxcols);CHKERRQ(ierr);
268 #else
269 for (r = rStart; r < rEnd; ++r) {
270 PetscInt ncols;
271 const PetscInt *cols;
272 const PetscScalar *vals;
273
274 ierr = MatGetRow(In, r, &ncols, &cols, &vals);CHKERRQ(ierr);
275 maxcols = PetscMax(maxcols, ncols);
276 ierr = MatRestoreRow(In, r, &ncols, &cols, &vals);CHKERRQ(ierr);
277 }
278 #endif
279 if (Nc < maxcols) PetscPrintf(PETSC_COMM_SELF, "The number of input vectors %D < %D the maximum number of column entries\n", Nc, maxcols);
280 for (k = 0; k < Nc; ++k) {
281 char name[PETSC_MAX_PATH_LEN];
282 const char *prefix;
283
284 ierr = PetscObjectGetOptionsPrefix((PetscObject) smoother, &prefix);CHKERRQ(ierr);
285 ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%sCoarse Vector %D", prefix ? prefix : NULL, k);CHKERRQ(ierr);
286 ierr = PetscObjectSetName((PetscObject) vc[k], name);CHKERRQ(ierr);
287 ierr = VecViewFromOptions(vc[k], NULL, "-dm_adapt_interp_view_coarse");CHKERRQ(ierr);
288 ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%sFine Vector %D", prefix ? prefix : NULL, k);CHKERRQ(ierr);
289 ierr = PetscObjectSetName((PetscObject) vf[k], name);CHKERRQ(ierr);
290 ierr = VecViewFromOptions(vf[k], NULL, "-dm_adapt_interp_view_fine");CHKERRQ(ierr);
291 }
292 ierr = PetscBLASIntCast(3*PetscMin(Nc, maxcols) + PetscMax(2*PetscMin(Nc, maxcols), PetscMax(Nc, maxcols)), &lwrk);CHKERRQ(ierr);
293 ierr = PetscMalloc7(Nc*maxcols, &A, PetscMax(Nc, maxcols), &b, Nc, &w, maxcols, &x, maxcols, &sing, lwrk, &workscalar, 5*PetscMin(Nc, maxcols), &workreal);CHKERRQ(ierr);
294 /* w_k = \frac{\HC{v_k} B_l v_k}{\HC{v_k} A_l v_k} or the inverse Rayleigh quotient, which we calculate using \frac{\HC{v_k} v_k}{\HC{v_k} B^{-1}_l A_l v_k} */
295 ierr = KSPGetOperators(smoother, &globalA, NULL);CHKERRQ(ierr);
296 ierr = DMGetGlobalVector(dmf, &tmp);CHKERRQ(ierr);
297 ierr = DMGetGlobalVector(dmf, &tmp2);CHKERRQ(ierr);
298 for (k = 0; k < Nc; ++k) {
299 PetscScalar vnorm, vAnorm;
300 PetscBool canMult = PETSC_FALSE;
301 const char *type;
302
303 w[k] = 1.0;
304 ierr = PetscObjectGetType((PetscObject) globalA, &type);CHKERRQ(ierr);
305 if (type) {ierr = MatAssembled(globalA, &canMult);CHKERRQ(ierr);}
306 if (type && canMult) {
307 ierr = VecDot(vf[k], vf[k], &vnorm);CHKERRQ(ierr);
308 ierr = MatMult(globalA, vf[k], tmp);CHKERRQ(ierr);
309 #if 0
310 ierr = KSPSolve(smoother, tmp, tmp2);CHKERRQ(ierr);
311 ierr = VecDot(vf[k], tmp2, &vAnorm);CHKERRQ(ierr);
312 #else
313 ierr = VecDot(vf[k], tmp, &vAnorm);CHKERRQ(ierr);
314 #endif
315 w[k] = PetscRealPart(vnorm) / PetscRealPart(vAnorm);
316 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "System matrix is not assembled.");
317 }
318 ierr = DMRestoreGlobalVector(dmf, &tmp);CHKERRQ(ierr);
319 ierr = DMRestoreGlobalVector(dmf, &tmp2);CHKERRQ(ierr);
320 if (!vc) {
321 allocVc = PETSC_TRUE;
322 ierr = PetscMalloc1(Nc, &vc);CHKERRQ(ierr);
323 for (k = 0; k < Nc; ++k) {
324 ierr = DMGetGlobalVector(dmc, &vc[k]);CHKERRQ(ierr);
325 ierr = MatMultTranspose(In, vf[k], vc[k]);CHKERRQ(ierr);
326 }
327 }
328 /* Solve a LS system for each fine row */
329 for (r = rStart; r < rEnd; ++r) {
330 PetscInt ncols, c;
331 const PetscInt *cols;
332 const PetscScalar *vals, *a;
333
334 ierr = MatGetRow(In, r, &ncols, &cols, &vals);CHKERRQ(ierr);
335 for (k = 0; k < Nc; ++k) {
336 /* Need to fit lowest mode exactly */
337 const PetscReal wk = ((ncols == 1) && (k > 0)) ? 0.0 : PetscSqrtReal(w[k]);
338
339 /* b_k = \sqrt{w_k} f^{F,k}_r */
340 ierr = VecGetArrayRead(vf[k], &a);CHKERRQ(ierr);
341 b[k] = wk * a[r-rStart];
342 ierr = VecRestoreArrayRead(vf[k], &a);CHKERRQ(ierr);
343 /* A_{kc} = \sqrt{w_k} f^{C,k}_c */
344 /* TODO Must pull out VecScatter from In, scatter in vc[k] values up front, and access them indirectly just as in MatMult() */
345 ierr = VecGetArrayRead(vc[k], &a);CHKERRQ(ierr);
346 for (c = 0; c < ncols; ++c) {
347 /* This is element (k, c) of A */
348 A[c*Nc+k] = wk * a[cols[c]-rStart];
349 }
350 ierr = VecRestoreArrayRead(vc[k], &a);CHKERRQ(ierr);
351 }
352 ierr = PetscBLASIntCast(Nc, &M);CHKERRQ(ierr);
353 ierr = PetscBLASIntCast(ncols, &N);CHKERRQ(ierr);
354 if (debug) {
355 #if defined(PETSC_USE_COMPLEX)
356 PetscScalar *tmp;
357 PetscInt j;
358
359 ierr = DMGetWorkArray(dmc, Nc, MPIU_SCALAR, (void *) &tmp);CHKERRQ(ierr);
360 for (j = 0; j < Nc; ++j) tmp[j] = w[j];
361 ierr = DMPrintCellMatrix(r, "Interpolator Row LS weights", Nc, 1, tmp);CHKERRQ(ierr);
362 ierr = DMPrintCellMatrix(r, "Interpolator Row LS matrix", Nc, ncols, A);CHKERRQ(ierr);
363 for (j = 0; j < Nc; ++j) tmp[j] = b[j];
364 ierr = DMPrintCellMatrix(r, "Interpolator Row LS rhs", Nc, 1, tmp);CHKERRQ(ierr);
365 ierr = DMRestoreWorkArray(dmc, Nc, MPIU_SCALAR, (void *) &tmp);CHKERRQ(ierr);
366 #else
367 ierr = DMPrintCellMatrix(r, "Interpolator Row LS weights", Nc, 1, w);CHKERRQ(ierr);
368 ierr = DMPrintCellMatrix(r, "Interpolator Row LS matrix", Nc, ncols, A);CHKERRQ(ierr);
369 ierr = DMPrintCellMatrix(r, "Interpolator Row LS rhs", Nc, 1, b);CHKERRQ(ierr);
370 #endif
371 }
372 #if defined(PETSC_USE_COMPLEX)
373 /* ZGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, RWORK, INFO) */
374 PetscStackCallBLAS("LAPACKgelss",LAPACKgelss_(&M, &N, &one, A, &M, b, M > N ? &M : &N, sing, &rcond, &irank, workscalar, &lwrk, workreal, &info));
375 #else
376 /* DGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, INFO) */
377 PetscStackCallBLAS("LAPACKgelss",LAPACKgelss_(&M, &N, &one, A, &M, b, M > N ? &M : &N, sing, &rcond, &irank, workscalar, &lwrk, &info));
378 #endif
379 if (info < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to GELSS");
380 if (info > 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "SVD failed to converge");
381 if (debug) {
382 ierr = PetscPrintf(PETSC_COMM_SELF, "rank %d rcond %g\n", irank, (double) rcond);CHKERRQ(ierr);
383 #if defined(PETSC_USE_COMPLEX)
384 {
385 PetscScalar *tmp;
386 PetscInt j;
387
388 ierr = DMGetWorkArray(dmc, Nc, MPIU_SCALAR, (void *) &tmp);CHKERRQ(ierr);
389 for (j = 0; j < PetscMin(Nc, ncols); ++j) tmp[j] = sing[j];
390 ierr = DMPrintCellMatrix(r, "Interpolator Row LS singular values", PetscMin(Nc, ncols), 1, tmp);CHKERRQ(ierr);
391 ierr = DMRestoreWorkArray(dmc, Nc, MPIU_SCALAR, (void *) &tmp);CHKERRQ(ierr);
392 }
393 #else
394 ierr = DMPrintCellMatrix(r, "Interpolator Row LS singular values", PetscMin(Nc, ncols), 1, sing);CHKERRQ(ierr);
395 #endif
396 ierr = DMPrintCellMatrix(r, "Interpolator Row LS old P", ncols, 1, vals);CHKERRQ(ierr);
397 ierr = DMPrintCellMatrix(r, "Interpolator Row LS sol", ncols, 1, b);CHKERRQ(ierr);
398 }
399 ierr = MatSetValues(*InAdapt, 1, &r, ncols, cols, b, INSERT_VALUES);CHKERRQ(ierr);
400 ierr = MatRestoreRow(In, r, &ncols, &cols, &vals);CHKERRQ(ierr);
401 }
402 ierr = PetscFree7(A, b, w, x, sing, workscalar, workreal);CHKERRQ(ierr);
403 if (allocVc) {
404 for (k = 0; k < Nc; ++k) {ierr = DMRestoreGlobalVector(dmc, &vc[k]);CHKERRQ(ierr);}
405 ierr = PetscFree(vc);CHKERRQ(ierr);
406 }
407 ierr = MatAssemblyBegin(*InAdapt, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
408 ierr = MatAssemblyEnd(*InAdapt, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
409 ierr = PetscLogEventEnd(DM_AdaptInterpolator,dmc,dmf,0,0);CHKERRQ(ierr);
410 PetscFunctionReturn(0);
411 }
412
DMCheckInterpolator(DM dmf,Mat In,PetscInt Nc,Vec vc[],Vec vf[],PetscReal tol)413 PetscErrorCode DMCheckInterpolator(DM dmf, Mat In, PetscInt Nc, Vec vc[], Vec vf[], PetscReal tol)
414 {
415 Vec tmp;
416 PetscReal norminf, norm2, maxnorminf = 0.0, maxnorm2 = 0.0;
417 PetscInt k;
418 PetscErrorCode ierr;
419
420 PetscFunctionBegin;
421 ierr = DMGetGlobalVector(dmf, &tmp);CHKERRQ(ierr);
422 ierr = MatViewFromOptions(In, NULL, "-dm_interpolator_adapt_error");CHKERRQ(ierr);
423 for (k = 0; k < Nc; ++k) {
424 ierr = MatMult(In, vc[k], tmp);CHKERRQ(ierr);
425 ierr = VecAXPY(tmp, -1.0, vf[k]);CHKERRQ(ierr);
426 ierr = VecViewFromOptions(vc[k], NULL, "-dm_interpolator_adapt_error");CHKERRQ(ierr);
427 ierr = VecViewFromOptions(vf[k], NULL, "-dm_interpolator_adapt_error");CHKERRQ(ierr);
428 ierr = VecViewFromOptions(tmp, NULL, "-dm_interpolator_adapt_error");CHKERRQ(ierr);
429 ierr = VecNorm(tmp, NORM_INFINITY, &norminf);CHKERRQ(ierr);
430 ierr = VecNorm(tmp, NORM_2, &norm2);CHKERRQ(ierr);
431 maxnorminf = PetscMax(maxnorminf, norminf);
432 maxnorm2 = PetscMax(maxnorm2, norm2);
433 ierr = PetscPrintf(PetscObjectComm((PetscObject) dmf), "Coarse vec %D ||vf - P vc||_\\infty %g, ||vf - P vc||_2 %g\n", k, norminf, norm2);CHKERRQ(ierr);
434 }
435 ierr = DMRestoreGlobalVector(dmf, &tmp);CHKERRQ(ierr);
436 if (maxnorm2 > tol) SETERRQ2(PetscObjectComm((PetscObject) dmf), PETSC_ERR_ARG_WRONG, "max_k ||vf_k - P vc_k||_2 %g > tol %g", maxnorm2, tol);
437 PetscFunctionReturn(0);
438 }
439