unit ugter_basico_PyCVariable;

interface

uses
  Math,
  SysUtils, Classes, xmatdefs, uGTer, uNodos,
  uglobs,
  usimplex,
  ufichasLPD,
  ufechas,
  ucosa, ucosaConNombre,
  uconstantesSimSEE,
  uFuentesAleatorias;

resourcestring
  rsGeneradorTermicoBasicoPYCVariable =
    'Generador térmico básico con potencia y costo variable';


{TGter_Basico_PyCVariable es un generador térmico básico, sin mínimo técnico
cuya potencia y coto variable para cada poste, son tomadas de fuentes aleatorias.
La primer versión fue implementada por Fernando Ron (UTE, diciembre 2010).
}

type

  { TFichaGTer_Basico_PyCVariable }

  TFichaGTer_Basico_PyCVariable = class(TFichaLPD)

  public
    (**************************************************************************)
    (*               A T R I B U T O S   P E R S I S T E N T E S              *)
    (**************************************************************************)

    //Array de fuentes aleatorias de potencias
    fuentesAleatoriasPotenciasPorPoste: TListaDeCosas;
    //Array de fuentes aleatorias de costos variables
    fuentesAleatoriasCostosVariablesPorPoste: TListaDeCosas;
    indicePreciosPorCombustible: TFuenteAleatoria;
    bornePreciosPorCombustible: string;
    disp: NReal; //Probabilidad de estar en el estado disponible
    HayRestriccionEmaxPasoDeTiempo: boolean; // indica si se aplica la restricción
    EmaxPasoDeTiempo: NReal; // Energía maxima generable en un paso de tiempo
    tRepHoras: NReal;   //tiempo promedio de reparación en horas
    PagoPorDisponibilidad_USD_MWh: NReal; // [USD/u-h] Pago por Potencia
    PagoPorEnergia_USD_MWh: NReal; // [USD/MWh] Pago por Potencia

    (**************************************************************************)

    nroBornePreciosPorCombustible: integer;

    constructor Create(capa: integer; fecha: TFecha; periodicidad: TPeriodicidad;
      indicePreciosPorCombustible: TFuenteAleatoria;
      bornePreciosPorCombustible: string; disp: NReal;
      HayRestriccionEmaxPasoDeTiempo: boolean; EmaxPasoDeTiempo: NReal;
      tRepHoras: NReal; listaFuentesAleatoriasPotencias: TListaDeCosas;
      listaFuentesAleatoriasCostosVariables: TListaDeCosas;
      PagoPorDisponibilidad_USD_MWh: NReal; PagoPorEnergia_MWh: NReal);

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

    procedure generarLineaResumen(var archi: TextFile); override;
    function infoAd_: string; override;
    destructor destroy; override;

  end;

  // TGTer_Basico es una potencia minima y maxima constante en todos los postes
  // y un costo variable cv [USD/MWh] tambien igual en todos los postes
  // y un costo variable cv_min "hasta el minimo" igual al costo de produccion en USD/MWh cuando
  // la central esta generado en el minimo.
  TGTer_Basico_PyCVariable = class(TGTer)
  public
    pa: TFichaGTer_Basico_PyCVariable;


    NMaquinasDespachadas: TDAOfNInt;
    // cantidad de máquinas despachadas por poste o por paso ( Acople )
    costos: TDAofNReal;              // costos por máquina por poste
    // costos[i]:= P[i] * durpos[i] * cv

    maxNMaquinasDespachadas: integer; // máximo del vector anterior

    // Costo en USD/h por máquina por estar operando en el mínimo técnico
    cvPorPoste: TDAofNReal; // USD/MWh usado para la optimización del paso.

    cve: NReal; // costo por la energía adicional a CV


    PMaxDisponiblePorPoste: TDAofNReal;

    //Cuanta potencia despacho en cada hora el generador en promedio
    potMedia_despachada: NReal;

    NMaquinasDisponibles: integer;
    factor_P: NReal;

    constructor Create(capa: integer; nombre: string; nacimiento, muerte: TFecha;
      lpdUnidades, lpd: TFichasLPD; nodo: TNodo;
      flg_CalcularGradienteDeInversion: boolean; TonCO2xMWh: NReal;
      LowCostMustRun, CleanDevelopmentMechanism: boolean; xFuenteIdxP: TFuenteAleatoria;
      xBorneIdxP: string); reintroduce;

    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;

    function PotenciaFirme: NReal; override;

    function InfoAd_: string; override;
    class function DescClase: string; override;


    procedure Sim_Cronica_Inicio; override;
    procedure SorteosDelPaso(sortear: boolean); override;
    procedure PrepararPaso_ps; override;

    procedure Sim_Paso_Fin; 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;

    destructor destroy; override;

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


    class function TipoFichaLPD: TClaseDeFichaLPD; override;

    function get_pa_FD(kTipoUnidad: integer): NReal; override;
    function get_pa_TMR(kTipoUnidad: integer): NReal; override;

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


