void _RateFieldTimeIntegrator_Delete( void* _self ) {
   RateFieldTimeIntegrator* self = (RateFieldTimeIntegrator*) _self;

   Journal_DPrintf( self->debug, "In %s for %s '%s'\n", __func__, self->type, self->name );

   /* Delete Class */
   _Stg_Component_Delete( self );

}
void _StokesBlockKSPInterface_SolverSetup( void* solver, void* stokesSLE ) {
	StokesBlockKSPInterface* self = (StokesBlockKSPInterface*) solver;
	//Stokes_SLE*             sle  = (Stokes_SLE*)             stokesSLE;

 	Journal_DPrintf( self->debug, "In %s:\n", __func__ );
	Stream_IndentBranch( StgFEM_Debug );

	Stream_UnIndentBranch( StgFEM_Debug );
}
void* _TimeIntegrand_Copy( void* timeIntegrand, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
	TimeIntegrand*	self = (TimeIntegrand*)timeIntegrand;
	TimeIntegrand*	newTimeIntegrand;
	
	Journal_DPrintf( self->debug, "In %s for %s '%s'\n", __func__, self->type, self->name );
	/* TODO */ abort();

	return (void*)newTimeIntegrand;
}
void _Stokes_SLE_PenaltySolver_Delete( void* solver ) {
    Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)solver;

    Journal_DPrintf( self->debug, "In: %s \n", __func__);

    Stream_IndentBranch( StgFEM_Debug );

    Stream_UnIndentBranch( StgFEM_Debug );
}
Esempio n. 5
0
void _NamedObject_Register_Delete( void* namedObjectRegister ) {
	NamedObject_Register* self = (NamedObject_Register*)namedObjectRegister;
	
	Journal_DPrintf( Journal_Register( Debug_Type, NamedObject_Register_Type ), "In: %s()\n", __func__ );
	
	Stg_Class_Delete( self->objects ); 

	/* Stg_Class_Delete parent */
	_Stg_Class_Delete( self );
}
void _SolutionVector_Delete( void* solutionVector ) {
	SolutionVector* self = (SolutionVector*)solutionVector;
	
	Journal_DPrintf( self->debug, "In %s - for soln. vector %s\n", __func__, self->name );
	Stream_IndentBranch( StgFEM_Debug );
	
	/* Stg_Class_Delete parent*/
	_Stg_Component_Delete( self );
	Stream_UnIndentBranch( StgFEM_Debug );
}
Esempio n. 7
0
void _DomainContext_Delete( void* context ) {
   DomainContext* self = (DomainContext*)context;
   
   Journal_DPrintf( self->debug, "In: %s()\n", __func__ );

   Journal_DPrintfL( self->debug, 2, "Deleting the FieldVariable register (and hence all FieldVariables).\n" );

   /* Stg_Class_Delete parent */
   _AbstractContext_Delete( self );
}
void _SLE_Solver_Execute( void* sleSolver, void* data ) {
	SLE_Solver*		self = (SLE_Solver*)sleSolver;

	Journal_DPrintf( self->debug, "In %s()\n", __func__ );

	Stream_IndentBranch( StgFEM_Debug );
	SLE_Solver_SolverSetup( self, data );
	SLE_Solver_Solve( self, data );
	Stream_UnIndentBranch( StgFEM_Debug );
   self->hasSolved = True; /* at this point always set has solved to true */
}
void _TimeIntegrator_ExecuteRK2Simultaneous( void* timeIntegrator, void* data ) {
	TimeIntegrator*	self = (TimeIntegrator*)timeIntegrator;
	AbstractContext*	context = (AbstractContext*) data;
	Index					integrand_I;   
	Index					integrandCount = TimeIntegrator_GetCount( self );
	double				dt = self->dt;
	TimeIntegrand*	integrand;
	Variable**			originalVariableList;

    assert(0); /* this shit be broken */
	Journal_DPrintf( self->debug, "In %s for %s '%s'\n", __func__, self->type, self->name );

	Journal_Firewall( 
		False,
		Journal_MyStream( Error_Type, self ),
		"Error in %s '%s' - This function is temporarily unavailable \n"
		"Please only use non-simultaneous update or only first order update.\n", 
		self->type, self->name );

	/* Set Time */
	TimeIntegrator_SetTime( self, context->currentTime );

	originalVariableList = Memory_Alloc_Array( Variable*, integrandCount, "originalVariableList" );
	
	TimeIntegrator_Setup( self );
	for ( integrand_I = 0 ; integrand_I < integrandCount ; integrand_I++ ) {
		integrand = TimeIntegrator_GetByIndex( self, integrand_I );
		Journal_RPrintf(self->info,"\t2nd order (simultaneous): %s\n", integrand->name);
		
		/* Store Original */
		originalVariableList[ integrand_I ] = Variable_NewFromOld( integrand->variable, "Original", True );

		/* Predictor Step */
		TimeIntegrand_FirstOrder( integrand, integrand->variable, 0.5 * dt );
	}
	TimeIntegrator_Finalise( self );
	
	/* Set Time */
	TimeIntegrator_SetTime( self, context->currentTime + 0.5 * dt );

	TimeIntegrator_Setup( self );
	for ( integrand_I = 0 ; integrand_I < integrandCount ; integrand_I++ ) {
		integrand = TimeIntegrator_GetByIndex( self, integrand_I );

		/* Corrector Step */
		TimeIntegrand_FirstOrder( integrand, originalVariableList[ integrand_I ], dt );

		/* Free Original */
		Stg_Class_Delete( originalVariableList[ integrand_I ] );
	}
	TimeIntegrator_Finalise( self );
	Memory_Free( originalVariableList );
}
void _StiffnessMatrixTerm_Initialise( void* stiffnessMatrixTerm, void* data ) {
	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
	
	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
	Stream_IndentBranch( StgFEM_Debug );

	Stg_Component_Initialise( self->integrationSwarm, data, False );
	if ( self->extraInfo ) 
		Stg_Component_Initialise( self->extraInfo, data, False );
	
	Stream_UnIndentBranch( StgFEM_Debug );
}
Esempio n. 11
0
void _SolutionVector_Initialise( void* solutionVector, void* data ) {
	SolutionVector*          self = (SolutionVector *)solutionVector;

	Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
	Stream_IndentBranch( StgFEM_Debug );
	/* ensure variables are initialised */
	if( self->feVariable ) {
		Stg_Component_Initialise( self->feVariable, data, False );
	}

	Stream_UnIndentBranch( StgFEM_Debug );
}
Esempio n. 12
0
double AdvectionDiffusionSLE_DiffusiveTimestep( void* advectionDiffusionSLE ) {
	AdvectionDiffusionSLE*    self              = (AdvectionDiffusionSLE*) advectionDiffusionSLE;
	double                    minSeparation;
	double                    minSeparationEachDim[3];

	Journal_DPrintf( self->debug, "In func: %s\n", __func__ );
	
	FeVariable_GetMinimumSeparation( self->phiField, &minSeparation, minSeparationEachDim );

	/* This is quite a conservative estimate */

	return self->courantFactor * minSeparation * minSeparation / self->maxDiffusivity;
}
void _Stokes_SLE_UzawaSolver_Build( void* solver, void* stokesSLE ) {
	Stokes_SLE_UzawaSolver*	self  = (Stokes_SLE_UzawaSolver*)solver;
	Stokes_SLE*             sle   = (Stokes_SLE*)stokesSLE;

   /* ok, this is far from satisfactory, but let's just bail if we have not been called from within
      the SLE routine  JM20140618 */
   if( sle == NULL )
      return;
   
 	Journal_DPrintf( self->debug, "In %s\n", __func__ );
	Stream_IndentBranch( StgFEM_Debug );
	
 	Journal_DPrintfL( self->debug, 2, "building a standard solver for the velocity system.\n" );
	/* was also being built in _Stokes_SLE_UzawaSolver_AssignFromXML function ? */
	KSPCreate( sle->comm, &self->velSolver );
	KSPSetOptionsPrefix( self->velSolver, "Uzawa_velSolver_" );
	
	/* Build Preconditioner */
	if ( self->preconditioner ) {
		Stg_Component_Build( self->preconditioner, stokesSLE, False );
		SystemLinearEquations_AddStiffnessMatrix( sle, self->preconditioner );

		Journal_DPrintfL( self->debug, 2, "build a standard solver for the preconditioner system.\n" );
		KSPCreate( sle->comm, &self->pcSolver );
		KSPSetOptionsPrefix( self->pcSolver, "Uzawa_pcSolver_" );
	}
	else 
		self->pcSolver = PETSC_NULL;

	if( self->pTempVec != PETSC_NULL ) Stg_VecDestroy(&self->pTempVec );
	if( self->rVec != PETSC_NULL )     Stg_VecDestroy(&self->rVec );
	if( self->sVec != PETSC_NULL )     Stg_VecDestroy(&self->sVec );
	if( self->fTempVec != PETSC_NULL ) Stg_VecDestroy(&self->fTempVec );
	if( self->vStarVec != PETSC_NULL ) Stg_VecDestroy(&self->vStarVec );

 	Journal_DPrintfL( self->debug, 2, "Allocate the auxillary vectors pTemp, r, s, fTemp and vStar.\n" ); 
	VecDuplicate( sle->pSolnVec->vector, &self->pTempVec );
	VecDuplicate( sle->pSolnVec->vector, &self->rVec );
	VecDuplicate( sle->pSolnVec->vector, &self->sVec );

	VecDuplicate( sle->fForceVec->vector, &self->fTempVec );
	VecDuplicate( sle->fForceVec->vector, &self->vStarVec );

	/* Need by the Picard nonlinear solver */
//        Vector_Duplicate( sle->pTempVec->vector, (void**)&self->f_hat );
//        Vector_SetLocalSize( self->vf_hat, Vector_GetLocalSize( sle->pTempVec->vector ) );

	Stream_UnIndentBranch( StgFEM_Debug );
}
void ForceVector_Assemble( void* forceVector ) {
	ForceVector* self = (ForceVector*)forceVector;
        int ii;
	
	Journal_DPrintf( self->debug, "In %s - for vector \"%s\" - calling the \"%s\" E.P.\n", __func__, self->name,
			 self->assembleForceVector->name );

	/* Call the Entry point directly from the base class */
	/* Note that it may be empty: this is deliberate. */
	if ( 0 == self->assembleForceVector->hooks->count ) {
		Journal_DPrintf( self->debug, "(E.P. has no hooks loaded -> no assembly required.)\n" ); 
	}	
	
	((FeEntryPoint_AssembleForceVector_CallFunction*)EntryPoint_GetRun( self->assembleForceVector ))(
		self->assembleForceVector,
		self );

        /* Run all the modify callbacks. */
        for( ii = 0; ii < self->nModifyCBs; ii++ ) {
           void* callback = self->modifyCBs[ii].callback;
           void* object = self->modifyCBs[ii].object;
           ((void(*)(void*))callback)( object );
        }
}
void _TimeIntegrator_Delete( void* timeIntegrator ) {
	TimeIntegrator* self = (TimeIntegrator*)timeIntegrator;
	
	Journal_DPrintf( self->debug, "In %s for %s '%s'\n", __func__, self->type, self->name );
	Memory_Free( self->_setupEPName );
	Memory_Free( self->_finishEPName );
	
	Stg_Class_Delete( self->setupData );
	Stg_Class_Delete( self->finishData );

        // delete register
	Stg_Class_Delete( self->integrandRegister );
	
	/* Stg_Class_Delete parent*/
	_Stg_Component_Delete( self );
}
void _TimeIntegrand_Print( void* timeIntegrand, Stream* stream ) {
	TimeIntegrand* self = (TimeIntegrand*)timeIntegrand;

	/* General info */
	Journal_DPrintf( self->debug, "TimeIntegrand - '%s'\n", self->name );
	Journal_PrintPointer( stream, self );
	Stream_Indent( stream );
	
	/* Print parent */
	_Stg_Component_Print( self, stream );
	
	/* Virtual info */

	/* Regular Info */
	
	Stream_UnIndent( stream );
}
/* +++ Virtual Functions +++ */
void TimeIntegrand_FirstOrder( void* timeIntegrand, Variable* startValue, double dt ) {
	TimeIntegrand*	self           = (TimeIntegrand*)timeIntegrand;
	Variable*       variable       = self->variable;
	double*         arrayDataPtr;
	double*         startDataPtr;
	double**        timeDeriv;
	Index           component_I; 
	Index           componentCount = *variable->dataTypeCounts;
	Index           array_I; 
	Index           arrayCount;
	Bool            successFlag = False;
	Stream*         errorStream = Journal_Register( Error_Type, (Name)self->type  );

	Journal_DPrintf( self->debug, "In func %s for %s '%s'\n", __func__, self->type, self->name );

	/* Update Variables */
	Variable_Update( variable );
	Variable_Update( startValue );
	arrayCount     = variable->arraySize;

	timeDeriv = Memory_Alloc_2DArray( double, arrayCount, componentCount, (Name)"Time Deriv" );
	for( array_I = 0; array_I < arrayCount; array_I++  ) {
		successFlag = TimeIntegrand_CalculateTimeDeriv( self, array_I, timeDeriv[array_I] );
                if(!successFlag) {
                   successFlag = TimeIntegrand_CalculateTimeDeriv( self, array_I, timeDeriv[array_I] );
                }
		Journal_Firewall( True == successFlag, errorStream,
			"Error - in %s(), for TimeIntegrand \"%s\" of type %s: When trying to find time "
			"deriv for item %u in step %u, *failed*.\n",
			__func__, self->name, self->type, array_I, 1 );
	}

	for ( array_I = 0 ; array_I < arrayCount ; array_I++ ) {
		arrayDataPtr = Variable_GetPtrDouble( variable, array_I );
		startDataPtr = Variable_GetPtrDouble( startValue, array_I );
		
		for ( component_I = 0 ; component_I < componentCount ; component_I++ ) {
			arrayDataPtr[ component_I ] = startDataPtr[ component_I ] + dt * timeDeriv[array_I][ component_I ];
		}
	
		TimeIntegrand_Intermediate( self, array_I );
	}

	Memory_Free( timeDeriv );
}
void IntegrationPointsSwarm_RemapIntegrationPointsAndRecalculateWeights( void* swarm ) {   
   IntegrationPointsSwarm* self = (IntegrationPointsSwarm*)swarm;
   double                  mapStartTime, mapTime;
   double                  weightsUpdateStartTime, weightsUpdateTime;

   Journal_DFirewall( self->mapper, global_error_stream,
        "Error in %s: The IntegrationPointsSwarm \'%s\' doesn't have a mapper to a MaterialPointsSwarm"
        "and should not be in this function. Check all instances of where \'%s\' is passed in the xml input file."
        "Most likely in can be replace with an IntegrationPointsSwarm with a mapper\n",
        __func__, self->name, self->name);

   Journal_DPrintf( self->debug, "In %s(): for swarm \"%s\":\n",
      __func__, self->name );
   Stream_IndentBranch( Swarm_Debug );

   Journal_DPrintf( self->debug, "Calling IntegrationPointsMapper \"%s\" (of type %s) to set up mappings\n"
      "\tfrom I.P.s to M.P.s, and calculate local coords:\n", self->mapper->name, self->mapper->type );
   mapStartTime = MPI_Wtime();   
   IntegrationPointMapper_Map( self->mapper );
   mapTime = MPI_Wtime() - mapStartTime;
   Journal_DPrintf( self->debug, "...done - took %g secs.\n", mapTime );

   if ( self->weights != NULL ) {
      Journal_DPrintf( self->debug, "Calling WeightsCalculator \"%s\" (of type %s)\n"
         "\tto calculate and set integration weights:\n",
         self->weights->name, self->weights->type );
      weightsUpdateStartTime = MPI_Wtime();
      WeightsCalculator_CalculateAll(self->weights, self );
      weightsUpdateTime = MPI_Wtime() - weightsUpdateStartTime;
      Journal_DPrintf( self->debug, "...weights updating finished - took %g secs.\n", weightsUpdateTime );
   }   
   else {
      Stream* errorStream = Journal_Register( Error_Type, (Name)self->type );
      Journal_Firewall( Stg_Class_IsInstance( self->mapper, GaussMapper_Type ) ||
         Stg_Class_IsInstance( self->mapper, GaussCoincidentMapper_Type ) ||
         !strcmp(self->mapper->type, "PCDVCGaussMapper"), errorStream,
         "Error - in %s(): for IntegrationPointSwarm \"%s\", no weights calculator provided "
         "and mapper is not a %s.\n", GaussMapper_Type );

      Journal_DPrintf( self->debug, "not recalculating weights since we are using a %s mapper and "
         "assume the points are not being advected.\n", GaussMapper_Type );
   }

   Stream_UnIndentBranch( Swarm_Debug );
   Journal_DPrintf( self->debug, "...done in %s() for swarm \"%s\"\n",
      __func__, self->name );
}
void _Stokes_SLE_UzawaSolver_SolverSetup( void* solver, void* stokesSLE ) {
	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*) solver;
	Stokes_SLE*             sle  = (Stokes_SLE*)             stokesSLE;
	
 	Journal_DPrintf( self->debug, "In %s:\n", __func__ );
	Stream_IndentBranch( StgFEM_Debug );

	Journal_DPrintfL( self->debug, 1, "Setting up MatrixSolver for the velocity eqn.\n" );
	Stg_KSPSetOperators( self->velSolver, sle->kStiffMat->matrix, sle->kStiffMat->matrix, DIFFERENT_NONZERO_PATTERN );
  	KSPSetFromOptions( self->velSolver );

	if( self->pcSolver ) {
		Journal_DPrintfL( self->debug, 1, "Setting up MatrixSolver for the Preconditioner.\n" );
		Stg_KSPSetOperators( self->pcSolver, self->preconditioner->matrix, self->preconditioner->matrix, DIFFERENT_NONZERO_PATTERN );
    		KSPSetFromOptions( self->pcSolver );
	}

	Stream_UnIndentBranch( StgFEM_Debug );
}
void _Stokes_SLE_UzawaSolver_Destroy( void* solver, void* data ) {
   Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*) solver;
	Journal_DPrintf( self->debug, "In: %s \n", __func__);

	Stream_IndentBranch( StgFEM_Debug );
	Journal_DPrintfL( self->debug, 2, "Destroying Solver contexts.\n" );
	Stg_KSPDestroy(&self->velSolver );
        if ( self->preconditioner ) { Stg_KSPDestroy(&self->pcSolver ); }

	Journal_DPrintfL( self->debug, 2, "Destroying temporary solver vectors.\n" );
	if( self->pTempVec != PETSC_NULL ) Stg_VecDestroy(&self->pTempVec );
	if( self->rVec != PETSC_NULL )     Stg_VecDestroy(&self->rVec );
	if( self->sVec != PETSC_NULL )     Stg_VecDestroy(&self->sVec );
	if( self->fTempVec != PETSC_NULL ) Stg_VecDestroy(&self->fTempVec );
	if( self->vStarVec != PETSC_NULL ) Stg_VecDestroy(&self->vStarVec );
	Stream_UnIndentBranch( StgFEM_Debug );
   _SLE_Solver_Destroy( self, data );

}
void _TimeIntegrator_Execute( void* timeIntegrator, void* data ) {
	TimeIntegrator*	self = (TimeIntegrator*)timeIntegrator;
	double wallTime,tmin,tmax;


	Journal_DPrintf( self->debug, "In %s for %s '%s'\n", __func__, self->type, self->name );

	wallTime = MPI_Wtime();

	/* Set function pointer */
	switch (self->order) {
		case 1:
			self->_execute = _TimeIntegrator_ExecuteEuler; 
			break;
		case 2:
			if (self->simultaneous) 
				self->_execute = _TimeIntegrator_ExecuteRK2Simultaneous; 
			else
				self->_execute = _TimeIntegrator_ExecuteRK2; 
			break;
		case 4:
			if (self->simultaneous) 
				self->_execute = _TimeIntegrator_ExecuteRK4Simultaneous; 
			else
				self->_execute = _TimeIntegrator_ExecuteRK4; 
			break;
		default:
			Journal_Firewall( False, Journal_Register( Error_Type, (Name)self->type  ),
					"%s '%s' cannot handle order %u\n", self->type, self->name, self->order );
	}

	/* Call real function */
	
	Journal_RPrintf( self->info, "Time Integration\n" );
	self->_execute( self, data );

	wallTime = MPI_Wtime()-wallTime;
        MPI_Reduce( &wallTime, &tmin, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD );
        MPI_Reduce( &wallTime, &tmax, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD );
	Journal_RPrintf(self->info,"Time Integration - %.6g [min] / %.6g [max] (secs)\n", tmin, tmax);
	
}
void ParticleMovementHandler_PrintParticleSlotsYetToFill( ParticleCommHandler* self ) {	
	Index leavingParticleEntry;

	Journal_DPrintf( self->debug, "%d slots yet to fill from particles leaving via shadow cells:\n",
		self->shadowParticlesLeavingMeUnfilledCount );
	leavingParticleEntry = self->currShadowParticleLeavingMeIndex;
	Journal_DPrintf( self->debug, "\t{ " );
	for ( ; leavingParticleEntry < self->shadowParticlesLeavingMeTotalCount; leavingParticleEntry++ ) {
		Journal_DPrintf( self->debug, "%d, ", 
			self->shadowParticlesLeavingMeIndices[leavingParticleEntry] );
	}
	Journal_DPrintf( self->debug, "}\n" );
		
	Journal_DPrintf( self->debug, "%d slots yet to fill from particles leaving domain directly:\n",
		self->particlesOutsideDomainUnfilledCount );
	leavingParticleEntry = self->currParticleLeavingMyDomainIndex;
	Journal_DPrintf( self->debug, "\t{ " );
	for ( ; leavingParticleEntry < self->particlesOutsideDomainTotalCount; leavingParticleEntry++ ) {
		Journal_DPrintf( self->debug, "%d, ", 
			self->particlesOutsideDomainIndices[leavingParticleEntry] );
	}
	Journal_DPrintf( self->debug, "}\n" );
}
void _SolutionVector_Build( void* solutionVector, void* data ) {
   SolutionVector* self = (SolutionVector*)solutionVector;

   Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
   Stream_IndentBranch( StgFEM_Debug );

   /* ensure variables are built */
   if( self->feVariable )
      Stg_Component_Build( self->feVariable, data, False );

   /* Allocate the vector */
   VecCreate( self->comm, &self->vector );
   VecSetSizes( self->vector, self->feVariable->eqNum->localEqNumsOwnedCount, PETSC_DECIDE );
   VecSetFromOptions( self->vector );
#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
   VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES );
#elif( PETSC_VERSION_MAJOR >= 3 )
   VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
#endif

   Stream_UnIndentBranch( StgFEM_Debug );
}
void _TimeIntegrator_ExecuteRK2( void* timeIntegrator, void* data ) {
	TimeIntegrator*	self = (TimeIntegrator*) timeIntegrator;
	Index					integrand_I;   
	Index					integrandCount = TimeIntegrator_GetCount( self );
	double				dt = self->dt;
	TimeIntegrand*	integrand;
	double wallTime,tmin,tmax;

	Journal_DPrintf( self->debug, "In %s for %s '%s'\n", __func__, self->type, self->name );

	
	wallTime = MPI_Wtime();

	/* Set Time */
    double startTime = TimeIntegrator_GetTime( self );
	
	TimeIntegrator_Setup( self );
	
	for ( integrand_I = 0 ; integrand_I < integrandCount ; integrand_I++ ) {
		integrand = TimeIntegrator_GetByIndex( self, integrand_I );
				
		TimeIntegrator_SetTime( self, startTime );
		
		wallTime = MPI_Wtime();
		TimeIntegrand_SecondOrder( integrand, integrand->variable, dt );

        	wallTime = MPI_Wtime()-wallTime;
        	MPI_Reduce( &wallTime, &tmin, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD );
        	MPI_Reduce( &wallTime, &tmax, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD );
		Journal_RPrintf(self->info,"\t2nd order: %35s - %9.4f [min] / %9.4f [max] (secs)\n", integrand->name, tmin, tmax);
		
	}
	
    TimeIntegrator_SetTime( self, TimeIntegrator_GetTime( self ) + 0.5*dt);

	TimeIntegrator_Finalise( self );
	
}
Esempio n. 25
0
void _SolutionVector_Build( void* solutionVector, void* data ) {
   SolutionVector* self = (SolutionVector*)solutionVector;

   Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
   Stream_IndentBranch( StgFEM_Debug );

   /* ensure variables are built */
   if( self->feVariable )
      Stg_Component_Build( self->feVariable, data, False );

   Journal_Firewall( (self->eqNum!=NULL), NULL, "Solution vector could not be built as provided FeVariable does not appear to have an equation number object.\nPlease contact developers." );
   /* Allocate the vector */
   VecCreate( self->comm, &self->vector );
   VecSetSizes( self->vector, self->eqNum->localEqNumsOwnedCount, PETSC_DECIDE );
   VecSetFromOptions( self->vector );
#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
   VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES );
