unit uHidroConEmbalse;

interface

uses
  Math, xMatDefs, uSimplex, ucosa, uGlobs, uFechas, uNodos,
  SysUtils,
  uRandDispos,
  uEstados, uodt_types,
  uFichasLPD,
  uGeneradores,
  uconstantesSimSEE,
  uFuentesAleatorias, uCosaConNombre, uevapUruguay;

const
  ro_Agua = 1000; // kg/m3 densidad del agua
  g_Gravitacion = 9.8; // N/kg constante gravitatoria


type

  THidroConEmbalse = class; // forward declaration

(* Para describir el embalse, damos el volumen máximo turbinable Vmax
que corresponde al volumen (en m3 ) que almacena el embalse entre las
cotas hmin y hmax.
Y el volumen almacenado entre hmin y hmed siendo hmed = (hmax+hmin)/2

Las cotas están medidas desde algún nivel (por ejemplo el del mar).
Para poder calcular el salto se suministra también la cota de aguas abajo
o de descarga de la turbina referida al mismo nivel. (hDescarga [m])
El nivel de descarga puede ser especificado dando su valor con la variable
hDescarga o mediante la referencia a otra central en cuyo caso se considera
que el nivel de descarga es el del lago de la otra central más el valor
hDescarga. En este caso la variable hDescarga se utiliza para tener en
cuenta cambios en la referencia de niven entre una central y otra.
Si todas las cotas están referidas al nivel del mar no hay cambios de
referencias y hDescarga se pondrá en cero.

Suponemos que el área del embalse crece linealmente con la cota
A(z) = a + b * z
V(z) = integral( A(z) )= a*z + 1/2 * b z^2

con z= (h-hmin)/(hmax-hmin)

Vmax= V(1) = a+ 0.5 b
Vhmed= V(0.5) = 0.5 a + 0.5^3 b

=> Vmax - 2*Vhmed= 0.5 b - 0.5^2 b =  0.5^2 b
=>  b = 4*(Vmax-2*Vhmed)
.:  a = Vmax - 0.5 b

V= ( 1/2*b/dhmax^2 * dh + a/dhmax ) dh =

Pérdida de Salto por Caudal Erogado.
====================================
El caudal erogado QErogado [m3/s] es calculado al final de cada paso
de simulación como la suma del caudal vertido más el caudal turbinado.
Dicho caudal puede afectar el nivel de aguas abajo reducciendo el salto
efectivo en la central. Para tener en cuenta este efecto se usan los
parámetros: caQE y cbQE calculados para modelar la pérdida de salto
de acuerdo a la siguiente ecuación:

dh(QE) = caQE* QE + cbQE* QE^2
*)
  TFichaHidroConEmbalse = class(TFichaLPD)
  public
    hmax: NReal; //[m] cota maxima
    hmin: NReal; //[m] cota minima
    Vmax: NReal; //[Hm3] volumen máximo almacenable
    Vhmed: NReal; //[Hm3] volumen con la cota media

    centralesAguasArriba: TListaCentralesAguasArriba {of TGeneradorHidraulico};
    hDescarga: NReal; //[m] cota de la descarga para cálculo del salto
    central_lagoDescarga: TGeneradorHidraulico;
    // Coeficientes de afectación del salto por caudal erogado
    // dh(QE) = caQE* QE + cbQE* QE^2
    caQE: NReal;
    cbQE: NReal;

    //La cota minima a partir de la cual se puede verter y la cota maxima a
    //partir de la cual el máximo vertimiento es constante
    cotaMV0, cotaMV1: NReal;
    //El caudal que se puede verter con la cota maxima.
    //QMV0 se omite porque siempre es 0
    QMV1: NReal;

    ren: NReal;       //[pu] rendimiento complexivo de turbina y generador
    Pmax_Gen: NReal;  //[MW] Potencia maxima hidraulica
    Qmax_Turb: NReal; //[m3/s]
    fDispo: NReal;    //[pu] factor de disponibilidad fortuita
    tRepHoras: NReal;

    // filtración = filtracion_Ca + filtracion_Cb * ( h- hmin )
    filtracion_Ca: NReal; //[m3/s]
    filtracion_Cb: NReal; //[m2/s]

    // Caudal de aportes por debajo del cual consideramos ambiente MUY SECO
    // para el cálculo de la evaporación
    QaMuySeco: NReal; //[m3/s]

    HayRestriccionEmaxPasoDeTiempo: boolean; // indica si se aplica la restricción
    EmaxPasoDeTiempo: NReal; // Energía maxima generable en un paso de tiempo
    HayRestriccionQTmin: boolean; // indica si se aplica la restricción
    QTmin: NReal; // caudal mínimo para asegurar navegabilidad


    (* rch080402 agrego esto para dar la opción de regular el uso de Salto y Palmar *)
    flg_controlCotaObjetivoInferior: boolean;
    flg_controlCotaObjetivoSuperior: boolean;
    hObjetivo: NReal; // [m] cota objetivo
    delta_cva_ParaControlDeCota: NReal; // USD/Hm3 aplicable para control de cota
    cv_USD_Hm3_ValorizadoManual: NReal;

    tomarCotaDeLaFuente: boolean;
    fuenteCota: TFuenteAleatoria;
    borneCota: string;
    numeroBorneCota: integer;

    constructor Create(fecha: TFecha; periodicidad: TPeriodicidad;
      hmin_, hmax_, Vmax_, V_hmed, hDescarga: NReal;
      central_lagoDescarga: TGeneradorHidraulico;
      centralesAguasArriba: TListaCentralesAguasArriba;
      caQE, cbQE, ren_, Pmax_Gen_, Qmax_Turb_: NReal;
      fDispo_: NReal; tRepHoras: NReal;
      filtracion_Ca, filtracion_Cb, QaMuySeco: NReal;
      cotaMV0, cotaMV1, QMV1: NReal;
      HayRestriccionEmaxPasoDeTiempo: boolean;
      EmaxPasoDeTiempo: NReal;
      HayRestriccionQTmin: boolean;
      QTmin: NReal;
      ControlarCotaPorDebajoDeObjetivo: boolean;
      ControlarCotaPorEnciaDeObjetivo: boolean;
      hObjetivo: NReal;
      Delta_cvaUSD_Hm3ParaControlDeCota: NReal;
      cv_USD_Hm3_ValorizadoManual: NReal;
      tomarCotaDeLaFuente: boolean;
      fuenteCota: TFuenteAleatoria;
      borneCota: string);

    constructor Create_ReadFromText(f: TArchiTexto); override;
    procedure WriteToText(f: TArchiTexto); override;
    function infoAd: string; override;
    procedure Free; override;
  end;

  THidroConEmbalse = class(TGeneradorHidraulico)
  public
    pa: TFichaHidroConEmbalse;
    lpd: TFichasLPD;
    fuenteDeAportes: TFuenteAleatoria;
    nombreBorne: string;
    numeroBorne: integer;

    //Variables de Estado
    NDisc: integer; // discretizacion del estado
    hini: NReal; // cota inicial

    //----------- variables auxiliares
    ro_g_ren: NReal; // ro_Agua * g_gravitacion * ren /(1E6*3600)
    dhmax: NReal; // hmax - hmin
    VTmin: NReal; // volumen turbinado mínimo en el paso para cumplir con QTmin
    AplicarRestriccionDeErogadoMinimo: boolean;

    h_actual: NReal; // cota actual. Es la de toma.


    salto_actual: NReal; // salto actual efectivo

    QErogado_IterAnterior: NReal;
    // Usamos esta variable para almacenar el QErogado en la
    // iteración anterior. Esto se hace en leerResultadosDelPaso
    // antes de cargar el nuevo valor de QErogado.

    QMaxVert: NReal;