procedure AlInicio;
procedure AlFinal;

implementation


{var
  nPasosDisponible, nPasosNoDisponibleSeguidos: Integer;
  fdbg: TextFile;}

//----------------------------------
// Métodos de TFichaGTer_Basico_PyCVariable
//==================================
constructor TFichaGTer_Basico_PyCVariable.Create(capa: integer;
  fecha: TFecha; periodicidad: TPeriodicidad;
  indicePreciosPorCombustible: TFuenteAleatoria; bornePreciosPorCombustible: string;
  disp: NReal; HayRestriccionEmaxPasoDeTiempo: boolean; EmaxPasoDeTiempo: NReal;
  tRepHoras: NReal; listaFuentesAleatoriasPotencias: TListaDeCosas;
  listaFuentesAleatoriasCostosVariables: TListaDeCosas;
  PagoPorDisponibilidad_USD_MWh: NReal; PagoPorEnergia_MWh: NReal);
begin
  inherited Create(capa, fecha, periodicidad);
  self.indicePreciosPorCombustible := indicePreciosPorCombustible;
  self.bornePreciosPorCombustible := bornePreciosPorCombustible;
  self.disp := disp;
  self.HayRestriccionEmaxPasoDeTiempo := HayRestriccionEmaxPasoDeTiempo;
  self.EmaxPasoDeTiempo := EmaxPasoDeTiempo;
  self.tRepHoras := tRepHoras;
  self.fuentesAleatoriasPotenciasPorPoste := listaFuentesAleatoriasPotencias;
  self.fuentesAleatoriasCostosVariablesPorPoste := listaFuentesAleatoriasCostosVariables;
  self.PagoPorDisponibilidad_USD_MWh := PagoPorDisponibilidad_USD_MWh;
  self.PagoPorEnergia_USD_MWh := PagoPorEnergia_USD_MWh;
end;

