/** Get coordinates for every node in closure (every subelement vertex) * * @note This function cannot be implemented for all \a dFS types. For most purposes, users should * \a dFSGetGeometryVectorExpanded and evaluate (element by element) on the nodes of their choice * (with a self-quadrature). * * @param fs Function space * @param inx the new vector with block size 3 and the same number of blocks as the closure vector **/ dErr dFSGetNodalCoordinatesGlobal(dFS fs,Vec *inx) { dErr err; Vec Expanded,Ones,X,Count,Xclosure,Countclosure; dFS fs3; dFunctionBegin; dValidHeader(fs,DM_CLASSID,1); dValidPointer(inx,2); *inx = 0; err = dFSGetNodalCoordinateFS(fs,&fs3); dCHK(err); err = dFSGetNodalCoordinatesExpanded(fs,&Expanded); dCHK(err); if (!fs->nodalcoord.global) { err = dFSCreateGlobalVector(fs3,&fs->nodalcoord.global); dCHK(err); } X = fs->nodalcoord.global; /* Count the number of occurances of each node in the closure. */ err = VecDuplicate(Expanded,&Ones); dCHK(err); err = VecDuplicate(X,&Count); dCHK(err); err = VecDohpZeroEntries(Count); dCHK(err); err = VecSet(Ones,1.); dCHK(err); err = dFSExpandedToGlobal(fs3,Ones,Count,dFS_INHOMOGENEOUS,ADD_VALUES); dCHK(err); err = VecDestroy(&Ones); dCHK(err); err = VecDohpZeroEntries(X); dCHK(err); err = dFSExpandedToGlobal(fs3,Expanded,X,dFS_INHOMOGENEOUS,ADD_VALUES); dCHK(err); err = VecDohpGetClosure(X,&Xclosure); dCHK(err); err = VecDohpGetClosure(Count,&Countclosure); dCHK(err); err = VecPointwiseDivide(Xclosure,Xclosure,Countclosure); dCHK(err); err = VecDohpRestoreClosure(X,&Xclosure); dCHK(err); err = VecDohpRestoreClosure(Count,&Countclosure); dCHK(err); err = VecDestroy(&Count); dCHK(err); *inx = X; dFunctionReturn(0); }
/** Create a cache for Dirichlet part of closure vector, and scatter from global closure to Dirichlet cache. @arg[in] gvec Global vector @arg[out] dcache New vector to hold the Dirichlet values @arg[out] dscat Scatter from global closure to \a dcache @note This could be local but it doesn't cost anything to make it global. **/ dErr VecDohpCreateDirichletCache(Vec gvec,Vec *dcache,VecScatter *dscat) { MPI_Comm comm; dErr err; dBool isdohp; IS from; Vec gc; dInt n,nc,crstart; dFunctionBegin; dValidHeader(gvec,VEC_CLASSID,1); dValidPointer(dcache,2); dValidPointer(dscat,3); err = PetscTypeCompare((PetscObject)gvec,VECDOHP,&isdohp);dCHK(err); if (!isdohp) dERROR(PETSC_COMM_SELF,PETSC_ERR_SUP,"Vec type %s",((PetscObject)gvec)->type_name); err = PetscObjectGetComm((PetscObject)gvec,&comm);dCHK(err); err = VecGetLocalSize(gvec,&n);dCHK(err); err = VecDohpGetClosure(gvec,&gc);dCHK(err); err = VecGetLocalSize(gc,&nc);dCHK(err); err = VecGetOwnershipRange(gc,&crstart,NULL);dCHK(err); err = VecCreateMPI(comm,nc-n,PETSC_DECIDE,dcache);dCHK(err); err = ISCreateStride(comm,nc-n,crstart+n,1,&from);dCHK(err); err = VecScatterCreate(gc,from,*dcache,NULL,dscat);dCHK(err); err = VecDohpRestoreClosure(gvec,&gc);dCHK(err); err = ISDestroy(&from);dCHK(err); /* \todo deal with rotations */ dFunctionReturn(0); }
dErr VecDohpZeroEntries(Vec v) { dErr err; dBool isdohp; Vec c; dFunctionBegin; dValidHeader(v,VEC_CLASSID,1); err = PetscTypeCompare((dObject)v,VECDOHP,&isdohp);dCHK(err); if (!isdohp) dERROR(PETSC_COMM_SELF,PETSC_ERR_SUP,"Vector type %s",((dObject)v)->type_name); err = VecDohpGetClosure(v,&c);dCHK(err); err = VecZeroEntries(c);dCHK(err); err = VecDohpRestoreClosure(v,&c);dCHK(err); dFunctionReturn(0); }
dErr dFSSubElementMeshView(dFS fs,dViewer view) { dErr err; dInt nelem,nverts,nconn,*suboff,*subind,n,bs; dEntTopology *subtopo; Vec X,Xc; const dReal *x; const char *name; dFunctionBegin; err = dFSGetSubElementMeshSize(fs,&nelem,&nverts,&nconn); dCHK(err); dASSERT(nconn == 8*nelem); /* Assume Hex */ err = dMallocA3(nelem,&subtopo,nelem+1,&suboff,nconn,&subind); dCHK(err); err = dFSGetSubElementMesh(fs,nelem,nconn,subtopo,suboff,subind); dCHK(err); err = PetscObjectGetName((dObject)fs,&name); dCHK(err); err = PetscViewerASCIIPrintf(view,"SubElementMesh name=%s nelem=%D nverts=%D\n",name,nelem,nverts); dCHK(err); err = dIntTableView(nelem,8,subind,view,"subconn"); dCHK(err); err = dFree3(subtopo,suboff,subind); dCHK(err); err = dFSGetNodalCoordinatesGlobal(fs,&X); dCHK(err); err = VecDohpGetClosure(X,&Xc); dCHK(err); err = VecGetLocalSize(Xc,&n); dCHK(err); err = VecGetBlockSize(Xc,&bs); dCHK(err); err = VecGetArrayRead(Xc,&x); dCHK(err); err = dRealTableView(n/bs,bs,x,view,"coords"); dCHK(err); err = VecRestoreArrayRead(Xc,&x); dCHK(err); err = VecDohpRestoreClosure(X,&Xc); dCHK(err); dFunctionReturn(0); }
static dErr VecDuplicate_Dohp(Vec x,Vec *iny) { Vec y,xc,yc; Vec_MPI *ympi; dScalar *a; dErr err; dFunctionBegin; dValidHeader(x,VEC_CLASSID,1); dValidPointer(iny,2); *iny = 0; err = VecDohpGetClosure(x,&xc);dCHK(err); err = VecDuplicate(xc,&yc);dCHK(err); err = VecDohpRestoreClosure(x,&xc);dCHK(err); /* The rest is mostly the same as VecDuplicate_MPI, but we can't call that because it allocates memory. * Unfortunately, this is fragile if the VecMPI implementation changes. I think this part of PETSc is quite stable and * I will be sufficiently involved to notice changes here. Famous last words. */ err = VecCreate(((dObject)x)->comm,&y);dCHK(err); err = PetscLayoutReference(x->map,&y->map);dCHK(err); err = VecGetArray(yc,&a);dCHK(err); err = VecCreate_MPI_Private(y,PETSC_FALSE,0,a);dCHK(err); err = VecRestoreArray(yc,&a);dCHK(err); ympi = y->data; err = dMemcpy(y->ops,x->ops,sizeof(struct _VecOps));dCHK(err); ympi->localrep = yc; /* subverting .localrep to mean closed form */ y->stash.donotstash = x->stash.donotstash; y->stash.ignorenegidx = x->stash.ignorenegidx; err = PetscOListDuplicate(((dObject)x)->olist,&((dObject)y)->olist);dCHK(err); err = PetscFListDuplicate(((dObject)x)->qlist,&((dObject)y)->qlist);dCHK(err); y->map->bs = x->map->bs; y->bstash.bs = x->bstash.bs; err = PetscObjectChangeTypeName((dObject)y,VECDOHP);dCHK(err); *iny = y; dFunctionReturn(0); }
/** Apply rotation to global vector * * @note does nothing if rotation is NULL **/ dErr dFSRotationApply(dFSRotation rot,Vec g,dFSRotateMode rmode,dFSHomogeneousMode hmode) { dErr err; Vec gc,lf; dFunctionBegin; if (!rot) dFunctionReturn(0); dValidHeader(rot,dFSROT_CLASSID,1); dValidHeader(g,VEC_CLASSID,2); if (rot->ops->apply) { err = rot->ops->apply(rot,g,rmode,hmode);dCHK(err); } else { err = VecDohpGetClosure(g,&gc);dCHK(err); err = VecGhostGetLocalForm(gc,&lf);dCHK(err); err = dFSRotationApplyLocal(rot,lf,rmode,hmode);dCHK(err); /* \todo only rotate the global portion */ err = VecGhostRestoreLocalForm(gc,&lf);dCHK(err); err = VecDohpRestoreClosure(g,&gc);dCHK(err); } dFunctionReturn(0); }