{$IFDEF RECORTEAPORTESCONTROLABLES}
    // Si se producen recortes de los aportes propios por necesidad de vertimiento
    // no controlado, esta variable será > 0 y al vertimiento resultado del simplex
    // hay que sumarle este volumen para tener el vertimiento total.
    VVertimientoNoControlable: NReal;
{$ENDIF}

    (******** Esta es la variable de estado ******)
    VolumenAlmacenado: NReal; // volumen actual

    PmaxParaQmax: NReal; // Pontecia máxima por máquina considerando Qmax y la cota
    NMaquinasDisponibles: integer;
    Pmax_Central: NReal; // [MW] Potencia Máxima disponible en la central
    Pmax_Gen: NReal; // [MW] Potencia máxima generable por turbina-generador
    Qmax: NReal; // [m3/s] Caudal máximo turbinable por turbina-generador

    PuedoGenerar: boolean;
    // indica si la Central está en condiciones de ofrecer potencia o no
    cv_USD_MWh: NReal; // costo variable de generación
    cv_agua_USD_Hm3_Dec: NReal; // valor del Agua expresado en USD/MWh

    Qevap: NReal; // caudal perdido por evaporacion
    Qfilt: NReal; // caudal perdido por filtración
    VPerdidas: NReal; //( QEvap+QFilt )* dt
    // variables auxiliares para las funciones cota-volumen y su inversa
    EsConico: boolean;
    embalse_cb, embalse_ca, embalse_c1, embalse_c2, embalse_c3,
    embalse_c4, embalse_c5: NReal;

    flg_ModificandoQEmaxParaEstabilidad: boolean;
    flg_RecortandoAportesParaEstabilidad: boolean;


    //Coeficientes de amortiguamiento, el otro es 1 - alfa
    alfa: NReal;



    flg_ValorizadoManual: boolean;


    constructor Create(nombre: string; nacimiento, muerte: TFecha;
      nodo: TNodo; hIni: NReal; NDisc_: integer;
      ficha: TFichaHidroConEmbalse; fuenteDeAportes: TFuenteAleatoria;
      nombreBorne: string; flg_ValorizadoManual: boolean);

    constructor Create_ReadFromText(f: TArchiTexto); override;
    procedure WriteToText(f: TArchiTexto); override;
    procedure PrepararMemoria(globs: TGlobs); override;
    procedure RegistrarParametrosDinamicos; override;

    function PotenciaFirme: NReal; override;

    function InfoAd: string; override;
    class function DescClase: string; override;

    //      procedure Sim_Inicio; override;
    procedure Sim_Cronica_Inicio; override;
    procedure SorteosDelPaso(sortear: boolean); override;
    procedure PrepararPaso_ps; override;
    procedure Sim_Paso_Fin; override;

    function ivarVertimientosMiosYAguasAbajo: TDAofNInt;

    procedure opt_nvers(var ivar, ivae, ires: integer); override;
    procedure opt_cargue(s: TSimplex); override;
    procedure ResolverEncadenamientos(s: TSimplex); override;
    procedure opt_fijarRestriccionesDeCaja(s: TSimplex); override;
    procedure opt_leerSolucion(s: TSimplex); override;
{$IFDEF ajusteDCF}
    function estimacionDCF: NReal; override;
{$ENDIF}

    function opt_NecesitoIterar(kIteracion: integer; var errRelativo: NReal): boolean;
      override;


{$IFDEF SPXCONLOG}
    procedure spx_NombrarVariables(s: TSimplex); override;
{$ENDIF}
    function getNombreVar(ivar: integer; var nombre: string): boolean; override;
    function getNombreRes(ires: integer; var nombre: string): boolean; override;

    procedure PosicionarseEnEstrellita; override;
    procedure ActualizarEstadoGlobal; override;
    procedure AcumAux1(peso: NReal); override;
    procedure SetAux1; override;

    procedure optx_nvxs(var ixr, ixd, iauxr, iauxd: integer); override;
    procedure optx_RegistrarVariablesDeEstado(adminEstados: TAdminEstados);
      override;

    procedure Free; override;

    // geometría del embalse
    function CotaToVolumen(h: NReal): NReal;
    function VolumenToCota(Vol: NReal): NReal;
    function CotaToSuperficie(h: NReal): NReal;

    procedure CambioFichaPD; override;
    //    function CostoDelPaso: NReal; override;
    procedure PubliVars; override;

    function CotaAguasArriba: NReal; override;
    // Calcula la cota de la descarga para poder calcular el Salto
    function CotaDescarga: NReal; override;
    // Caclula la reducción del salto causada por el caudal Erogado
    function ReduccionDeCotaPorCaudalErogado: NReal; override;
    function centralLagoDescarga: TGeneradorHidraulico; override;

    // imprime Potencias despachadas, h_actual, cv_agua_Dec
    procedure sim_PrintResultados_Encab(var fsal: textfile;
      kencab: integer); override;
    procedure sim_PrintResultados(var fsal: textfile); override;

    // imprime tabla de valores del agua en USD/Hm3
    procedure opt_PrintResultados_Encab(var fsal: textfile); override;
    procedure opt_PrintResultados(var fsal: textfile); override;

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

procedure THidroConEmbalse_cambioFichaPD(Actor: TCosa);

procedure AlInicio;
procedure AlFinal;

implementation

uses uActores;
// imprime Potencias despachadas, h_actual, cv_agua_Dec
procedure THidroConEmbalse.Sim_PrintResultados_Encab(var fsal: textfile;
  kencab: integer);
var
  iPoste: integer;
