/*
 * Copyright (C) 2008-2012 Delft University of Technology - All rights reserved.
 *
 * Author: Reijer Idema
 */

/*
 * Power System Power Vector class source.
 */
#include "PowerVector.h"


POWERFLOWER_NAMESPACE_BEGIN

POWERSYSTEM_NAMESPACE_USING


/////////////////////////////// PUBLIC ///////////////////////////////////////


//============================= LIFECYCLE ====================================


#undef __FUNCT__
#define __FUNCT__ "PowerVector::PowerVector"
PowerVector::PowerVector(void) : mErr(0), mP(PETSC_NULL), mQ(PETSC_NULL)
{
	if (PetscUtils::IsInitialized())
	{
		mErr = PetscInfo(PETSC_NULL, "Creating PowerVector object.\n"); CHKERRV(mErr);
	}
}


#undef __FUNCT__
#define __FUNCT__ "PowerVector::~PowerVector"
PowerVector::~PowerVector(void)
{
	Clear();
	if (PetscUtils::IsInitialized())
	{
		mErr = PetscInfo(PETSC_NULL, "Destroying PowerVector object.\n"); CHKERRV(mErr);
	}
} // PowerVector::~PowerVector


//============================= OPERATIONS ===================================


#undef __FUNCT__
#define __FUNCT__ "PowerVector::Clear"
void PowerVector::Clear(void)
{
	if (PetscUtils::IsInitialized())
	{
		mErr = PetscInfo(PETSC_NULL, "Clearing PowerVector object data.\n"); CHKERRV(mErr);
		if (mP != PETSC_NULL) { mErr = VecDestroy(&mP); mP = PETSC_NULL; CHKERRV(mErr); }
		if (mQ != PETSC_NULL) { mErr = VecDestroy(&mQ); mQ = PETSC_NULL; CHKERRV(mErr); }
	}
	mErr = 0;
} // PowerVector::Clear


#undef __FUNCT__
#define __FUNCT__ "PowerVector::Build"
bool PowerVector::Build(const POWERSYSTEM_NAMESPACE_NAME::PowerSystem& rPowerSystem)
{
	if (!PetscUtils::IsInitialized()) return false;
 	mErr =  PetscInfo(PETSC_NULL, "Building injected power vector.\n"); CHKERRB(mErr);
	return Build_Private(rPowerSystem);
} // PowerVector::Build


//============================= ACCESS     ===================================


PetscUtils::ConstVec PowerVector::GetReal(void) const { return mP; }
PetscUtils::ConstVec PowerVector::GetImag(void) const { return mQ; }


/////////////////////////////// PRIVATE    ///////////////////////////////////


#undef __FUNCT__
#define __FUNCT__ "PowerVector::Build_Private"
bool PowerVector::Build_Private(const POWERSYSTEM_NAMESPACE_NAME::PowerSystem& rPowerSystem)
{
 	mErr =  PetscInfo(PETSC_NULL, "Creating and preallocating injected power vector.\n"); CHKERRB(mErr);

 	// Get the number of elements in the injected power vector
	PetscInt n = rPowerSystem.GetBusCount();
	if (n == 0) return false;

	if (mP != PETSC_NULL) { mErr = VecDestroy(&mP); mP = PETSC_NULL; CHKERRB(mErr); }
	mErr = VecCreate(PETSC_COMM_WORLD, &mP); CHKERRB(mErr);
	mErr = VecSetSizes(mP, n, PETSC_DETERMINE); CHKERRB(mErr);
	mErr = VecSetType(mP, VECSEQ); CHKERRB(mErr);

	if (mQ != PETSC_NULL) { mErr = VecDestroy(&mQ); mQ = PETSC_NULL; CHKERRB(mErr); }
	mErr = VecCreate(PETSC_COMM_WORLD, &mQ); CHKERRB(mErr);
	mErr = VecSetSizes(mQ, n, PETSC_DETERMINE); CHKERRB(mErr);
	mErr = VecSetType(mQ, VECSEQ); CHKERRB(mErr);

 	mErr =  PetscInfo(PETSC_NULL, "Calculating and setting injected power vector values.\n"); CHKERRB(mErr);

 	PetscScalar *pValsP, *pValsQ;
	mErr = VecGetArray(mP, &pValsP); CHKERRB(mErr);
	mErr = VecGetArray(mQ, &pValsQ); CHKERRB(mErr);
	for (PetscInt i = 0; i < n; ++i)
	{
		pValsP[i] = (rPowerSystem.GetBus(i)->GetActivePowerGeneration() - rPowerSystem.GetBus(i)->GetActivePowerDemand()) / rPowerSystem.GetBasePower();
		pValsQ[i] = (rPowerSystem.GetBus(i)->GetReactivePowerGeneration() - rPowerSystem.GetBus(i)->GetReactivePowerDemand()) / rPowerSystem.GetBasePower();
	}
	mErr = VecRestoreArray(mQ, &pValsP); CHKERRB(mErr);
	mErr = VecRestoreArray(mP, &pValsP); CHKERRB(mErr);
	return true;
} // PowerVector::Build_Private


POWERFLOWER_NAMESPACE_END
