// Logically collective dErr dUnitsCreateUnit(dUnits un,const char *type,const char *longname,const char *shortname,dInt n,const dReal expon[],dUnit *newunit) { dErr err; dUnit unit; dFunctionBegin; dValidHeader(un,dUNITS_CLASSID,1); if (n < 1 || n > dUNITS_MAX) dERROR(((dObject)un)->comm,PETSC_ERR_ARG_OUTOFRANGE,"The number of exponents %D must be positive, but no larger than %D",n,(dInt)dUNITS_MAX); dValidRealPointer(expon,5); dValidPointer(newunit,6); err = dUnitsGetEmptyUnit_Private(un,&unit);dCHK(err); err = PetscStrallocpy(type,&unit->quantity);dCHK(err); err = dUnitsAssignName(un,dUnitName,longname,n,expon,&unit->longname);dCHK(err); err = dUnitsAssignName(un,dUnitShortName,shortname,n,expon,&unit->shortname);dCHK(err); err = dUnitsAssignName(un,dUnitSIName,NULL,n,expon,&unit->siname);dCHK(err); unit->toSI = 1.0; unit->toCommon = 1.0; for (dInt i=0; i<n; i++) { dUnit base; err = dUnitsGetBase(un,i,&base);dCHK(err); unit->toCommon *= PetscPowScalar(dUnitDimensionalize(base,1.0),expon[i]); unit->toSI *= PetscPowScalar(dUnitDimensionalizeSI(base,1.0),expon[i]); unit->expon[i] = expon[i]; } *newunit = unit; dFunctionReturn(0); }
/** Set rotation for certain nodes in a function space * * @param fs the function space * @param is index set of nodes to rotate, sequential, with respect blocks of local vector * @param rot Rotation matrices at all nodes in \a is. Should have length \c bs*bs*size(is). * @param ns number of dofs to enforce strongly at each node (every entry must have 0<=ns[i]<=bs) * @param v Vector of values for strongly enforced dofs * * @example Consider 2D flow over a bed with known melt rates. Suppose the local velocity vector is * * [u0x,u0y; u1x,u1y; u2x,u2y; u3x,u3y | u4x,u4y] * * (4 owned blocks, one ghosted block) and nodes 1,4 are on the slip boundary with normal and tangent vectors n1,t1,n4,t4 * and melt rates r1,r4. To enforce the melt rate strongly, use * * \a is = [1,4] * \a rot = [n10,n11,t10,t11, n40,n41,t40,t41] * \a ns = [1,1] * \a v = [r1,r4] * * The rotated vector will become (. = \cdot) * * [u0x,u0y; u1.n1,u1.t1; u2x,u2y; u3x,u3y | u4.n4,u4.t4] * * and strongly enforcing melt rate produces the global vector * * [u0x,u0y; r1,u1.t1; u2x,u2y; u3x,u3y | r4,u4.t4] . * * This is what the solver sees, the Jacobian will always have rows and columns of the identity corresponding to the * strongly enforced components (2,8 of the local vector) and the residual will always be 0 in these components. Hence * the Newton step v will always be of the form * * [v0x,v0y; 0,v1y; v2x,v2y; v3x,v3y | 0,v4y] . **/ dErr dFSRotationCreate(dFS fs,IS is,dReal rmat[],dInt ns[],Vec v,dFSRotation *inrot) { dFSRotation rot; dInt bs,n; dErr err; dFunctionBegin; dValidHeader(fs,DM_CLASSID,1); dValidHeader(is,IS_CLASSID,2); dValidRealPointer(rmat,3); dValidIntPointer(ns,4); dValidHeader(v,VEC_CLASSID,5); dValidPointer(inrot,6); *inrot = 0; err = PetscHeaderCreate(rot,_p_dFSRotation,struct _dFSRotationOps,dFSROT_CLASSID,"dFSRotation","Local function space rotation","FS",PETSC_COMM_SELF,dFSRotationDestroy,dFSRotationView);dCHK(err); err = dFSGetBlockSize(fs,&bs);dCHK(err); rot->bs = bs; err = ISGetSize(is,&n);dCHK(err); rot->n = n; err = PetscObjectReference((PetscObject)is);dCHK(err); rot->is = is; err = PetscObjectReference((PetscObject)v);dCHK(err); rot->strong = v; for (dInt i=0; i<n; i++) { if (ns[i] < 0 || bs < ns[i]) dERROR(PETSC_COMM_SELF,1,"Number of strong dofs must be between 0 and bs=%d (inclusive)",bs); /* \todo Check that every rmat is orthogonal */ } err = dMallocA2(n*bs*bs,&rot->rmat,n,&rot->nstrong);dCHK(err); err = dMemcpy(rot->rmat,rmat,n*bs*bs*sizeof rmat[0]);dCHK(err); err = dMemcpy(rot->nstrong,ns,n*sizeof ns[0]);dCHK(err); *inrot = rot; dFunctionReturn(0); }