unit uusogestionable_postizado;

(****
rch@201305032255
La idea de este actor es poder definir sobre una demanda dada, un USO_GESIONABLE
dando factores de determinación de la energía gestionable por poste y valores
de la utilidad en USD/MWh de suministrar la energía gestionable en cada poste.

***)

interface

uses
  Classes,
  SysUtils,
  uFichasLPD, uFechas, xMatDefs, uNodos,
  uFuentesAleatorias, uCosa, uCosaConNombre, uGlobs,
  uActorNodal, uDemandas,
  uSimplex;

resourcestring
  rsUsoGestionable_postizado = 'Demanda con Respuesta';

type

  { TFichaUsoGestionable_postizado }

  TFichaUsoGestionable_postizado = class(TFichaLPD)
  public
    fdpp: TDAOfNReal; // factor en p.u. de participación por poste en la demanda.
    uvpp: TDAOfNReal; // Utilidad Variable en USD/MWh por poste de la demanda.

    constructor Create(capa: integer; fecha: TFecha; periodicidad: TPeriodicidad;
      fdpp, uvpp: TDAOfNReal);
     
    function Rec: TCosa_RecLnk; override;
    procedure BeforeRead(version, id_hilo: integer); override;
    procedure AfterRead(f:TArchiTexto); override;

    function infoAd_: string; override;
  end;


  { TUsoGestionable_postizado }

  TUsoGestionable_postizado = class(TActorUniNodal)
  public
    pa: TFichaUsoGestionable_postizado;

    Demanda: TDemanda; // demanda a la que está asociado.

    // variables auxiliares
    EnergiaGestionableDelPaso: NReal;

    pgpp: TDAOfNReal; // potencia generada,  media por poste del uso gestionable.
    // Las pgpp son calculadas a partir de la demanda
    // asociada al uso-gestionable usando los factores de participación.
    // Son Generadas, pues deben sumar al nodo para tener el efecto
    // de restar de la demanda principal.

    pdpp: TDAOfNReal; // potencias gestionables despachadas. Estas son el resultado del
    // despacho óptimo. La potencia NETA inyectada por el actor
    // en el nodo es pgpp-pdpp

    constructor Create(capa: integer; nombre: string; nacimiento, muerte: TFecha;
      lpdUnidades, lpd: TFichasLPD; Nodo: TNodo; xDemanda: TDemanda;
  xFuenteIdxP: TFuenteAleatoria; xBorneIdxP: string);

    function Rec: TCosa_RecLnk; override;
    procedure BeforeRead(version, id_hilo: integer); override;
    procedure AfterRead(f:TArchiTexto); override;


    procedure PrepararMemoria( Catalogo: TCatalogoReferencias; globs: TGlobs); override;
    procedure RegistrarParametrosDinamicos( CatalogoReferencias: TCatalogoReferencias ); override;

    procedure PrepararPaso_ps; override;

    procedure opt_nvers(var ivar, ivae, ires: integer); override;
    procedure opt_cargue(s: TSimplex); override;
    procedure opt_fijarRestriccionesDeCaja(s: TSimplex); override;
    procedure opt_leerSolucion(s: TSimplex); override;

    function getNombreVar(ivar: integer; var nombre: string): boolean; override;
    function getNombreRes(ires: integer; var nombre: string): boolean; override;

    procedure dump_Variables(var f: TextFile; charIndentacion: char); override;

    procedure PubliVars; override;
    class function TipoFichaLPD: TClaseDeFichaLPD; override;
    class function DescClase: string; override;
    destructor destroy; override;

    



    {$IFDEF BOSTA}
    procedure AfterInstantiation; override;
    {$ENDIF}



  end;

procedure AlInicio;
procedure AlFinal;

implementation

uses uActores;

//----------------------------
//Metodos de TFichaUsoGestionable_postizado
//============================

constructor TFichaUsoGestionable_postizado.Create(capa: integer;
  fecha: TFecha; periodicidad: TPeriodicidad; fdpp, uvpp: TDAOfNReal);
begin
  inherited Create(capa, fecha, periodicidad);
  self.fdpp := fdpp;
  self.uvpp := uvpp;
end;

function TFichaUsoGestionable_postizado.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef('fdpp', fdpp);
  Result.addCampoDef('uvpp', uvpp);
end;

procedure TFichaUsoGestionable_postizado.BeforeRead(version, id_hilo: integer);
begin
  inherited BeforeRead(version, id_hilo);
end;

