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
}
Ejemplo n.º 2
0
void lecode_tools_Isostasy_CalcBasalFlow(lecode_tools_Isostasy *self)
{
   int rank;
   Grid *nodeGrid, *elGrid;
   double *avg_sep, *avg_height;
   double *avg_density, *rho_zero_density;
   double *phi, **phi_ptr;
   double *node_avg_sep, *node_avg_height;
   double *node_avg_density, *node_rho_zero_density, *node_phi;
   double *global_node_avg_sep, *global_node_avg_height;
   double *global_node_avg_density, *global_node_rho_zero_density, *global_node_phi;
   double avgFlow, tmp;
   int param[3], nodeIdx, arraySize, arrayPos, elPos;
   int nDims, iterSizes[2];
   IArray *inc;
   int ii, jj, kk;

   MPI_Comm_rank(MPI_COMM_WORLD, &rank);

   nDims = Mesh_GetDimSize( self->mesh );
   nodeGrid = *Mesh_GetExtension( self->mesh, Grid**,  self->mesh->vertGridId );
   elGrid = *Mesh_GetExtension( self->mesh, Grid**,  self->mesh->elGridId );
   inc = IArray_New();

   if (self->thermalSLE)
   {
      lecode_tools_Isostasy_SolveThermal(self);
      phi_ptr = &phi;
   }
   else
      phi_ptr = NULL;

   lecode_tools_Isostasy_AverageSurfaces(self, &avg_sep, &avg_height);
   lecode_tools_Isostasy_AverageBody(self, &avg_density, &rho_zero_density, phi_ptr);
   // avg_density seems to be the avg rho across the basal node columns.
   // rho_zero_density seems to be the avg density of the rho_zero material.

   if ( self->avg )
   {

      self->flow[0] = -1.0*avg_density[0]*avg_sep[0]/rho_zero_density[0];
      if (phi_ptr)
         self->flow[0] -= avg_height[0]*phi[0]/rho_zero_density[0];

      avgFlow = self->flow[0];

   }
   else
   {

      // nodeGrid->sizes is the dimensions of the mesh in x (0), y (1), and z(2)
      arraySize=0;
      if ( nDims == 2 ) arraySize = nodeGrid->sizes[0];
      else if ( nDims == 3 ) arraySize = nodeGrid->sizes[0]*nodeGrid->sizes[self->zontalAxis];
      else assert(0);
      // the arraysize is the base of the model, in nodes.

      node_avg_density = (double*)malloc( arraySize*sizeof(double) );
      memset( node_avg_density, 0, arraySize*sizeof(double) );
      node_rho_zero_density = (double*)malloc( arraySize*sizeof(double) );
      memset( node_rho_zero_density, 0, arraySize*sizeof(double) );
      node_avg_sep = (double*)malloc( arraySize*sizeof(double) );
      memset( node_avg_sep, 0, arraySize*sizeof(double) );
      node_avg_height = (double*)malloc( arraySize*sizeof(double) );
      memset( node_avg_height, 0, arraySize*sizeof(double) );
      if ( phi_ptr )
      {
         node_phi = (double*)malloc( arraySize*sizeof(double) );
         memset( node_phi, 0, arraySize*sizeof(double) );
      }
     
      param[0] = param[1] = param[2] = 0;
      iterSizes[0] = nodeGrid->sizes[0];
      iterSizes[1] = (nDims == 3) ? nodeGrid->sizes[self->zontalAxis] : 1;
      for ( ii = 0; ii < iterSizes[1]; ii++ )
      {
         // Going into the 'Y' or 'Z' of the basal surface. If 2D, then this loop only goes once.
         for ( kk = 0; kk < iterSizes[0]; kk++)
         {

            param[self->zontalAxis] = ii;
            param[0] = kk;
            arrayPos = param[0] + param[self->zontalAxis]*nodeGrid->sizes[0];

            nodeIdx = Grid_Project( nodeGrid, param );
            if ( !FeMesh_NodeGlobalToDomain( self->mesh, nodeIdx, &nodeIdx ) ||
                  nodeIdx >= FeMesh_GetNodeLocalSize( self->mesh ) )
            {
               continue;
            }

            FeMesh_GetNodeElements( self->mesh, nodeIdx, inc );
            for ( jj = 0; jj < inc->size; jj++ )
            {
               Grid_Lift( elGrid, FeMesh_ElementDomainToGlobal( self->mesh, inc->ptr[jj] ), param );

               elPos = param[0];
               if ( nDims == 3 ) elPos += param[self->zontalAxis]*elGrid->sizes[0];

               node_avg_density[arrayPos] += avg_density[elPos];
               node_rho_zero_density[arrayPos] += rho_zero_density[elPos];
               node_avg_sep[arrayPos] += avg_sep[elPos];
               node_avg_height[arrayPos] += avg_height[elPos];
               if ( phi_ptr )
                  node_phi[arrayPos] += phi[elPos];
            }

            node_avg_density[arrayPos] /= (double)inc->size;
            node_rho_zero_density[arrayPos] /= (double)inc->size;
            node_avg_sep[arrayPos] /= (double)inc->size;
            node_avg_height[arrayPos] /= (double)inc->size;
            if ( phi_ptr )
               node_phi[arrayPos] /= (double)inc->size;

         }

      }

      global_node_avg_density = (double*)malloc( arraySize*sizeof(double) );
      memset( global_node_avg_density, 0, arraySize*sizeof(double) );
      global_node_rho_zero_density = (double*)malloc( arraySize*sizeof(double) );
      memset( global_node_rho_zero_density, 0, arraySize*sizeof(double) );
      global_node_avg_sep = (double*)malloc( arraySize*sizeof(double) );
      memset( global_node_avg_sep, 0, arraySize*sizeof(double) );
      global_node_avg_height = (double*)malloc( arraySize*sizeof(double) );
      memset( global_node_avg_height, 0, arraySize*sizeof(double) );
      if ( phi_ptr )
      {
         global_node_phi = (double*)malloc( arraySize*sizeof(double) );
         memset( global_node_phi, 0, arraySize*sizeof(double) );
      }

      MPI_Allreduce(node_avg_density, global_node_avg_density, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce(node_rho_zero_density, global_node_rho_zero_density, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce(node_avg_sep, global_node_avg_sep, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce(node_avg_height, global_node_avg_height, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      if ( phi_ptr )
         MPI_Allreduce(node_phi, global_node_phi, arraySize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);

      free( avg_sep );
      free( avg_height );
      free( avg_density );
      free( rho_zero_density );
      if ( phi_ptr )
         free( phi );
      Stg_Class_Delete( inc );

      avgFlow = 0.0;

      for ( ii = 0; ii < arraySize; ii++ )
      {

         /*
           param[0] = ii;
           nodeIdx = Grid_Project( nodeGrid, param );
           if( !FeMesh_NodeGlobalToDomain( self->mesh, nodeIdx, &nodeIdx ) ||
           nodeIdx >= FeMesh_GetNodeLocalSize( self->mesh ) )
           {
           continue;
           }
         */

         self->flow[ii] = -1.0*global_node_avg_density[ii]*global_node_avg_sep[ii]/global_node_rho_zero_density[ii];
         if (phi_ptr)
            self->flow[ii] -= global_node_avg_height[ii]*global_node_phi[ii]/global_node_rho_zero_density[ii];

         avgFlow += self->flow[ii];

      }


      //MPI_Allreduce(&avgFlow, &tmp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      tmp = avgFlow;
      avgFlow = tmp/(double)arraySize;

      free( node_avg_sep );
      free( node_avg_height );
      free( node_avg_density );
      free( node_rho_zero_density );
      if ( phi_ptr )
         free( node_phi );

      free( global_node_avg_sep );
      free( global_node_avg_height );
      free( global_node_avg_density );
      free( global_node_rho_zero_density );
      if ( phi_ptr )
         free( global_node_phi );

   }

   if (rank == 0)
   {
      printf("===========\n");
      printf("= Isostasy\n");
      printf("=\n");
      printf("= Average basal flow: %g\n", avgFlow);
      printf("===========\n");
   }
}
Ejemplo n.º 3
0
void lucMeshCrossSection_Sample( void* drawingObject, Bool reverse)
{
   lucMeshCrossSection* self          = (lucMeshCrossSection*)drawingObject;
   FeVariable*          fieldVariable = (FeVariable*) self->fieldVariable;
   Mesh*                mesh          = (Mesh*) fieldVariable->feMesh;
   Grid*                vertGrid;
   Node_LocalIndex      crossSection_I;
   IJK                  node_ijk;
   Node_GlobalIndex     node_gI;
   Node_DomainIndex     node_dI;
   int                  i,j, d, sizes[3] = {1,1,1};
   Coord                globalMin, globalMax, min, max;

      int localcount = 0;

   vertGrid = *(Grid**)ExtensionManager_Get( mesh->info, mesh, self->vertexGridHandle );
   for (d=0; d<fieldVariable->dim; d++) sizes[d] = vertGrid->sizes[d];
   self->dim[0] = sizes[ self->axis ];
   self->dim[1] = sizes[ self->axis1 ];
   self->dim[2] = sizes[ self->axis2 ];

   crossSection_I = lucCrossSection_GetValue(self, 0, self->dim[0]-1);

   FieldVariable_GetMinAndMaxLocalCoords( fieldVariable, min, max );
   FieldVariable_GetMinAndMaxGlobalCoords( fieldVariable, globalMin, globalMax );

   Journal_Printf( lucDebug, "%s called on field %s, with axis of cross section as %d, crossSection_I as %d (dims %d,%d,%d) field dim %d\n",
                    __func__, fieldVariable->name, self->axis, crossSection_I, self->dim[0], self->dim[1], self->dim[2], self->fieldDim);

   /* Get mesh cross section self->vertices and values */
   self->resolutionA = self->dim[1];
   self->resolutionB = self->dim[2];
   lucCrossSection_AllocateSampleData(self, self->fieldDim);
   int lSize = Mesh_GetLocalSize( mesh, MT_VERTEX );
   double time = MPI_Wtime();
   Journal_Printf(lucInfo, "Sampling mesh (%s) %d x %d...  0%", self->name, self->dim[1], self->dim[2]);
   node_ijk[ self->axis ] = crossSection_I;
   for ( i = 0 ; i < self->dim[1]; i++ )
   {
      int percent = 100 * (i + 1) / self->dim[1];
      Journal_Printf(lucInfo, "\b\b\b\b%3d%%", percent);
      fflush(stdout);

      /* Reverse order if requested */
      int i0 = i;
      if (reverse) i0 = self->dim[1] - i - 1;

      node_ijk[ self->axis1 ] = i0;

      for ( j = 0 ; j < self->dim[2]; j++ )
      {
         self->vertices[i][j][0] = HUGE_VAL;
         self->vertices[i][j][2] = 0;
         node_ijk[ self->axis2 ] = j;
         node_gI = Grid_Project( vertGrid, node_ijk );
         /* Get coord and value if node is local... */
         if (Mesh_GlobalToDomain( mesh, MT_VERTEX, node_gI, &node_dI ) && node_dI < lSize)
         {  
            /* Found on this processor */
            double value[self->fieldDim];
            FeVariable_GetValueAtNode( fieldVariable, node_dI, value );
            double* pos = Mesh_GetVertex( mesh, node_dI );
            /*fprintf(stderr, "[%d] (%d,%d) Node %d %f,%f,%f value %f\n", self->context->rank, i, j, node_gI, pos[0], pos[1], pos[2], value);*/
         
            for (d=0; d<fieldVariable->dim; d++)
               self->vertices[i][j][d] = pos[d];

            for (d=0; d<self->fieldDim; d++)
               self->values[i][j][d] = (float)value[d];

            localcount++;
         }
      }
   }
   Journal_Printf(lucInfo, " %f sec. ", MPI_Wtime() - time);

   /* Collate */
   time = MPI_Wtime();
   for ( i=0 ; i < self->dim[1]; i++ )
   {
      for ( j=0 ; j < self->dim[2]; j++ )
      {
         /* Receive values at root */
         if (self->context->rank == 0)
         {
            /* Already have value? */
            if (self->vertices[i][j][0] != HUGE_VAL) {localcount--; continue; }

            /* Recv (pos and value together = (3 + fevar dims)*float) */
            float data[3 + self->fieldDim];
            (void)MPI_Recv(data, 3+self->fieldDim, MPI_FLOAT, MPI_ANY_SOURCE, i*self->dim[2]+j, self->context->communicator, MPI_STATUS_IGNORE);
            /* Copy */
            memcpy(self->vertices[i][j], data, 3 * sizeof(float));
            memcpy(self->values[i][j], &data[3], self->fieldDim * sizeof(float));
         }
         else
         {
            /* Found on this proc? */
            if (self->vertices[i][j][0] == HUGE_VAL) continue;

            /* Copy */
            float data[3 + self->fieldDim];
            memcpy(data, self->vertices[i][j], 3 * sizeof(float));
            memcpy(&data[3], self->values[i][j], self->fieldDim * sizeof(float));

            /* Send values to root (pos & value = 4 * float) */
            MPI_Ssend(data, 3+self->fieldDim, MPI_FLOAT, 0, i*self->dim[2]+j, self->context->communicator);
            localcount--;
         }
      }
   }
   MPI_Barrier(self->context->communicator);    /* Barrier required, prevent subsequent MPI calls from interfering with transfer */
   Journal_Printf(lucInfo, " Gather in %f sec.\n", MPI_Wtime() - time);
   Journal_Firewall(localcount == 0, lucError,
                     "Error - in %s: count of values sampled compared to sent/received by mpi on proc %d does not match (balance = %d)\n",
                     __func__, self->context->rank, localcount);
}