#elif( PETSC_VERSION_MAJOR >= 3 )
   VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
#endif

   Stream_UnIndentBranch( StgFEM_Debug );
}
void ForceVector_PrintElementForceVector(
	ForceVector* self,
	Element_LocalIndex element_lI,
	Dof_EquationNumber** elementLM,
	double* elForceVecToAdd )
{
	DofLayout*		dofLayout = self->feVariable->dofLayout;
	FeMesh*			feMesh = self->feVariable->feMesh;
	unsigned		nInc, *inc;
	Dof_Index		dofsPerNode;
	Node_LocalIndex		nodesThisEl;
	Node_LocalIndex		node_I;
	Dof_Index		dof_I;
	Index			vec_I;
	IArray*			incArray;

	incArray = IArray_New();
	FeMesh_GetElementNodes( feMesh, element_lI, incArray );
	nInc = IArray_GetSize( incArray );
	inc = IArray_GetPtr( incArray );
	dofsPerNode = dofLayout->dofCounts[inc[0]];
	nodesThisEl = nInc;

	for ( node_I=0; node_I < nodesThisEl; node_I++ ) {
		for ( dof_I = 0; dof_I < dofsPerNode; dof_I++ ) {
			vec_I = node_I * dofsPerNode + dof_I;

			Journal_DPrintf( self->debug, "Entry[%d][%d] (LM (%4d)) = %.3f\n",
					 node_I, dof_I,
					 elementLM[node_I][dof_I],
					 elForceVecToAdd[vec_I] ); 
		}			
	}

	Stg_Class_Delete( incArray );
}
void _Stokes_SLE_UzawaSolver_Solve( void* solver, void* stokesSLE ) {
	Stokes_SLE_UzawaSolver* self            = (Stokes_SLE_UzawaSolver*)solver;	
	Stokes_SLE*             sle             = (Stokes_SLE*)stokesSLE;
	
	/* Create shortcuts to stuff needed on sle */
	Mat                     K_Mat           = sle->kStiffMat->matrix;
	Mat                     G_Mat           = sle->gStiffMat->matrix;
	Mat                     D_Mat           = NULL;
	Mat                     M_Mat           = NULL;
	Vec                     uVec            = sle->uSolnVec->vector;
	Vec                     qVec            = sle->pSolnVec->vector;
	Vec                     fVec            = sle->fForceVec->vector;
	Vec                     hVec            = sle->hForceVec->vector;
	
	/* Create shortcuts to solver related stuff */
	Vec                     qTempVec        = self->pTempVec;  
	Vec                     rVec            = self->rVec;
	Vec                     sVec            = self->sVec;
	Vec                     fTempVec        = self->fTempVec;
	Vec                     vStarVec        = self->vStarVec; 
	KSP                     velSolver       = self->velSolver;	/*  Inner velocity solver */
	KSP                     pcSolver        = self->pcSolver;   /*  Preconditioner  */

	Iteration_Index         maxIterations   = self->maxUzawaIterations;
	Iteration_Index         minIterations   = self->minUzawaIterations;
	Iteration_Index         iteration_I     = 0;
	Iteration_Index         outputInterval  = 1;
	
	double                  zdotr_current	= 0.0;
	double                  zdotr_previous 	= 1.0;
	double                  sdotGTrans_v;
	double                  alpha, beta;
	double                  absResidual;  
	double                  relResidual;
	double*                 chosenResidual;	  /* We can opt to use either the absolute or relative residual in termination condition */
    	double                  uzawaRhsScale;      
	double                  divU;
	double                  weightedResidual;
	double                  weightedVelocityScale;
	double                  momentumEquationResidual;
	
	Iteration_Index         innerLoopIterations;
	Stream*                 errorStream     = Journal_Register( Error_Type, (Name)Stokes_SLE_UzawaSolver_Type  );
	
	PetscInt		fVecSize, qTempVecSize, uVecSize, qVecSize;
	PetscScalar		fVecNorm, qTempVecNorm, uVecNorm, rVecNorm, fTempVecNorm, uVecNormInf, qVecNorm, qVecNormInf;

	double                  qGlobalProblemScale;
	double                  qReciprocalGlobalProblemScale;
	int			init_info_stream_rank;	
	PetscScalar p_sum;
	/* Bool nullsp_present; */
	Bool uzawa_summary;
	double time,t0,rnorm0;

	PetscTruth     flg;
	double        ksptime;

	VecGetSize( qTempVec, &qTempVecSize );
	qGlobalProblemScale = sqrt( (double) qTempVecSize );
	qReciprocalGlobalProblemScale = 1.0 / qGlobalProblemScale;
	init_info_stream_rank = Stream_GetPrintingRank( self->info );
	Stream_SetPrintingRank( self->info, 0 ); 

	/*	DEFINITIONS:
					See accompanying documentation
					u - the displacement / velocity solution (to which constraints are applied)
					q - the pressure-like variable which constrains the divergence displacement / velocity	(= pressure for incompressible)	
					F - standard FE force vector
					Fhat - Uzawa RHS = K^{-1} G F  - h 
					K - standard FE stiffness matrix
					Khat - Uzawa transformed stiffness matrix = G^T K^{-1} G
					G matrix - discrete gradient operator
					D matrix - discrete divergence operator = G^T for this particular algorithm
					C matrix - Mass matrix (M) for compressibility 
					
		LM & DAM			
	*/

	/* CHOICE OF RESIDUAL: 
					we may opt to converge on the absolute value (self->useAbsoluteTolerance == True ... default)
					or the relative value of the residual (self->useAbsoluteTolerance == False) 
			 		(another possibility would be always to improve the residual by a given tolerance)
					The Moresi & Solomatov (Phys Fluids, 1995) approach is to use the relative tolerance	
	*/ 

	VecNorm( fVec, NORM_2, &fVecNorm );
	VecGetSize( fVec, &fVecSize );
	if ( fVecNorm / sqrt( (double)fVecSize ) <= 1e-99 ) {
		Journal_Printf( errorStream,
			"Error in func %s: The momentum force vector \"%s\" is zero. "
			"The force vector should be non-zero either because of your chosen boundary "
			"conditions, or because of the element force vector assembly. You have %d "
			"element force vectors attached.\n",
			__func__, sle->fForceVec->name, sle->fForceVec->assembleForceVector->hooks->count );
		if ( sle->fForceVec->assembleForceVector->hooks->count > 0 ) {
			Journal_Printf( errorStream, "You used the following force vector assembly terms:\n" );
			EntryPoint_PrintConcise( sle->fForceVec->assembleForceVector, errorStream );
/* 			 TODO : need to print the elementForceVector assembly, not the global guy!! */
		}	
		Journal_Printf( errorStream,
			"Please check values for building the force vector.\n" );
		Journal_Firewall( 0, errorStream, "Exiting.\n" ); 	
	}
	
					
 	Journal_DPrintf( self->debug, "In %s:\n", __func__ );
	Journal_RPrintfL( self->debug, 2, "Conjugate Gradient Uzawa solver with:\n");
	
	Stream_IndentBranch( StgFEM_Debug );
	
	Journal_RPrintfL( self->debug, 2, "Compressibility %s\n", (sle->cStiffMat)? "on" : "off");
	Journal_RPrintfL( self->debug, 2, "Preconditioning %s\n", (pcSolver)? "on" : "off" );   
	
	
	
	if ( sle->cStiffMat ) {
		Journal_DPrintfL( self->debug, 2, "(compressibility active)\n" );
		M_Mat = sle->cStiffMat->matrix;   
	}
	else {
		Journal_DPrintfL( self->debug, 2, "(compressibility inactive)\n" );
	}
	if ( sle->dStiffMat ) {
		Journal_DPrintfL( self->debug, 2, "(asymmetric geometry: handling D Matrix [incorrectly - will be ignored])\n" );
		D_Mat = sle->dStiffMat->matrix;
	}
	else {
		Journal_DPrintfL( self->debug, 2, "(No D -> symmetric geometry: D = Gt)\n" );
	}
	
	#if DEBUG
	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
		Journal_DPrintf( self->debug, "Matrices and Vectors to solve are:\n" );
		Journal_DPrintf( self->debug, "K Matrix:\n" );
		/* No nice way of viewing Matrices, so commented out as incompatible with
		 * new 3D decomp at present --Kathleen Humble 30-04-07 
		 * Matrix_View( sle->kStiffMat->matrix, self->debug ); */
		Journal_DPrintf( self->debug, "G Matrix:\n" );
		if ( D_Mat ) {
			Journal_DPrintf( self->debug, "D Matrix:\n" );
		}	
		if ( M_Mat ) {
			Journal_DPrintf( self->debug, "M Matrix:\n" );
		}	
		Journal_DPrintf( self->debug, "Z (preconditioner) Matrix:\n" );
		Journal_DPrintf( self->debug, "f Vector:\n" );
		_SLE_VectorView( fVec, self->debug );
		Journal_DPrintf( self->debug, "h Vector:\n" );
		_SLE_VectorView( hVec, self->debug );
	}
	#endif
	
	/* STEP 1: Estimate the magnitude of the RHS for the transformed problem
			   we compute (usually to lower accuracy than elsewhere) the RHS (Fhat - h) 
	         and store the result in qTempVec.
		LM & DAM			
	*/
	
	Journal_DPrintfL( self->debug, 2, "Building Fhat - h.\n" );
	PetscOptionsHasName(PETSC_NULL,"-uzawa_printksptimes",&flg);
	KSPSetTolerances( velSolver, self->tolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT );
	if (flg) {
	    ksptime = MPI_Wtime();
	}
	KSPSolve( velSolver, fVec, vStarVec );
	if (flg) {
	    ksptime = MPI_Wtime() - ksptime;
	    PetscPrintf( PETSC_COMM_WORLD,  "KSP on velSolver took %lf seconds in Building Fhat step\n", ksptime);
	}
	KSPGetIterationNumber( velSolver, &innerLoopIterations );
	
	Journal_DPrintfL( self->debug, 2, "Fhat inner solution: Number of iterations: %d\n", innerLoopIterations );
	
        if ( D_Mat ) {
          MatMult( D_Mat, vStarVec, qTempVec );
        }
        else {
          MatMultTranspose( G_Mat, vStarVec, qTempVec );
        }
	VecAXPY( qTempVec, -1.0, hVec );
	
	/*  WARNING:
			If D != G^T then the resulting \hat{K} is not likely to be symmetric, positive definite as
			required by this implementation of the Uzawa iteration.  This next piece of code
			is VERY unlikely to work properly so it's in the sin bin for the time being - LM.
			
			if ( D_Mat ) {
				MatrixMultiply( D_Mat, vStarVec, qTempVec );
			}
			else {
				MatrixTransposeMultiply( G_Mat, vStarVec, qTempVec );
			}
		LM & DAM			
	*/	

	
	/* STEP 2: The problem scaling - optionally normalize the uzawa residual by the magnitude of the RHS (use a relative tolerance)
			For the inner velocity solver,  Citcom uses a relative tolerance equal to that used for the Uzawa iteration as a whole
		LM & DAM			
	*/
	
	if (self->useAbsoluteTolerance) {
		chosenResidual = &absResidual;
		Journal_PrintfL( self->info, 2, "Absolute residual < %g for Uzawa stopping condition\n", self->tolerance);
		/* We should calculate the effective relative tolerance and insert that here !! */
		KSPSetTolerances( velSolver, 0.1 * self->tolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT );
	}
	else {  /* The CITCOM compatible choice */
		chosenResidual = &relResidual;
		Journal_PrintfL( self->info, 2, "Relative residual < %g for Uzawa stopping condition\n", self->tolerance);	
		KSPSetTolerances( velSolver, 0.1 * self->tolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT );
	}
	
	Journal_DPrintfL( self->debug, 2, "Determining scaling factor for residual:\n" );
	VecNorm( qTempVec, NORM_2, &qTempVecNorm );
	uzawaRhsScale = ((double)qTempVecNorm) * qReciprocalGlobalProblemScale;
	
	Journal_DPrintfL( self->debug, 2, "uzawaRhsScale = %f\n", uzawaRhsScale );	
	Journal_Firewall( isGoodNumber( uzawaRhsScale ), errorStream, 
			"Error in func '%s' for %s '%s' - uzawaRhsScale has illegal value '%g'.\n", __func__, self->type, self->name, uzawaRhsScale );
	
	/* STEP 3: Calculate initial residual for transformed equation  (\hat{F} - h - \hat{K} q_0)
	    Compute the solution to K u_0 = F - G q_0  (u_0 unknown)
		  Then G^T u* = \hat{F} - \hat{K} q_0 
	    u_0 is also the initial velocity solution to which the constraint is applied by the subsequent iteration
		LM & DAM			
	*/
	
	Journal_DPrintfL( self->debug, 2, "Solving for transformed Uzawa RHS.\n" );
	
	VecCopy( fVec, fTempVec );
	VecScale( fTempVec, -1.0 );
	MatMultAdd( G_Mat, qVec, fTempVec, fTempVec );
	VecScale( fTempVec, -1.0 );
	KSPSolve( velSolver, fTempVec, uVec );

	/* Handling for NON-SYMMETRIC: relegated to sin bin (see comment above) LM & DAM */
        if ( D_Mat ) {
           MatMult( D_Mat, uVec, rVec );
        }
        else {
           MatMultTranspose( G_Mat, uVec, rVec );
        }
	VecNorm( rVec, NORM_2, &rnorm0 );
	VecNorm( uVec, NORM_2, &uVecNorm );
	divU = rnorm0 / uVecNorm;
	
	Journal_PrintfL( self->info, 2, "Initial l2Norm( Div u ) / l2Norm( u ) = %f \n", divU);
	
	Journal_Firewall( isGoodNumber( divU ), errorStream, 
			"Error in func '%s' for %s '%s' - l2Norm( Div u ) has illegal value '%g'.\n",
			__func__, self->type, self->name, divU );
	
	
	Journal_DPrintfL( self->debug, 2, "Adding compressibility and prescribed divergence terms.\n" );
	
	if ( M_Mat ) {
		MatMultAdd( M_Mat, qVec, rVec, rVec );
	}	
	VecAXPY( rVec, -1.0, hVec );
			
	/* Check for existence of constant null space */