function TFichaGTer_Basico_PyCVariable.Rec: TCosa_RecLnk;
begin
  Result := inherited Rec;

  Result.addCampoDef('fuentesAleatoriasPotenciasPorPoste',
    TCosa(fuentesAleatoriasPotenciasPorPoste), 0, 6);
  Result.addCampoDef('fuentesAleatoriasCostosVariablesPorPoste',
    TCosa(fuentesAleatoriasCostosVariablesPorPoste), 0, 6);
  Result.addCampoDef_ref('indicePreciosPorCombustible',
    TCosa(indicePreciosPorCombustible), self, 0, 6);
  Result.addCampoDef('disp', disp, 0, 6);
  Result.addCampoDef('HayRestriccionEmaxPasoDeTiempo',
    HayRestriccionEmaxPasoDeTiempo, 0, 6);
  Result.addCampoDef('EmaxPasoDeTiempo', EmaxPasoDeTiempo, 0, 6);
  Result.addCampoDef('tRepHoras', tRepHoras, 0, 6);
  Result.addCampoDef('fuentesAleatoriasPotenciasPorPoste',
    TCosa(fuentesAleatoriasPotenciasPorPoste), 6);
  Result.addCampoDef('fuentesAleatoriasCostosVariablesPorPoste',
    TCosa(fuentesAleatoriasCostosVariablesPorPoste), 6);
  Result.addCampoDef_ref('indicePreciosPorCombustible',
    TCosa(indicePreciosPorCombustible), self, 6);
  Result.addCampoDef('bornePreciosPorCombustible', bornePreciosPorCombustible, 6);
  Result.addCampoDef('disp', disp, 6);
  Result.addCampoDef('HayRestriccionEmaxPasoDeTiempo',
    HayRestriccionEmaxPasoDeTiempo, 6);
  Result.addCampoDef('EmaxPasoDeTiempo', EmaxPasoDeTiempo, 6);
  Result.addCampoDef('tRepHoras', tRepHoras, 6);
  Result.addCampoDef('PagoPorDisponibilidad_USD_uh',
    PagoPorDisponibilidad_USD_MWh, 71, 98);
  Result.addCampoDef('PagoPorEnergia', PagoPorEnergia_USD_MWh, 71, 98);
  Result.addCampoDef('PagoPorDisponibilidad_USD_MWh',
    PagoPorDisponibilidad_USD_MWh, 98);
  Result.addCampoDef('PagoPorEnergia_USD_MWh', PagoPorEnergia_USD_MWh, 98);
end;

procedure TFichaGTer_Basico_PyCVariable.BeforeRead(version, id_hilo: integer);
begin
  inherited BeforeRead(version, id_hilo);
  PagoPorDisponibilidad_USD_MWh := 0;
  PagoPorEnergia_USD_MWh := 0;
end;

procedure TFichaGTer_Basico_PyCVariable.AfterRead(f: TArchiTexto);
begin
  inherited AfterRead(f);
  if f.Version < 6 then
  begin
    self.indicePreciosPorCombustible := nil;
    self.bornePreciosPorCombustible := '';
  end;
end;


