1*3c611800SMark Adams static char help[] = "Example program demonstrating projection between particle and finite element spaces using OpenMP in 2D cylindrical coordinates\n"; 2*3c611800SMark Adams 3*3c611800SMark Adams #include "petscdmplex.h" 4*3c611800SMark Adams #include "petscds.h" 5*3c611800SMark Adams #include "petscdmswarm.h" 6*3c611800SMark Adams #include "petscksp.h" 7*3c611800SMark Adams #include <petsc/private/petscimpl.h> 8*3c611800SMark Adams #if defined(PETSC_HAVE_OPENMP) && defined(PETSC_HAVE_THREADSAFETY) 9*3c611800SMark Adams #include <omp.h> 10*3c611800SMark Adams #endif 11*3c611800SMark Adams 12*3c611800SMark Adams typedef struct { 13*3c611800SMark Adams Mat MpTrans; 14*3c611800SMark Adams Mat Mp; 15*3c611800SMark Adams Vec ff; 16*3c611800SMark Adams Vec uu; 17*3c611800SMark Adams } MatShellCtx; 18*3c611800SMark Adams 19*3c611800SMark Adams PetscErrorCode MatMultMtM_SeqAIJ(Mat MtM,Vec xx,Vec yy) 20*3c611800SMark Adams { 21*3c611800SMark Adams MatShellCtx *matshellctx; 22*3c611800SMark Adams PetscErrorCode ierr; 23*3c611800SMark Adams 24*3c611800SMark Adams PetscFunctionBeginUser; 25*3c611800SMark Adams ierr = MatShellGetContext(MtM,&matshellctx);CHKERRQ(ierr); 26*3c611800SMark Adams if (!matshellctx) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "No context"); 27*3c611800SMark Adams ierr = MatMult(matshellctx->Mp, xx, matshellctx->ff);CHKERRQ(ierr); 28*3c611800SMark Adams ierr = MatMult(matshellctx->MpTrans, matshellctx->ff, yy);CHKERRQ(ierr); 29*3c611800SMark Adams PetscFunctionReturn(0); 30*3c611800SMark Adams } 31*3c611800SMark Adams 32*3c611800SMark Adams PetscErrorCode MatMultAddMtM_SeqAIJ(Mat MtM,Vec xx, Vec yy, Vec zz) 33*3c611800SMark Adams { 34*3c611800SMark Adams MatShellCtx *matshellctx; 35*3c611800SMark Adams PetscErrorCode ierr; 36*3c611800SMark Adams 37*3c611800SMark Adams PetscFunctionBeginUser; 38*3c611800SMark Adams ierr = MatShellGetContext(MtM,&matshellctx);CHKERRQ(ierr); 39*3c611800SMark Adams if (!matshellctx) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "No context"); 40*3c611800SMark Adams ierr = MatMult(matshellctx->Mp, xx, matshellctx->ff);CHKERRQ(ierr); 41*3c611800SMark Adams ierr = MatMultAdd(matshellctx->MpTrans, matshellctx->ff, yy, zz);CHKERRQ(ierr); 42*3c611800SMark Adams PetscFunctionReturn(0); 43*3c611800SMark Adams } 44*3c611800SMark Adams 45*3c611800SMark Adams PetscErrorCode createSwarm(const DM dm, DM *sw) 46*3c611800SMark Adams { 47*3c611800SMark Adams PetscErrorCode ierr; 48*3c611800SMark Adams PetscInt Nc = 1, dim = 2; 49*3c611800SMark Adams 50*3c611800SMark Adams PetscFunctionBeginUser; 51*3c611800SMark Adams ierr = DMCreate(PETSC_COMM_SELF, sw);CHKERRQ(ierr); 52*3c611800SMark Adams ierr = DMSetType(*sw, DMSWARM);CHKERRQ(ierr); 53*3c611800SMark Adams ierr = DMSetDimension(*sw, dim);CHKERRQ(ierr); 54*3c611800SMark Adams ierr = DMSwarmSetType(*sw, DMSWARM_PIC);CHKERRQ(ierr); 55*3c611800SMark Adams ierr = DMSwarmSetCellDM(*sw, dm);CHKERRQ(ierr); 56*3c611800SMark Adams ierr = DMSwarmRegisterPetscDatatypeField(*sw, "w_q", Nc, PETSC_SCALAR);CHKERRQ(ierr); 57*3c611800SMark Adams ierr = DMSwarmFinalizeFieldRegister(*sw);CHKERRQ(ierr); 58*3c611800SMark Adams ierr = DMSetFromOptions(*sw);CHKERRQ(ierr); 59*3c611800SMark Adams PetscFunctionReturn(0); 60*3c611800SMark Adams } 61*3c611800SMark Adams 62*3c611800SMark Adams PetscErrorCode gridToParticles(const DM dm, DM sw, PetscReal *moments, Vec rhs, Mat M_p) 63*3c611800SMark Adams { 64*3c611800SMark Adams PetscBool is_lsqr; 65*3c611800SMark Adams KSP ksp; 66*3c611800SMark Adams Mat PM_p=NULL,MtM,D; 67*3c611800SMark Adams Vec ff; 68*3c611800SMark Adams PetscErrorCode ierr; 69*3c611800SMark Adams PetscInt Np, timestep = 0, bs, N, M, nzl; 70*3c611800SMark Adams PetscReal time = 0.0; 71*3c611800SMark Adams PetscDataType dtype; 72*3c611800SMark Adams MatShellCtx *matshellctx; 73*3c611800SMark Adams 74*3c611800SMark Adams PetscFunctionBeginUser; 75*3c611800SMark Adams ierr = KSPCreate(PETSC_COMM_SELF, &ksp);CHKERRQ(ierr); 76*3c611800SMark Adams ierr = KSPSetOptionsPrefix(ksp, "ftop_");CHKERRQ(ierr); 77*3c611800SMark Adams ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); 78*3c611800SMark Adams ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPLSQR,&is_lsqr); 79*3c611800SMark Adams if (!is_lsqr) { 80*3c611800SMark Adams ierr = MatGetLocalSize(M_p, &M, &N);CHKERRQ(ierr); 81*3c611800SMark Adams if (N>M) { 82*3c611800SMark Adams PC pc; 83*3c611800SMark Adams ierr = PetscInfo2(ksp, " M (%D) < M (%D) -- skip revert to lsqr\n",M,N);CHKERRQ(ierr); 84*3c611800SMark Adams is_lsqr = PETSC_TRUE; 85*3c611800SMark Adams ierr = KSPSetType(ksp,KSPLSQR);CHKERRQ(ierr); 86*3c611800SMark Adams ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 87*3c611800SMark Adams ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); // could put in better solver -ftop_pc_type bjacobi -ftop_sub_pc_type lu -ftop_sub_pc_factor_shift_type nonzero 88*3c611800SMark Adams } else { 89*3c611800SMark Adams ierr = PetscNew(&matshellctx);CHKERRQ(ierr); 90*3c611800SMark Adams ierr = MatCreateShell(PetscObjectComm((PetscObject)dm),N,N,PETSC_DECIDE,PETSC_DECIDE,matshellctx,&MtM);CHKERRQ(ierr); 91*3c611800SMark Adams ierr = MatTranspose(M_p,MAT_INITIAL_MATRIX,&matshellctx->MpTrans);CHKERRQ(ierr); 92*3c611800SMark Adams matshellctx->Mp = M_p; 93*3c611800SMark Adams ierr = MatShellSetOperation(MtM, MATOP_MULT, (void (*)(void))MatMultMtM_SeqAIJ);CHKERRQ(ierr); 94*3c611800SMark Adams ierr = MatShellSetOperation(MtM, MATOP_MULT_ADD, (void (*)(void))MatMultAddMtM_SeqAIJ);CHKERRQ(ierr); 95*3c611800SMark Adams ierr = MatCreateVecs(M_p,&matshellctx->uu,&matshellctx->ff);CHKERRQ(ierr); 96*3c611800SMark Adams ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,N,N,1,NULL,&D);CHKERRQ(ierr); 97*3c611800SMark Adams for (int i=0 ; i<N ; i++) { 98*3c611800SMark Adams const PetscScalar *vals; 99*3c611800SMark Adams const PetscInt *cols; 100*3c611800SMark Adams PetscScalar dot = 0; 101*3c611800SMark Adams ierr = MatGetRow(matshellctx->MpTrans,i,&nzl,&cols,&vals);CHKERRQ(ierr); 102*3c611800SMark Adams for (int ii=0 ; ii<nzl ; ii++) dot += PetscSqr(vals[ii]); 103*3c611800SMark Adams if (dot==0.0) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Row %D is empty", i); 104*3c611800SMark Adams ierr = MatSetValue(D,i,i,dot,INSERT_VALUES); 105*3c611800SMark Adams } 106*3c611800SMark Adams ierr = MatAssemblyBegin(D, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 107*3c611800SMark Adams ierr = MatAssemblyEnd(D, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 108*3c611800SMark Adams PetscInfo2(M_p,"createMtMKSP Have %D eqs, nzl = %D\n",N,nzl); 109*3c611800SMark Adams ierr = KSPSetOperators(ksp, MtM, D);CHKERRQ(ierr); 110*3c611800SMark Adams ierr = MatViewFromOptions(D,NULL,"-ftop2_D_mat_view");CHKERRQ(ierr); 111*3c611800SMark Adams ierr = MatViewFromOptions(M_p,NULL,"-ftop2_Mp_mat_view");CHKERRQ(ierr); 112*3c611800SMark Adams ierr = MatViewFromOptions(matshellctx->MpTrans,NULL,"-ftop2_MpTranspose_mat_view");CHKERRQ(ierr); 113*3c611800SMark Adams } 114*3c611800SMark Adams } 115*3c611800SMark Adams if (is_lsqr) { 116*3c611800SMark Adams PC pc; 117*3c611800SMark Adams PetscBool is_bjac; 118*3c611800SMark Adams ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 119*3c611800SMark Adams ierr = PetscObjectTypeCompare((PetscObject)pc,PCBJACOBI,&is_bjac); 120*3c611800SMark Adams if (is_bjac) { 121*3c611800SMark Adams ierr = DMSwarmCreateMassMatrixSquare(sw, dm, &PM_p);CHKERRQ(ierr); 122*3c611800SMark Adams ierr = KSPSetOperators(ksp, M_p, PM_p);CHKERRQ(ierr); 123*3c611800SMark Adams } else { 124*3c611800SMark Adams ierr = KSPSetOperators(ksp, M_p, M_p);CHKERRQ(ierr); 125*3c611800SMark Adams } 126*3c611800SMark Adams } 127*3c611800SMark Adams ierr = DMSwarmCreateGlobalVectorFromField(sw, "w_q", &ff);CHKERRQ(ierr); // this grabs access !!!!! 128*3c611800SMark Adams if (!is_lsqr) { 129*3c611800SMark Adams ierr = KSPSolve(ksp, rhs, matshellctx->uu);CHKERRQ(ierr); 130*3c611800SMark Adams ierr = MatMult(M_p, matshellctx->uu, ff);CHKERRQ(ierr); 131*3c611800SMark Adams ierr = MatDestroy(&matshellctx->MpTrans);CHKERRQ(ierr); 132*3c611800SMark Adams ierr = VecDestroy(&matshellctx->ff);CHKERRQ(ierr); 133*3c611800SMark Adams ierr = VecDestroy(&matshellctx->uu);CHKERRQ(ierr); 134*3c611800SMark Adams ierr = MatDestroy(&D);CHKERRQ(ierr); 135*3c611800SMark Adams ierr = MatDestroy(&MtM);CHKERRQ(ierr); 136*3c611800SMark Adams ierr = PetscFree(matshellctx);CHKERRQ(ierr); 137*3c611800SMark Adams } else { 138*3c611800SMark Adams ierr = KSPSolveTranspose(ksp, rhs, ff);CHKERRQ(ierr); 139*3c611800SMark Adams } 140*3c611800SMark Adams ierr = KSPDestroy(&ksp);CHKERRQ(ierr); 141*3c611800SMark Adams /* Visualize particle field */ 142*3c611800SMark Adams ierr = DMSetOutputSequenceNumber(sw, timestep, time);CHKERRQ(ierr); 143*3c611800SMark Adams ierr = VecViewFromOptions(ff, NULL, "-weights_view");CHKERRQ(ierr); 144*3c611800SMark Adams ierr = DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &ff);CHKERRQ(ierr); 145*3c611800SMark Adams 146*3c611800SMark Adams /* compute energy */ 147*3c611800SMark Adams if (moments) { 148*3c611800SMark Adams PetscReal *wq, *coords; 149*3c611800SMark Adams ierr = DMSwarmGetLocalSize(sw,&Np);CHKERRQ(ierr); 150*3c611800SMark Adams ierr = DMSwarmGetField(sw, "w_q", &bs, &dtype, (void**)&wq);CHKERRQ(ierr); 151*3c611800SMark Adams ierr = DMSwarmGetField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void**)&coords);CHKERRQ(ierr); 152*3c611800SMark Adams moments[0] = moments[1] = moments[2] = 0; 153*3c611800SMark Adams for (int p=0;p<Np;p++) { 154*3c611800SMark Adams moments[0] += wq[p]; 155*3c611800SMark Adams moments[1] += wq[p] * coords[p*2+0]; // x-momentum 156*3c611800SMark Adams moments[2] += wq[p] * (PetscSqr(coords[p*2+0])+PetscSqr(coords[p*2+1])); 157*3c611800SMark Adams } 158*3c611800SMark Adams ierr = DMSwarmRestoreField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void**)&coords);CHKERRQ(ierr); 159*3c611800SMark Adams ierr = DMSwarmRestoreField(sw, "w_q", &bs, &dtype, (void**)&wq);CHKERRQ(ierr); 160*3c611800SMark Adams } 161*3c611800SMark Adams ierr = MatDestroy(&PM_p); 162*3c611800SMark Adams 163*3c611800SMark Adams PetscFunctionReturn(0); 164*3c611800SMark Adams } 165*3c611800SMark Adams 166*3c611800SMark Adams PetscErrorCode particlesToGrid(const DM dm, DM sw, const PetscInt Np, const PetscInt a_tid, const PetscInt dim, const PetscInt target, 167*3c611800SMark Adams const PetscReal xx[], const PetscReal yy[], const PetscReal a_wp[], Vec rho, Mat *Mp_out) 168*3c611800SMark Adams { 169*3c611800SMark Adams 170*3c611800SMark Adams PetscBool removePoints = PETSC_TRUE; 171*3c611800SMark Adams PetscReal *wq, *coords; 172*3c611800SMark Adams PetscDataType dtype; 173*3c611800SMark Adams Mat M_p; 174*3c611800SMark Adams Vec ff; 175*3c611800SMark Adams PetscErrorCode ierr; 176*3c611800SMark Adams PetscInt bs,p,zero=0; 177*3c611800SMark Adams 178*3c611800SMark Adams PetscFunctionBeginUser; 179*3c611800SMark Adams ierr = DMSwarmSetLocalSizes(sw, Np, zero);CHKERRQ(ierr); 180*3c611800SMark Adams ierr = DMSwarmGetField(sw, "w_q", &bs, &dtype, (void**)&wq);CHKERRQ(ierr); 181*3c611800SMark Adams ierr = DMSwarmGetField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void**)&coords);CHKERRQ(ierr); 182*3c611800SMark Adams for (p=0;p<Np;p++) { 183*3c611800SMark Adams coords[p*2+0] = xx[p]; 184*3c611800SMark Adams coords[p*2+1] = yy[p]; 185*3c611800SMark Adams wq[p] = a_wp[p]; 186*3c611800SMark Adams } 187*3c611800SMark Adams ierr = DMSwarmRestoreField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void**)&coords);CHKERRQ(ierr); 188*3c611800SMark Adams ierr = DMSwarmRestoreField(sw, "w_q", &bs, &dtype, (void**)&wq);CHKERRQ(ierr); 189*3c611800SMark Adams ierr = DMSwarmMigrate(sw, removePoints);CHKERRQ(ierr); 190*3c611800SMark Adams ierr = PetscObjectSetName((PetscObject)sw, "Particle Grid");CHKERRQ(ierr); 191*3c611800SMark Adams if (a_tid==target) {ierr = DMViewFromOptions(sw, NULL, "-swarm_view");CHKERRQ(ierr);} 192*3c611800SMark Adams 193*3c611800SMark Adams /* Project particles to field */ 194*3c611800SMark Adams /* This gives M f = \int_\Omega \phi f, which looks like a rhs for a PDE */ 195*3c611800SMark Adams ierr = DMCreateMassMatrix(sw, dm, &M_p);CHKERRQ(ierr); 196*3c611800SMark Adams ierr = PetscObjectSetName((PetscObject)rho, "rho");CHKERRQ(ierr); 197*3c611800SMark Adams 198*3c611800SMark Adams ierr = DMSwarmCreateGlobalVectorFromField(sw, "w_q", &ff);CHKERRQ(ierr); // this grabs access !!!!! 199*3c611800SMark Adams ierr = PetscObjectSetName((PetscObject)ff, "weights");CHKERRQ(ierr); 200*3c611800SMark Adams ierr = MatMultTranspose(M_p, ff, rho);CHKERRQ(ierr); 201*3c611800SMark Adams ierr = DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &ff);CHKERRQ(ierr); 202*3c611800SMark Adams 203*3c611800SMark Adams /* Visualize mesh field */ 204*3c611800SMark Adams if (a_tid==target) {ierr = VecViewFromOptions(rho, NULL, "-rho_view");CHKERRQ(ierr);} 205*3c611800SMark Adams // output 206*3c611800SMark Adams *Mp_out = M_p; 207*3c611800SMark Adams 208*3c611800SMark Adams PetscFunctionReturn(0); 209*3c611800SMark Adams } 210*3c611800SMark Adams static PetscErrorCode maxwellian(PetscInt dim, const PetscReal x[], PetscReal kt_m, PetscReal n, PetscScalar *u) 211*3c611800SMark Adams { 212*3c611800SMark Adams PetscInt i; 213*3c611800SMark Adams PetscReal v2 = 0, theta = 2*kt_m; /* theta = 2kT/mc^2 */ 214*3c611800SMark Adams 215*3c611800SMark Adams PetscFunctionBegin; 216*3c611800SMark Adams /* compute the exponents, v^2 */ 217*3c611800SMark Adams for (i = 0; i < dim; ++i) v2 += x[i]*x[i]; 218*3c611800SMark Adams /* evaluate the Maxwellian */ 219*3c611800SMark Adams u[0] = n*PetscPowReal(PETSC_PI*theta,-1.5)*(PetscExpReal(-v2/theta)) * 2.*PETSC_PI*x[1]; // radial term for 2D axi-sym. 220*3c611800SMark Adams PetscFunctionReturn(0); 221*3c611800SMark Adams } 222*3c611800SMark Adams #define NUM_SOLVE_LOOPS 100 223*3c611800SMark Adams #define MAX_NUM_THRDS 12 224*3c611800SMark Adams PetscErrorCode go() 225*3c611800SMark Adams { 226*3c611800SMark Adams DM dm_t[MAX_NUM_THRDS], sw_t[MAX_NUM_THRDS]; 227*3c611800SMark Adams PetscFE fe; 228*3c611800SMark Adams PetscInt dim = 2, Nc = 1, timestep = 0, i, faces[3]; 229*3c611800SMark Adams PetscInt Np[2] = {10,10}, Np2[2], field = 0, target = 0, Np_t[MAX_NUM_THRDS]; 230*3c611800SMark Adams PetscReal time = 0.0, moments_0[3], moments_1[3], vol; 231*3c611800SMark Adams PetscReal lo[3] = {-5,0,-5}, hi[3] = {5,5,5}, h[3], hp[3], *xx_t[MAX_NUM_THRDS], *yy_t[MAX_NUM_THRDS], *wp_t[MAX_NUM_THRDS], solve_time = 0; 232*3c611800SMark Adams Vec rho_t[MAX_NUM_THRDS], rhs_t[MAX_NUM_THRDS]; 233*3c611800SMark Adams Mat M_p_t[MAX_NUM_THRDS]; 234*3c611800SMark Adams PetscErrorCode ierr; 235*3c611800SMark Adams #if defined PETSC_USE_LOG 236*3c611800SMark Adams PetscLogStage stage; 237*3c611800SMark Adams PetscLogEvent swarm_create_ev, solve_ev, solve_loop_ev; 238*3c611800SMark Adams #endif 239*3c611800SMark Adams #if defined(PETSC_HAVE_OPENMP) && defined(PETSC_HAVE_THREADSAFETY) 240*3c611800SMark Adams PetscInt numthreads = PetscNumOMPThreads; 241*3c611800SMark Adams double starttime, endtime; 242*3c611800SMark Adams #else 243*3c611800SMark Adams PetscInt numthreads = 1; 244*3c611800SMark Adams #endif 245*3c611800SMark Adams 246*3c611800SMark Adams PetscFunctionBeginUser; 247*3c611800SMark Adams #if defined(PETSC_HAVE_OPENMP) && defined(PETSC_HAVE_THREADSAFETY) 248*3c611800SMark Adams if (numthreads>MAX_NUM_THRDS) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Too many threads %D > %D", numthreads, MAX_NUM_THRDS); 249*3c611800SMark Adams if (numthreads<=0) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "No threads %D > %D ", numthreads, MAX_NUM_THRDS); 250*3c611800SMark Adams #endif 251*3c611800SMark Adams if (target >= numthreads) target = numthreads-1; 252*3c611800SMark Adams ierr = PetscLogEventRegister("Create Swarm", DM_CLASSID, &swarm_create_ev);CHKERRQ(ierr); 253*3c611800SMark Adams ierr = PetscLogEventRegister("Single solve", DM_CLASSID, &solve_ev);CHKERRQ(ierr); 254*3c611800SMark Adams ierr = PetscLogEventRegister("Solve loop", DM_CLASSID, &solve_loop_ev);CHKERRQ(ierr); 255*3c611800SMark Adams ierr = PetscLogStageRegister("Solve", &stage);CHKERRQ(ierr); 256*3c611800SMark Adams i = dim; 257*3c611800SMark Adams ierr = PetscOptionsGetIntArray(NULL, NULL, "-dm_plex_box_faces", faces, &i, NULL);CHKERRQ(ierr); 258*3c611800SMark Adams i = dim; 259*3c611800SMark Adams ierr = PetscOptionsGetIntArray(NULL, NULL, "-np", Np, &i, NULL);CHKERRQ(ierr); 260*3c611800SMark Adams /* Create thread meshes */ 261*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 262*3c611800SMark Adams // setup mesh dm_t, could use PETSc's Landau create velocity space mesh here to get dm_t[tid] 263*3c611800SMark Adams ierr = DMCreate(PETSC_COMM_SELF, &dm_t[tid]);CHKERRQ(ierr); 264*3c611800SMark Adams ierr = DMSetType(dm_t[tid], DMPLEX);CHKERRQ(ierr); 265*3c611800SMark Adams ierr = DMSetFromOptions(dm_t[tid]);CHKERRQ(ierr); 266*3c611800SMark Adams ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, Nc, PETSC_FALSE, "", PETSC_DECIDE, &fe);CHKERRQ(ierr); 267*3c611800SMark Adams ierr = PetscFESetFromOptions(fe);CHKERRQ(ierr); 268*3c611800SMark Adams ierr = PetscObjectSetName((PetscObject)fe, "fe");CHKERRQ(ierr); 269*3c611800SMark Adams ierr = DMSetField(dm_t[tid], field, NULL, (PetscObject)fe);CHKERRQ(ierr); 270*3c611800SMark Adams ierr = DMCreateDS(dm_t[tid]);CHKERRQ(ierr); 271*3c611800SMark Adams ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 272*3c611800SMark Adams // helper vectors 273*3c611800SMark Adams ierr = DMSetOutputSequenceNumber(dm_t[tid], timestep, time);CHKERRQ(ierr); // not used 274*3c611800SMark Adams ierr = DMCreateGlobalVector(dm_t[tid], &rho_t[tid]);CHKERRQ(ierr); 275*3c611800SMark Adams ierr = DMCreateGlobalVector(dm_t[tid], &rhs_t[tid]);CHKERRQ(ierr); 276*3c611800SMark Adams // this mimics application code 277*3c611800SMark Adams ierr = DMGetBoundingBox(dm_t[tid], lo, hi);CHKERRQ(ierr); 278*3c611800SMark Adams if (tid==target) { 279*3c611800SMark Adams ierr = DMViewFromOptions(dm_t[tid], NULL, "-dm_view");CHKERRQ(ierr); 280*3c611800SMark Adams for (i=0,vol=1;i<dim;i++) { 281*3c611800SMark Adams h[i] = (hi[i] - lo[i])/faces[i]; 282*3c611800SMark Adams hp[i] = (hi[i] - lo[i])/Np[i]; 283*3c611800SMark Adams vol *= (hi[i] - lo[i]); 284*3c611800SMark Adams ierr = PetscInfo5(dm_t[tid]," lo = %g hi = %g n = %D h = %g hp = %g\n",lo[i],hi[i],faces[i],h[i],hp[i]);CHKERRQ(ierr); 285*3c611800SMark Adams } 286*3c611800SMark Adams } 287*3c611800SMark Adams } 288*3c611800SMark Adams // prepare particle data for problems. This mimics application code 289*3c611800SMark Adams ierr = PetscLogEventBegin(swarm_create_ev,0,0,0,0);CHKERRQ(ierr); 290*3c611800SMark Adams Np2[0] = Np[0]; Np2[1] = Np[1]; 291*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { // change size of particle list a little 292*3c611800SMark Adams Np_t[tid] = Np2[0]*Np2[1]; 293*3c611800SMark Adams ierr = PetscMalloc3(Np_t[tid],&xx_t[tid],Np_t[tid],&yy_t[tid],Np_t[tid],&wp_t[tid]);CHKERRQ(ierr); 294*3c611800SMark Adams if (tid==target) {moments_0[0] = moments_0[1] = moments_0[2] = 0;} 295*3c611800SMark Adams for (int pi=0, pp=0;pi<Np2[0];pi++) { 296*3c611800SMark Adams for (int pj=0;pj<Np2[1];pj++,pp++) { 297*3c611800SMark Adams xx_t[tid][pp] = lo[0] + hp[0]/2. + pi*hp[0]; 298*3c611800SMark Adams yy_t[tid][pp] = lo[1] + hp[1]/2. + pj*hp[1]; 299*3c611800SMark Adams { 300*3c611800SMark Adams PetscReal x[] = {xx_t[tid][pp],yy_t[tid][pp]}; 301*3c611800SMark Adams ierr = maxwellian(2, x, 1.0, vol/(PetscReal)Np_t[tid], &wp_t[tid][pp]); 302*3c611800SMark Adams } 303*3c611800SMark Adams if (tid==target) { //energy_0 += wp_t[tid][pp]*(PetscSqr(xx_t[tid][pp])+PetscSqr(yy_t[tid][pp])); 304*3c611800SMark Adams moments_0[0] += wp_t[tid][pp]; 305*3c611800SMark Adams moments_0[1] += wp_t[tid][pp] * xx_t[tid][pp]; // x-momentum 306*3c611800SMark Adams moments_0[2] += wp_t[tid][pp] * (PetscSqr(xx_t[tid][pp]) + PetscSqr(yy_t[tid][pp])); 307*3c611800SMark Adams } 308*3c611800SMark Adams } 309*3c611800SMark Adams } 310*3c611800SMark Adams Np2[0]++; Np2[1]++; 311*3c611800SMark Adams } 312*3c611800SMark Adams ierr = PetscLogEventEnd(swarm_create_ev,0,0,0,0);CHKERRQ(ierr); 313*3c611800SMark Adams ierr = PetscLogEventBegin(solve_ev,0,0,0,0);CHKERRQ(ierr); 314*3c611800SMark Adams /* Create particle swarm */ 315*3c611800SMark Adams PetscPragmaOMP(parallel for) 316*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 317*3c611800SMark Adams PetscErrorCode ierr_t; 318*3c611800SMark Adams ierr_t = createSwarm(dm_t[tid], &sw_t[tid]); 319*3c611800SMark Adams if (ierr_t) ierr = ierr_t; 320*3c611800SMark Adams } 321*3c611800SMark Adams CHKERRQ(ierr); 322*3c611800SMark Adams PetscPragmaOMP(parallel for) 323*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 324*3c611800SMark Adams PetscErrorCode ierr_t; 325*3c611800SMark Adams ierr_t = particlesToGrid(dm_t[tid], sw_t[tid], Np_t[tid], tid, dim, target, xx_t[tid], yy_t[tid], wp_t[tid], rho_t[tid], &M_p_t[tid]); 326*3c611800SMark Adams if (ierr_t) ierr = ierr_t; 327*3c611800SMark Adams } 328*3c611800SMark Adams CHKERRQ(ierr); 329*3c611800SMark Adams /* Project field to particles */ 330*3c611800SMark Adams /* This gives f_p = M_p^+ M f */ 331*3c611800SMark Adams PetscPragmaOMP(parallel for) 332*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 333*3c611800SMark Adams PetscErrorCode ierr_t; 334*3c611800SMark Adams ierr_t = VecCopy(rho_t[tid], rhs_t[tid]); /* Identity: M^1 M rho */ 335*3c611800SMark Adams if (ierr_t) ierr = ierr_t; 336*3c611800SMark Adams } 337*3c611800SMark Adams CHKERRQ(ierr); 338*3c611800SMark Adams PetscPragmaOMP(parallel for) 339*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 340*3c611800SMark Adams PetscErrorCode ierr_t; 341*3c611800SMark Adams ierr_t = gridToParticles(dm_t[tid], sw_t[tid], (tid==target) ? moments_1 : NULL, rhs_t[tid], M_p_t[tid]); 342*3c611800SMark Adams if (ierr_t) ierr = ierr_t; 343*3c611800SMark Adams } 344*3c611800SMark Adams CHKERRQ(ierr); 345*3c611800SMark Adams /* Cleanup */ 346*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 347*3c611800SMark Adams ierr = MatDestroy(&M_p_t[tid]);CHKERRQ(ierr); 348*3c611800SMark Adams ierr = DMDestroy(&sw_t[tid]);CHKERRQ(ierr); 349*3c611800SMark Adams } 350*3c611800SMark Adams ierr = PetscLogEventEnd(solve_ev,0,0,0,0);CHKERRQ(ierr); 351*3c611800SMark Adams /* for timing */ 352*3c611800SMark Adams ierr = PetscOptionsClearValue(NULL,"-ftop_ksp_converged_reason");CHKERRQ(ierr); 353*3c611800SMark Adams ierr = PetscOptionsClearValue(NULL,"-ftop_ksp_monitor");CHKERRQ(ierr); 354*3c611800SMark Adams ierr = PetscOptionsClearValue(NULL,"-ftop_ksp_view");CHKERRQ(ierr); 355*3c611800SMark Adams ierr = PetscOptionsClearValue(NULL,"-info");CHKERRQ(ierr); 356*3c611800SMark Adams // repeat solve many times to get warmed up data 357*3c611800SMark Adams ierr = PetscLogStagePush(stage);CHKERRQ(ierr); 358*3c611800SMark Adams #if defined(PETSC_HAVE_OPENMP) && defined(PETSC_HAVE_THREADSAFETY) 359*3c611800SMark Adams starttime = MPI_Wtime(); 360*3c611800SMark Adams #endif 361*3c611800SMark Adams ierr = PetscLogEventBegin(solve_loop_ev,0,0,0,0);CHKERRQ(ierr); 362*3c611800SMark Adams for (int d=0; d<NUM_SOLVE_LOOPS; d++) { 363*3c611800SMark Adams /* Create particle swarm */ 364*3c611800SMark Adams PetscPragmaOMP(parallel for) 365*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 366*3c611800SMark Adams PetscErrorCode ierr_t; 367*3c611800SMark Adams ierr_t = createSwarm(dm_t[tid], &sw_t[tid]); 368*3c611800SMark Adams if (ierr_t) ierr = ierr_t; 369*3c611800SMark Adams } 370*3c611800SMark Adams CHKERRQ(ierr); 371*3c611800SMark Adams PetscPragmaOMP(parallel for) 372*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 373*3c611800SMark Adams PetscErrorCode ierr_t; 374*3c611800SMark Adams ierr_t = particlesToGrid(dm_t[tid], sw_t[tid], Np_t[tid], tid, dim, target, xx_t[tid], yy_t[tid], wp_t[tid], rho_t[tid], &M_p_t[tid]); 375*3c611800SMark Adams if (ierr_t) ierr = ierr_t; 376*3c611800SMark Adams } 377*3c611800SMark Adams CHKERRQ(ierr); 378*3c611800SMark Adams PetscPragmaOMP(parallel for) 379*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 380*3c611800SMark Adams PetscErrorCode ierr_t; 381*3c611800SMark Adams ierr_t = VecCopy(rho_t[tid], rhs_t[tid]); /* Identity: M^1 M rho */ 382*3c611800SMark Adams if (ierr_t) ierr = ierr_t; 383*3c611800SMark Adams } 384*3c611800SMark Adams CHKERRQ(ierr); 385*3c611800SMark Adams PetscPragmaOMP(parallel for) 386*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 387*3c611800SMark Adams PetscErrorCode ierr_t; 388*3c611800SMark Adams ierr_t = gridToParticles(dm_t[tid], sw_t[tid], NULL, rhs_t[tid], M_p_t[tid]); 389*3c611800SMark Adams if (ierr_t) ierr = ierr_t; 390*3c611800SMark Adams } 391*3c611800SMark Adams CHKERRQ(ierr); 392*3c611800SMark Adams /* Cleanup */ 393*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 394*3c611800SMark Adams ierr = MatDestroy(&M_p_t[tid]);CHKERRQ(ierr); 395*3c611800SMark Adams ierr = DMDestroy(&sw_t[tid]);CHKERRQ(ierr); 396*3c611800SMark Adams } 397*3c611800SMark Adams } 398*3c611800SMark Adams ierr = PetscLogEventEnd(solve_loop_ev,0,0,0,0);CHKERRQ(ierr); 399*3c611800SMark Adams #if defined(PETSC_HAVE_OPENMP) && defined(PETSC_HAVE_THREADSAFETY) 400*3c611800SMark Adams endtime = MPI_Wtime(); 401*3c611800SMark Adams solve_time += (endtime - starttime); 402*3c611800SMark Adams #endif 403*3c611800SMark Adams ierr = PetscLogStagePop();CHKERRQ(ierr); 404*3c611800SMark Adams // 405*3c611800SMark Adams ierr = PetscPrintf(PETSC_COMM_SELF,"Total number density: %20.12e (%20.12e); x-momentum = %g (%g); energy = %g error = %e, %D particles. Use %D threads, Solve time: %g\n", moments_1[0], moments_0[0], moments_1[1], moments_0[1], moments_1[2], (moments_1[2]-moments_0[2])/moments_0[2],Np[0]*Np[1],numthreads,solve_time);CHKERRQ(ierr); 406*3c611800SMark Adams /* Cleanup */ 407*3c611800SMark Adams for (int tid=0; tid<numthreads; tid++) { 408*3c611800SMark Adams ierr = VecDestroy(&rho_t[tid]);CHKERRQ(ierr); 409*3c611800SMark Adams ierr = VecDestroy(&rhs_t[tid]);CHKERRQ(ierr); 410*3c611800SMark Adams ierr = DMDestroy(&dm_t[tid]);CHKERRQ(ierr); 411*3c611800SMark Adams ierr = PetscFree3(xx_t[tid],yy_t[tid],wp_t[tid]);CHKERRQ(ierr); 412*3c611800SMark Adams } 413*3c611800SMark Adams 414*3c611800SMark Adams PetscFunctionReturn(0); 415*3c611800SMark Adams } 416*3c611800SMark Adams 417*3c611800SMark Adams int main(int argc, char **argv) 418*3c611800SMark Adams { 419*3c611800SMark Adams PetscErrorCode ierr; 420*3c611800SMark Adams ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr; 421*3c611800SMark Adams ierr = go();CHKERRQ(ierr); 422*3c611800SMark Adams ierr = PetscFinalize(); 423*3c611800SMark Adams return ierr; 424*3c611800SMark Adams } 425*3c611800SMark Adams 426*3c611800SMark Adams /*TEST 427*3c611800SMark Adams 428*3c611800SMark Adams build: 429*3c611800SMark Adams requires: !complex 430*3c611800SMark Adams 431*3c611800SMark Adams test: 432*3c611800SMark Adams suffix: 0 433*3c611800SMark Adams requires: double triangle 434*3c611800SMark Adams args: -dm_plex_simplex 0 -dm_plex_box_faces 4,2 -dm_plex_box_lower -2.0,0.0 -dm_plex_box_upper 2.0,2.0 -petscspace_degree 2 -ftop_ksp_type lsqr -ftop_pc_type none -dm_view -ftop_ksp_converged_reason -ftop_ksp_rtol 1.e-14 435*3c611800SMark Adams filter: grep -v DM_ | grep -v atomic 436*3c611800SMark Adams 437*3c611800SMark Adams test: 438*3c611800SMark Adams suffix: 1 439*3c611800SMark Adams requires: double triangle 440*3c611800SMark Adams args: -dm_plex_simplex 0 -dm_plex_box_faces 4,2 -dm_plex_box_lower -2.0,0.0 -dm_plex_box_upper 2.0,2.0 -petscspace_degree 2 -dm_plex_hash_location -ftop_ksp_type lsqr -ftop_pc_type bjacobi -ftop_sub_pc_type lu -ftop_sub_pc_factor_shift_type nonzero -dm_view -ftop_ksp_converged_reason -ftop_ksp_rtol 1.e-14 441*3c611800SMark Adams filter: grep -v DM_ | grep -v atomic 442*3c611800SMark Adams 443*3c611800SMark Adams test: 444*3c611800SMark Adams suffix: 2 445*3c611800SMark Adams requires: double triangle 446*3c611800SMark Adams args: -dm_plex_simplex 0 -dm_plex_box_faces 4,2 -dm_plex_box_lower -2.0,0.0 -dm_plex_box_upper 2.0,2.0 -petscspace_degree 2 -dm_plex_hash_location -ftop_ksp_type cg -ftop_pc_type jacobi -dm_view -ftop_ksp_converged_reason -ftop_ksp_rtol 1.e-14 447*3c611800SMark Adams filter: grep -v DM_ | grep -v atomic 448*3c611800SMark Adams 449*3c611800SMark Adams TEST*/ 450