//====Modificado metodos: CreateDataColumnList y CreateDataConversionList===
//====Micho@26/5==mvarela@adme.com.uy=======================================
unit ugsimple_bicombustible;

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

interface

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

resourcestring
  rsGeneradorSimpleBiCombustible = 'Generador simple bicombustible';

type

  { TFichaGSimple_BiCombustible }

  TFichaGSimple_BiCombustible = class(TFichaLPD)

  public

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

    PMax: NReal; // [MW] Potencia Máxima Por maquina
    disp: NReal; // disponibilidad (fortuita)
    tRepHoras: NReal;
    PagoPorDisponibilidad_USD_MWh: NReal; // [USD/MWh] Pago por Potencia
    PagoPorEnergia_USD_MWh: NReal; // [USD/MWh] Pago por Potencia
    QMax_A, QMax_B: NReal; // Máximos caudales de cada combustible
    ren_A: NReal; // rendimiento en por unidad con el combustible A
    ren_B: NReal; // rendimiento en por unidad con el combustible B

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

    constructor Create(capa: integer; fecha: TFecha; periodicidad: TPeriodicidad;
      PMax, QMax_A, QMax_B, ren_A, ren_B: NReal; disp: NReal;
      tRepHoras: NReal; PagoPorDisponibilidad_USD_MWh: NReal;
      PagoPorEnergia_USD_MWh: NReal);

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

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




  // TGSimple_Bicombustible es un generador sin minimos tecnicos ni tiempos ni costos
  // de arranque y parada
  TGSimple_BiCombustible = class(TGTer)

  public

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

    nodoCombA: TNodoCombustible;
    nodoCombB: TNodoCombustible;

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

    pa: TFichaGSimple_BiCombustible;

    NMaquinasDespachadas: TDAOfNInt;
    // cantidad de máquinas despachadas por poste o por paso ( Acople )

    consumos: TDAofNReal;              // consumos por máquina por poste

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

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

    P_opmax: NReal;

    qa: TDAOfNReal;
    qb: TDAOfNReal;

    alfa: TDAOfNReal;
    // resultado de los sorteos de disponibilidad y del mantenimiento programado
    NMaquinasDisponibles: integer;

    PMaxDisponible: NReal;
    QAMaxOperativo_pu, QBMaxOperativo_pu: NReal;
    QAMax, QBMax: NReal;

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

    constructor Create(capa: integer; nombre: string;
      lpdUnidades, lpd: TFichasLPD; nodo: TNodo;
  flg_CalcularGradienteDeInversion: boolean; nodoCombA,
  nodoCombB: TNodoCombustible; TonCO2xMWh: NReal; LowCostMustRun,
  CleanDevelopmentMechanism: boolean; 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(Catalogo: TCatalogoReferencias); override;

    function PotenciaFirme: NReal; override;

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

    procedure SorteosDelPaso(sortear: boolean); override;
    procedure CambioFichaPD; override;
    procedure PrepararPaso_as; 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 TGSimple_BiCombustible_CambioFichaPD(actor: TCosa);

procedure AlInicio;
procedure AlFinal;

implementation


procedure TGSimple_BiCombustible_CambioFichaPD(actor: TCosa);
begin
  (Actor as TGSimple_BiCombustible).cambioFichaPD;
end;



//---------------------------------------
// Métodos de TFichaGSimple_BiCombustible
//=======================================
constructor TFichaGSimple_BiCombustible.Create(capa: integer;
  fecha: TFecha; periodicidad: TPeriodicidad; PMax, QMax_A, QMax_B, ren_A, ren_B: NReal;
  disp: NReal; tRepHoras: NReal; PagoPorDisponibilidad_USD_MWh: NReal;
  PagoPorEnergia_USD_MWh: NReal);

begin
  inherited Create(capa, fecha, periodicidad);
  self.PMax := PMax;
  self.QMax_A := QMax_A;
  self.QMax_B := QMax_B;
  self.ren_A := ren_A;
  self.ren_B := ren_B;
  self.disp := disp;
  self.tRepHoras := tRepHoras;
  self.PagoPorDisponibilidad_USD_MWh := PagoPorDisponibilidad_USD_MWh;
  self.PagoPorEnergia_USD_MWh := PagoPorEnergia_USD_MWh;
end;

function TFichaGSimple_BiCombustible.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef('PMax', PMax);
  Result.addCampoDef('disp', disp);
  Result.addCampoDef('tRepHoras', tRepHoras);
  Result.addCampoDef('PagoPorDisponibilidad_USD_MWh', PagoPorDisponibilidad_USD_MWh);
  Result.addCampoDef('PagoPorEnergia_USD_MWh', PagoPorEnergia_USD_MWh);
  Result.addCampoDef('QMax_A', QMax_A, 114 );
  Result.addCampoDef('QMax_B', QMax_B, 114 );
  Result.addCampoDef('ren_A', ren_A, 114, 0, '0.5'  );
  Result.addCampoDef('ren_B', ren_B, 114, 0, '0.5'  );
  Result.addCampoDef('QAMax', QMax_A, 0, 114 );
  Result.addCampoDef('QBMax', QMax_B, 0, 114 );
end;

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

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




function TFichaGSimple_BiCombustible.infoAd_: string;
begin
  Result := 'PMax= ' + FloatToStrF(PMax, ffGeneral, 10, 1) + ' MW, ' +
    'fdisp= ' + FloatToStrF(disp, ffGeneral, 10, 2) + ' p.u., ' +
    'tRep= ' + FloatToStrF(tRepHoras, ffGeneral, 10, 1) + 'h';
end;

destructor TFichaGSimple_BiCombustible.destroy;
begin
  inherited destroy;
end;


procedure TFichaGSimple_BiCombustible.generarLineaResumen(var archi: TextFile);
begin
  Write(archi, '-', #9,                                     //PMín
    FloatToStrF(PMax, formatoReales, 8, 1), #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;



//------------------------
// Métodos de TGSimple_BiCombustible
//========================
procedure TGSimple_BiCombustible.dump_Variables(var f: TextFile; charIndentacion: char);
begin
  inherited dump_Variables(f, charIndentacion);

  writeln(f, charIndentacion, 'PMax[MW]= ', FloatToStrF(pa.PMax, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'PMaxDisponible[MW]= ',
    FloatToStrF(PMaxDisponible, ffFixed, 10, 3));

  writeln(f, charIndentacion, 'NMaquinasDisponibles= ', NMaquinasDisponibles);

  writeln(f);
end;

class function TGSimple_BiCombustible.TipoFichaLPD: TClaseDeFichaLPD;
begin
  Result := TFichaGSimple_BiCombustible;
end;

constructor TGSimple_BiCombustible.Create(capa: integer; nombre: string;
  lpdUnidades, lpd: TFichasLPD; nodo: TNodo;
  flg_CalcularGradienteDeInversion: boolean; nodoCombA, nodoCombB: TNodoCombustible;
  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;
  qa := nil;
  qb := nil;
  NMaquinasDespachadas := nil;
  self.nodoCombA := nodoCombA;
  self.nodoCombB := nodoCombB;
end;

function TGSimple_BiCombustible.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef_ref('NodoCombA', TCosa(NodoCombA), self);
  Result.addCampoDef_ref('NodoCombB', TCosa(NodoCombB), self);
end;

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

procedure TGSimple_BiCombustible.AfterRead(f:TArchiTexto);
begin
  inherited AfterRead(f);
  P := nil;
  qa := nil;
  qb := nil;
  NMaquinasDespachadas := nil;
  pa := nil;
end;


procedure TGSimple_BiCombustible.PrepararMemoria(Catalogo: TCatalogoReferencias;
  globs: TGlobs);
begin
  inherited prepararMemoria(Catalogo, globs);
  setlength(qa, globs.NPostes);
  setlength(qb, globs.NPostes);
  setlength(alfa, globs.NPostes);
  SetLength(NMaquinasDespachadas, globs.NPostes);
end;

procedure TGSimple_BiCombustible.RegistrarParametrosDinamicos(
  Catalogo: TCatalogoReferencias);
begin
  inherited registrarParametrosDinamicos(Catalogo);
  lpd.expandirFichas(Catalogo, globs);
  lpd.RegistrarFichasAActualizar(Self, globs.ActualizadorLPD, @pA,
    nil, TGSimple_BiCombustible_CambioFichaPD);
end;

function TGSimple_BiCombustible.PotenciaFirme: NReal;
begin
  Result := (paUnidades.nUnidades_Operativas[0]) * pa.PMax * pa.disp;
end;

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

class function TGSimple_BiCombustible.DescClase: string;
begin
  Result := rsGeneradorSimpleBiCombustible;
end;


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

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


{$IFDEF BOSTA}
procedure TGSimple_BiCombustible.AfterInstantiation;
begin
  inherited AfterInstantiation;
  P := nil;
  qa := nil;
  qb := nil;
  NMaquinasDespachadas := nil;
  pa := nil;
end;
{$ENDIF}

procedure TGSimple_BiCombustible.SorteosDelPaso(sortear: boolean);
begin
  if hayForzamientos or globs.ObligarDisponibilidad_1_ then
  begin
    NMaquinasDisponibles := paUnidades.nUnidades_Operativas[0];
    //supongo que nUnidades[0] tiene el total de maquinas de la central
    PMaxDisponible := pa.PMax * NMaquinasDisponibles;
    QAmax := QAMaxOperativo_pu * NMaquinasDisponibles;
    QBmax := QBMaxOperativo_pu * NMaquinasDisponibles;
  end
  else if sortear then
  begin
    ActualizarProbabilidadesReparacionYRotura_(pa.disp, pa.tRepHoras);
    NMaquinasDisponibles := Sorteos_RepRotUnidades;
    PMaxDisponible := pa.PMax * NMaquinasDisponibles;
    QAmax := QAMaxOperativo_pu * NMaquinasDisponibles;
    QBmax := QBMaxOperativo_pu * NMaquinasDisponibles;
    //si hay que sortear hace el sorteo y la potencia total
  end
  //queda afectada por la cantidad de maquinas disponibles
  else
  begin
    NMaquinasDisponibles := paUnidades.nUnidades_Operativas[0];
    //si no hay que sortear deja todas las maquinas disponibles
    //pero afecta a la potencia disponible por la disponibilidad
    PMaxDisponible := pa.PMax * pa.disp * NMaquinasDisponibles;
    QAmax := QAMaxOperativo_pu * pa.disp * NMaquinasDisponibles;
    QBmax := QBMaxOperativo_pu * pa.disp * NMaquinasDisponibles;
  end;
end;


procedure TGSimple_BiCombustible.PrepararPaso_as;
begin
  ren_ro_PCI_A := pa.ren_A * nodoCombA.combustible.MWh_por_Q1h_;
  ren_ro_PCI_B := pa.ren_B * nodoCombB.combustible.MWh_por_Q1h_;
end;

procedure TGSimple_BiCombustible.PrepararPaso_ps;
{$IFDEF CALC_MMEE}
var
  k: integer;
{$ENDIF}
begin

  {$IFDEF CALC_MMEE}
  for k := 0 to globs.NPOstes - 1 do
    mmee_cv_paraPrecioSpot[k] := cv;
  {$ENDIF}

end;

procedure TGSimple_BiCombustible.Sim_Paso_Fin;
var
  iposte: integer;
  ePoste: NReal;
begin
  potMedia_despachada := 0;


  if NMaquinasDisponibles = 0 then
  begin
  {$IFDEF CALC_MMEE}
    vclear(mmee_IngresosSpot_USD);
    vclear(mmee_CargosAlSeguimientoDeLaDemanda_USD);
  {$ENDIF}
  end
  else
  begin
    for iposte := 0 to high(P) do
    begin
      ePoste := P[iposte] * globs.durpos[iposte];
      potMedia_despachada := potMedia_despachada + ePoste;

      {$IFDEF CALC_MMEE}
      if (mmee_cv_paraPrecioSpot[iposte] > globs.mmee_topePrecioSpot) then
      begin
        mmee_CargosAlSeguimientoDeLaDemanda_USD[iposte] :=
          ePoste * (mmee_cv_paraPrecioSpot[iposte] - globs.mmee_topePrecioSpot);
        mmee_IngresosSpot_USD[iposte] := ePoste * globs.mmee_topPrecioSpot;
      end
      else
      begin
        mmee_CargosAlSeguimientoDeLaDemanda_USD[iposte] := 0;
        mmee_IngresosSpot_USD[iposte] := ePoste * globs.mmee_PrecioSpot[iposte];
      end;
      {$ENDIF}
    end;
    potMedia_despachada := potMedia_despachada * globs.invHorasDelPaso;
  end;
end;

procedure TGSimple_BiCombustible.opt_nvers(var ivar, ivae, ires: integer);
begin
  if NMaquinasDisponibles = 0 then
    exit; // si no hay máquinas no juego
  Self.ivar := ivar;
  ivar := ivar + 3 * globs.NPostes; //qa, qb, alfa
  Self.ires := ires;
  ires := ires + 2 * globs.NPostes;
  //una restriccion por caudal de combustible qa<qamax*alfa y qb<qbmax*(1-alfa)
end;


procedure TGSimple_BiCombustible.CambioFichaPD;
//donde uso las potencias de operacion? en el simplex impongo restriccion
//de caudales pero podria ser que la Pop este limitada por la Pmax y en ese caso el caudal que obtengo me dara una P mayor
//que la que puedo dar Pop=Pmax.
begin
  // P = ren * Q * ro * PCI
  QAMaxOperativo_pu := Math.Min(pa.PMax * 1.0E6 /
    (pa.ren_a * nodoCombA.combustible.ro_PCI), pa.QMax_A);
  QBMaxOperativo_pu := Math.Min(pa.PMax * 1.0E6 /
    (pa.ren_b * nodoCombB.combustible.ro_PCI), pa.QMax_B);
end;

procedure TGSimple_BiCombustible.opt_cargue(s: TSimplex);
var
  inodores, inodoACombres, inodoBCombres: integer;
  iposte: integer;
begin

  if NMaquinasDisponibles = 0 then
    exit; // si no hay máquinas no juego

  inodores := nodo.ires; //indice de la restricion de nodo electrico
  inodoACombres := nodoCombA.ires; //indice de la restricion del nodo A de combustible
  inodoBCombres := nodoCombB.ires; //indice de la restricion del nodo B de combustible

  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 + 0 + iposte * 3, ren_ro_PCI_A);
    s.pon_e(inodores + iposte, ivar + 1 + iposte * 3, ren_ro_PCI_B);

    // cargamos los caudales en la restricción de balance de caudal de los nodos
    s.pon_e(inodoACombres + iposte, ivar + 0 + iposte * 3, -1);
    s.pon_e(inodoBCombres + iposte, ivar + 1 + iposte * 3, -1);

    // restricciones de los caudales qa y qb
    // QA < QAmax * alfa
    s.pon_e(ires + 0 + 2 * iposte, ivar + 0 + iposte * 3, -1);
    s.pon_e(ires + 0 + 2 * iposte, ivar + 2 + iposte * 3, QAMax);

    // QB < QBmax * (1-alfa)
    s.pon_e(ires + 1 + 2 * iposte, ivar + 1 + iposte * 3, -1);
    s.pon_e(ires + 1 + 2 * iposte, ivar + 2 + iposte * 3, -QBMax);
    s.pon_e(ires + 1 + 2 * iposte, s.nc, QBMax);

  end;

end;

procedure TGSimple_BiCombustible.opt_fijarRestriccionesDeCaja(s: TSimplex);
var
  iposte: integer;
begin
  if NMaquinasDisponibles = 0 then
    exit;

  // obligamos a que alfa se encuentre entre 0 y 1 en todos lso postes
  // y que los caudales sean menores que qamax y qbmax

  for iposte := 0 to globs.NPostes - 1 do
  begin
    s.cota_sup_set(ivar + 0 + 3 * iposte, QAMax);
    s.cota_sup_set(ivar + 1 + 3 * iposte, QBMax);
    s.cota_sup_set(ivar + 2 + 3 * iposte, 1);
  end;
end;

procedure TGSimple_BiCombustible.opt_leerSolucion(s: TSimplex);
var
  iposte: integer;
  me, meAcum: NReal;

begin

  maxNMaquinasDespachadas := 0;
  costoDirectoDelPaso := 0;

  if NMaquinasDisponibles = 0 then
  begin
    vclear(P);
    //vclear( cv_Spot );
    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(qa);
    vclear(qb);
    vclear(alfa);

    vclear(NMaquinasDespachadas);
    Ingreso_PorDisponibilidad_ := 0;
    Ingreso_PorEnergia_ := 0;
    exit;
  end;

  Ingreso_PorDisponibilidad_ :=
    self.PMaxDisponible * globs.HorasDelPaso *    //ingreso por potencia
    pa.PagoPorDisponibilidad_USD_MWh;

  // recuperamos los valores de qa y qb despachadas
  meAcum := 0;
  for iposte := 0 to globs.NPostes - 1 do
  begin
    QA[iposte] := s.xval(ivar + 0 + iposte * 3);
    QB[iposte] := s.xval(ivar + 1 + iposte * 3);
    alfa[iposte] := s.xval(ivar + 2 + iposte * 3);

    P[iposte] := // ren * ro * PCI * Q
      qa[iposte] * ren_ro_PCI_A + qb[iposte] * ren_ro_PCI_B;


    if P[iposte] > GTER_PRECISIONPOTENCIANMAQS then
    begin
      NMaquinasDespachadas[iposte] :=
        Math.Ceil((P[iposte] - GTER_PRECISIONPOTENCIANMAQS) / pa.PMax);
      me := P[iposte] * globs.DurPos[iposte];

      meAcum := meAcum + me;
      if NMaquinasDespachadas[iposte] > maxNMaquinasDespachadas then
        maxNMaquinasDespachadas := NMaquinasDespachadas[iposte];
    end
    else
    begin
      NMaquinasDespachadas[iposte] := 0;
    end;
  end;

  Ingreso_PorEnergia_ := meAcum * pa.PagoPorEnergia_USD_MWh;

end;

function TGSimple_BiCombustible.getNombreVar(ivar: integer; var nombre: string): boolean;
var
  kPoste: integer;
  rVar: integer;
  jvar: integer;
begin
  if NMaquinasDisponibles = 0 then
    Result := False
  else
  begin
    jvar := ivar - self.ivar;
    if (jvar >= 0) and (jvar < (3 * globs.NPostes)) then
    begin
      kPoste := jvar div 3;
      rVar := jvar mod 3;
      case rVar of
        0: nombre := self.Nombre + '_QA[m3/s]_' + IntToStr(kPoste + 1);
        1: nombre := self.Nombre + '_QB[m3/s]_' + IntToStr(kPoste + 1);
        2: nombre := self.Nombre + '_alfa_' + IntToStr(kPoste + 1);
      end;
      Result := True;
    end
    else
      Result := False;
  end;
end;

function TGSimple_BiCombustible.getNombreRes(ires: integer; var nombre: string): boolean;
var
  kPoste: integer;
  rRes: integer;
  jRes: integer;
begin
  if NMaquinasDisponibles = 0 then
    Result := False
  else
  begin
    jRes := ires - self.ires;
    if (jres >= 0) and (jres < (2 * globs.NPostes)) then
    begin
      kPoste := jRes div 2;
      rRes := jRes mod 2;

      case rRes of
        0: nombre := self.nombre + '_res_QA_' + IntToStr(kPoste + 1);
        1: nombre := self.nombre + '_res_QB_' + IntToStr(kPoste + 1);
      end;
      Result := True;
    end
    else
      Result := False;
  end;
end;

procedure TGSimple_BiCombustible.PubliVars;
begin
  inherited PubliVars;
  PublicarVariableVI('NMaqsDespachadas', '-', NMaquinasDespachadas, True, True);
  PublicarVariableVR('QA', '[m3/s]', 6, 2, QA, True, True);
  PublicarVariableVR('QB', '[m3/s]', 6, 2, QB, True, True);
  PublicarVariableVR('alfa', '[p.u.]', 6, 4, alfa, True, True);

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

  PublicarVariableNI('MaxNMaqsDespachadasEnElPaso', '-', maxNMaquinasDespachadas, False);
  PublicarVariableNI('NMaqsDisponibles', '-', NMaquinasDisponibles, False);
  PublicarVariableNR('PMáxDisponible', '[MW]', 6, 2, PMaxDisponible, False);
  PublicarVariableNR('PMediaDespachada', '[MW]', 6, 2, potMedia_despachada, False);
end;

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

procedure AlInicio;
begin
  registrarClaseDeCosa(TGSimple_BiCombustible.ClassName, TGSimple_BiCombustible);
  registrarClaseDeCosa(TFichaGSimple_BiCombustible.ClassName,
    TFichaGSimple_BiCombustible);
end;

procedure AlFinal;
begin
end;

end.