procedure TFichaUsoGestionable_postizado.AfterRead(f:TArchiTexto);
begin
  inherited AfterRead(f);
end;


function TFichaUsoGestionable_postizado.infoAd_: string;
begin
  Result := 'Uso Gestionable.';
end;



//-----------------------
//Metodos de TUsoGestionable_postizado
//=======================

constructor TUsoGestionable_postizado.Create(capa: integer; nombre: string;
  nacimiento, muerte: TFecha; lpdUnidades, lpd: TFichasLPD; Nodo: TNodo;
  xDemanda: TDemanda;
  xFuenteIdxP: TFuenteAleatoria; xBorneIdxP: string );
begin
  inherited Create(capa, nombre, nacimiento, muerte, lpdUnidades, Nodo,
  xFuenteIdxP, xBorneIdxP );
  self.lpd := lpd;
  self.demanda := xDemanda;
  pa := nil;
end;

function TUsoGestionable_postizado.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef('lpd', TCosa(lpd));
  Result.addCampoDef_ref('Demanda', TCosa(Demanda), self);
end;

procedure TUsoGestionable_postizado.BeforeRead(version, id_hilo: integer);
begin
  inherited BeforeRead(version, id_hilo);
end;

procedure TUsoGestionable_postizado.AfterRead(f:TArchiTexto);
begin
  inherited AfterRead(f);
  lpd.Propietario := self;
end;



procedure expandir_copiando_ultimo(var v: TDAOfNReal; N: integer);
var
  k, j: integer;
  m: NReal;
begin
  k := length(v);
  if k < N then
  begin
    if k = 0 then
      m := 0.0
    else
      m := v[k - 1];
    setlength(v, N);
    for j := k to N - 1 do
      v[j] := m;
  end;
end;

procedure TUsoGestionable_postizado.PrepararMemoria(
  Catalogo: TCatalogoReferencias; globs: TGlobs);
var
  k: integer;
  af: TFichaUsoGestionable_postizado;
begin
  inherited prepararMemoria(Catalogo, globs);
  setlength(self.pgpp, globs.NPostes);
  setlength(self.pdpp, globs.NPostes);
  for k := 0 to lpd.Count - 1 do
  begin
    af := lpd.items[k] as TFichaUsoGestionable_postizado;
    if length(af.fdpp) < globs.NPostes then
      expandir_copiando_ultimo(af.fdpp, globs.NPostes);
    if length(af.uvpp) < globs.NPostes then
      expandir_copiando_ultimo(af.uvpp, globs.NPostes);
  end;
end;

procedure TUsoGestionable_postizado.RegistrarParametrosDinamicos(
  CatalogoReferencias: TCatalogoReferencias);
begin
  inherited registrarParametrosDinamicos( CatalogoReferencias );
  lpd.expandirFichas( CatalogoReferencias, globs);
  lpd.RegistrarFichasAActualizar(Self, globs.ActualizadorLPD, @pa, nil);
end;

// suponemos que este prepararPaso_ps se realiza después de que la Demanda
// hizo su preparar paso_ps
procedure TUsoGestionable_postizado.PrepararPaso_ps;
var
  kPoste: integer;
begin
  EnergiaGestionableDelPaso := 0;
  for kPoste := 0 to globs.NPostes - 1 do
  begin
    pgpp[kposte] := Demanda.PPa[kPoste] * pa.fdpp[kPoste];
    EnergiaGestionableDelpaso :=
      EnergiaGestionableDelpaso + pgpp[kposte] * globs.DurPos[kPoste];
  end;
end;

procedure TUsoGestionable_postizado.opt_nvers(var ivar, ivae, ires: integer);
begin
  Self.ivar := ivar;
  self.ires := ires;
  ivar := ivar + globs.NPostes;
  ires := ires + 1;
end;

procedure TUsoGestionable_postizado.opt_cargue(s: TSimplex);
var
  inodores, iPoste: integer;

begin
  inodores := Nodo.ires;

  for iPoste := 0 to globs.NPostes - 1 do
  begin
    // cargamos la potencia en la restricción de balance de potencia del nodo
    s.pon_e(inodores + iposte, ivar + iposte, -1);

    // descontamos la generación en el poste correspondiente
    s.acum_e(inodores + iposte, s.nc, pgpp[iposte]);

    // ahora agregamos a la ecuación de balance de energía
    s.pon_e(ires, ivar + iposte, -globs.durpos[iposte]);

    // aportes a la función de -costo
    s.pon_e(s.nf, ivar + iposte, globs.durpos[iposte] * pa.uvpp[iposte]);

  end;
  // completamos el término independiente de la ecuación de balance.
  s.pon_e(ires, s.nc, EnergiaGestionableDelPaso);