procedure TFichaGTer_Basico_PyCVariable.generarLineaResumen(var archi: TextFile);
begin
  Write(archi, '-', #9,       //PMín
    '-', #9,       //PMáx
    '-', #9,       //CV_Mín
    '-', #9,       //CV_Medio
    '-', #9,       //CV_Incremental
    FloatToStrF(disp, formatoReales, 8, 2), #9,  //FDisp
    '-', #9,       //Costo Arranque
    '-', #9,       //Costo Parada
    '-', #9,       //mínNPasosOn
    '-', #9,       //mínNPasosOff
    '-', #9,       //desiciónPasosOnPorCiclo
    '-', #9,       //desiciónPasosOffPorCiclo
    '-', #9,       //costoPorCicloOn
    '-', #9);      //costoPorCicloOff
end;

function TFichaGTer_Basico_PyCVariable.infoAd_: string;
begin
  Result := 'fDisp= ' + FloatToStrF(disp, ffGeneral, 10, 2) + ' p.u., ' +
    'tRep= ' + FloatToStrF(tRepHoras, ffGeneral, 10, 1) + ' hs';
end;

destructor TFichaGTer_Basico_PyCVariable.destroy;
begin
  inherited destroy;
end;




//-----------------------------
// Métodos de TGTer_Basico_PyCVariable
//=============================
procedure TGTer_Basico_PyCVariable.dump_Variables(var f: TextFile;
  charIndentacion: char);
var
  iPoste: integer;
  cantPostes: integer;
  fuenteAleatoria: TFuenteAleatoria_Borne;
begin
  inherited dump_Variables(f, charIndentacion);

  cantPostes := globs.NPostes;
  for iPoste := 0 to cantPostes - 1 do
  begin
    fuenteAleatoria := TFuenteAleatoria_Borne(
      pa.fuentesAleatoriasCostosVariablesPorPoste[iPoste]);
    writeln(f, charIndentacion, 'NombreFuenteCostoVariable[Poste=',
      iPoste, ']= ', fuenteAleatoria.fuente.nombre);
  end;

  for iPoste := 0 to cantPostes - 1 do
  begin
    fuenteAleatoria := TFuenteAleatoria_Borne(
      pa.fuentesAleatoriasPotenciasPorPoste[iPoste]);
    writeln(f, charIndentacion, 'NombreFuentePotencia[Poste=', iPoste,
      ']= ', fuenteAleatoria.fuente.nombre);
  end;

  writeln(f, charIndentacion, 'disp= ', pa.disp);

  writeln(f, charIndentacion, 'HayRestrEMaxPasoDeTiempo= ',
    pa.hayRestriccionEmaxPasoDeTiempo);
  writeln(f, charIndentacion, 'EMaxPasoDeTiempo[MW/h]= ',
    FloatToStrF(pa.EmaxPasoDeTiempo, ffFixed, 10, 3));

  writeln(f);
end;

class function TGTer_Basico_PyCVariable.TipoFichaLPD: TClaseDeFichaLPD;
begin
  Result := TFichaGTer_Basico_PyCVariable;
end;

constructor TGTer_Basico_PyCVariable.Create(capa: integer; nombre: string;
  nacimiento, muerte: TFecha; lpdUnidades, lpd: TFichasLPD; nodo: TNodo;
  flg_CalcularGradienteDeInversion: boolean; TonCO2xMWh: NReal;
  LowCostMustRun, CleanDevelopmentMechanism: boolean; xFuenteIdxP: TFuenteAleatoria;
  xBorneIdxP: string);
begin
  inherited Create(capa, nombre, nacimiento, muerte, lpdUnidades, lpd, nodo,
    flg_CalcularGradienteDeInversion,
    TonCO2xMWh, LowCostMustRun, CleanDevelopmentMechanism,
    xFuenteIdxP, xBorneIdxP);
  P := nil;
end;

function TGTer_Basico_PyCVariable.Rec: TCosa_RecLnk;
begin
  Result := inherited Rec;
end;

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

procedure TGTer_Basico_PyCVariable.AfterRead(f: TArchiTexto);
begin
  inherited AfterRead(f);
  P := nil;
  pa := nil;
  nodo := nil;
end;



procedure TGTer_Basico_PyCVariable.PrepararMemoria(Catalogo: TCatalogoReferencias;
  globs: TGlobs);
var
  i: integer;
  ficha: TFichaGTer_Basico_PyCVariable;
  res: boolean;

  function testf(l: TListaDeCosas): boolean;
  var
    res: boolean;
    k: integer;
  begin
    if l.Count <> globs.NPostes then
    begin
      Result := False;
      exit;
    end;
    res := True;
    for k := 0 to l.Count - 1 do
      if l.lst.Items[k] = nil then
      begin
        res := False;
        break;
      end;
    Result := res;
  end;

begin
  inherited prepararMemoria(Catalogo, globs);
  setlength(costos, globs.NPostes);
  SetLength(NMaquinasDespachadas, globs.NPostes);
  setlength(PMaxDisponiblePorPoste, globs.NPostes);
  setlength(cvPorPoste, globs.NPostes);

  res := True;
  for i := 0 to lpd.Count - 1 do
  begin
    ficha := TFichaGTer_Basico_PyCVariable(lpd[i]);
    if not (testf(ficha.fuentesAleatoriasCostosVariablesPorPoste) and
      testf(ficha.fuentesAleatoriasPotenciasPorPoste)) then
    begin
      res := False;
      break;
    end;
  end;
  if not res then
    raise Exception.Create('Actor: ' + nombre +
      ' del tipo TGTer_Basico_PyCVariable no tiene bien definidas las fuentes por postes. ');

end;

procedure TGTer_Basico_PyCVariable.RegistrarParametrosDinamicos(
  CatalogoReferencias: TCatalogoReferencias);
var
  i: integer;
  ficha: TFichaGTer_Basico_PyCVariable;
begin
  inherited registrarParametrosDinamicos(CatalogoReferencias);
  lpd.expandirFichas(CatalogoReferencias, globs);
  lpd.RegistrarFichasAActualizar(Self, globs.ActualizadorLPD, @pA, nil);

  for i := 0 to lpd.Count - 1 do
  begin
    ficha := TFichaGTer_Basico_PyCVariable(lpd[i]);
    if ficha.indicePreciosPorCombustible <> nil then
      ficha.nroBornePreciosPorCombustible :=
        ficha.indicePreciosPorCombustible.IdBorne(ficha.bornePreciosPorCombustible);
  end;
end;

function TGTer_Basico_PyCVariable.PotenciaFirme: NReal;
begin
  Result := 0; // ojo, esto es una convensión.
  // Si este actor lo usamos para Generación Distribuída o Importación
  // devolvemos CERO pues la potencia firme debe ser calculada por algún otro
  // método.


  // result:= (paUnidades.nUnidades) * pa.PMax * pa.disp;
end;

function TGTer_Basico_PyCVariable.InfoAd_: string;
begin
  Result := '';
end;

class function TGTer_Basico_PyCVariable.DescClase: string;
begin
  Result := rsGeneradorTermicoBasicoPYCVariable;
end;

procedure TGTer_Basico_PyCVariable.Sim_Cronica_Inicio;
begin
  inherited Sim_Cronica_Inicio;
end;



function TGTer_Basico_PyCVariable.get_pa_FD(kTipoUnidad: integer): NReal;
begin
  Result := pa.disp;
end;

function TGTer_Basico_PyCVariable.get_pa_TMR(kTipoUnidad: integer): NReal;
begin
  Result := pa.tRepHoras;
end;

{$IFDEF BOSTA}
procedure TGTer_Basico_PyCVariable.AfterInstantiation;
begin
  inherited AfterInstantiation;
  P := nil;
  pa := nil;
  nodo := nil;
end;

{$ENDIF}

procedure TGTer_Basico_PyCVariable.SorteosDelPaso(sortear: boolean);
begin
  if hayForzamientos or globs.ObligarDisponibilidad_1_ then
  begin
    NMaquinasDisponibles := paUnidades.nUnidades_Operativas[0];
    factor_P := NMaquinasDisponibles;
  end
  else if sortear then
  begin
    ActualizarProbabilidadesReparacionYRotura_(pa.disp, pa.tRepHoras);
    NMaquinasDisponibles := Sorteos_RepRotUnidades;
    factor_P := NMaquinasDisponibles;
  end
  else
  begin
    NMaquinasDisponibles := paUnidades.nUnidades_Operativas[0];
    factor_P := pa.disp * NMaquinasDisponibles;
  end;
end;

procedure TGTer_Basico_PyCVariable.PrepararPaso_ps;
var
  iPoste: integer;
  fuenteAleatoria: TFuenteAleatoria_Borne;
  valp: NReal;


begin
  if factor_P = 0 then
  begin
    vclear(PMaxDisponiblePorPoste);
    vclear(cvPorPoste);
    exit;
  end;


  for iPoste := 0 to globs.NPostes - 1 do
  begin
    fuenteAleatoria := TFuenteAleatoria_Borne(
      pa.fuentesAleatoriasPotenciasPorPoste.items[iPoste]);
    valp := fuenteAleatoria.fuente.Bornera[fuenteAleatoria.DarIdBorne(self)] * factor_P;
    PMaxDisponiblePorPoste[iPoste] := valp;

    fuenteAleatoria := TFuenteAleatoria_Borne(
      pa.fuentesAleatoriasCostosVariablesPorPoste.items[iPoste]);

    if pa.indicePreciosPorCombustible <> nil then
      cvPorPoste[iPoste] := fuenteAleatoria.fuente.Bornera[
        fuenteAleatoria.DarIdBorne(self)] *
        pa.indicePreciosPorCombustible.bornera[pa.nroBornePreciosPorCombustible]
    else
      cvPorPoste[iPoste] := fuenteAleatoria.fuente.Bornera[
        fuenteAleatoria.DarIdBorne(self)];
  end;

  if pa.indicePreciosPorCombustible <> nil then
    cve := pa.PagoPorEnergia_USD_MWh *
      pa.indicePreciosPorCombustible.bornera[pa.nroBornePreciosPorCombustible]
  else
    cve := pa.PagoPorEnergia_USD_MWh;

end;

procedure TGTer_Basico_PyCVariable.Sim_Paso_Fin;
var
  iposte: integer;
begin

  potMedia_despachada := 0;
  if factor_P = 0 then
    exit; // si no hay máquinas no juego

  for iposte := 0 to high(P) do
    potMedia_despachada := potMedia_despachada + P[iposte] * globs.durpos[iposte];
  potMedia_despachada := potMedia_despachada * globs.invHorasDelPaso;
end;



procedure TGTer_Basico_PyCVariable.opt_nvers(var ivar, ivae, ires: integer);
begin

  if factor_P = 0 then
    exit; // si no hay máquinas no juego
  Self.ivar := ivar;
  ivar := ivar + globs.NPostes;
  if pA.HayRestriccionEmaxPasoDeTiempo then
  begin
    Self.ires := ires;
    Inc(ires);
  end;
end;



procedure TGTer_Basico_PyCVariable.opt_cargue(s: TSimplex);
var
  inodores: integer;
  iposte: integer;
begin
  if factor_P = 0 then
    exit; // si no hay máquinas no juego

  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);
    // Ahora agregamos a la función de UTILIDAD (-costo)
    s.pon_e(s.nf, ivar + iposte, -cvPorPoste[iPoste] * globs.durpos[iposte]);
  end;

  //Restriccion a la energía máxima generable
  if pA.HayRestriccionEmaxPasoDeTiempo then
  begin
    for iposte := 0 to globs.NPostes - 1 do
      s.pon_e(ires, ivar + iposte, -globs.durpos[iposte]);
    s.pon_e(ires, s.nc, pA.EmaxPasoDeTiempo);
  end;
