示例#1
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 _Trubitsyn2006_PressureFunction( void* _context, double* coord, double* pressure ) {
   UnderworldContext* context = (UnderworldContext*)_context;
   Trubitsyn2006*     self = (Trubitsyn2006*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Trubitsyn2006_Type );
   double             T0 = self->T0;
   double             Ra = self->Ra;
   double             x; 
   double             y;
   XYZ                min, max;
   double             eta;
   double             eta01;
   double             upperLeftCorner[]  = { 0.0, 1.0, 0.0 };
   
   Mesh_GetGlobalCoordRange( self->velocityField->feMesh, min, max );
   x = coord[ I_AXIS ] - min[ I_AXIS ];
   y = coord[ J_AXIS ] - min[ J_AXIS ];

   /* Get Viscosities */
   self->viscosityFunc->apply( self, coord, &eta );
   self->viscosityFunc->apply( self, upperLeftCorner, &eta01 );

   *pressure = - Ra * ( ( y * y * 0.5 - y + 0.5 )
         + 0.5 * T0 / M_PI * ( eta * cos( M_PI * y ) * cos( M_PI * x ) + eta01 ) );/* Equation 46 */
   /*printf("pressure from t0 = %g\n", *pressure );
   *pressure = - 2.0 * M_PI * v0 * ( eta * cos( M_PI * y ) * cos( M_PI * x ) + eta01 ) 
         - Ra * ( y*y * 0.5 - y + 0.5 );
   printf("pressure from v0 = %g\n\n", *pressure );*/
}
void _Trubitsyn2006_StreamFunction( void* _context, double* coord, double* psi ) {
   UnderworldContext* context = (UnderworldContext*)_context;
   Trubitsyn2006*     self = (Trubitsyn2006*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Trubitsyn2006_Type );
   double             v0 = Trubitsyn2006_V0( self );
   double             x; 
   double             y;
   XYZ                min, max;

   Mesh_GetGlobalCoordRange( self->velocityField->feMesh, min, max );
   x = coord[ I_AXIS ] - min[ I_AXIS ];
   y = coord[ J_AXIS ] - min[ J_AXIS ];

   *psi = - v0 / M_PI * sin( M_PI * y ) * sin( M_PI * x ); /* Equation 40 */
}
void Trubitsyn2006_TemperatureIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* data, void* _result ) {
   DomainContext* context = (DomainContext*)_context;
   FeVariable*    temperatureField = NULL;
   FeMesh*        mesh = NULL;
   double*        temperature = (double*) _result;
   double*        coord;
   double         x; 
   double         y;
   Trubitsyn2006* self = NULL;
   double         T0;
   double         Ra;
   double         v0 ;
   XYZ            min, max;
   double         eta;
   double         d_eta_dy;
   XYZ            viscDeriv;

   self = Stg_ComponentFactory_ConstructByName( context->CF, (Name)Trubitsyn2006_Type,
      Trubitsyn2006, True, context );

   T0 = self->T0;
   Ra = self->Ra;
   v0 = Trubitsyn2006_V0( self );

   temperatureField = (FeVariable*) FieldVariable_Register_GetByName(
      context->fieldVariable_Register,
      "TemperatureField" );

   mesh = temperatureField->feMesh;
   
   /* Find coordinate of node */
   coord = Mesh_GetVertex( mesh, node_lI );
   Mesh_GetGlobalCoordRange( mesh, min, max );
   x = coord[ I_AXIS ] - min[ I_AXIS ];
   y = coord[ J_AXIS ] - min[ J_AXIS ];

   self->viscosityFunc->apply( self, coord, &eta );
   self->viscosityDerivativeFunc->apply( self, coord, viscDeriv );
   d_eta_dy = viscDeriv[ J_AXIS ];

   *temperature = 1 - y + T0 * cos( M_PI * x ) * ( eta * sin( M_PI * y ) - d_eta_dy / M_PI * cos( M_PI * y ) ) ;    /* Equation 47 */ 
   
   *temperature = 1 - y + 4.0 * M_PI * v0 / Ra * cos( M_PI * x ) * 
      ( M_PI * eta * sin( M_PI * y ) - d_eta_dy * cos( M_PI * y ) ) ;    /* Equation 47 */ 
}
示例#5
0
void SROpGenerator_GenLevelMesh( SROpGenerator* self, unsigned level ) {
	Stream*			errorStream = Journal_Register( ErrorStream_Type, (Name)"SROpGenerator::GenLevelMesh"  );
	Mesh			*fMesh, *cMesh;
	CartesianGenerator	*fGen, *cGen;
	unsigned		nDims;
	unsigned*		cSize;
	double			crdMin[3], crdMax[3];
	unsigned		d_i;

	assert( self && Stg_CheckType( self, SROpGenerator ) );
	assert( self->meshes );
	assert( level < self->nLevels );

	fMesh = self->meshes[level + 1];
	nDims = Mesh_GetDimSize( fMesh );
	fGen = (CartesianGenerator*)fMesh->generator;
	Journal_Firewall( fGen && !strcmp( fGen->type, CartesianGenerator_Type ),
			  errorStream,
			  "\n" \
			  "****************************************************************\n" \
			  "* Error: Simple regular multigrid operator generation requires *\n" \
			  "*        a fine mesh that has been generated with a            *\n" \
			  "*        cartesian generator.                                  *\n" \
			  "****************************************************************\n" \
			  "\n" );

	cGen = CartesianGenerator_New( "", NULL );
	CartesianGenerator_SetDimSize( cGen, nDims );
	cSize = AllocArray( unsigned, nDims );
	for( d_i = 0; d_i < nDims; d_i++ )
		cSize[d_i] = fGen->elGrid->sizes[d_i] / 2;
	CartesianGenerator_SetTopologyParams( cGen, cSize, fGen->maxDecompDims, fGen->minDecomp, fGen->maxDecomp );
	Mesh_GetGlobalCoordRange( fMesh, crdMin, crdMax );
	CartesianGenerator_SetGeometryParams( cGen, crdMin, crdMax );
	CartesianGenerator_SetShadowDepth( cGen, 0 );
	FreeArray( cSize );

	cMesh = (Mesh*)FeMesh_New( "" );
	Mesh_SetGenerator( cMesh, cGen );
	FeMesh_SetElementFamily( cMesh, ((FeMesh*)fMesh)->feElFamily );
	Stg_Component_Build( cMesh, NULL, False );
	Stg_Component_Initialise( cMesh, NULL, False );
	self->meshes[level] = cMesh;
}
void PeriodicBoundariesManager_AddPeriodicBoundary( void* periodicBCsManager, Axis axis ) {
	PeriodicBoundariesManager*	self = (PeriodicBoundariesManager*)periodicBCsManager;	
	PeriodicBoundary*				newPeriodicBoundary;
	double							min[3], max[3];

	Mesh_GetGlobalCoordRange( self->mesh, min, max );
	
	if ( self->count == self->size ) {
		self->size += self->delta;
		self->boundaries = Memory_Realloc_Array( self->boundaries, PeriodicBoundary, self->size );
	}

	newPeriodicBoundary = &self->boundaries[self->count];
	newPeriodicBoundary->axis = axis;
	newPeriodicBoundary->minWall = min[axis];
	newPeriodicBoundary->maxWall = max[axis];
	newPeriodicBoundary->particlesUpdatedMinEndCount = 0;	
	newPeriodicBoundary->particlesUpdatedMaxEndCount = 0;	
	self->count++;
}
double _Byerlee_GetYieldCriterion(
      void*                            rheology,
      ConstitutiveMatrix*              constitutiveMatrix,
      MaterialPointsSwarm*             materialPointsSwarm,
      Element_LocalIndex               lElement_I,
      MaterialPoint*                   materialPoint,
      Coord                            xi )
{
   Byerlee*                         self             = (Byerlee*) rheology;
   double                           depth = 0.0;
   double                           height;
   int err;
   Coord                            coord;
   /* stupid way to recover the integration point from the materialPoint
    * TODO: FIXCONSTITUTIVE use integration point only */
   IntegrationPoint* integrationPoint = (IntegrationPoint*) Swarm_ParticleAt( constitutiveMatrix->integrationSwarm,
                                        constitutiveMatrix->currentParticleIndex );

   /* Calculate Depth */
   if( self->height_id != -1 ) {
      err = PpcManager_Get( self->mgr, lElement_I, integrationPoint, self->height_id, &height );
      Journal_Firewall( !err, global_error_stream,
            "Error in file %s. Cannot get reference height for '%s'. Ensure you have passed in the correct input with a line like\n\t<param name=\"HeightReferenceInput\">someInputfunction</param>\n", __func__, self->name );
   } else {
      double min[3], max[3];
      Mesh_GetGlobalCoordRange( self->mesh, min, max );
      height = max[ J_AXIS ];
   }

   /* This rheology assumes particle is an integration points thats can be mapped to a particle
    * that has no meaningful coord. Best to re-calc the global from local */
   FeMesh_CoordLocalToGlobal( self->mesh, lElement_I, xi, coord );
   depth = height - coord[ J_AXIS ];

   return self->cohesion + self->depthCoefficient * depth;
}
void _lucIsosurfaceCrossSection_Draw( void* drawingObject, lucDatabase* database, void* _context )
{
   lucIsosurfaceCrossSection* self = (lucIsosurfaceCrossSection*)drawingObject;
   lucIsosurface*             isosurf = self->isosurface;
   double                     minIsovalue     = self->minIsovalue;
   double                     maxIsovalue     = self->maxIsovalue;
   lucColourMap*              colourMap       = self->colourMap;
   int                        i, j, k;
   double                     isovalue;
   Index                      triangle_I;

   /* Custom max, min, use global min/max if equal (defaults to both zero) */
   if (minIsovalue == maxIsovalue)
   {
      //minIsovalue = FieldVariable_GetMinGlobalFieldMagnitude(self->fieldVariable);
      //maxIsovalue = FieldVariable_GetMaxGlobalFieldMagnitude(self->fieldVariable);
   }

   if (colourMap)
      lucColourMap_SetMinMax(colourMap, minIsovalue, maxIsovalue);

   /* Copy object id */
   isosurf->id = self->id; 

   if (self->rank == 0)
   {
      /* Calculate a value we can use to offset each surface section slightly
       *  so they appear in the same position but don't actually overlap */
      Coord min, max;
      float shift = 0;
      float range = 0;
      int d;
      Mesh_GetGlobalCoordRange(self->mesh, min, max );
      for (d=0; d<3; d++)
         range += (max[d] - min[d]) / 5000.0;
      range /= 3.0;

      /* Allocate Memory */
      Vertex** points = Memory_Alloc_2DArray( Vertex , 8, 1, "array for marching squares");

      /* Draw isovalues at each interval from min to max */
      for ( isovalue = minIsovalue ; isovalue <= maxIsovalue ; isovalue += self->interval )
      {
         float nshift[3] = {shift * self->normal[0], shift * self->normal[1], shift * self->normal[2]};
         shift += range;

         isosurf->triangleCount = 0;   /* Reset */
         isosurf->colourMap = NULL;

         if ( colourMap )
            lucColourMap_GetColourFromValue(colourMap, isovalue, &isosurf->colour, self->opacity);

         /* Run marching rectangles for this isovalue */
         isosurf->isovalue = isovalue;
         for ( i = 0 ; i < self->resolutionA-1 ; i++ )
         {
            for ( j = 0 ; j < self->resolutionB-1 ; j++ )
            {
               /* Copy vertex */
               for (k = 0; k<3; k++)
               {
                  points[LEFT_BOTTOM]->pos[k] = self->vertices[i][j][k] + nshift[k];
                  points[RIGHT_BOTTOM]->pos[k] = self->vertices[i+1][j][k] + nshift[k];
                  points[LEFT_TOP]->pos[k] = self->vertices[i][j+1][k] + nshift[k];
                  points[RIGHT_TOP]->pos[k] = self->vertices[i+1][j+1][k] + nshift[k];
               }
               /* Copy value */
               points[LEFT_BOTTOM]->value = self->values[i][j][0];
               points[RIGHT_BOTTOM]->value = self->values[i+1][j][0];
               points[LEFT_TOP]->value = self->values[i][j+1][0];
               points[RIGHT_TOP]->value = self->values[i+1][j+1][0];

               /* Interpolate mid-points and create triangles */
               lucIsosurface_WallElement( isosurf, points );
            }
         }

         /* Draw the surface section */
         isosurf->colourMap = self->colourMap;
         _lucIsosurface_Draw(self->isosurface, database, _context );

         /* Export colour values */
         if (self->colourMap)
         {
            float iso = isovalue;
            for ( triangle_I = 0 ; triangle_I < isosurf->triangleCount ; triangle_I++)
               for (i=0; i<3; i++)
                  lucDatabase_AddValues(database, 1, lucTriangleType, lucColourValueData, self->colourMap, &iso);
         }

      }

      Memory_Free( points );
   }

   /* Free memory */
   lucCrossSection_FreeSampleData(self);
}
void StGermain_SingleAttractor_UpdatePositions( DomainContext* context ) {
	Cell_LocalIndex			lCell_I;
	Particle_InCellIndex		cParticle_I;
	Particle* 	        	currParticle;
	Index				dim_I;
	Swarm*                          swarm = (Swarm*) LiveComponentRegister_Get( context->CF->LCRegister, (Name)"swarm"  );
	Coord                           attractorPoint;
	Mesh*				mesh;
	Stream*                         stream = Journal_Register( Info_Type, (Name)"particleUpdate"  );
	unsigned int                    movementSpeedDivisor = 0;
	int                             movementSign = 1;
	unsigned int                    explosionPeriod = 20;
	double				minCrd[3], maxCrd[3];

	Stream_SetPrintingRank( stream, Dictionary_GetUnsignedInt_WithDefault( context->dictionary, "procToWatch", 0 ) );
	movementSpeedDivisor = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"movementSpeedDivisor", 10 );
	
	mesh = (Mesh* )LiveComponentRegister_Get( context->CF->LCRegister, (Name)"mesh-linear"  );
	Mesh_GetGlobalCoordRange( mesh, minCrd, maxCrd );
	for ( dim_I=0; dim_I < 3; dim_I++ ) {
		attractorPoint[dim_I] = (maxCrd[dim_I] - minCrd[dim_I]) / 3;
	}
	Journal_Printf( stream, "Calculated attractor point is at (%f,%f,%f):\n", attractorPoint[0], attractorPoint[1], attractorPoint[2] );
	
	/* Now decide if we are attracting or repelling */
	if ( ( ( (context->timeStep - 1) / explosionPeriod ) % 2 ) == 0 ) {
		Journal_Printf( stream, "Timestep %d - Implosive mode\n", context->timeStep );
		movementSign = 1;
	}
	else {
		Journal_Printf( stream, "Timestep %d - Explosive mode\n", context->timeStep );
		movementSign = -1;
	}	

	
	for ( lCell_I=0; lCell_I < swarm->cellLocalCount; lCell_I++ ) {
		Journal_Printf( stream, "\tUpdating Particles positions in local cell %d:\n", lCell_I );
		for ( cParticle_I=0; cParticle_I < swarm->cellParticleCountTbl[lCell_I]; cParticle_I++ ) {
			Coord movementVector = {0,0,0};
			Coord newParticleCoord = {0,0,0};
			Coord* oldCoord;

			currParticle = (Particle*)Swarm_ParticleInCellAt( swarm, lCell_I, cParticle_I );
			oldCoord = &currParticle->coord;
			Journal_Printf( stream, "\t\tUpdating particleInCell %d:\n", cParticle_I );

			for ( dim_I=0; dim_I < 3; dim_I++ ) {
				movementVector[dim_I] = ( attractorPoint[dim_I] - (*oldCoord)[dim_I] ) /
					movementSpeedDivisor;
				movementVector[dim_I] *= movementSign;	
				if ( movementSign == -1 ) {
					movementVector[dim_I] *= (float)movementSpeedDivisor / (movementSpeedDivisor-1); 
				}
				newParticleCoord[dim_I] = (*oldCoord)[dim_I] + movementVector[dim_I];
			}
			memcpy( currParticle->velocity, movementVector, 3*sizeof(double) ); 

			Journal_Printf( stream, "\t\tChanging its coords from (%f,%f,%f) to (%f,%f,%f):\n",
				(*oldCoord)[0], (*oldCoord)[1], (*oldCoord)[2],
				newParticleCoord[0], newParticleCoord[1], newParticleCoord[2] );

			for ( dim_I=0; dim_I < 3; dim_I++ ) {
				currParticle->coord[dim_I] = newParticleCoord[dim_I];
			}
		}
	}

	Swarm_UpdateAllParticleOwners( swarm );
}
void lucMeshCrossSection_Sample( void* drawingObject, Bool reverse)
{
   lucMeshCrossSection* self          = (lucMeshCrossSection*)drawingObject;
   FeVariable*          fieldVariable = (FeVariable*) NULL;  // JM need to fix this guy
      assert(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->dims[0] = sizes[ self->axis ];
   self->dims[1] = sizes[ self->axis1 ];
   self->dims[2] = sizes[ self->axis2 ];

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

   Mesh_GetLocalCoordRange(self->mesh, min, max );
   Mesh_GetGlobalCoordRange(self->mesh, 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->dims[0], self->dims[1], self->dims[2], self->fieldDim);

   /* Get mesh cross section self->vertices and values */
   self->resolutionA = self->dims[1];
   self->resolutionB = self->dims[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->dims[1], self->dims[2]);
   node_ijk[ self->axis ] = crossSection_I;
   for ( i = 0 ; i < self->dims[1]; i++ )
   {
      int percent = 100 * (i + 1) / self->dims[1];
      Journal_Printf(lucInfo, "\b\b\b\b%3d%%", percent);
      fflush(stdout);

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

      node_ijk[ self->axis1 ] = i0;

      for ( j = 0 ; j < self->dims[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->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->dims[1]; i++ )
   {
      for ( j=0 ; j < self->dims[2]; j++ )
      {
         /* Receive values at root */
         if (self->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->dims[2]+j, self->comm, 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->dims[2]+j, self->comm);
            localcount--;
         }
      }
   }
   MPI_Barrier(self->comm);    /* 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->rank, localcount);
}
void ParticleMelting_MeltFrationUpdate( ParticleMelting *self, void *data ) {
   MaterialPoint *mat_part=NULL;
   ExtensionManager *part_extMgr=NULL;
   MaterialPointsSwarm *mat_swarm=NULL;
   ParticleMelting_ParExt *parExt=NULL;
   ParticleMelting_MatExt *matExt=NULL;
   FeVariable *temperatureField=self->temperatureField;
   FeVariable *pressureField=self->pressureField;
	FeMesh* mesh = temperatureField->feMesh;
   Scaling *scaling=self->scaling;
	double depth, min[3], max[3]; 
   double temperature, pressure, deepPressure, theta;
   unsigned lpartCount, par_i, part_extHandle, mat_extHandle;

	Mesh_GetGlobalCoordRange( mesh, min, max );

   mat_swarm = self->materialSwarm;
   part_extMgr = mat_swarm->particleExtensionMgr;
   lpartCount = self->materialSwarm->particleLocalCount;
   part_extHandle = self->particleExtHandle;
   mat_extHandle = self->materialExtHandle;

   for( par_i = 0 ; par_i < lpartCount ; par_i++  ) {
      mat_part = (MaterialPoint*)Swarm_ParticleAt( mat_swarm, par_i );

      /* get the particle extension */
      parExt = ExtensionManager_Get( part_extMgr, mat_part, part_extHandle );

      /* get the material extension */
      matExt = MaterialPointsSwarm_GetMaterialExtensionOn( mat_swarm, mat_part, mat_extHandle );
      if( !matExt->TurnMeltOn ) continue;

		/* Get temperature*/
      _FeVariable_InterpolateValueAt( temperatureField, mat_part->coord, &temperature );
		/* Get pressure*/
		if( pressureField )
		  _FeVariable_InterpolateValueAt( pressureField, mat_part->coord, &pressure );
		else {
		  depth = fabs( max[J_AXIS] - mat_part->coord[J_AXIS] );
		  pressure = depth * self->refRho * self->gravity;
		}
		/* Get deep pressure */
		deepPressure = matExt->deepPressure;

		/* Scale all  */
		if( self->scaling ) {
		  temperature = Scaling_Unscale( scaling, temperature, sTemperature );
        pressure = Scaling_Unscale( scaling, pressure, sPressure );
		  /* Safety checks - TODO: put some warnings here */
		  if( temperature < 0 )
			 temperature = 0;
		  if( pressure < 0 )
			 pressure = 0;
		  /*deepPressure = Scaling_Unscale( scaling, matExt->deepPressure, sPressure );*/
		  /* pressure in GPa */
		  pressure /= 1e9;
		  deepPressure /= 1e9;
		} 

      /* Calculate Depletion */
      parExt->prevF = parExt->F;

		if( pressure < deepPressure )
		  theta = ParticleMelting_CalculateSuperSolidusTemperature( pressure, temperature, matExt->sCoeff, matExt->lCoeff );
		else
		  theta = ParticleMelting_CalculateSuperSolidusTemperature( pressure, temperature, matExt->sCoeffDeep, matExt->lCoeffDeep );
		
      if( self->extractMelt == True ) {
         /* F is depletion so it cannot decrease! 
          * Once some melt has been produced and removed, 
          * the residual rock is depleted forever and ever, amen */
         if( theta > parExt->maxTheta ) {
           parExt->F = ParticleMelting_CalculateMeltFraction( theta );

           parExt->melt = parExt->F  -  ParticleMelting_CalculateMeltFraction( parExt->maxTheta );

           parExt->maxTheta = theta;
         } else {
           parExt->melt = 0;
         }		
      } else {

         /* melt isn't extracted so depletion can decrease */
         parExt->F = ParticleMelting_CalculateMeltFraction( theta );

         parExt->melt = parExt->F - parExt->prevF; 
      }

   }

}