begin
  if kencab = 0 then
  begin
    for iPoste := 0 to globs.NPostes - 1 do
      Write(fsal, #9, Nombre);
    Write(fsal, #9, Nombre, #9, Nombre, #9, nombre, #9, nombre, #9, nombre, #9, nombre);
  end
  else if kencab = 1 then
  begin
    for iPoste := 0 to globs.NPostes - 1 do
      Write(fsal, #9, '[MW]');          //Potencias por poste
    Write(fsal, #9, '[m3/s]', #9, '[m3/s]', #9, '[m3/s]', #9, '[m]',
      #9, '[USD/Hm3]', #9, '[USD/Hm3]');//QTurbinado, QVertido, h, cv_aguaDec, cv_AguaInc
  end
  else if kencab = 2 then
  begin
    for iPoste := 1 to globs.NPostes do
      Write(fsal, #9, 'P_P', iPoste);
    Write(fsal, #9, 'QAportesP', #9, 'QTurbinado', #9, 'QVertido',
      #9, 'h', #9, 'CV_aguaDec', #9, 'CV_aguaInc');
  end
  else
  begin
    for iPoste := 1 to globs.NPostes do
      Write(fsal, #9, iPoste);
    Write(fsal, #9, '0', #9, '0', #9, '0', #9, '0', #9, '0', #9, '0');
  end;
end;

procedure THidroConEmbalse.Sim_PrintResultados(var fsal: textfile);
var
  iposte: integer;
  //  cv_agua: NReal;
begin
  for iposte := 0 to globs.NPostes - 1 do
    Write(fsal, #9, P[iposte]: 6: 1);

{  //ce = (dH * ro * g * ren) / (1E6 * 3600)
  if pa.central_lagoDescarga <> NIL then
    cv_agua:= (Self.cv_agua_USD_Hm3_Dec - pa.central_lagoDescarga.cv_agua_USD_Hm3_Inc) / (ce * 1E6)
  else
    cv_agua:= (self.cv_agua_USD_Hm3_Dec) / (ce * 1E6);}

  Write(fsal, #9, Self.QAportePropio: 8: 1, #9, QTurbinado: 8: 1, #9,
    QVertido: 8: 1, #9, h_actual: 6: 1, #9, cv_agua_USD_Hm3_Dec: 6: 1, #9,
    cv_agua_USD_Hm3_Inc: 6: 1);
end;

constructor THidroConEmbalse.Create(nombre: string;
  nacimiento, muerte: TFecha; nodo: TNodo; hIni: NReal;
  NDisc_: integer; ficha: TFichaHidroConEmbalse;
  fuenteDeAportes: TFuenteAleatoria; nombreBorne: string;
  flg_ValorizadoManual: boolean);

begin
  inherited Create(nombre, nacimiento, muerte, nodo);
  flg_ModificandoQEmaxParaEstabilidad := False;
  flg_RecortandoAportesParaEstabilidad := False;

  Self.lpd := TFichasLPD.Create(self, TFichaHidroConEmbalse);
  self.hini := hIni;
  self.NDisc := NDisc_;
  self.fuenteDeAportes := fuenteDeAportes;
  self.nombreBorne := nombreBorne;
  if ficha <> nil then
    lpd.Add(ficha);
  self.flg_ValorizadoManual := flg_ValorizadoManual;
end;

constructor THidroConEmbalse.Create_ReadFromText(f: TArchiTexto);
begin
  inherited Create_ReadFromText(f);
  f.IniciarLecturaRetrasada;
  f.rd('hIni', hIni);
  f.rd('NDisc', NDisc);
  f.rd('lpd', TCosa(lpd));
  f.rdReferencia('fuenteDeAportes', TCosa(fuenteDeAportes), Self);
  f.rd('nombreBorne', nombreBorne);
  f.rd('flg_ValorizadoManual', flg_ValorizadoManual);
  f.EjecutarLectura;
  flg_ModificandoQEmaxParaEstabilidad := False;
  flg_RecortandoAportesParaEstabilidad := False;
  pa := nil;
  nodo := nil;
  lpd.Propietario := self;
end;

procedure THidroConEmbalse.WriteToText(f: TArchiTexto);
begin
  inherited WriteToText(f);
  f.wr('hIni', hini, CF_PRECISION, CF_DECIMALES);
  f.wr('NDisc', NDisc);
  f.wr('lpd', lpd);
  f.wrReferencia('fuenteDeAportes', fuenteDeAportes);
  f.wr('nombreBorne', nombreBorne);
  f.wr('flg_ValorizadoManual', flg_ValorizadoManual);
end;

procedure THidroConEmbalse.prepararMemoria(globs: TGlobs);
begin
  inherited prepararMemoria(globs);
  numeroBorne := fuenteDeAportes.idBorne(nombreBorne);
end;

procedure THidroConEmbalse.registrarParametrosDinamicos;
var
  i: integer;
  ficha: TFichaHidroConEmbalse;
begin
  inherited registrarParametrosDinamicos;
  lpd.expandirFichas(globs);
  lpd.RegistrarFichasAActualizar(Self, globs.ActualizadorLPD, @pA, nil,
    THidroConEmbalse_cambioFichaPD);
  for i := 0 to lpd.Count - 1 do
  begin
    ficha := TFichaHidroConEmbalse(lpd[i]);
    if ficha.fuenteCota <> nil then
      ficha.numeroBorneCota := ficha.fuenteCota.IdBorne(ficha.borneCota);
  end;
end;

function THidroConEmbalse.infoAd: string;
begin
  Result := '';
end;

function THidroConEmbalse.potenciaFirme: NReal;
begin
  Result := (paUnidades.nUnidades) * pa.Pmax_Gen * pa.ren;
end;

class function THidroConEmbalse.DescClase: string;
begin
  Result := 'Generador Hidráulico Con Embalse';
end;

procedure THidroConEmbalse.SorteosDelPaso(sortear: boolean);
begin
  if globs.ObligarDisponibilidad_1_ then
  begin
    NMaquinasDisponibles := paUnidades.nUnidades;
    Pmax_Gen := pA.Pmax_gen;
    Qmax := pA.Qmax_Turb;
  end
  else if (sortear) then
  begin
    ActualizarProbabilidadesReparacionYRotura(pa.fDispo, pa.tRepHoras);
    NMaquinasDisponibles := Sorteos_RepRotUnidades;
    Pmax_Gen := pA.Pmax_gen;
    Qmax := pA.Qmax_Turb;
  end
  else
  begin
    NMaquinasDisponibles := paUnidades.nUnidades;
    Pmax_Gen := pA.Pmax_gen * pA.fdispo;
    Qmax := pA.Qmax_Turb * pA.fdispo;
  end;
end;

function THidroConEmbalse.ReduccionDeCotaPorCaudalErogado: NReal;
begin
  Result := (pa.cbQE * QErogado + pa.caQE) * QErogado;
end;

function THidroConEmbalse.centralLagoDescarga: TGeneradorHidraulico;
begin
  Result := pa.central_lagoDescarga;
end;

function THidroConEmbalse.cotaAguasArriba: NReal;
begin
  Result := h_actual;
end;

function THidroConEmbalse.CotaDescarga: NReal;
begin
  if pa.central_lagoDescarga = nil then
    Result := pa.hDescarga
  else
    Result := pa.central_LagoDescarga.cotaAguasArriba;
end;

procedure THidroConEmbalse.opt_PrintResultados_Encab(var fsal: textfile);
begin
  Write(fsal, #9, FloatToStrF(VolumenToCota(VolumenAlmacenado), ffgeneral, 6, 3));
end;

procedure THidroConEmbalse.opt_PrintResultados(var fsal: textfile);
begin
  Write(fsal, #9, FloatToStrF(cv_agua_USD_Hm3_Dec, ffgeneral, 6, 3));
end;

procedure THidroConEmbalse.dump_Variables(var f: TextFile; charIndentacion: char);
begin
  inherited dump_Variables(f, charIndentacion);
  writeln(f, charIndentacion, 'h_actual[m]= ', FloatToStrF(h_actual, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'salto_actual[m]= ',
    FloatToStrF(salto_actual, ffFixed, 10, 3));

  writeln(f, charIndentacion, 'QAportePropio[m^3/s]= ',
    FloatToStrF(QAportePropio, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'QFilt[m^3/s]= ', FloatToStrF(QFilt, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'QEvap[m^3/s]= ', FloatToStrF(QEvap, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'QMaxVert[m^3/s]= ',
    FloatToStrF(QMaxVert, ffFixed, 10, 3));

  writeln(f, charIndentacion, 'VolumenAlmacenado[hm^3]= ',
    FloatToStrF(VolumenAlmacenado, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'VMax[hm^3]= ', FloatToStrF(pa.Vmax, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'VAportePropio[hm^3]= ',
    FloatToStrF(VAportePropio, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'VPerdidas[hm^3]= ',
    FloatToStrF(VPerdidas, ffFixed, 10, 3));
(*
  writeln(f, charIndentacion, 'cv_agua_USD_MWh_Inc[USD/MWh]= ', FloatToStrF(cv_agua_USD_MWh_Inc, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'cv_agua_USD_MWh_Dec[USD/MWh]= ', FloatToStrF(cv_agua_USD_MWh_Dec, ffFixed, 10, 3));
*)
  writeln(f);
end;

procedure THidroConEmbalse.prepararPaso_ps;
var
  dCFdV_Inc, dCFdV_Dec: NReal;
  volMV0, volMV1: NReal;
  auxParaCalculos: NReal;
{$IFDEF CONTROLE_MAXVERT}
  Qlimite, QEmaxEstabilidadNumerica: NReal;
{$ENDIF}
{$IFDEF RECORTEAPORTESCONTROLABLES}
  QAportePropioRecortado: NReal;
  VAportePropioRecortado: NReal;
{$ENDIF}
  h_real: NReal;
begin
  if not self.pa.tomarCotaDeLaFuente then
    h_real := h_actual
  else
    h_real := pa.fuenteCota.Bornera[pa.numeroBorneCota];

  salto_actual := max(0.1, h_real - CotaDescarga - ReduccionDeCotaPorCaudalErogado);

  ce := salto_actual * ro_g_ren;
  auxParaCalculos := 1 / (1.0E6 * ce);

  // calculamos el valor del agua en USD/MWh
  if flg_ValorizadoManual then
  begin
    cv_agua_USD_Hm3_Inc := pa.cv_USD_Hm3_ValorizadoManual * globs.fActPaso;
    cv_agua_USD_Hm3_Dec := cv_agua_USD_Hm3_Inc;
  end
  else
  begin
    if globs.EstadoDeLaSala = CES_OPTIMIZANDO then
      globs.CF.devxr_estrella(ixr, globs.kPaso_ + 1, dCFdV_Inc, dCFdV_Dec)
    else
      globs.CF.devxr_continuo(ixr, globs.kPaso_ + 1, dCFdV_Inc, dCFdV_Dec);
    cv_agua_USD_Hm3_Inc := -dCFdV_Inc * globs.fActPaso;
    cv_agua_USD_Hm3_Dec := -dCFdV_Dec * globs.fActPaso;
  end;

  (**** AGREGADO PARA CONTROL DE COTA OBJETIVO DURANTE LA SIMULACION****)
  if globs.EstadoDeLaSala = CES_SIMULANDO then
  begin
    if pa.flg_controlCotaObjetivoInferior and (h_actual < pa.hObjetivo) then
    begin
      cv_agua_USD_Hm3_Dec := cv_agua_USD_Hm3_Dec + pa.delta_cva_ParaControlDeCota;
      //    cv_agua_USD_Hm3_Inc:= cv_agua_USD_Hm3_Inc+ pa.delta_cva_ParaControlDeCota;
    end;

    if pa.flg_controlCotaObjetivoSuperior and (h_actual > pa.hObjetivo) then
    begin
      cv_agua_USD_Hm3_Dec := cv_agua_USD_Hm3_Dec - pa.delta_cva_ParaControlDeCota;
      //    cv_agua_USD_Hm3_Inc:= cv_agua_USD_Hm3_Inc- pa.delta_cva_ParaControlDeCota;
    end;
  end;

{$IFDEF COSTOSHIDROPOSITIVOS}
  if cv_agua_USD_Hm3_Inc < 1E-2 then
    cv_agua_USD_Hm3_Inc := 1e-2;

  if cv_agua_USD_Hm3_Dec < 1E-2 then
    cv_agua_USD_Hm3_Dec := 1e-2;
{$ENDIF}

  cv_USD_MWh := cv_agua_USD_Hm3_Dec * auxParaCalculos;

  QAportePropio := Self.fuenteDeAportes.bornera[Self.numeroBorne];


  Assert(QAportePropio >= 0, 'El generador hidráulico con embalse ' +
    nombre + ' tiene caudal de aportes propios negativo. Fuente: ' +
    fuenteDeAportes.nombre + ', Borne: ' + nombreBorne);
  QFilt := pa.filtracion_Ca + pa.filtracion_Cb * (h_actual - pa.hmin);
  QEvap := CotaToSuperficie(h_actual) * CoeficienteDeEvaporacion(
    globs.MesInicioDelPaso, QAportePropio, pa.QaMuySeco);

  VAportePropio := QAportePropio * globs.SegundosDelPaso / 1.0E6;
  VPerdidas := (QFilt + QEvap) * globs.SegundosDelPaso / 1.0E6;
  VPerdidas := max(0, min(VPerdidas, VolumenAlmacenado - (10 / 1.0E6)));
  // acotamos a que no pueda perderse más que lo que hay

  // en base al volumen actual calcula el vertimiento posible
  volMV0 := CotaToVolumen(pa.cotaMV0);
  if VolumenAlmacenado < volMV0 then
    QMaxVert := 0.1
  else
  begin
    volMV1 := CotaToVolumen(pa.cotaMV1);
    if VolumenAlmacenado < volMV1 then
      QMaxVert := pa.QMV1 * (VolumenAlmacenado - VolMV0) / (VolMV1 - VolMV0)
    else
      QMaxVert := pa.QMV1;

(*
    if (VolumenAlmacenado + VAportePropio - VPerdidas) >= (0.9 * pa.Vmax) then
    begin
      QMaxVert:= QMaxVert * 100;
    end
    *)
  end;

  //  QMaxVert:= pa.Vmax * 1E7 / globs.SegundosDelPaso;

  (* QEmaxEstabilidadNumerica:=  0.4* pa.Vmax / (Ndisc-1) /globs.SegundosDelPaso
                              -1.2 * Qmax*NMaquinasDisponibles;*)
  //ESTA MAL, FALTA CONSIDERAR EL APORTE DE LAS CENTRALES AGUAS ARRIBA


{$IFDEF CONTROLE_MAXVERT}
  Qlimite := 0.7 * pa.Vmax * 1.0E6 / (Ndisc - 1) / globs.SegundosDelPaso;
  // 0.7 QLimite para DeltaV;
  QEmaxEstabilidadNumerica := Qlimite - QMax * NMaquinasDisponibles;
  if QEmaxEstabilidadNumerica < QMaxVert then
  begin
    QMaxVert := max(0, QEmaxEstabilidadNumerica);
    if not flg_ModificandoQEmaxParaEstabilidad then
    begin
      globs.Alerta(Self.Nombre +
        ': OJO, modificando QMaxVert para lograr estabilidad, debiera achicar dT/dV');
      flg_ModificandoQEmaxParaEstabilidad := True;
    end;
    {$IFDEF RECORTEAPORTESCONTROLABLES}
    if QAportePropio > QMaxVert then
    begin
      if (VolumenAlmacenado + VAportePropio - VPerdidas -
        QMaxVert * globs.SegundosDelPaso / 1.0E6) >= (pa.Vmax * 0.97) then
      begin
        if not flg_RecortandoAportesParaEstabilidad then
        begin
          globs.Alerta(Self.Nombre +
            ': OJO Recortando aportes para lograr estabilidad, debiera achicar dT/dV');
          flg_RecortandoAportesParaEstabilidad := True;
        end;
        QAportePropioRecortado :=
          max(0, 0.97 * ((pa.Vmax - VolumenAlmacenado + VPerdidas) *
          1.0E6 / globs.SegundosDelPaso + QMaxVert));
        VAportePropioRecortado := QAportePropioRecortado * globs.SegundosDelPaso / 1.0E6;
        VVertimientoNoControlable := VAportePropio - VAportePropioRecortado;
        VAportePropio := VAportePropioRecortado;
      end;
    end
    else
      VVertimientoNoControlable := 0;
   {$ENDIF}
  end;
{$ENDIF}

  PmaxParaQmax := Qmax * ce * 3600;

  if NMaquinasDisponibles > 0 then
    Pmax_Central := NMaquinasDisponibles * min(Pmax_Gen, PMaxParaQmax)
  else
    PMax_Central := 0;

  if PMax_Central > 0.1 then
    PuedoGenerar := True
  else
    PuedoGenerar := False;

  if pA.HayRestriccionQTmin then
  begin
    VTmin := VolumenAlmacenado + VAportePropio - VPerdidas;
    VTmin := 0.95 * VTmin; // lo bajo un poco cumplo si realmente puedo
    VTmin := min(PA.QTmin * globs.SegundosDelPaso / 1.0E6, VTmin);
    AplicarRestriccionDeErogadoMinimo := VTmin > 1;
  end
  else
    AplicarRestriccionDeErogadoMinimo := False;

end;

procedure THidroConEmbalse.opt_nvers(var ivar, ivae, ires: integer);
begin
  self.ivar := ivar;

  ivar := ivar + globs.NPostes + 1; // PGen por poste y VVertimiento
  self.ires := ires; // 0 <= volumen <= Vmáx  ( dos restricciones )
  ires := ires + 2;

  if (PuedoGenerar) then
  begin
    if pA.HayRestriccionEmaxPasoDeTiempo then
      Inc(ires);
    if AplicarRestriccionDeErogadoMinimo then
      Inc(ires);
  end;
end;

procedure THidroConEmbalse.opt_cargue(s: TSimplex);
var
  ibaseres: integer;
  iposte: integer;
  jres: integer;
begin
{$IFDEF SPXCONLOG}
  spx_NombrarVariables(s);
{$ENDIF}
  ibaseres := nodo.ires;
  // Tenemos que aportar a las restricciones de demanda del nodo al que está
  // conectado el generador
  for iposte := 0 to globs.NPostes - 1 do
    s.pon_e(ibaseres + iposte, ivar + iposte, 1);
  ivert := ivar + globs.NPostes;

  // Ahora agregamos a la función de UTILIDAD (-costo)
  for iposte := 0 to globs.NPostes - 1 do
    s.pon_e(s.nf, ivar + iposte, -cv_USD_MWh * globs.durpos[iposte]);

  s.pon_e(s.nf, ivert, -cv_agua_USD_Hm3_Dec); //  Vertimiento
  s.acum_e(s.nf, s.nc, cv_agua_USD_Hm3_Inc * VAportePropio -
    cv_agua_USD_Hm3_Dec * VPerdidas); // Aporte

  // restriccion de volumen >= 0 = Vmín
  jres := ires;
  for iposte := 0 to globs.NPostes - 1 do
    s.pon_e(jres, ivar + iposte, -globs.durpos[iposte] / (ce * 1.0E6));
  s.pon_e(jres, ivert, -1);  // vertimiento
  s.pon_e(jres, s.nc, (VolumenAlmacenado + VAportePropio - VPerdidas));

  // restricción de volumen <= Vmax
  Inc(jres);
  if (PuedoGenerar) then
    for iposte := 0 to globs.NPostes - 1 do
      s.pon_e(jres, ivar + iposte, globs.durpos[iposte] / (ce * 1.0E6));
  s.pon_e(jres, ivert, 1);  // vertimiento
  s.pon_e(jres, s.nc, pA.Vmax - (VolumenAlmacenado + VAportePropio - VPerdidas));

  s.permitirViolarBordeSupParaSatisfacerRestriccion(jres,
    ivarVertimientosMiosYAguasAbajo);

  // Restricción de Energía máxima en el paso de tiempo
  if (PuedoGenerar) then
  begin
    if pA.HayRestriccionEmaxPasoDeTiempo then
    begin
      Inc(jres);
      for iposte := 0 to globs.NPostes - 1 do
        s.pon_e(jres, ivar + iposte, -globs.durpos[iposte]);
      s.pon_e(jres, s.nc, pA.EmaxPasoDeTiempo);
    end;

    // Restricción de caudal erogado mínimo por navegabilidad
    if AplicarRestriccionDeErogadoMinimo then
    begin
      Inc(jres);
      if (PuedoGenerar) then
      begin
        for iposte := 0 to globs.NPostes - 1 do
          s.pon_e(jres, ivar + iposte, globs.durpos[iposte] / ce / 1.0E6);
      end;
      s.pon_e(jres, ivert, 1);  // vertimiento
      s.pon_e(jres, s.nc, -VTmin);
    end;
  end;
end;

procedure THidroConEmbalse.ResolverEncadenamientos(s: TSimplex);
var
  iCentrales: integer;
  icof: integer;
  iposte: integer;
  kfil, jcol: integer;
  cofAporte, valor: NReal;
  gh: TFichaCentralAguasArriba;
begin
  // Aportes de las centrales aguas arriba
  // sumamos los aportes de las centrales aguas arriba
  // sobre la restricción de vertimiento
  for iCentrales := 0 to pa.centralesAguasArriba.Count - 1 do
  begin
    gh := TFichaCentralAguasArriba(pa.centralesAguasArriba[iCentrales]);
    kfil := gh.central.ires;
    jcol := gh.central.ivar;

    cofAporte := -gh.coef;
    // el signo menos es para compenzar el menos que tienen los coeficientes
    // de las restricciones y obtener así el volumen de aporte.
    // Es una optimización lamentable que induce a errores, pero esta bien


    // consideramos los volúmens turbinados de la central aguas arriba sacándolos
    // de su primera restricción adicional que será la de Vk+1 >=0 en el caso de
    // tratarse de una hidro con embalse o la de -Turbinado -Vertimiento + Aportes = 0
    // para el caso en que se trate de una hidro de pasada
    for iposte := 0 to globs.NPostes - 1 do
    begin
      icof := jcol + iposte;
      valor := s.e(kfil, icof) * cofAporte;
      s.acum_e(ires, icof, valor); // Vk+1 >= 0
      s.acum_e(ires + 1, icof, -valor); // Vmax - Vk+1 >= 0
      s.acum_e(s.nf, icof, valor * self.cv_agua_USD_Hm3_Inc);
    end;

    // consideramos el vertimiento
    icof := jcol + globs.NPostes;
    valor := s.e(kfil, icof) * cofAporte;
    s.acum_e(ires, icof, valor); // Vk+1 >= 0
    s.acum_e(ires + 1, icof, -valor); // Vmax - Vk+1 >= 0
    s.acum_e(s.nf, icof, valor * self.cv_agua_USD_Hm3_Inc);
  end;
end;

procedure THidroConEmbalse.opt_fijarRestriccionesDeCaja(s: TSimplex);
var
  iposte, ivert: integer;
begin
  // Le fijamos como cota máxima PMax a la potencia en todos los postes
  if PuedoGenerar then
  begin
    for iposte := 0 to globs.NPostes - 1 do
      s.cota_sup_set(ivar + iposte, PMax_Central);
  end
  else
    for iposte := 0 to globs.NPostes - 1 do
      s.FijarVariable(ivar + iposte, 0);
  ivert := ivar + globs.NPostes;
  s.cota_sup_set(ivert, QMaxVert * globs.SegundosDelPaso / 1.0E6);
end;

procedure THidroConEmbalse.Sim_Cronica_Inicio;
begin
  QErogado := 0;
  VErogado := 0;
  QVertido := 0;
  VVertido := 0;
  QTurbinado := 0;
  VTurbinado := 0;
  EnergiaGenerada := 0;
  VolumenAlmacenado := CotaToVolumen(hini);
  h_actual := hini;
end;

procedure THidroConEmbalse.opt_leerSolucion(s: TSimplex);
var
  iposte: integer;
begin
  if PuedoGenerar then
  begin
    // recuperamos los valores de Potencia despachada
    EnergiaGenerada := 0;
    for iposte := 0 to globs.NPostes - 1 do
    begin
      P[iposte] := s.xval(ivar + iposte);
      EnergiaGenerada := EnergiaGenerada + P[iposte] * globs.durpos[iposte];
    end;
  end
  else
  begin
    for iposte := 0 to globs.NPostes - 1 do
      P[iposte] := 0;
    EnergiaGenerada := 0;
  end;

 {$IFDEF RECORTEAPORTESCONTROLABLES}
  VVertido := s.xval(ivert) + VVertimientoNoControlable;
  {$ELSE}
  VVertido := s.xval(ivert);
  {$ENDIF}

  VTurbinado := EnergiaGenerada / (ce * 1.0E6);
  VErogado := VTurbinado + VVertido;

  QVertido := VVertido * (1.0E6 * globs.invSegundosDelPaso);
  QTurbinado := VTurbinado * (1.0E6 * globs.invSegundosDelPaso);

  QErogado_IterAnterior := QErogado;

  QErogado := VErogado * (1.0E6 * globs.invSegundosDelPaso);


  if globs.cntIteracionesDelPaso = 1 then
    alfa := 0.5
  else
    alfa := alfa + ((1 - alfa) * 0.1);
{  if QErogado - QErogado_IterAnterior >= 0 then
    alfa:= 0.2
  else
    alfa:= 0.9;}
  QErogado := (1 - alfa) * QErogado + alfa * QErogado_IterAnterior;


  VolumenAlmacenado := s.yval(ires);
end;

{$IFDEF ajusteDCF}
function THidroConEmbalse.EstimacionDCF: NReal;
var
  i: integer;
  VAportesTotales: NReal;
  gh: TFichaCentralAguasArriba;
begin
  VAportesTotales := VAportePropio;
  for i := 0 to pa.centralesAguasArriba.Count - 1 do
  begin
    gh := TFichaCentralAguasArriba(pa.centralesAguasArriba[i]);
    VAportesTotales := VAportesTotales +
      TGeneradorHidraulico(gh.central).VErogado
      * gh.coef;
  end;
  Result := (VErogado + VPerdidas) * cv_agua_USD_Hm3_Dec - VAportesTotales *
    cv_agua_USD_Hm3_Inc;
end;

{$ENDIF}


function THidroConEmbalse.opt_NecesitoIterar(kIteracion: integer;
  var errRelativo: NReal): boolean;
var
  qm: NReal;
begin
  qm := max(QErogado, QErogado_IterAnterior);
  if qm > 0.01 then
    errRelativo := abs(QErogado - QErogado_IterAnterior) / qm
  else
    errRelativo := 1;
  Result := errRelativo > 0.1;
end;


{$IFDEF SPXCONLOG}
procedure THidroConEmbalse.spx_NombrarVariables(s: TSimplex);
var
  iposte, jres: integer;
begin
  for iposte := 0 to globs.NPostes - 1 do
    s.set_NombreVar(ivar + iposte, Nombre + '_P[MW]' + IntToStr(iposte + 1));

  s.set_NombreVar(ivar + globs.NPostes, Nombre + '_Vertimiento[Hm3]');
  jres := ires;
  s.set_NombreRest(jres, Nombre + '_VOL>=0');
  Inc(jres);
  s.set_NombreRest(jres, Nombre + '_VOL<=Vmax');
  Inc(jres);
  if pA.HayRestriccionEmaxPasoDeTiempo then
  begin
    s.set_NombreRest(jres, Nombre + '_Emax');
    Inc(jres);
  end;
  if AplicarRestriccionDeErogadoMinimo then
    s.set_NombreRest(jres, Nombre + '_QTmin');
end;

{$ENDIF}

function THidroConEmbalse.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 if (ivar = ivert) then
  begin
    nombre := self.Nombre + '_Vertimiento[Hm3]';
    Result := True;
  end
  else
    Result := False;
end;

function THidroConEmbalse.getNombreRes(ires: integer; var nombre: string): boolean;
begin
  if (ires = self.ires) then
  begin
    nombre := self.nombre + '_VOL>=0';
    Result := True;
  end
  else if (ires = self.ires + 1) then
  begin
    nombre := self.nombre + '_VOL<=Vmax';
    Result := True;
  end
  else if PuedoGenerar then
  begin
    if pa.HayRestriccionEmaxPasoDeTiempo and (ires = self.ires + 2) then
    begin
      nombre := self.nombre + '_res-EMax';
      Result := True;
    end
    else if AplicarRestriccionDeErogadoMinimo and (ires = self.ires + 2) then
    begin
      nombre := self.nombre + '_res-QTMin';
      Result := True;
    end
    else if pa.HayRestriccionEmaxPasoDeTiempo and AplicarRestriccionDeErogadoMinimo and
      (ires = self.ires + 3) then
    begin
      nombre := self.nombre + '_res-QTMin';
      Result := True;
    end
    else
      Result := False;
  end
  else
    Result := False;
end;

procedure THidroConEmbalse.PubliVars;
begin
  inherited PubliVars;
  PublicarVariableNR('Vertimiento[Hm^3]', VVertido);
  PublicarVariableNR('Cota[m]', h_actual);
  PublicarVariableNR('Vol[Hm^3]', VolumenAlmacenado);
  PublicarVariableNI('NMaqsDisponibles', NMaquinasDisponibles);
  PublicarVariableNR('cv_agua_Dec[USD/Hm3]', cv_agua_USD_Hm3_Dec);
  PublicarVariableNR('cv_agua_Inc[USD/Hm3]', cv_agua_USD_Hm3_Inc);
  PublicarVariableNR('QErogado[m3/s]', QErogado);
  PublicarVariableNR('QTurbinado[m3/s]', QTurbinado);
  PublicarVariableNR('QVertido[m3/s]', QVertido);
  PublicarVariableNR('QAportesPropios[m3/s]', QAportePropio);
  PublicarVariableNR('QEvaporación[m3/s]', QEvap);
  PublicarVariableNR('QFiltración[m3/s]', QFilt);
end;

procedure THidroConEmbalse.Sim_Paso_Fin;
begin
  h_actual := VolumenToCota(VolumenAlmacenado);
end;

function THidroConEmbalse.ivarVertimientosMiosYAguasAbajo: TDAofNInt;
var
  nCentrales: integer;
  iter: TGeneradorHidraulico;
  res: TDAofNInt;
begin
  nCentrales := 1; //yo

  //BUG??? rch0906030800 comento el siguiente renglón y agrego
  //  iter:= self;
  iter := centralLagoDescarga;  // agregado
  while iter <> nil do
  begin
    nCentrales := nCentrales + 1;
    iter := iter.centralLagoDescarga;
  end;

  SetLength(res, nCentrales);
  nCentrales := 0;
  iter := self;
  while iter <> nil do
  begin
    res[nCentrales] := iter.ivert;
    nCentrales := nCentrales + 1;
    iter := iter.centralLagoDescarga;
  end;
  Result := res;
end;

procedure THidroConEmbalse.optx_nvxs(var ixr, ixd, iauxr, iauxd: integer);
begin
  if not flg_ValorizadoManual then
  begin
    self.ixr := ixr;
    ixr := ixr + 1;
    Self.iauxr := iauxr;
    iauxr := iauxr + 1;
  end;
end;

procedure THidroConEmbalse.PosicionarseEnEstrellita;
begin
  if not flg_ValorizadoManual then
  begin
    Self.VolumenAlmacenado := globs.CF.xr[ixr];
    h_actual := VolumenToCota(VolumenAlmacenado);
    Self.QErogado := globs.Auxs_r0[iauxr][globs.CF.ordinalEstrellaActual];
  end;
end;

procedure THidroConEmbalse.ActualizarEstadoGlobal;
begin
  if flg_ValorizadoManual then
    exit;
  globs.CF.xr[ixr] := Self.VolumenAlmacenado;
  //  Self.QErogado:= globs.Auxs_r0[iauxr][globs.CF.ordinalEstrellaActual];
end;

procedure THidroConEmbalse.AcumAux1(peso: NReal);
begin
  if flg_ValorizadoManual then
    exit;
  globs.Auxs_r1[iauxr][globs.CF.ordinalEstrellaActual] :=
    globs.Auxs_r1[iauxr][globs.CF.ordinalEstrellaActual] + Self.QErogado * peso;
end;

procedure THidroConEmbalse.SetAux1;
begin
  if flg_ValorizadoManual then
    exit;
  globs.Auxs_r1[iauxr][globs.CF.ordinalEstrellaActual] := Self.QErogado;
end;

procedure THidroConEmbalse.optx_RegistrarVariablesDeEstado(
  adminEstados: TAdminEstados);
begin
  if flg_ValorizadoManual then
    exit;

  adminEstados.Registrar_Continua(
    ixr,
    0.0,
    pA.Vmax,
    ndisc,
    nombre + '_Vol', // nombre de la variable
    'Hm3' // unidades
    );
  adminEstados.RegistrarTraduccion_Continua(ixr,
    VolumenToCota(0),
    VolumenToCota(pa.Vmax),
    NDisc,
    nombre + '_Cota',
    'm', self.VolumenToCota);
end;

procedure THidroConEmbalse.Free;
begin
  lpd.Free;
  inherited Free;
end;

function THidroConEmbalse.CotaToVolumen(h: NReal): NReal;
var
  dh: NReal;
begin
  dh := h - pA.hmin;
  if EsConico then
    Result := (embalse_c2 * dh + embalse_c1) * dh
  else
    Result := embalse_c1 * dh;
end;

function THidroConEmbalse.CotaToSuperficie(h: NReal): NReal;
var
  dh: NReal;
begin
  dh := h - pA.hmin;
  if EsConico then
    Result := 2 * embalse_c2 * dh + embalse_c1
  else
    Result := embalse_c1;
end;

function THidroConEmbalse.VolumenToCota(Vol: NReal): NReal;
begin
  if EsConico then
    Result := sqrt(embalse_c3 * Vol + embalse_c4) + embalse_c5
  else
    Result := Vol / embalse_c1 + pA.hmin;
end;

procedure THidroConEmbalse.cambioFichaPD;
begin
  ro_g_ren := pA.ren * ro_Agua * g_gravitacion / (1.0E6 * 3600.0);

  dhmax := (pA.hmax - pA.hmin);

  embalse_cb := 4.0 * (pA.Vmax - 2.0 * pA.Vhmed);
  embalse_ca := pA.Vmax - embalse_cb / 2.0;
  if (embalse_cb < 0) then
    raise Exception.Create('Revise los datos del embalse(' + Nombre +
      '), el área decrece al aumentar la cota.');
  if (embalse_ca < 0) then
    raise Exception.Create('Revise los datos del embalse(' + Nombre +
      '), el volumen parece anularse antes de la cota mínima.');

  embalse_c1 := embalse_ca / dhmax;

  if EsCero(embalse_cb) then
  begin
    EsConico := False;
  end
  else
  begin
    EsConico := True;
    embalse_c2 := embalse_cb / 2.0 / sqr(dhmax);
    embalse_c3 := 1 / embalse_c2;
    embalse_c4 := sqr(embalse_c1 / (2 * embalse_c2));
    embalse_c5 := pA.hmin - (embalse_c1 / (2 * embalse_c2));
  end;
end;

{*********************************
*Métodos de TFichaHidroConEmbalse*
*********************************}

constructor TFichaHidroConEmbalse.Create(fecha: TFecha;
  periodicidad: TPeriodicidad;
  hmin_, hmax_, Vmax_, V_hmed, // volumen con la cota media
  hDescarga: NReal; central_lagoDescarga: TGeneradorHidraulico;
  centralesAguasArriba: TListaCentralesAguasArriba;
  caQE, cbQE, ren_, Pmax_Gen_, Qmax_Turb_: NReal; fDispo_: NReal;
  tRepHoras: NReal; filtracion_Ca, filtracion_Cb, QaMuySeco: NReal;
  cotaMV0, cotaMV1, QMV1: NReal; HayRestriccionEmaxPasoDeTiempo: boolean;
  EmaxPasoDeTiempo: NReal; HayRestriccionQTmin: boolean;
  QTmin: NReal; ControlarCotaPorDebajoDeObjetivo: boolean;
  ControlarCotaPorEnciaDeObjetivo: boolean; hObjetivo: NReal;
  Delta_cvaUSD_Hm3ParaControlDeCota: NReal; cv_USD_Hm3_ValorizadoManual: NReal;
  tomarCotaDeLaFuente: boolean; fuenteCota: TFuenteAleatoria;
  borneCota: string);
begin
  inherited Create(fecha, periodicidad);
  self.hmin := hmin_;
  self.hmax := hmax_;
  self.Vmax := Vmax_;
  self.Vhmed := V_hmed;
  self.hDescarga := hDescarga;
  self.central_lagoDescarga := central_lagoDescarga;
  self.caQE := caQE;
  self.cbQE := cbQE;
  self.ren := ren_;
  self.Pmax_Gen := Pmax_Gen_;
  self.Qmax_Turb := Qmax_Turb_;
  self.fDispo := fDispo_;
  self.tRepHoras := tRepHoras;

  Self.filtracion_Ca := filtracion_Ca;
  Self.filtracion_Cb := filtracion_Cb;
  Self.QaMuySeco := QaMuySeco;

  self.cotaMV0 := cotaMV0;
  self.cotaMV1 := cotaMV1;
  self.QMV1 := QMV1;

  self.centralesAguasArriba := centralesAguasArriba;

  self.HayRestriccionEmaxPasoDeTiempo := HayRestriccionEmaxPasoDeTiempo;
  self.EmaxPasoDeTiempo := EmaxPasoDeTiempo;
  self.HayRestriccionQTmin := HayRestriccionQTmin;
  self.QTmin := QTmin;


  self.flg_controlCotaObjetivoInferior := ControlarCotaPorDebajoDeObjetivo;
  self.flg_controlCotaObjetivoSuperior := ControlarCotaPorEnciaDeObjetivo;
  self.hObjetivo := hObjetivo;
  self.delta_cva_ParaControlDeCota := Delta_cvaUSD_Hm3ParaControlDeCota;
  self.cv_USD_Hm3_ValorizadoManual := cv_USD_Hm3_ValorizadoManual;

  Self.tomarCotaDeLaFuente := tomarCotaDeLaFuente;
  self.fuenteCota := fuenteCota;
  self.borneCota := borneCota;
end;

procedure TFichaHidroConEmbalse.WriteToText(f: TArchiTexto);
begin
  inherited WriteToText(f);

  f.wr('hmin', hmin, uconstantesSimSEE.CF_PRECISION, uconstantesSimSEE.CF_DECIMALES);
  f.wr('hmax', hmax, uconstantesSimSEE.CF_PRECISION, uconstantesSimSEE.CF_DECIMALES);
  f.wr('Vmax', Vmax, uconstantesSimSEE.CF_PRECISION, uconstantesSimSEE.CF_DECIMALES);
  f.wr('Vhmed', Vhmed, uconstantesSimSEE.CF_PRECISION, uconstantesSimSEE.CF_DECIMALES);
  f.wr('hDescarga', hDescarga, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);
  f.wr('caQE', caQE, uconstantesSimSEE.CF_PRECISION, uconstantesSimSEE.CF_DECIMALES);
  f.wr('cbQE', cbQE, uconstantesSimSEE.CF_PRECISION, uconstantesSimSEE.CF_DECIMALES);
  f.wr('ren', ren, uconstantesSimSEE.CF_PRECISION, uconstantesSimSEE.CF_DECIMALES);
  f.wr('Pmax_Gen', Pmax_Gen, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);
  f.wr('Qmax_Turb', Qmax_Turb, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);
  f.wr('fDispo', fDispo, uconstantesSimSEE.CF_PRECISION, uconstantesSimSEE.CF_DECIMALES);
  f.wr('tRepHoras', tRepHoras, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALESPU);

  f.wr('filtracion_Ca', filtracion_Ca, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);
  f.wr('filtracion_Cb', filtracion_Cb, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);
  f.wr('QaMuySeco', QaMuySeco, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);

  f.wr('cotaMV0', cotaMV0, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);
  f.wr('cotaMV1', cotaMV1, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);
  f.wr('QMV1', QMV1, uconstantesSimSEE.CF_PRECISION, uconstantesSimSEE.CF_DECIMALES);

  f.wrReferencia('central_lagoDescarga', central_lagoDescarga);
  f.wr('centralesAguasArriba', centralesAguasArriba);

  f.wr('HayRestriccionEmaxPasoDeTiempo', HayRestriccionEmaxPasoDeTiempo);
  f.wr('EmaxPasoDeTiempo', EmaxPasoDeTiempo);
  f.wr('HayRestriccionQTmin', HayRestriccionQTmin);
  f.wr('QTmin', QTmin);

  f.wr('hObjetivo', hObjetivo);
  f.wr('cva_delta', delta_cva_ParaControlDeCota);
  f.wr('flg_controlCotaObjetivoInferior', flg_controlCotaObjetivoInferior);
  f.wr('flg_controlCotaObjetivoSuperior', flg_controlCotaObjetivoSuperior);

  f.wr('cv_USD_MWh_ValorizadoManual', cv_USD_Hm3_ValorizadoManual);

  f.wr('tomarCotaDeLaFuente', tomarCotaDeLaFuente);
  f.wrReferencia('fuenteCota', fuenteCota);
  f.wr('borneCota', borneCota);
end;

function TFichaHidroConEmbalse.InfoAd: string;
begin
  Result := 'PMáxGen= ' + FloatToStrF(Pmax_Gen, ffGeneral, 10, 1) +
    ' MW, ' + 'QMáxTurb= ' + FloatToStrF(Qmax_Turb, ffGeneral, 10, 1) +
    ' Hm^3/s, ' + 'ren= ' + FloatToStrF(ren, ffGeneral, 10, 2) +
    ' p.u., ' + 'fDisp= ' + FloatToStrF(fDispo, ffGeneral, 10, 2) +
    ' p.u., ' + 'tRep= ' + FloatToStrF(tRepHoras, ffGeneral, 10, 1) +
    'h, ' + 'hMín= ' + FloatToStrF(hmin, ffGeneral, 10, 2) +
    ' m, ' + 'hMáx= ' + FloatToStrF(hmax, ffGeneral, 10, 2) +
    ' m, ' + 'hDescarga= ' + FloatToStrF(hDescarga, ffGeneral, 10, 2) +
    'm, ' + 'vMáx= ' + FloatToStrF(Vmax, ffGeneral, 10, 1) + ' m^3';
end;

constructor TFichaHidroConEmbalse.Create_ReadFromText(f: TArchiTexto);
begin
  if f.Version < 13 then
  begin
    inherited Create_ReadFromText(f);
    f.IniciarLecturaRetrasada;
    f.rd('hmin', hmin);
    f.rd('hmax', hmax);
    f.rd('Vmax', Vmax);
    f.rd('Vhmed', Vhmed);
    f.rd('hDescarga', hDescarga);
    f.rd('caQE', caQE);
    f.rd('cbQE', cbQE);
    f.rd('ren', ren);
    f.rd('Pmax_Gen', Pmax_Gen);
    f.rd('Qmax_Turb', Qmax_Turb);
    f.rd('fDispo', fDispo);

    f.rd('filtracion_Ca', filtracion_Ca);
    f.rd('filtracion_Cb', filtracion_Cb);
    f.rd('QaMuySeco', QaMuySeco);

    f.rd('cotaMV0', cotaMV0);
    f.rd('cotaMV1', cotaMV1);
    f.rd('QMV1', QMV1);

    f.rdReferencia('central_lagoDescarga', TCosa(central_lagoDescarga), Self);
    f.rd('centralesAguasArriba', TCosa(centralesAguasArriba));

    f.rd('HayRestriccionEmaxPasoDeTiempo', HayRestriccionEmaxPasoDeTiempo);
    f.rd('EmaxPasoDeTiempo', EmaxPasoDeTiempo);
    f.rd('HayRestriccionQTmin', HayRestriccionQTmin);
    f.rd('QTmin', QTmin);

    f.rd('hObjetivo', hObjetivo);
    f.rd('cva_delta', delta_cva_ParaControlDeCota);
    f.rd('flg_controlCotaObjetivoInferior', flg_controlCotaObjetivoInferior);
    f.rd('flg_controlCotaObjetivoSuperior', flg_controlCotaObjetivoSuperior);
    f.rd('cv_USD_MWh_ValorizadoManual', cv_USD_Hm3_ValorizadoManual);
    f.EjecutarLectura;

    tomarCotaDeLaFuente := False;
    fuenteCota := nil;
    borneCota := '';
    Self.tRepHoras := 48;
  end
  else if f.Version < 14 then
  begin
    inherited Create_ReadFromText(f);
    f.IniciarLecturaRetrasada;
    f.rd('hmin', hmin);
    f.rd('hmax', hmax);
    f.rd('Vmax', Vmax);
    f.rd('Vhmed', Vhmed);
    f.rd('hDescarga', hDescarga);
    f.rd('caQE', caQE);
    f.rd('cbQE', cbQE);
    f.rd('ren', ren);
    f.rd('Pmax_Gen', Pmax_Gen);
    f.rd('Qmax_Turb', Qmax_Turb);
    f.rd('fDispo', fDispo);

    f.rd('filtracion_Ca', filtracion_Ca);
    f.rd('filtracion_Cb', filtracion_Cb);
    f.rd('QaMuySeco', QaMuySeco);

    f.rd('cotaMV0', cotaMV0);
    f.rd('cotaMV1', cotaMV1);
    f.rd('QMV1', QMV1);

    f.rdReferencia('central_lagoDescarga', TCosa(central_lagoDescarga), Self);
    f.rd('centralesAguasArriba', TCosa(centralesAguasArriba));

    f.rd('HayRestriccionEmaxPasoDeTiempo', HayRestriccionEmaxPasoDeTiempo);
    f.rd('EmaxPasoDeTiempo', EmaxPasoDeTiempo);
    f.rd('HayRestriccionQTmin', HayRestriccionQTmin);
    f.rd('QTmin', QTmin);

    f.rd('hObjetivo', hObjetivo);
    f.rd('cva_delta', delta_cva_ParaControlDeCota);
    f.rd('flg_controlCotaObjetivoInferior', flg_controlCotaObjetivoInferior);
    f.rd('flg_controlCotaObjetivoSuperior', flg_controlCotaObjetivoSuperior);
    f.rd('cv_USD_MWh_ValorizadoManual', cv_USD_Hm3_ValorizadoManual);
    f.rd('tomarCotaDeLaFuente', tomarCotaDeLaFuente);
    f.rdReferencia('fuenteCota', TCosa(fuenteCota), self);
    f.rd('borneCota', borneCota);
    f.EjecutarLectura;

    Self.tRepHoras := 48;
  end
  else
  begin
    inherited Create_ReadFromText(f);
    f.IniciarLecturaRetrasada;
    f.rd('hmin', hmin);
    f.rd('hmax', hmax);
    f.rd('Vmax', Vmax);
    f.rd('Vhmed', Vhmed);
    f.rd('hDescarga', hDescarga);
    f.rd('caQE', caQE);
    f.rd('cbQE', cbQE);
    f.rd('ren', ren);
    f.rd('Pmax_Gen', Pmax_Gen);
    f.rd('Qmax_Turb', Qmax_Turb);
    f.rd('fDispo', fDispo);
    f.rd('tRepHoras', tRepHoras);

    f.rd('filtracion_Ca', filtracion_Ca);
    f.rd('filtracion_Cb', filtracion_Cb);
    f.rd('QaMuySeco', QaMuySeco);

    f.rd('cotaMV0', cotaMV0);
    f.rd('cotaMV1', cotaMV1);
    f.rd('QMV1', QMV1);

    f.rdReferencia('central_lagoDescarga', TCosa(central_lagoDescarga), Self);
    f.rd('centralesAguasArriba', TCosa(centralesAguasArriba));

    f.rd('HayRestriccionEmaxPasoDeTiempo', HayRestriccionEmaxPasoDeTiempo);
    f.rd('EmaxPasoDeTiempo', EmaxPasoDeTiempo);
    f.rd('HayRestriccionQTmin', HayRestriccionQTmin);
    f.rd('QTmin', QTmin);

    f.rd('hObjetivo', hObjetivo);
    f.rd('cva_delta', delta_cva_ParaControlDeCota);
    f.rd('flg_controlCotaObjetivoInferior', flg_controlCotaObjetivoInferior);
    f.rd('flg_controlCotaObjetivoSuperior', flg_controlCotaObjetivoSuperior);
    f.rd('cv_USD_MWh_ValorizadoManual', cv_USD_Hm3_ValorizadoManual);
    f.rd('tomarCotaDeLaFuente', tomarCotaDeLaFuente);
    f.rdReferencia('fuenteCota', TCosa(fuenteCota), self);
    f.rd('borneCota', borneCota);
    f.EjecutarLectura;
  end;
end;

procedure TFichaHidroConEmbalse.Free;
begin
  inherited Free;
end;

procedure THidroConEmbalse_cambioFichaPD(Actor: TCosa);
begin
  (Actor as THidroConEmbalse).cambioFichaPD;
end;

procedure AlInicio;
begin
  registrarClaseDeCosa(THidroConEmbalse.ClassName, THidroConEmbalse);
  registrarClaseDeCosa(TFichaHidroConEmbalse.ClassName, TFichaHidroConEmbalse);
end;

procedure AlFinal;
begin
end;

end.
