Actual source code: swarmpic_plex.c
petsc-3.8.4 2018-03-24
1: #include <petscdm.h>
2: #include <petscdmplex.h>
3: #include <petscdmswarm.h>
4: #include "data_bucket.h"
6: PetscErrorCode subdivide_triangle(PetscReal v1[2],PetscReal v2[2],PetscReal v3[3],PetscInt depth,PetscInt max,PetscReal xi[],PetscInt *np)
7: {
8: PetscReal v12[2],v23[2],v31[2];
9: PetscInt i;
11:
13: if (depth == max) {
14: PetscReal cx[2];
15:
16: cx[0] = (v1[0] + v2[0] + v3[0])/3.0;
17: cx[1] = (v1[1] + v2[1] + v3[1])/3.0;
18:
19: xi[2*(*np)+0] = cx[0];
20: xi[2*(*np)+1] = cx[1];
21: (*np)++;
22: return(0);
23: }
24:
25: /* calculate midpoints of each side */
26: for (i = 0; i < 2; i++) {
27: v12[i] = (v1[i]+v2[i])/2.0;
28: v23[i] = (v2[i]+v3[i])/2.0;
29: v31[i] = (v3[i]+v1[i])/2.0;
30: }
31:
32: /* recursively subdivide new triangles */
33: subdivide_triangle(v1,v12,v31,depth+1,max,xi,np);
34: subdivide_triangle(v2,v23,v12,depth+1,max,xi,np);
35: subdivide_triangle(v3,v31,v23,depth+1,max,xi,np);
36: subdivide_triangle(v12,v23,v31,depth+1,max,xi,np);
37: return(0);
38: }
41: PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX2D_SubDivide(DM dm,DM dmc,PetscInt nsub)
42: {
44: const PetscInt dim = 2;
45: PetscInt q,npoints_q,e,nel,npe,pcnt,ps,pe,d,k,depth;
46: PetscReal *xi;
47: PetscReal **basis;
48: Vec coorlocal;
49: PetscSection coordSection;
50: PetscScalar *elcoor = NULL;
51: PetscReal *swarm_coor;
52: PetscInt *swarm_cellid;
53: PetscReal v1[2],v2[2],v3[2];
54:
56:
57: npoints_q = 1;
58: for (d=0; d<nsub; d++) { npoints_q *= 4; }
59: PetscMalloc1(dim*npoints_q,&xi);
60:
61: v1[0] = 0.0; v1[1] = 0.0;
62: v2[0] = 1.0; v2[1] = 0.0;
63: v3[0] = 0.0; v3[1] = 1.0;
64: depth = 0;
65: pcnt = 0;
66: subdivide_triangle(v1,v2,v3,depth,nsub,xi,&pcnt);
68: npe = 3; /* nodes per element (triangle) */
69: PetscMalloc1(npoints_q,&basis);
70: for (q=0; q<npoints_q; q++) {
71: PetscMalloc1(npe,&basis[q]);
72:
73: basis[q][0] = 1.0 - xi[dim*q+0] - xi[dim*q+1];
74: basis[q][1] = xi[dim*q+0];
75: basis[q][2] = xi[dim*q+1];
76: }
77:
78: /* 0->cell, 1->edge, 2->vert */
79: DMPlexGetHeightStratum(dmc,0,&ps,&pe);
80: nel = pe - ps;
81:
82: DMSwarmSetLocalSizes(dm,npoints_q*nel,-1);
83: DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
84: DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
85:
86: DMGetCoordinatesLocal(dmc,&coorlocal);
87: DMGetCoordinateSection(dmc,&coordSection);
88:
89: pcnt = 0;
90: for (e=0; e<nel; e++) {
91: DMPlexVecGetClosure(dmc,coordSection,coorlocal,e,NULL,&elcoor);
92:
93: for (q=0; q<npoints_q; q++) {
94: for (d=0; d<dim; d++) {
95: swarm_coor[dim*pcnt+d] = 0.0;
96: for (k=0; k<npe; k++) {
97: swarm_coor[dim*pcnt+d] += basis[q][k] * PetscRealPart(elcoor[dim*k+d]);
98: }
99: }
100: swarm_cellid[pcnt] = e;
101: pcnt++;
102: }
103: DMPlexVecRestoreClosure(dmc,coordSection,coorlocal,e,NULL,&elcoor);
104: }
105: DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
106: DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
107:
108: PetscFree(xi);
109: for (q=0; q<npoints_q; q++) {
110: PetscFree(basis[q]);
111: }
112: PetscFree(basis);
113:
114: return(0);
115: }
117: PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX2D_Regular(DM dm,DM dmc,PetscInt npoints)
118: {
120: const PetscInt dim = 2;
121: PetscInt ii,jj,q,npoints_q,e,nel,npe,pcnt,ps,pe,d,k;
122: PetscReal *xi,ds,ds2;
123: PetscReal **basis;
124: Vec coorlocal;
125: PetscSection coordSection;
126: PetscScalar *elcoor = NULL;
127: PetscReal *swarm_coor;
128: PetscInt *swarm_cellid;
131: PetscMalloc1(dim*npoints*npoints,&xi);
132: pcnt = 0;
133: ds = 1.0/((PetscReal)(npoints-1));
134: ds2 = 1.0/((PetscReal)(npoints));
135: for (jj = 0; jj<npoints; jj++) {
136: for (ii=0; ii<npoints-jj; ii++) {
137: xi[dim*pcnt+0] = ii * ds;
138: xi[dim*pcnt+1] = jj * ds;
139:
140: xi[dim*pcnt+0] *= (1.0 - 1.2*ds2);
141: xi[dim*pcnt+1] *= (1.0 - 1.2*ds2);
142:
143: xi[dim*pcnt+0] += 0.35*ds2;
144: xi[dim*pcnt+1] += 0.35*ds2;
146: pcnt++;
147: }
148: }
149: npoints_q = pcnt;
150:
151: npe = 3; /* nodes per element (triangle) */
152: PetscMalloc1(npoints_q,&basis);
153: for (q=0; q<npoints_q; q++) {
154: PetscMalloc1(npe,&basis[q]);
155:
156: basis[q][0] = 1.0 - xi[dim*q+0] - xi[dim*q+1];
157: basis[q][1] = xi[dim*q+0];
158: basis[q][2] = xi[dim*q+1];
159: }
161: /* 0->cell, 1->edge, 2->vert */
162: DMPlexGetHeightStratum(dmc,0,&ps,&pe);
163: nel = pe - ps;
164:
165: DMSwarmSetLocalSizes(dm,npoints_q*nel,-1);
166: DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
167: DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
168:
169: DMGetCoordinatesLocal(dmc,&coorlocal);
170: DMGetCoordinateSection(dmc,&coordSection);
172: pcnt = 0;
173: for (e=0; e<nel; e++) {
174: DMPlexVecGetClosure(dmc,coordSection,coorlocal,e,NULL,&elcoor);
175:
176: for (q=0; q<npoints_q; q++) {
177: for (d=0; d<dim; d++) {
178: swarm_coor[dim*pcnt+d] = 0.0;
179: for (k=0; k<npe; k++) {
180: swarm_coor[dim*pcnt+d] += basis[q][k] * PetscRealPart(elcoor[dim*k+d]);
181: }
182: }
183: swarm_cellid[pcnt] = e;
184: pcnt++;
185: }
186: DMPlexVecRestoreClosure(dmc,coordSection,coorlocal,e,NULL,&elcoor);
187: }
188: DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
189: DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
190:
191: PetscFree(xi);
192: for (q=0; q<npoints_q; q++) {
193: PetscFree(basis[q]);
194: }
195: PetscFree(basis);
196:
197: return(0);
198: }
200: PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM dm,DM celldm,DMSwarmPICLayoutType layout,PetscInt layout_param)
201: {
203: PetscInt dim;
204:
206: DMGetDimension(celldm,&dim);
207: if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No 3D support for PLEX");
208: switch (layout) {
209: case DMSWARMPIC_LAYOUT_REGULAR:
210: private_DMSwarmInsertPointsUsingCellDM_PLEX2D_Regular(dm,celldm,layout_param);
211: break;
212: case DMSWARMPIC_LAYOUT_GAUSS:
213: SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Gauss layout not supported for PLEX");
214: break;
215: case DMSWARMPIC_LAYOUT_SUBDIVISION:
216: private_DMSwarmInsertPointsUsingCellDM_PLEX2D_SubDivide(dm,celldm,layout_param);
217: break;
218: }
219: return(0);
220: }
222: /*
223: typedef struct {
224: PetscReal x,y;
225: } Point2d;
227: static PetscErrorCode signp2d(Point2d p1, Point2d p2, Point2d p3,PetscReal *s)
228: {
230: *s = (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
231: return(0);
232: }
233: */
234: /*
235: static PetscErrorCode PointInTriangle(Point2d pt, Point2d v1, Point2d v2, Point2d v3,PetscBool *v)
236: {
237: PetscReal s1,s2,s3;
238: PetscBool b1, b2, b3;
239:
241: signp2d(pt, v1, v2,&s1); b1 = s1 < 0.0f;
242: signp2d(pt, v2, v3,&s2); b2 = s2 < 0.0f;
243: signp2d(pt, v3, v1,&s3); b3 = s3 < 0.0f;
244:
245: *v = ((b1 == b2) && (b2 == b3));
246: return(0);
247: }
248: */
249: /*
250: static PetscErrorCode _ComputeLocalCoordinateAffine2d(PetscReal xp[],PetscReal coords[],PetscReal xip[],PetscReal *dJ)
251: {
252: PetscReal x1,y1,x2,y2,x3,y3;
253: PetscReal c,b[2],A[2][2],inv[2][2],detJ,od;
254:
256: x1 = coords[2*0+0];
257: x2 = coords[2*1+0];
258: x3 = coords[2*2+0];
259:
260: y1 = coords[2*0+1];
261: y2 = coords[2*1+1];
262: y3 = coords[2*2+1];
263:
264: c = x1 - 0.5*x1 - 0.5*x1 + 0.5*x2 + 0.5*x3;
265: b[0] = xp[0] - c;
266: c = y1 - 0.5*y1 - 0.5*y1 + 0.5*y2 + 0.5*y3;
267: b[1] = xp[1] - c;
268:
269: A[0][0] = -0.5*x1 + 0.5*x2; A[0][1] = -0.5*x1 + 0.5*x3;
270: A[1][0] = -0.5*y1 + 0.5*y2; A[1][1] = -0.5*y1 + 0.5*y3;
271:
272: detJ = A[0][0]*A[1][1] - A[0][1]*A[1][0];
273: *dJ = PetscAbsReal(detJ);
274: od = 1.0/detJ;
275:
276: inv[0][0] = A[1][1] * od;
277: inv[0][1] = -A[0][1] * od;
278: inv[1][0] = -A[1][0] * od;
279: inv[1][1] = A[0][0] * od;
280:
281: xip[0] = inv[0][0]*b[0] + inv[0][1]*b[1];
282: xip[1] = inv[1][0]*b[0] + inv[1][1]*b[1];
283: return(0);
284: }
285: */
287: static PetscErrorCode ComputeLocalCoordinateAffine2d(PetscReal xp[],PetscScalar coords[],PetscReal xip[],PetscReal *dJ)
288: {
289: PetscReal x1,y1,x2,y2,x3,y3;
290: PetscReal b[2],A[2][2],inv[2][2],detJ,od;
291:
293: x1 = PetscRealPart(coords[2*0+0]);
294: x2 = PetscRealPart(coords[2*1+0]);
295: x3 = PetscRealPart(coords[2*2+0]);
296:
297: y1 = PetscRealPart(coords[2*0+1]);
298: y2 = PetscRealPart(coords[2*1+1]);
299: y3 = PetscRealPart(coords[2*2+1]);
300:
301: b[0] = xp[0] - x1;
302: b[1] = xp[1] - y1;
303:
304: A[0][0] = x2-x1; A[0][1] = x3-x1;
305: A[1][0] = y2-y1; A[1][1] = y3-y1;
306:
307: detJ = A[0][0]*A[1][1] - A[0][1]*A[1][0];
308: *dJ = PetscAbsReal(detJ);
309: od = 1.0/detJ;
310:
311: inv[0][0] = A[1][1] * od;
312: inv[0][1] = -A[0][1] * od;
313: inv[1][0] = -A[1][0] * od;
314: inv[1][1] = A[0][0] * od;
315:
316: xip[0] = inv[0][0]*b[0] + inv[0][1]*b[1];
317: xip[1] = inv[1][0]*b[0] + inv[1][1]*b[1];
318: return(0);
319: }
321: PetscErrorCode DMSwarmProjectField_ApproxP1_PLEX_2D(DM swarm,PetscReal *swarm_field,DM dm,Vec v_field)
322: {
324: const PetscReal PLEX_C_EPS = 1.0e-8;
325: Vec v_field_l,denom_l,coor_l,denom;
326: PetscInt k,p,e,npoints;
327: PetscInt *mpfield_cell;
328: PetscReal *mpfield_coor;
329: PetscReal xi_p[2];
330: PetscScalar Ni[3];
331: PetscSection coordSection;
332: PetscScalar *elcoor = NULL;
333:
335: VecZeroEntries(v_field);
336:
337: DMGetLocalVector(dm,&v_field_l);
338: DMGetGlobalVector(dm,&denom);
339: DMGetLocalVector(dm,&denom_l);
340: VecZeroEntries(v_field_l);
341: VecZeroEntries(denom);
342: VecZeroEntries(denom_l);
343:
344: DMGetCoordinatesLocal(dm,&coor_l);
345: DMGetCoordinateSection(dm,&coordSection);
346:
347: DMSwarmGetLocalSize(swarm,&npoints);
348: DMSwarmGetField(swarm,DMSwarmPICField_coor,NULL,NULL,(void**)&mpfield_coor);
349: DMSwarmGetField(swarm,DMSwarmPICField_cellid,NULL,NULL,(void**)&mpfield_cell);
350:
351: for (p=0; p<npoints; p++) {
352: PetscReal *coor_p,dJ;
353: PetscScalar elfield[3];
354: PetscBool point_located;
355:
356: e = mpfield_cell[p];
357: coor_p = &mpfield_coor[2*p];
358:
359: DMPlexVecGetClosure(dm,coordSection,coor_l,e,NULL,&elcoor);
361: /*
362: while (!point_located && (failed_counter < 25)) {
363: PointInTriangle(point, coords[0], coords[1], coords[2], &point_located);
364: point.x = coor_p[0];
365: point.y = coor_p[1];
366: point.x += 1.0e-10 * (2.0 * rand()/((double)RAND_MAX)-1.0);
367: point.y += 1.0e-10 * (2.0 * rand()/((double)RAND_MAX)-1.0);
368: failed_counter++;
369: }
371: if (!point_located){
372: PetscPrintf(PETSC_COMM_SELF,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D) with triangle coords (%1.8e,%1.8e) : (%1.8e,%1.8e) : (%1.8e,%1.8e) in %D iterations\n",point.x,point.y,e,coords[0].x,coords[0].y,coords[1].x,coords[1].y,coords[2].x,coords[2].y,failed_counter);
373: }
374:
375: if (!point_located) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D)\n",point.x,point.y,e);
376: else {
377: _ComputeLocalCoordinateAffine2d(coor_p,elcoor,xi_p,&dJ);
378: xi_p[0] = 0.5*(xi_p[0] + 1.0);
379: xi_p[1] = 0.5*(xi_p[1] + 1.0);
380:
381: PetscPrintf(PETSC_COMM_SELF,"[p=%D] x(%+1.4e,%+1.4e) -> mapped to element %D xi(%+1.4e,%+1.4e)\n",p,point.x,point.y,e,xi_p[0],xi_p[1]);
382:
383: }
384: */
386: ComputeLocalCoordinateAffine2d(coor_p,elcoor,xi_p,&dJ);
387: /*
388: PetscPrintf(PETSC_COMM_SELF,"[p=%D] x(%+1.4e,%+1.4e) -> mapped to element %D xi(%+1.4e,%+1.4e)\n",p,point.x,point.y,e,xi_p[0],xi_p[1]);
389: */
390: /*
391: point_located = PETSC_TRUE;
392: if (xi_p[0] < 0.0) {
393: if (xi_p[0] > -PLEX_C_EPS) {
394: xi_p[0] = 0.0;
395: } else {
396: point_located = PETSC_FALSE;
397: }
398: }
399: if (xi_p[1] < 0.0) {
400: if (xi_p[1] > -PLEX_C_EPS) {
401: xi_p[1] = 0.0;
402: } else {
403: point_located = PETSC_FALSE;
404: }
405: }
406: if (xi_p[1] > (1.0-xi_p[0])) {
407: if ((xi_p[1] - 1.0 + xi_p[0]) < PLEX_C_EPS) {
408: xi_p[1] = 1.0 - xi_p[0];
409: } else {
410: point_located = PETSC_FALSE;
411: }
412: }
413: if (!point_located){
414: PetscPrintf(PETSC_COMM_SELF,"[Error] xi,eta = %+1.8e, %+1.8e\n",xi_p[0],xi_p[1]);
415: PetscPrintf(PETSC_COMM_SELF,"[Error] Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D) with triangle coords (%1.8e,%1.8e) : (%1.8e,%1.8e) : (%1.8e,%1.8e)\n",coor_p[0],coor_p[1],e,elcoor[0],elcoor[1],elcoor[2],elcoor[3],elcoor[4],elcoor[5]);
416: }
417: if (!point_located) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D)\n",coor_p[0],coor_p[1],e);
418: */
420: Ni[0] = 1.0 - xi_p[0] - xi_p[1];
421: Ni[1] = xi_p[0];
422: Ni[2] = xi_p[1];
424: point_located = PETSC_TRUE;
425: for (k=0; k<3; k++) {
426: if (PetscRealPart(Ni[k]) < -PLEX_C_EPS) point_located = PETSC_FALSE;
427: if (PetscRealPart(Ni[k]) > (1.0+PLEX_C_EPS)) point_located = PETSC_FALSE;
428: }
429: if (!point_located){
430: PetscPrintf(PETSC_COMM_SELF,"[Error] xi,eta = %+1.8e, %+1.8e\n",(double)xi_p[0],(double)xi_p[1]);
431: PetscPrintf(PETSC_COMM_SELF,"[Error] Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D) with triangle coords (%1.8e,%1.8e) : (%1.8e,%1.8e) : (%1.8e,%1.8e)\n",(double)coor_p[0],(double)coor_p[1],e,(double)PetscRealPart(elcoor[0]),(double)PetscRealPart(elcoor[1]),(double)PetscRealPart(elcoor[2]),(double)PetscRealPart(elcoor[3]),(double)PetscRealPart(elcoor[4]),(double)PetscRealPart(elcoor[5]));
432: }
433: if (!point_located) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D)\n",(double)coor_p[0],(double)coor_p[1],e);
434:
435: for (k=0; k<3; k++) {
436: Ni[k] = Ni[k] * dJ;
437: elfield[k] = Ni[k] * swarm_field[p];
438: }
439:
440: DMPlexVecRestoreClosure(dm,coordSection,coor_l,e,NULL,&elcoor);
442: DMPlexVecSetClosure(dm, NULL,v_field_l, e, elfield, ADD_VALUES);
443: DMPlexVecSetClosure(dm, NULL,denom_l, e, Ni, ADD_VALUES);
444: }
445:
446: DMSwarmRestoreField(swarm,DMSwarmPICField_cellid,NULL,NULL,(void**)&mpfield_cell);
447: DMSwarmRestoreField(swarm,DMSwarmPICField_coor,NULL,NULL,(void**)&mpfield_coor);
448:
449: DMLocalToGlobalBegin(dm,v_field_l,ADD_VALUES,v_field);
450: DMLocalToGlobalEnd(dm,v_field_l,ADD_VALUES,v_field);
451: DMLocalToGlobalBegin(dm,denom_l,ADD_VALUES,denom);
452: DMLocalToGlobalEnd(dm,denom_l,ADD_VALUES,denom);
453:
454: VecPointwiseDivide(v_field,v_field,denom);
455:
456: DMRestoreLocalVector(dm,&v_field_l);
457: DMRestoreLocalVector(dm,&denom_l);
458: DMRestoreGlobalVector(dm,&denom);
459:
460: return(0);
461: }
463: PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[])
464: {
466: PetscInt f,dim;
467:
469: DMGetDimension(swarm,&dim);
470: switch (dim) {
471: case 2:
472: for (f=0; f<nfields; f++) {
473: PetscReal *swarm_field;
474:
475: DataFieldGetEntries(dfield[f],(void**)&swarm_field);
476: DMSwarmProjectField_ApproxP1_PLEX_2D(swarm,swarm_field,celldm,vecs[f]);
477: }
478: break;
479: case 3:
480: SETERRQ(PetscObjectComm((PetscObject)swarm),PETSC_ERR_SUP,"No support for 3D");
481: break;
482: default:
483: break;
484: }
485:
486: return(0);
487: }