#if 0
	nullsp_present = _check_if_constant_nullsp_present( self, K_Mat,G_Mat,M_Mat, fTempVec,vStarVec,qTempVec,sVec, velSolver );
#endif
			
	/* STEP 4: Preconditioned conjugate gradient iteration loop */	
		
	Journal_DPrintfL( self->debug, 1, "Beginning main Uzawa conjugate gradient loop:\n" );	

	iteration_I = 0;

        /* outer_it, residual, time */
        uzawa_summary = self->monitor;
	time = 0.0;
	t0 = MPI_Wtime();
//	Journal_PrintfL( self->info, 1, "  |r0| = %.8e \n", rnorm0 );

	do{	
		/* reset initial time and end time for inner its back to 0 - probs don't need to do this but just in case */
		self->outeritsinitialtime = 0;
		self->outeritsendtime = 0;
		//BEGINNING OF OUTER ITERATIONS!!!!!
		/*get wall time for start of outer loop*/
		self->outeritsinitialtime = MPI_Wtime();
		
		Journal_DPrintfL( self->debug, 2, "Beginning solve '%u'.\n", iteration_I );
		Stream_IndentBranch( StgFEM_Debug );
		
		/* STEP 4.1: Preconditioner
			Solve:
				Q_\hat{K} z_1 =  r_1
				Q_\hat{K} is an approximation to \hat{K} which is simple / trivial / quick to invert
			LM & DAM			
		*/
		
		if ( pcSolver ) {
		    PetscOptionsHasName(PETSC_NULL,"-uzawa_printksptimes",&flg);
		    if (flg) {
			ksptime = MPI_Wtime();
		    }
		    KSPSolve( pcSolver, rVec, qTempVec );
		    if (flg) {
			ksptime = MPI_Wtime() - ksptime;
			PetscPrintf( PETSC_COMM_WORLD,  "KSP on pcSolver took %lf seconds\n", ksptime);
		    }
		}
		else {
			VecCopy( rVec, qTempVec );
		}

		/* Remove the constant null space, but only if NOT compressible */
#if 0
		if( nullsp_present == True ) {
			_remove_constant_nullsp( qTempVec );
		}
#endif
				
		/* STEP 4.2: Calculate s_I, the pressure search direction
				z_{I-1} . r_{I-1}  
				\beta = (z_{I-1} . r_{I-1}) / (z_{I-2} . r_{I-2})  
					\beta = 0 for the first iteration
		      s_I = z_(I-1) + \beta * s_(I-1) 
			LM & DAM			
		*/ 
		
		VecDot( qTempVec, rVec, &zdotr_current );
	
		VecNorm( qTempVec, NORM_2, &qTempVecNorm );
		VecNorm( rVec, NORM_2, &rVecNorm );	
		Journal_DPrintfL( self->debug, 2, "l2Norm (qTempVec) %g; (rVec) %g \n", 
			qTempVecNorm * qReciprocalGlobalProblemScale,
			rVecNorm * qReciprocalGlobalProblemScale );
		
		if ( iteration_I == 0 ) {
			VecCopy( qTempVec, sVec );
		}
		else {
			beta = zdotr_current/zdotr_previous;
			VecAYPX( sVec, beta, qTempVec );
		}
		
		/* STEP 4.3: Velocity search direction corresponding to s_I is found by solving
				K u* = G s_I
			LM & DAM			
		*/
			
		MatMult( G_Mat, sVec, fTempVec );
		
		Journal_DPrintfL( self->debug, 2, "Uzawa inner iteration step\n");
		
		//START OF INNER ITERATIONS!!!!
		PetscOptionsHasName(PETSC_NULL,"-uzawa_printksptimes",&flg);
		/*get initial wall time for inner loop*/
		self->inneritsinitialtime = MPI_Wtime();
		if (flg) {
		    ksptime = MPI_Wtime();
		}
		KSPSolve( velSolver, fTempVec, vStarVec );
		if (flg) {
		    ksptime = MPI_Wtime() - ksptime;
		    PetscPrintf( PETSC_COMM_WORLD,  "KSP on velSolver took %lf seconds in Uzawa inner iteration step\n", ksptime);
		}
		/*get end wall time for inner loop*/
		self->inneritsendtime = MPI_Wtime();
		
		/* add time to total time inner its: */
		self->totalinneritstime = self->totalinneritstime + (-self->inneritsinitialtime + self->inneritsendtime);
		/* reset initial time and end time for inner its back to 0 - probs don't need to do this but just in case */
		self->inneritsinitialtime = 0;
		self->inneritsendtime = 0;
		
		KSPGetIterationNumber( velSolver, &innerLoopIterations );
		/* add the inner loop iterations to the total inner iterations */
		self->totalnuminnerits = self->totalnuminnerits + innerLoopIterations;
		
		Journal_DPrintfL( self->debug, 2, "Completed Uzawa inner iteration in '%u' iterations \n", innerLoopIterations );
				
		/* STEP 4.4: Calculate the step size ( \alpha = z_{I-1} . r_{I-1} / (s_I . \hat{K} s_I) )
				 \hat{K} s_I = G^T u* - M s_I (u* from step 4.3) 	
			LM & DAM			
		*/ 
		
                if ( D_Mat ) {
                   MatMult( D_Mat, vStarVec, qTempVec );
                }
                else {
                   MatMultTranspose( G_Mat, vStarVec, qTempVec );
                }
		
		/* Handling for NON-SYMMETRIC: relegated to sin bin (see comment above) 
		
			if ( D_Mat ) {
				MatrixMultiply( D_Mat, vStarVec, qTempVec );
			}
			else {
				MatrixTransposeMultiply( G_Mat, vStarVec, qTempVec );
			}
			LM & DAM			
		*/

		if ( M_Mat ) {
			Journal_DPrintfL( self->debug, 2, "Correcting for Compressibility\n" );
			VecScale( qTempVec, -1.0 );
			MatMultAdd( M_Mat, sVec, qTempVec, qTempVec );
			VecScale( qTempVec, -1.0 );
		}

		VecDot( sVec, qTempVec, &sdotGTrans_v );
		
		alpha = zdotr_current/sdotGTrans_v;
		
		/* STEP 4.5: Update pressure, velocity and value of residual
				 by \alpha times corresponding search direction 
			LM & DAM			
		*/
		
		Journal_DPrintfL( self->debug, 2, "zdotr_current = %g \n", zdotr_current);
		Journal_DPrintfL( self->debug, 2, "sdotGTrans_v = %g \n", sdotGTrans_v);
		Journal_DPrintfL( self->debug, 2, "alpha = %g \n", alpha);
	
		Journal_Firewall( 
				isGoodNumber( zdotr_current ) && isGoodNumber( sdotGTrans_v ) && isGoodNumber( alpha ), 
				errorStream, 
				"Error in func '%s' for %s '%s' - zdotr_current, sdotGTrans_v or alpha has an illegal value: '%g','%g' or '%g'\n",
				__func__, self->type, self->name, zdotr_current, sdotGTrans_v, alpha );
		
		VecAXPY( qVec, alpha, sVec );
		VecAXPY( uVec, -alpha, vStarVec );
		VecAXPY( rVec, -alpha, qTempVec );
		
		/* STEP 4.6: store the value of z_{I-1} . r_{I-1} for the next iteration
		 LM & DAM
		*/
		
		zdotr_previous = zdotr_current; 
		
		VecNorm( rVec, NORM_2, &rVecNorm );
		absResidual = rVecNorm * qReciprocalGlobalProblemScale;
		relResidual = absResidual / uzawaRhsScale;
		
		Stream_UnIndentBranch( StgFEM_Debug );
		
		if( iteration_I % outputInterval == 0 ) {
			Journal_PrintfL( self->info, 2, "\tLoop = %u, absResidual = %.8e, relResidual = %.8e\n", 
				iteration_I, absResidual, relResidual );
		}
		
		Journal_Firewall( isGoodNumber( absResidual ), errorStream, 
				"Error in func '%s' for %s '%s' - absResidual has an illegal value: '%g'\n",
				__func__, self->type, self->name, absResidual );
		
		Journal_Firewall( iteration_I < maxIterations, 
				errorStream, "In func %s: Reached maximum number of iterations %u without converging; absResidual = %.5g, relResidual = %.5g \n",
				__func__, iteration_I, absResidual, relResidual );

/* 		 TODO: test for small change in 10 iterations and if so restart? */

		time = MPI_Wtime()-t0;
		if (uzawa_summary) {
                	Journal_PrintfL( self->info, 1, "  %1.4d uzawa residual norm %12.13e, cpu time %5.5e\n", iteration_I+1,*chosenResidual,time );
        	}
			
	iteration_I++;  
	//END OF OUTER ITERATION LOOP!!!
		/*get wall time for end of outer loop*/
		self->outeritsendtime = MPI_Wtime();
		/* add time to total time inner its: */
		self->totalouteritstime = self->totalouteritstime + (-self->outeritsinitialtime + self->outeritsendtime);
		/* reset initial time and end time for inner its back to 0 - probs don't need to do this but just in case */
		self->outeritsinitialtime = 0;
		self->outeritsendtime = 0;
		/* add the outer loop iterations to the total outer iterations */
		self->totalnumouterits++; 
	}  while ( (*chosenResidual > self->tolerance) || (iteration_I<minIterations) );  