end;

procedure TGTer_Basico_PyCVariable.opt_fijarRestriccionesDeCaja(s: TSimplex);
var
  iposte: integer;
begin
  if factor_P = 0 then
    exit; // si no hay máquinas no juego

  if (not hayForzamientos) then
  begin
    // Le fijamos como cota superior PMax a la potencia en todos los postes
    for iposte := 0 to globs.NPostes - 1 do
      if PMaxDisponiblePorPoste[iposte] > AsumaCero then
       s.cota_sup_set(ivar + iposte, PMaxDisponiblePorPoste[iposte])
      else if  PMaxDisponiblePorPoste[iposte] < -AsumaCero then
      begin
       s.cota_sup_set(ivar + iposte, 0 );
       s.cota_inf_set(ivar + iposte, PMaxDisponiblePorPoste[iposte])
      end
      else
        s.FijarVariable(ivar + iposte, 0 );
  end
  else
  begin
    {
    for iposte := 0 to globs.NPostes - 1 do
      s.FijarVariable(ivar + iposte, paForzamiento.P[0]);
      }
       for iposte := 0 to globs.NPostes - 1 do
        begin
          if paForzamiento.flg_fijarP then
            s.FijarVariable(ivar + iposte, paForzamiento.P[0] )
          else if paForzamiento.activar_Pmax then
            s.cota_sup_set(ivar + iposte, paForzamiento.P_max[0] )
          else if paForzamiento.activar_Pmin then
            s.cota_inf_set(ivar + iposte, paForzamiento.P_min[0] );
        end;
  end;
