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

			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 se actualiza en sim_Paso_fin
			VolumenAlmacenado_s: NReal; // variable auxiliar, el valor se pasa

			PmaxParaQmax: NReal; // Potencia 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;

  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;
	Qlimite, QEmaxEstabilidadNumerica: NReal;
  auxParaCalculos: NReal;

{$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




  if h_real > pa.cotaMV0 then // si estoy por encima del inicio del vertedero puedo verter
  begin
    // en base al volumen actual calcula el vertimiento posible
	  volMV0:= CotaToVolumen(pa.cotaMV0);

	  begin
      if h_real < pa.cotaMV1 then
      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;

  end
  else
  	QMaxVert:= 0.1;

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

  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;

	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
	  VTmin:= min(PA.QTmin * globs.SegundosDelPaso / 1.0E6, VolumenAlmacenado + VAportePropio - VPerdidas);
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 pA.HayRestriccionQTmin 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 pA.HayRestriccionQTmin 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);


  QErogado:= ( QErogado +  QErogado_IterAnterior )/2.0;


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


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:= 0;
	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 pA.HayRestriccionQTmin 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 pa.HayRestriccionQTmin and (ires = self.ires + 2) then
    begin
      nombre:= self.nombre + '_res-QTMin';
      result:= true;
    end
    else if pa.HayRestriccionEmaxPasoDeTiempo and pa.HayRestriccionQTmin 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
  VolumenAlmacenado:= VolumenAlmacenado_s;
  h_actual:= VolumenToCota(VolumenAlmacenado);
end;

function THidroConEmbalse.ivarVertimientosMiosYAguasAbajo: TDAofNInt;
var
  nCentrales: Integer;
  iter: TGeneradorHidraulico;
  res: TDAofNInt;
begin
  nCentrales:= 1; //yo
  iter:= self;
  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;
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.


