void Spherical_MaxVel_Output( UnderworldContext* context ) {
   Spherical_CubedSphereNusselt* 	self		= (Spherical_CubedSphereNusselt*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Spherical_CubedSphereNusselt_Type );
   FeVariable*				velocityField   = self->velocityField;
   FeMesh* 				mesh 		= velocityField->feMesh;
   Grid*				grid		= NULL;
   unsigned*				sizes		= NULL;
   int 					vertId, dId;
   unsigned 				dT_i, dT_j, nDomainSize, ijk[3];
   double 				vel[3], velMax[2], gVelMax[2], velMag;

   //set 'em big and negative
   velMax[0] = velMax[1] = -1*HUGE_VAL;

   // get vert grid
   RegularMeshUtils_ErrorCheckAndGetDetails( (Mesh*)mesh, MT_VERTEX, &nDomainSize, &grid );
   sizes = grid->sizes;

   // go around 
   for( dT_i = 0; dT_i < sizes[1]; dT_i++ ) {
      for( dT_j = 0; dT_j < sizes[2]; dT_j++ ) {
         // find inner vertex
         ijk[0] = 0;
         // angular discretisation
         ijk[1] = dT_i;
         ijk[2] = dT_j;
         vertId = Grid_Project( grid, ijk );

         // if the node is local
         if( Mesh_GlobalToDomain( mesh, MT_VERTEX, vertId, &dId ) == True ) {
            FeVariable_GetValueAtNode( velocityField, dId, vel );
            velMag = sqrt( vel[0]*vel[0] + vel[1]*vel[1] + vel[2]*vel[2] );
            if( velMag > velMax[0] ) velMax[0] = velMag;
         }

         // find outer vertex
         ijk[0] = grid->sizes[0]-1;
         vertId = Grid_Project( grid, ijk );

         // if the node is local
         if( Mesh_GlobalToDomain( mesh, MT_VERTEX, vertId, &dId ) == True ) {
            FeVariable_GetValueAtNode( velocityField, dId, vel );
            velMag = sqrt( vel[0]*vel[0] + vel[1]*vel[1] + vel[2]*vel[2] );
            if( velMag > velMax[1] ) velMax[1] = velMag;
         }
      }
   }

   (void)MPI_Allreduce( velMax, gVelMax, 2, MPI_DOUBLE, MPI_MAX, context->communicator );

   StgFEM_FrequentOutput_PrintValue( context, gVelMax[1] ); // print outer velocity max
   StgFEM_FrequentOutput_PrintValue( context, gVelMax[0] ); // print inner velocity max
}
void Underworld_MaxVelocity_Output( void* _context ) {
/**
 * 	\Purpose
 * 		User defined function. In this case is just prints out the max velocity to 
 * 		the FrequentOutput.dat file.
 *
 * 	\Inputs
 * 		The context, which can be used to control any other object in the code.
 * 		As this function is on the AbstractContext_EP_FrequentOutput it
 * 		receives the input which is defined for that entry point. Other entry points
 * 		have a different set of input args so be sure your user defined plugin is receiving
 * 		the right data structure as the void*. 
 * 		(Note some entry point specify multiple input args).
 *
 * 	\Interactions
 * 		Using the velocityField, which is pointered to from the context, the max velocity
 * 		component value is gathered and piped to the frequent output file. 
 */

	UnderworldContext* context       = (UnderworldContext*) _context;
	FeVariable*        velocityFe    = (FeVariable*) LiveComponentRegister_Get( context->CF->LCRegister, (Name)"VelocityField" );
	double             maxVel;

	/* Find the max field component */
	maxVel = _FeVariable_GetMaxGlobalFieldMagnitude( velocityFe  );
	/* Print to the FrequentOutput stream */
	StgFEM_FrequentOutput_PrintValue( context, maxVel );
}
Example #3
0
/* Integrate Every Step and dump to file */
void Underworld_Vrms_Dump( void* _context ) {
   UnderworldContext* context = (UnderworldContext* ) _context;
   Mesh*              mesh;
   double             maxCrd[3], minCrd[3];
   double             integral;
   double             vrms;
   double             volume = 0.0;
   Dimension_Index    dim = context->dim;

   Underworld_Vrms* self;

   self = (Underworld_Vrms*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Underworld_Vrms_Type );

   mesh = (Mesh*)self->velocitySquaredField->feMesh;
   Mesh_GetGlobalCoordRange( mesh, minCrd, maxCrd );
   
   /* Sum integral */
   integral = FeVariable_Integrate( self->velocitySquaredField, self->gaussSwarm );

   /* Get Volume of Mesh - TODO Make general for irregular meshes */
   volume = ( maxCrd[ I_AXIS ] - minCrd[ I_AXIS ] ) * 
      ( maxCrd[ J_AXIS ] - minCrd[ J_AXIS ] );
   if ( dim == 3 ) 
      volume *= maxCrd[ K_AXIS ] - minCrd[ K_AXIS ];

   /* Calculate Vrms 
    * V_{rms} = \sqrt{ \frac{ \int_\Omega \mathbf{u . u} d\Omega }{\Omega} } */
   vrms = sqrt( integral / volume );

   /* Print data to file */
   StgFEM_FrequentOutput_PrintValue( context, vrms );

   /* Put Value onto context */
   self->vrms = vrms;
}
void Spherical_Work_Output( UnderworldContext* context ) {
   Spherical_CubedSphereNusselt* self=(Spherical_CubedSphereNusselt*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Spherical_CubedSphereNusselt_Type );
   double vol, volAvgVD, volAvgW;

   // get energy metrics
   vol = PpcIntegral_Integrate( self->vol );
   volAvgVD = PpcIntegral_Integrate( self->volAvgVD );
   volAvgW = PpcIntegral_Integrate( self->volAvgW );

   // make volume averaged values
   volAvgVD = volAvgVD/vol;
   volAvgW = volAvgW/vol;

   //print
   StgFEM_FrequentOutput_PrintValue( context, volAvgVD ); 
   StgFEM_FrequentOutput_PrintValue( context, volAvgW );
}
void CalcDeflectionAndCheckGravity( UnderworldContext* context ) {

	IntegrationPointsSwarm*    swarm              = (IntegrationPointsSwarm*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)"picIntegrationPoints" );
	GlobalParticle*            particle; 

	MaterialPointsSwarm**      materialSwarms;
	MaterialPointsSwarm*       materialSwarm;
	Index                      swarmLength;

	double        defMax            = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"defMax", 0.35  );
	double        deflection        = 0.0;
	Coord         coord;
	double        distance;
	static int    visits            = 0;
	static double initial_position  = 0.0;

	materialSwarms = IntegrationPointMapper_GetMaterialPointsSwarms( swarm->mapper, &swarmLength );
	/* assume first swarm for now!!! */
	materialSwarm = materialSwarms[0];

	if (visits == 0) {
		coord[0] = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"x_mid", 0.75  );
		coord[1] = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"y_mid", 0.75  );
		coord[2] = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"z_mid", 0.0  );
		closestParticle_I = Swarm_FindClosestParticle( materialSwarm, 2, coord, &distance );
	}

	particle = (GlobalParticle*)Swarm_ParticleAt( materialSwarm, closestParticle_I );

	if (visits==0)
		initial_position = particle->coord[1];
	
	visits=1;

	deflection = initial_position - particle->coord[1];
	
	if ( deflection >= defMax ) {
		TurnOffGravity( context );
	}

	StgFEM_FrequentOutput_PrintValue( context, deflection );
}
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] );
}