Variable* Mesh_GenerateElGlobalIdVar( void* mesh ) { /* Returns a Variable that stores the global element indices. * Assumes the number of mesh elements never changes. */ Mesh* self = (Mesh*)mesh; char* name; unsigned dim; // if variable already exists return it if( self->eGlobalIdsVar ) return self->eGlobalIdsVar; dim = Mesh_GetDimSize(mesh); // Create the Variable data structure, int[local node count] self->lEls = Mesh_GetLocalSize( self, dim ); self->elgid = Memory_Alloc_Array( int, self->lEls, "Mesh::vertsgid" ); Stg_asprintf( &name, "%s-%s", self->name, "verticesGlobalIds" ); self->eGlobalIdsVar = Variable_NewScalar( name, NULL, Variable_DataType_Int, &self->lEls, NULL, (void**)&self->elgid, NULL ); Stg_Component_Build(self->eGlobalIdsVar, NULL, False); Stg_Component_Initialise(self->eGlobalIdsVar, NULL, False); free(name); // Evaluate the global indices for the local nodes int ii, gid; for( ii=0; ii<self->lEls; ii++ ) { gid = Mesh_DomainToGlobal( self, dim, ii ); Variable_SetValue( self->eGlobalIdsVar, ii, (void*)&gid ); } // return new variable return self->eGlobalIdsVar; }
PetscErrorCode KSPBuildPressure_CB_Nullspace_BSSCR(KSP ksp) { KSP_BSSCR *bsscr = (KSP_BSSCR *)ksp->data; FeEquationNumber *eq_num = bsscr->solver->st_sle->pSolnVec->feVariable->eqNum; FeMesh *feMesh = bsscr->solver->st_sle->pSolnVec->feVariable->feMesh; /* is the pressure mesh */ unsigned ijk[3]; Vec t, v; int numLocalNodes, globalNodeNumber, i, j, eq; MatStokesBlockScaling BA = bsscr->BA; PetscErrorCode ierr; Mat Amat,Pmat, G; MatStructure pflag; PetscFunctionBegin; /* get G matrix from Amat matrix operator on ksp */ ierr=Stg_PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);CHKERRQ(ierr); MatNestGetSubMat( Amat, 0,1, &G );/* G should always exist */ /* now create Vecs t and v to match size of G: i.e. pressure */ /* NOTE: not using "h" vector from ksp->vec_rhs because this part of the block vector doesn't always exist */ MatGetVecs( G, &t, PETSC_NULL );/* t and v are destroyed in KSPDestroy_BSSCR */ MatGetVecs( G, &v, PETSC_NULL );/* t and v such that can do G*t */ numLocalNodes = Mesh_GetLocalSize( feMesh, MT_VERTEX); /* number of nodes on current proc not counting any shadow nodes */ for(j=0;j<numLocalNodes;j++){ i = globalNodeNumber = Mesh_DomainToGlobal( feMesh, MT_VERTEX, j); RegularMeshUtils_Element_1DTo3D(feMesh, i, ijk); eq = eq_num->destinationArray[j][0];/* get global equation number -- 2nd arg is always 0 because pressure has only one dof */ if(eq != -1){ if( (ijk[0]+ijk[1]+ijk[2])%2 ==0 ){ VecSetValue(t,eq,1.0,INSERT_VALUES); } else{ VecSetValue(v,eq,1.0,INSERT_VALUES); }}} VecAssemblyBegin( t ); VecAssemblyEnd( t ); VecAssemblyBegin( v ); VecAssemblyEnd( v ); /* Scaling the null vectors here because it easier at the moment *//* maybe should do this in the original scaling function */ if( BA->scaling_exists == PETSC_TRUE ){ Vec R2; /* Get the scalings out the block mat data */ VecNestGetSubVec( BA->Rz, 1, &R2 ); VecPointwiseDivide( t, t, R2); /* x <- x * 1/R2 */ VecPointwiseDivide( v, v, R2); } bsscr_writeVec( t, "t", "Writing t vector"); bsscr_writeVec( v, "v", "Writing v vector"); bsscr->t=t; bsscr->v=v; PetscFunctionReturn(0); }
Bool _Mesh_Algorithms_SearchElements( void* algorithms, double* point, unsigned* elInd ) { Mesh_Algorithms* self = (Mesh_Algorithms*)algorithms; Mesh* mesh; unsigned dim, ind; assert( self ); assert( self->mesh ); assert( elInd ); mesh = self->mesh; if( Mesh_Algorithms_Search( self, point, &dim, &ind ) ) { unsigned nDims; nDims = Mesh_GetDimSize( mesh ); if( dim != nDims ) { unsigned nInc, *inc; unsigned lowest; unsigned global; unsigned inc_i; /* Must have required incidence for this to work. */ assert( Mesh_HasIncidence( mesh, dim, nDims ) ); Mesh_GetIncidence( mesh, dim, ind, nDims, self->incArray ); nInc = IArray_GetSize( self->incArray ); inc = (unsigned*)IArray_GetPtr( self->incArray ); assert( nInc ); lowest = Mesh_DomainToGlobal( mesh, nDims, inc[0] ); for( inc_i = 1; inc_i < nInc; inc_i++ ) { global = Mesh_DomainToGlobal( mesh, nDims, inc[inc_i] ); if( global < lowest ) lowest = global; } insist( Mesh_GlobalToDomain( mesh, nDims, lowest, elInd), == True ); }
void Spherical_CubedSphereNusselt_Output( UnderworldContext* context ) { Spherical_CubedSphereNusselt* self = NULL; Swarm* swarm = NULL; FeMesh* mesh = NULL; ElementType* elementType = NULL; Grid* grid = NULL; double avgT, vol; self = (Spherical_CubedSphereNusselt*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Spherical_CubedSphereNusselt_Type ); FeVariable *temperatureGradientsField = self->temperatureGradientsField; FeVariable *temperatureField = self->temperatureField; FeVariable *velocityField = self->velocityField; swarm = self->gaussSwarm; mesh = (FeMesh*)self->mesh; assert( self ); assert( mesh ); assert( swarm ); /* for each boundary element at the top integrate dT/dr & integrate T*v_r ASSUMPTIONS: * uses grid data structure for r,theta mesh (cartesian topology so i can) */ unsigned nEls, e_i, cell_i, nPoints, p_i, ijk[3]; IntegrationPoint* particle; double value[3], xyz[3], rtp[3], detJac, dT_dr, factor, vel[3], T, vel_rtp[3]; double gVolume[2], volume[2]; double J_Nu[2], gJ_Nu[2]; double rMin = ((RSGenerator*)mesh->generator)->crdMin[0]; double rMax = ((RSGenerator*)mesh->generator)->crdMin[1]; double dxdr[3], r; elementType = FeMesh_GetElementType( mesh, 0 ); // assuming all element are the same as el 0 memset( J_Nu, 0, 2*sizeof(double) ); memset( volume, 0, 2*sizeof(double) ); RegularMeshUtils_ErrorCheckAndGetDetails( (Mesh*)mesh, MT_VOLUME, &nEls, &grid ); for( e_i = 0; e_i < nEls; e_i++ ) { // use cartesian grid data structure - can improve later on to make more general RegularMeshUtils_Element_1DTo3D( mesh, Mesh_DomainToGlobal( (Mesh*)mesh, MT_VOLUME, e_i ), ijk ); // if element is on the outer radius boundary if( ijk[0] == grid->sizes[0] - 1 ) { // get integration number of integration points in cell cell_i = CellLayout_MapElementIdToCellId( swarm->cellLayout, e_i ); nPoints = swarm->cellParticleCountTbl[ cell_i ]; for( p_i = 0; p_i < nPoints; p_i++ ) { // get integration particle particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_i, p_i ); // get temperatureDeriv and xyz FeVariable_InterpolateFromMeshLocalCoord( temperatureField, (FeMesh*)mesh, e_i, particle->xi, &T); FeVariable_InterpolateFromMeshLocalCoord( velocityField, (FeMesh*)mesh, e_i, particle->xi, vel); FeVariable_InterpolateFromMeshLocalCoord( temperatureGradientsField, (FeMesh*)mesh, e_i, particle->xi, value); FeMesh_CoordLocalToGlobal( mesh, e_i, particle->xi, xyz ); Spherical_XYZ2regionalSphere( xyz, rtp ); Spherical_VectorXYZ2regionalSphere( vel, xyz, vel_rtp ); detJac = ElementType_JacobianDeterminant( elementType, (FeMesh*)mesh, e_i, particle->xi, 3 ); r = sqrt( rtp[0]*rtp[0] + rtp[1]*rtp[1] + rtp[2]*rtp[2] ); dxdr[0] = r/xyz[0]; dxdr[1] = r/xyz[1]; dxdr[2] = r/xyz[2]; // calc dT_dr = dT_dx * dx_dr + dT_dy * dy_dr + dT_dz * dz_dr dT_dr = value[0]*dxdr[0] + value[1]*dxdr[1] + value[2]*dxdr[2]; // add to element integral J_Nu[0] += particle->weight * detJac * (dT_dr - T*vel_rtp[0]); volume[0] += detJac * particle->weight; } } // if element is on the inner radius boundary if( ijk[0] == 0 ) { // get integration number of integration points in cell cell_i = CellLayout_MapElementIdToCellId( swarm->cellLayout, e_i ); nPoints = swarm->cellParticleCountTbl[ cell_i ]; for( p_i = 0; p_i < nPoints; p_i++ ) { // get integration particle particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_i, p_i ); // get temperatureDeriv and xyz FeVariable_InterpolateFromMeshLocalCoord( temperatureField, (FeMesh*)mesh, e_i, particle->xi, &T); FeVariable_InterpolateFromMeshLocalCoord( velocityField, (FeMesh*)mesh, e_i, particle->xi, vel); FeVariable_InterpolateFromMeshLocalCoord( temperatureGradientsField, (FeMesh*)mesh, e_i, particle->xi, value); FeMesh_CoordLocalToGlobal( mesh, e_i, particle->xi, xyz ); Spherical_XYZ2regionalSphere( xyz, rtp ); Spherical_VectorXYZ2regionalSphere( vel, xyz, vel_rtp ); detJac = ElementType_JacobianDeterminant( elementType, (FeMesh*)mesh, e_i, particle->xi, 3 ); r = sqrt( rtp[0]*rtp[0] + rtp[1]*rtp[1] + rtp[2]*rtp[2] ); dxdr[0] = r/xyz[0]; dxdr[1] = r/xyz[1]; dxdr[2] = r/xyz[2]; // calc dT_dr = dT_dx * dx_dr + dT_dy * dy_dr + dT_dz * dz_dr dT_dr = value[0]*dxdr[0] + value[1]*dxdr[1] + value[2]*dxdr[2]; J_Nu[1] += particle->weight * detJac * (dT_dr - T*vel_rtp[0]); volume[1] += detJac * particle->weight; } } } /* Sum of procs integral */ (void)MPI_Allreduce( J_Nu, gJ_Nu, 2, MPI_DOUBLE, MPI_SUM, context->communicator ); (void)MPI_Allreduce( volume, gVolume, 2, MPI_DOUBLE, MPI_SUM, context->communicator ); // to get horizontally averaged quantities we divide by volume gJ_Nu[0] /= gVolume[0]; gJ_Nu[1] /= gVolume[1]; // normalise CubedSphereNusselt upper condition - this is for scaling against published results // 1.22 and 2.22 are the inner and outer radii for those results factor = rMax * log(0.55); gJ_Nu[0] = factor * gJ_Nu[0]; // normalise CubedSphereNusselt lower condition factor = rMin * log(0.55); gJ_Nu[1] = factor * gJ_Nu[1]; avgT = PpcIntegral_Integrate( self->volAvgT ); vol = PpcIntegral_Integrate( self->vol ); StgFEM_FrequentOutput_PrintValue( context, avgT/vol ); StgFEM_FrequentOutput_PrintValue( context, gJ_Nu[0] ); StgFEM_FrequentOutput_PrintValue( context, gJ_Nu[1] ); }
Variable* Mesh_GenerateENMapVar( void* mesh ) { /* Returns a Variable that stores the mapping of * [local element] [global node indices] * Assumes the mapping never changes. */ Mesh* self = (Mesh*)mesh; char* name; int n_i, e_i, nNbr, localElements, localtotal; unsigned buffy_tvs; // buffer for global node indices unsigned dim, *nbr, temp; int *numberNodesPerEl = NULL; IArray* inc = NULL; Stream* error = Journal_Register( Error_Type, (Name)self->type ); // if variable already exists return it if( self->enMapVar ) return self->enMapVar; /* go over local elementNode map to get size of data */ inc = IArray_New( ); self->localtotalNodes=0; dim = Mesh_GetDimSize( self ); localElements = Mesh_GetLocalSize( self, dim ); numberNodesPerEl = Memory_Alloc_Array( int, localElements, "Mesh::numberNodesPerEl" ); for( e_i=0 ; e_i < localElements; e_i++ ) { Mesh_GetIncidence( self, dim, (unsigned)e_i, MT_VERTEX, inc ); nNbr = IArray_GetSize( inc ); nbr = IArray_GetPtr( inc ); numberNodesPerEl[e_i] = nNbr; self->localtotalNodes += nNbr; } /* Create the Variable data structure, int[nbrNodesPerEl*local element count] * Note: this is stored in a 1D array - so whatever read or writes to this variable * needs to know how to parse it. */ self->e_n = Memory_Alloc_Array( int, self->localtotalNodes, "Mesh::nodeConn" ); Stg_asprintf( &name, "%s-%s", self->name, "nodeConn" ); self->enMapVar = Variable_NewScalar( name, NULL, Variable_DataType_Int, &self->localtotalNodes, NULL, (void**)&self->e_n, NULL ); Stg_Component_Build(self->enMapVar, NULL, False); Stg_Component_Initialise(self->enMapVar, NULL, False); free(numberNodesPerEl); free(name); // Evaluate the global indices for the local nodes localtotal=0; for( e_i=0; e_i<localElements; e_i++ ) { Mesh_GetIncidence( self, dim, (unsigned)e_i, MT_VERTEX, inc ); nNbr = IArray_GetSize( inc ); nbr = IArray_GetPtr( inc ); for( n_i=0; n_i< nNbr; n_i++ ) { buffy_tvs = Mesh_DomainToGlobal( self, MT_VERTEX, nbr[n_i] ); Variable_SetValue( self->enMapVar, localtotal, (void*)&buffy_tvs ); localtotal++; } } Stg_Class_Delete( inc ); // return new variable return self->enMapVar; }