end;

procedure TGTer_Basico_PyCVariable.opt_leerSolucion(s: TSimplex);
var
  iposte: integer;
  m, energia: NReal;
  //  fuenteAleatoria : TFuenteAleatoria_Borne;
begin

  maxNMaquinasDespachadas := 0;

  Ingreso_PorDisponibilidad_ := 0;
  Ingreso_PorEnergia_ := 0;
  costoDirectoDelPaso := 0;

  if factor_P = 0 then
  begin
    vclear(P);
    for iposte := 0 to globs.NPostes - 1 do
    begin
      Lambda_P[iPoste] := 0;
      cv_Spot[iPoste] := get_cv_falla;
      // para que en el ordenamiento quede último, con costo variable igual a la falla;
    end;
    vclear(NMaquinasDespachadas);
    vclear(costos);
    exit;
  end;

  Energia := 0;

  // recuperamos los valores de Potencia despachada
  for iposte := 0 to globs.NPostes - 1 do
  begin
    Ingreso_PorDisponibilidad_ :=
      Ingreso_PorDisponibilidad_ + PMaxDisponiblePorPoste[iPoste] *
      pa.PagoPorDisponibilidad_USD_MWh * globs.DurPos[iposte];
    P[iposte] := s.xval(ivar + iposte);
    Lambda_P[iPoste] := s.xmult(ivar + iposte) / globs.DurPos[iposte];
    cv_Spot[iPoste] := Nodo.cmarg[iposte] - Lambda_P[iPoste];

    if P[iposte] > 1E-6 then
    begin
      NMaquinasDespachadas[iposte] :=
        Math.Ceil((P[iposte] - 1E-6) / PMaxDisponiblePorPoste[iPoste] * factor_P);
      m := P[iposte] * globs.DurPos[iposte];
      energia := energia + m;
      costos[iposte] := m * cvPorPoste[iPoste];

      CostoDirectoDelPaso := CostoDirectoDelpaso + costos[iposte];
      if NMaquinasDespachadas[iposte] > maxNMaquinasDespachadas then
        maxNMaquinasDespachadas := NMaquinasDespachadas[iposte];
    end
    else
    begin
      NMaquinasDespachadas[iposte] := 0;
      costos[iposte] := 0;
    end;
  end;
  Ingreso_PorEnergia_ := Energia * cve;