//	}  while ( *chosenResidual > self->tolerance );

	Journal_DPrintfL( self->debug, 1, "Pressure solution converged. Exiting uzawa \n ");
	
	/* STEP 5:  Check all the relevant residuals and report back */
	
	if (Stream_IsEnable( self->info ) ) {
	
	/* This information should be in an info stream */
	Journal_PrintfL( self->info, 1, "Summary:\n");
	Journal_PrintfL( self->info, 1, "  Uzawa its. = %04d , Uzawa residual = %12.13e\n", iteration_I, relResidual );
	MatMultTranspose( G_Mat, uVec, rVec );
	VecNorm( rVec, NORM_2, &rVecNorm );
	VecNorm( uVec, NORM_2, &uVecNorm );
	divU = rVecNorm / uVecNorm;
	Journal_PrintfL( self->info, 1, "  |G^T u|/|u|               = %.8e\n", divU);
	
	/* Residual for the momentum equation 
		Compute r = || F - Ku - Gp || / || F ||
	*/
	
	MatMult( G_Mat, qVec, vStarVec );
	MatMultAdd( K_Mat, uVec, vStarVec, fTempVec );
	VecAYPX( fTempVec, -1.0, fVec );
	
	VecNorm( fTempVec, NORM_2, &fTempVecNorm );
	VecNorm( fVec, NORM_2, &fVecNorm );
	momentumEquationResidual = fTempVecNorm / fVecNorm;
	Journal_PrintfL( self->info, 1, "  |f - K u - G p|/|f|       = %.8e\n", momentumEquationResidual );
	Journal_Firewall( isGoodNumber( momentumEquationResidual ), errorStream, 
			"Bad residual for the momentum equation (|| F - Ku - Gp || / || F || = %g):\n"
			"\tCheck to see if forcing term is zero or nan - \n\t|| F - Ku - Gp || = %g \n\t|| F || = %g.\n", 
			momentumEquationResidual,
			fTempVecNorm, fVecNorm );
		
	/* "Preconditioned"	residual for the momentum equation 
	 		r_{w} = || Q_{K}(r) || / || Q_{K}(F)
			fTempVec contains the residual but is overwritten once used
			vStarVec is used to hold the diagonal preconditioner Q_{K} 
	*/
	
	MatGetDiagonal( K_Mat, vStarVec );
	VecReciprocal( vStarVec );
	VecPointwiseMult( vStarVec, fTempVec, fTempVec );
	VecNorm( fTempVec, NORM_2, &weightedResidual );
	VecPointwiseMult( vStarVec, fVec, fTempVec );
	VecNorm( fTempVec, NORM_2, &weightedVelocityScale );
		
	Journal_PrintfL( self->info, 1, "  |f - K u - G p|_w/|f|_w   = %.8e\n", weightedResidual / weightedVelocityScale );	
		
	/* Report back on the solution - velocity and pressure 
	 Note - correction for dof in Vrms ??
	*/

	VecNorm( uVec, NORM_INFINITY, &uVecNormInf );
	VecNorm( uVec, NORM_2, &uVecNorm );
	VecGetSize( uVec, &uVecSize );
	VecNorm( qVec, NORM_INFINITY, &qVecNormInf );
	VecNorm( qVec, NORM_2, &qVecNorm );
	VecGetSize( qVec, &qVecSize );
        Journal_PrintfL( self->info, 1, "  |u|_{\\infty} = %.8e , u_rms = %.8e\n", 
		uVecNormInf, uVecNorm / sqrt( (double)uVecSize ) );
	Journal_PrintfL( self->info, 1, "  |p|_{\\infty} = %.8e , p_rms = %.8e\n",
               	qVecNormInf, qVecNorm / sqrt( (double)qVecSize ) );

	{	PetscInt lmin,lmax;
		PetscReal min,max;
		VecMax( uVec, &lmax, &max );
		VecMin( uVec, &lmin, &min );
		Journal_PrintfL( self->info, 1, "  min/max(u) = %.8e [%d] / %.8e [%d]\n",min,lmin,max,lmax);
                VecMax( qVec, &lmax, &max );
                VecMin( qVec, &lmin, &min );
                Journal_PrintfL( self->info, 1, "  min/max(p) = %.8e [%d] / %.8e [%d]\n",min,lmin,max,lmax);
        }
	VecSum( qVec, &p_sum );
	Journal_PrintfL( self->info, 1, "  \\sum_i p_i = %.8e \n", p_sum );

	} /* journal stream enabled */

	#if DEBUG
	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
		Journal_DPrintf( self->debug, "Velocity solution:\n" );
		_SLE_VectorView( uVec, self->debug );
		Journal_DPrintf( self->debug, "Pressure solution:\n" );
		_SLE_VectorView( qVec, self->debug );
	}
	#endif
	Stream_UnIndentBranch( StgFEM_Debug );

        Stream_SetPrintingRank( self->info, init_info_stream_rank );
		/* Now gather up data for printing out to FrequentOutput file: */
	
	
	/*!!! if non-linear need to divide by number of nonlinear iterations and we do this in SystemLinearEquations */
	if((sle->isNonLinear != True)){
		self->avgnuminnerits = self->totalnuminnerits/self->totalnumouterits;
		self->avgnumouterits = self->totalnumouterits;
		self->avgtimeouterits = (self->totalouteritstime - self->totalinneritstime)/self->totalnumouterits;
		self->avgtimeinnerits = self->totalinneritstime/self->totalnuminnerits;
	}	
}
Esempio n. 28
0
void _FrictionVC_ReadDictionary( void* variableCondition, void* dictionary ) {
	FrictionVC*			self = (FrictionVC*)variableCondition;
	Dictionary_Entry_Value*	vcDictVal;
	Dictionary_Entry_Value	_vcDictVal;
	Dictionary_Entry_Value*	varsVal;
	FrictionVC_Entry_Index	entry_I;
	
	/* Find dictionary entry */
	if (self->_dictionaryEntryName)
		vcDictVal = Dictionary_Get(dictionary, self->_dictionaryEntryName);
	else
	{
		vcDictVal = &_vcDictVal;
		Dictionary_Entry_Value_InitFromStruct(vcDictVal, dictionary);
	}
	
	if (vcDictVal)
	{
		char*	wallStr;
		
		/* Obtain which wall */
		wallStr = Dictionary_Entry_Value_AsString(Dictionary_Entry_Value_GetMember(vcDictVal, "wall" ));
		if (!strcasecmp(wallStr, "back"))
			self->_wall = FrictionVC_Wall_Back;
		else if (!strcasecmp(wallStr, "left"))
			self->_wall = FrictionVC_Wall_Left;
		else if (!strcasecmp(wallStr, "bottom"))
			self->_wall = FrictionVC_Wall_Bottom;
		else if (!strcasecmp(wallStr, "right"))
			self->_wall = FrictionVC_Wall_Right;
		else if (!strcasecmp(wallStr, "top"))
			self->_wall = FrictionVC_Wall_Top;
		else if (!strcasecmp(wallStr, "front"))
			self->_wall = FrictionVC_Wall_Front;
		else {
			assert( 0 );
			self->_wall = FrictionVC_Wall_Size; /* invalid entry */
		}
		
		/* Obtain the variable entries */
		self->_entryCount = 0;
		self->_entryCount = Dictionary_Entry_Value_GetCount(Dictionary_Entry_Value_GetMember(vcDictVal, "variables"));
		self->_entryTbl = Memory_Alloc_Array( FrictionVC_Entry, self->_entryCount, "FrictionVC->_entryTbl" );
		varsVal = Dictionary_Entry_Value_GetMember(vcDictVal, "variables");
		
		for (entry_I = 0; entry_I < self->_entryCount; entry_I++)
		{
			char*			valType;
			Dictionary_Entry_Value*	valueEntry;
			Dictionary_Entry_Value*	varDictListVal;
			
			varDictListVal = Dictionary_Entry_Value_GetElement(varsVal, entry_I);
			valueEntry = Dictionary_Entry_Value_GetMember(varDictListVal, "value");
			
			self->_entryTbl[entry_I].varName = Dictionary_Entry_Value_AsString(
				Dictionary_Entry_Value_GetMember(varDictListVal, "name"));
				
			valType = Dictionary_Entry_Value_AsString(Dictionary_Entry_Value_GetMember(varDictListVal, "type"));
			if (0 == strcasecmp(valType, "func"))
			{
				char*	funcName = Dictionary_Entry_Value_AsString(valueEntry);
				Index	cfIndex;
				
				self->_entryTbl[entry_I].value.type = VC_ValueType_CFIndex;
				cfIndex = ConditionFunction_Register_GetIndex( self->conFunc_Register, funcName);
				if ( cfIndex == (unsigned)-1 ) {	
					Stream*	errorStr = Journal_Register( Error_Type, self->type );

					Journal_Printf( errorStr, "Error- in %s: While parsing "
						"definition of wallVC \"%s\" (applies to wall \"%s\"), the cond. func. applied to "
						"variable \"%s\" - \"%s\" - wasn't found in the c.f. register.\n",
						__func__, self->_dictionaryEntryName, FrictionVC_WallEnumToStr[self->_wall],
						self->_entryTbl[entry_I].varName, funcName );
					Journal_Printf( errorStr, "(Available functions in the C.F. register are: ");	
					ConditionFunction_Register_PrintNameOfEachFunc( self->conFunc_Register, errorStr );
					Journal_Printf( errorStr, ")\n");	
					assert(0);
				}	
				self->_entryTbl[entry_I].value.as.typeCFIndex = cfIndex;
			}
			else if (0 == strcasecmp(valType, "array"))
			{
				Dictionary_Entry_Value*	valueElement;
				Index			i;

				self->_entryTbl[entry_I].value.type = VC_ValueType_DoubleArray;
				self->_entryTbl[entry_I].value.as.typeArray.size = Dictionary_Entry_Value_GetCount(valueEntry);
				self->_entryTbl[entry_I].value.as.typeArray.array = Memory_Alloc_Array( double,
					self->_entryTbl[entry_I].value.as.typeArray.size, "FrictionVC->_entryTbl[].value.as.typeArray.array" );
					
				for (i = 0; i < self->_entryTbl[entry_I].value.as.typeArray.size; i++)
				{
					valueElement = Dictionary_Entry_Value_GetElement(valueEntry, i);
					self->_entryTbl[entry_I].value.as.typeArray.array[i] = 
						Dictionary_Entry_Value_AsDouble(valueElement);
				}
			}
			else if( 0 == strcasecmp( valType, "double" ) || 0 == strcasecmp( valType, "d" ) ||
				0 == strcasecmp( valType, "float" ) || 0 == strcasecmp( valType, "f" ) )
			{
				self->_entryTbl[entry_I].value.type = VC_ValueType_Double;
				self->_entryTbl[entry_I].value.as.typeDouble = Dictionary_Entry_Value_AsDouble( valueEntry );
			}
			else if( 0 == strcasecmp( valType, "integer" ) || 0 == strcasecmp( valType, "int" ) || 0 == strcasecmp( valType, "i" ) ) {
				self->_entryTbl[entry_I].value.type = VC_ValueType_Int;
				self->_entryTbl[entry_I].value.as.typeInt = Dictionary_Entry_Value_AsUnsignedInt( valueEntry );
			}
			else if( 0 == strcasecmp( valType, "short" ) || 0 == strcasecmp( valType, "s" ) ) {
				self->_entryTbl[entry_I].value.type = VC_ValueType_Short;
				self->_entryTbl[entry_I].value.as.typeShort = Dictionary_Entry_Value_AsUnsignedInt( valueEntry );
			}
			else if( 0 == strcasecmp( valType, "char" ) || 0 == strcasecmp( valType, "c" ) ) {
				self->_entryTbl[entry_I].value.type = VC_ValueType_Char;
				self->_entryTbl[entry_I].value.as.typeChar = Dictionary_Entry_Value_AsUnsignedInt( valueEntry );
			}
			else if( 0 == strcasecmp( valType, "pointer" ) || 0 == strcasecmp( valType, "ptr" ) || 0 == strcasecmp( valType, "p" ) ) {
				self->_entryTbl[entry_I].value.type = VC_ValueType_Ptr;
				self->_entryTbl[entry_I].value.as.typePtr = (void*) ( (ArithPointer)Dictionary_Entry_Value_AsUnsignedInt( valueEntry ));
			}
			else {
				/* Assume double */
				Journal_DPrintf( 
					Journal_Register( InfoStream_Type, "myStream" ), 
					"Type to variable on variable condition not given, assuming double\n" );
				self->_entryTbl[entry_I].value.type = VC_ValueType_Double;
				self->_entryTbl[entry_I].value.as.typeDouble = Dictionary_Entry_Value_AsDouble( valueEntry );
			}
		}
void _TimeIntegrator_ExecuteRK4Simultaneous( void* timeIntegrator, void* data ) {
	TimeIntegrator*	self = (TimeIntegrator*)timeIntegrator;
	AbstractContext*	context = (AbstractContext*) data;
	Index					integrand_I;   
	Index					integrandCount = TimeIntegrator_GetCount( self );
	double				dt = self->dt;
	TimeIntegrand*	integrand;
	Variable**			originalVariableList;
	Variable**			timeDerivVariableList;
    assert(0); /* this shit be broken */

	Journal_DPrintf( self->debug, "In %s for %s '%s'\n", __func__, self->type, self->name );

	/* Set Time */
	TimeIntegrator_SetTime( self, context->currentTime );
	
	originalVariableList  = Memory_Alloc_Array( Variable*, integrandCount, "originalVariableList" );
	timeDerivVariableList = Memory_Alloc_Array( Variable*, integrandCount, "timeDerivVariableList" );

	/* First Step */
	TimeIntegrator_Setup( self );
	for ( integrand_I = 0 ; integrand_I < integrandCount ; integrand_I++ ) {
		integrand = TimeIntegrator_GetByIndex( self, integrand_I );
		Journal_RPrintf(self->info,"\t4nd order (simultaneous): %s\n", integrand->name);

		/* Store Original Position Variable */
		originalVariableList[ integrand_I ]  = Variable_NewFromOld( integrand->variable, "Original", True );
		timeDerivVariableList[ integrand_I ] = Variable_NewFromOld( integrand->variable, "k1+2k2+2k3", False );

		/* Store k1 */
		TimeIntegrand_StoreTimeDeriv( integrand, timeDerivVariableList[ integrand_I ] );

		/* 1st Step */
		TimeIntegrand_FirstOrder( integrand, integrand->variable, 0.5 * dt );
	}
	TimeIntegrator_Finalise( self );
	
	/* Set Time */
	TimeIntegrator_SetTime( self, context->currentTime + 0.5 * dt );
	
	/* Second Step */
	TimeIntegrator_Setup( self );
	for ( integrand_I = 0 ; integrand_I < integrandCount ; integrand_I++ ) {
		integrand = TimeIntegrator_GetByIndex( self, integrand_I );

		/* Add k2 */
		TimeIntegrand_Add2TimesTimeDeriv( integrand, timeDerivVariableList[ integrand_I ] );

		TimeIntegrand_FirstOrder( integrand, originalVariableList[ integrand_I ], 0.5 * dt );
	}
	TimeIntegrator_Finalise( self );

	TimeIntegrator_Setup( self );
	for ( integrand_I = 0 ; integrand_I < integrandCount ; integrand_I++ ) {
		integrand = TimeIntegrator_GetByIndex( self, integrand_I );
		
		/* Add k3 */
		TimeIntegrand_Add2TimesTimeDeriv( integrand, timeDerivVariableList[ integrand_I ] );

		/* 3rd Step */
		TimeIntegrand_FirstOrder( integrand, originalVariableList[ integrand_I ], dt );
	}
	TimeIntegrator_Finalise( self );
	
	/* Set Time */
	TimeIntegrator_SetTime( self, context->currentTime + dt );
	
	TimeIntegrator_Setup( self );
	for ( integrand_I = 0 ; integrand_I < integrandCount ; integrand_I++ ) {
		integrand = TimeIntegrator_GetByIndex( self, integrand_I );

		TimeIntegrand_FourthOrderFinalStep( integrand, originalVariableList[ integrand_I ], timeDerivVariableList[ integrand_I ], dt );

		/* Free Original */
		Stg_Class_Delete( timeDerivVariableList[ integrand_I ] );
		Stg_Class_Delete( originalVariableList[ integrand_I ] );
	}
	TimeIntegrator_Finalise( self );

	Memory_Free( originalVariableList );
	Memory_Free( timeDerivVariableList );
}
void _TimeIntegrator_Destroy( void* timeIntegrator, void* data ) {
	TimeIntegrator*	self = (TimeIntegrator*)timeIntegrator;

	Journal_DPrintf( self->debug, "In %s for %s '%s'\n", __func__, self->type, self->name );
}