示例#1
0
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] );
}
示例#5
0
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;
}