end;

procedure TUsoGestionable_postizado.opt_fijarRestriccionesDeCaja(s: TSimplex);
begin
  s.FijarRestriccionIgualdad(ires);
end;

procedure TUsoGestionable_postizado.opt_leerSolucion(s: TSimplex);
var
  iposte: integer;
  m: NReal;
begin
  UtilidadDirectaDelPaso := 0;
  // recuperamos los valores de Potencia despachada
  for iposte := 0 to globs.NPostes - 1 do
  begin
    pdpp[iposte] := s.xval(ivar + iposte);
    P[iposte] := pgpp[iposte] - pdpp[iposte];
    Lambda_P[iPoste]:= s.xmult( ivar + iposte )/globs.DurPos[iposte];
    cv_Spot[iPoste]:= Nodo.cmarg[iposte] -  Lambda_P[iPoste];    //ojo! hay que agregarle prioridad de demanda, y como generador cv=0
    m := pdpp[iposte] * globs.DurPos[iposte] * pa.uvpp[iposte];
    UtilidadDirectaDelPaso := UtilidadDirectaDelPaso + m;
  end;
end;



function TUsoGestionable_postizado.getNombreVar(ivar: integer;
  var nombre: string): boolean;
begin
  if (ivar >= self.ivar) and (ivar < (self.ivar + globs.NPostes)) then
  begin
    nombre := self.Nombre + '_pdpp[MW]' + IntToStr(ivar - self.ivar + 1);
    Result := True;
  end
  else
    Result := False;
end;

function TUsoGestionable_postizado.getNombreRes(ires: integer;
  var nombre: string): boolean;
begin
  if ires = self.ires then
  begin
    nombre := 'sum( pdpp[iposte]* dupos[iposte] ; iposte ) = EnergiaGestionableDelPaso ';
    Result := True;
  end
  else
    Result := False;
end;

procedure TUsoGestionable_postizado.dump_Variables(var f: TextFile;
  charIndentacion: char);
var
  iposte: integer;
begin
  inherited dump_Variables(f, charIndentacion);
  for iposte := 0 to globs.npostes - 1 do
  begin
    writeln(f, charIndentacion, 'Poste: ', iposte + 1);
    writeln(f, charIndentacion, 'uvpp[USD/MWh]= ',
      FloatToStrF(pa.uvpp[iposte], ffFixed, 10, 3));
    writeln(f, charIndentacion, 'pdpp[MW]= ',
      FloatToStrF(pdpp[iposte], ffFixed, 10, 3));
    writeln(f, charIndentacion, 'pgpp[MW]= ',
      FloatToStrF(pgpp[iposte], ffFixed, 10, 3));
  end;
  writeln(f);
end;

procedure TUsoGestionable_postizado.PubliVars;
begin
  inherited PubliVars;
  PublicarVariableNR('UtilidadDirectaDelpaso', '[USD]', 6, 1,
    UtilidadDirectaDelPaso, True);
  PublicarVariableVR('pdpp', '[MW]', 6, 1, pdpp, True, True);
  PublicarVariableVR('pgpp', '[MW]', 6, 1, pgpp, True, True);
end;

class function TUsoGestionable_postizado.TipoFichaLPD: TClaseDeFichaLPD;
begin
  Result := TFichaUsoGestionable_postizado;
end;

class function TUsoGestionable_postizado.DescClase: string;
begin
  Result := rsUsoGestionable_postizado;
end;

destructor TUsoGestionable_postizado.destroy;
begin
  setlength(self.pgpp, 0);
  setlength(self.pdpp, 0);
  if lpd <> nil then
    lpd.Free;
  inherited destroy;
end;










{$IFDEF BOSTA}
procedure TUsoGestionable_postizado.AfterInstantiation;
begin
  inherited AfterInstantiation;
  lpd.Propietario := self;
end;
{$ENDIF}

procedure AlInicio;
begin
  uCosa.registrarClaseDeCosa(TUsoGestionable_postizado.ClassName,
    TUsoGestionable_postizado);
  uCosa.registrarClaseDeCosa(TFichaUsoGestionable_postizado.ClassName,
    TFichaUsoGestionable_postizado);
end;

procedure AlFinal;
begin
end;

end.