end;



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

function TGTer_Basico_PyCVariable.getNombreRes(ires: integer;
  var nombre: string): boolean;
begin
  if pa.HayRestriccionEmaxPasoDeTiempo and (ires = self.ires) then
  begin
    nombre := self.nombre + '_res-EMax';
    Result := True;
  end
  else
    Result := False;
end;

procedure TGTer_Basico_PyCVariable.PubliVars;
begin
  inherited PubliVars;
  PublicarVariableVR('Costo', '[USD]', 6, 1, costos, True, True);
  PublicarVariableVI('NMaqsDespachadas', '-', NMaquinasDespachadas, True, True);
  PublicarVariableVR('PMax', '[MW]', 6, 1, PMaxDisponiblePorPoste, True, True);
  PublicarVariableNI('NMaquinasDisponibles', '-', NMaquinasDisponibles, True);
  PublicarVariableNR('PMediaDespachada', '[MW]', 6, 1, potMedia_despachada, False);
  PublicarVariableNI('MaxNMaqsDespachadasEnElPaso', '-', maxNMaquinasDespachadas, False);

  {$IFDEF DECLARAR_VARIABLES_SIMRES_DEF}
  declararVarsPSimResPorDefectoIntercalandoPostes(['P', 'Costo',
    'NMaqsDespachadas', 'PMax'], globs.NPostes);
  {$ENDIF}
end;

destructor TGTer_Basico_PyCVariable.destroy;
begin
  setlength(costos, 0);
  setlength(NMaquinasDespachadas, 0);
  inherited destroy;
end;


procedure AlInicio;
begin
  registrarClaseDeCosa(TGTer_Basico_PyCVariable.ClassName, TGTer_Basico_PyCVariable);
  registrarClaseDeCosa(TFichaGTer_Basico_PyCVariable.ClassName,
    TFichaGTer_Basico_PyCVariable);
  //registrarClaseDeCosa(TFuenteAleatoria_Borne.ClassName, TFuenteAleatoria_Borne);
{  AssignFile(fdbg, uconstantesSimSEE.getDir_Dbg + 'RachasRoto.xlt');
  rewrite(fdbg);}
end;

procedure AlFinal;
begin
  //  CloseFile(fdbg);
end;

end.
