unit uactoresflucar;

interface

uses
  Classes,
  SysUtils,
  xmatdefs,
  usistema,
  MatCPX,
  algebrac,
  intlist,
  uauxiliares,
  math,
  ucpxresolvecuacs;
//  , umatrizadmitancias;

type

  TSalaFlucar = class;

  { TActorFlucar }

  TActorFlucar = class
  public
    sala: TSalaFlucar;

    constructor Create(sala: TSalaFlucar); virtual;
    constructor LoadFromText(sala: TSalaFlucar; var f: textfile); virtual;
    procedure resolver_referencias; virtual;

    // carga el actor en el sistema de ecuaciones
    procedure cargue; virtual;

    // retorna TRUE si el actor está conectado al sistema
    function conectada: boolean; virtual;
    function nombre: string; virtual;

    function MatrizAdmitancias: TSistema;
    function SBASE: NReal;

  end;


  TActorDato = class(TActorFlucar)
    //  información adicional -- no son componentes
  end;

  { TBarra }

  TBarra = class(TActorFlucar)
  public
    TIPO: integer;

    I: longint;   // Bus number (1 through 999997).

    IMP_CERO: boolean;
    BarraExtImpCero: longint;
    PrincipalLinImpCero: boolean;

    // variables auxiliares para la resolución del sistema.
    PL, QL: double;
    QINIT, QMIN, QMAX: double;

  private //lo pongo privado para detectar quíen lo usa
    NID_: longint;
    // Columna-1 de la tensión en la representación matricial del problema Y * V = Ig

  public

    constructor Create(sala: TSalaFlucar); override;

    procedure borrar_dem_gen;
    procedure cargue; override;
    function jcol: integer; // (NID_+1)
    procedure resolver_referencias; override;

    // retorna FALSE si la barra es del tipo 4 (aislada)
    // retorna TRUE si la barra está conectada
    function conectada: boolean; override;
    function nombre: string; override;
  end;



  { TActorMonoBarra }

  TActorMonoBarra = class(TActorFlucar)
    I: longint; // Bus Number or Extended bus name enclosed  in single quotes.
    Barra_I: TBarra;
    constructor Create(sala: TSalaFlucar); override;
    procedure resolver_referencias; override;
    function conectada: boolean; override;
    function nombre: string; override;
  end;


  { TActorBiBarra }

  TActorBiBarra = class(TActorFlucar)
    Barra_I, Barra_J: TBarra;
    I: longint;    // Id barra 1
    J: longint;    // Id barra 2
    IMP_Zero: boolean;

    constructor Create(sala: TSalaFlucar); override;
    procedure resolver_referencias; override;
    function conectada: boolean; override;
  end;

  { TActorTriBarra }

  TActorTriBarra = class(TActorFlucar)
    Barra_I, Barra_J, Barra_K: TBarra;
    I: longint;    // Id barra 1
    J: longint;    // Id barra 2
    K: longint;    // Id barra 3
    constructor Create(sala: TSalaFlucar); override;
    procedure resolver_referencias; override;
    function conectada: boolean; override;
  end;



  { TSalaFlucar }

  TSalaFlucar = class
    actores: TList; // todos los actores

    TodasLasBarras: TList; // todos las barras del sistemas estén activas o no


    Barras: TList; // barras que participan de la solución del FLujo
    Cargas: TList;
    Generadores: TList;
    Lineas: TList;
    LineasImpCero: TList;
    TrafosAdjust: TList;
    areas: TList;
    TerminalesDC: TList;
    ShuntsFijos: TList;
    Shunts: TList;
    ICTRATables: TList;
    TerminalesDCMult: TList;
    LineasSeccion: TList;
    zonas: TList;
    transfareas: TList;
    owners: TList;
    Facts: TList;
    VSC: TList;

    caso: TList;

    //reg:taps;
    nodos_reguladores: TIntList;
    nodos_regulados: TIntList;
    trafos_reguladores : TList;

    Impedancias: TList;
    Trafos: TList;
    //Reguladores: TList;
    Cuadripolos: TList;
    Tolerancia: NReal;
    MAXNITs: integer;

    SBASE: NReal; // Base del sistema en MVA.
    TapsVariables: boolean;
    MY: TMatrizDeAdmitancias;

    nNodos: integer;
    IiConj: TVectComplex;
    problemaCPX: TPRoblemaCPX;

    constructor Create;
    procedure Free;

    procedure liberar_lstActores(var Lista: TList);

    procedure liberar(var Lista: TIntList);
    procedure ordenar(var Lista: TIntList);
    procedure resolver_referencias;

    // arma el sistema de ecuaciones e inicializa variables auxiliares del cálculo
    procedure cargue;


    function I_to_ListaBarras(Sender: TActorFlucar; I: longint; ListaBarras: TList
      ): pointer;
    function I_to_numeroBarra(Sender: TActorFlucar; I: longint): integer;
    function I_to_N_Barras(Sender: TActorFlucar; I: longint): integer;

    function Find_Generador(barra: longint; codigo: string): TActorMonoBarra;
    function Find_Demanda(barra: longint; codigo: string): TActorMonoBarra;
    function Find_Slack: TBarra;

    procedure LeerRaw(archi: string);

    procedure leer_caso(var f: textfile);
    procedure leer_barras_raw(var f: textfile);
    procedure leer_cargas_raw(var f: textfile);
    procedure leer_fixed_shunt_raw(var f: textfile);
    procedure leer_generadores_raw(var f: textfile);
    procedure leer_lineas_raw(var f: textfile);
    procedure leer_trafos_adjust_raw(var f: textfile);
    procedure leer_areas_raw(var f: textfile);
    procedure leer_termDC2vias(var f: textfile);
    procedure leer_switched_shunts_raw(var f: textfile);
    procedure leer_VSC_raw(var f: textfile);
    procedure leer_TransformerImpedanceCorrectionTables_raw(var f: textfile);
    procedure leer_MultiTerminal_DCLine_raw(var f: textfile);
    procedure leer_MultiSectionLineGrouping_raw(var f: textfile);
    procedure leer_Zone_raw(var f: textfile);
    procedure leer_InterAreaTransfer_raw(var f: textfile);
    procedure leer_Owner_raw(var f: textfile);
    procedure leer_facts_raw(var f: textfile);

    procedure cargarNodoTipo1(var libres, nolibres: integer; Nudos,
      iEcuacion: integer);
    procedure cargarNodoTipo2(var libres, nolibres, cantNodosGenConTap,
      cantNodosGenSinTap: integer; Nudos, iEcuacion: integer);
    procedure cargarNodoTipo3(var libres, nolibres: integer; Nudos,
      iEcuacion: integer);
    function BarraConectada( barratemp: TBarra; var NConexiones: integer):
      boolean;
  end;


implementation

uses
  urawdata;

constructor TActorFlucar.Create(sala: TSalaFlucar);
begin
  inherited Create;
  self.sala := sala;
end;

constructor TActorFlucar.LoadFromText(sala: TSalaFlucar; var f: textfile);
begin
  Create(sala);
end;

procedure TActorFlucar.resolver_referencias;
begin
  //nada
end;


function TActorFlucar.conectada: boolean;
begin
  Result := False;
end;

function TActorFlucar.nombre: string;
begin
  Result := 'ANONIMO';
end;

function TActorFlucar.MatrizAdmitancias: TSistema;
begin
  Result := sala.MY;
end;

function TActorFlucar.SBASE: NReal;
begin
  Result := sala.SBASE;
end;


procedure TActorFlucar.cargue;
begin
  // nada
end;

constructor TActorMonoBarra.Create(sala: TSalaFlucar);
begin
  inherited Create(sala);
end;

procedure TActorMonoBarra.resolver_referencias;

begin
  Barra_I := sala.I_to_ListaBarras(self, I, sala.TodasLasBarras);

  if not Barra_I.IMP_CERO then
    Barra_I := sala.I_to_ListaBarras(self, I, sala.TodasLasBarras)
  else
  begin
    self.I := self.Barra_I.BarraExtImpCero;
    Barra_I := sala.I_to_ListaBarras(self, self.Barra_I.BarraExtImpCero, sala.TodasLasBarras);
  end;

end;


function TActorMonoBarra.conectada: boolean;
begin
  Result := Barra_I.conectada;
end;

function TActorMonoBarra.nombre: string;
begin
  Result := IntToStr(I);
end;

constructor TActorBiBarra.Create(sala: TSalaFlucar);
begin
  inherited Create(sala);
end;

procedure TActorBiBarra.resolver_referencias;

begin
//  Se revisa si alguna de las barras es de impedancia cero. Si una de las
//  barras es de impedancia cero, se tiene que tomar como extremo de la linea la
//  barra a la cual esta conectada esa barra.
//  Se debe hacer tanto para la barra I como la J.

//  1- Buscamos las barras entre todas las barras.
  Barra_I := sala.I_to_ListaBarras(self, I, sala.TodasLasBarras);
  Barra_J := sala.I_to_ListaBarras(self, J, sala.TodasLasBarras);
//  2- Chequeamos si la barra I es de impedancia cero y si lo es cargamos la
//     barra asociada.
  if self.Barra_I.IMP_CERO then
  begin
    self.I := self.Barra_I.BarraExtImpCero;
    self.Barra_I := sala.I_to_ListaBarras( self, self.Barra_I.BarraExtImpCero,
                                           sala.TodasLasBarras);
  end;
//  3- Idem para la barra J
  if self.Barra_J.IMP_CERO then
  begin
    self.J := self.Barra_J.BarraExtImpCero;
    self.Barra_J := sala.I_to_ListaBarras( self, self.Barra_J.BarraExtImpCero,
                                           sala.TodasLasBarras);
  end;
end;

function TActorBiBarra.conectada: boolean;
begin
  Result := Barra_I.conectada and Barra_J.conectada;
end;

constructor TActorTriBarra.Create(sala: TSalaFlucar);
begin
  inherited Create(sala);
end;

procedure TActorTriBarra.resolver_referencias;
var
  ext: longint;
begin

  Barra_I := sala.I_to_ListaBarras(self, I, sala.TodasLasBarras);
  Barra_J := sala.I_to_ListaBarras(self, J, sala.TodasLasBarras);

  if K<>0 then
    Barra_K := sala.I_to_ListaBarras(self, K, sala.TodasLasBarras);


  ext := Barra_I.BarraExtImpCero;
  if self.Barra_I.IMP_CERO then
  begin
    self.I := ext;
    self.Barra_I := sala.I_to_ListaBarras( self, self.Barra_I.BarraExtImpCero,
                                           sala.TodasLasBarras);
  end;

  ext := Barra_J.BarraExtImpCero;
  if self.Barra_J.IMP_CERO then
  begin
    self.J := ext;
    self.Barra_J := sala.I_to_ListaBarras( self, self.Barra_J.BarraExtImpCero,
                                           sala.TodasLasBarras);
  end;

  if Barra_K <> nil then
  begin
    ext := Barra_K.BarraExtImpCero;
    if self.Barra_K.IMP_CERO then
    begin
      self.K := ext;
      self.Barra_K := sala.I_to_ListaBarras( self, self.Barra_K.BarraExtImpCero,
                                             sala.TodasLasBarras);
    end;
  end;

end;


function TActorTriBarra.conectada: boolean;
begin
  if Barra_K = nil then
    Result := Barra_I.conectada and Barra_J.conectada
  else
    Result := (Barra_I.conectada and Barra_J.conectada) or
              (Barra_J.conectada and Barra_K.conectada) or
              (Barra_I.conectada and Barra_K.conectada);
end;


procedure TBarra.cargue;
begin
  PL := 0;
  QL := 0;
  QINIT := 0;
  QMAX := 0;
  QMIN := 0;
  IMP_CERO := False;
  BarraExtImpCero := -1;
  PrincipalLinImpCero := False;

end;

constructor TBarra.Create(sala: TSalaFlucar);
begin
  inherited Create(sala);
end;

procedure TBarra.borrar_dem_gen;
begin
  PL := 0;
  QL := 0;
end;

function TBarra.jcol: integer; // (NID_+1)
begin
  Result := NID_ + 1;
end;

procedure TBarra.resolver_referencias;
begin
  inherited resolver_referencias;
end;


function TBarra.conectada: boolean;

begin
  Result := (TIPO <> 4) and not (IMP_CERO);
end;


function TBarra.nombre: string;
begin
  Result := IntToStr(I);
end;

// hace Free de los elementos y luego Free de la lista
procedure TSalaFlucar.liberar_lstActores(var Lista: TList);
var
  k: integer;
begin
  for k := 0 to lista.Count - 1 do
    if lista[k] <> nil then
      TActorFlucar(lista[k]).Free;
  lista.Free;
  lista := nil;
end;

procedure TSalaFlucar.liberar(var Lista: TIntList);

begin
  Lista.Destroy;
end;


procedure TSalaFlucar.resolver_referencias;
var
  k: integer;
  a: TActorFlucar;

begin
  for k := 0 to actores.Count - 1 do
  begin
    a := actores[k];
    a.resolver_referencias;
  end;
end;


procedure TSalaFlucar.cargue;
var
  Barra: TBarra;
  k: integer;
  indice: integer;
  Barra_CONT : TBarra;
  ata: TRaw_TransformerAdjust;
  Ncontrolado: LongInt;

begin
//  resolver_referencias;  // GFlieller@2019-11-22:
                         //       Viene de resolver referencias, no parece que
                         //       sea necesario hacerlo de nuevo.

//  Aca se cargan las barras al sistema


  barras.Clear; // limpio las lista de las barras que participan
  for k := 0 to TodasLasBarras.Count - 1 do
  begin
    barra := TodasLasBarras[k];
    if (barra.tipo <> 4) and not (barra.IMP_CERO) then
    begin
      barra.NID_ := barras.Count;
      barras.add(barra);
    end
    else
    begin
      barra.NID_ := -1;

    end;
  end;


  //Resuelvo referencias para los nodos reguladores de los trafos
  if TapsVariables then
    for indice := 0 to self.trafosAdjust.Count - 1 do
    begin
      ata := self.trafosAdjust[indice];
      ata.resolver_referencias;
      if (ata.CONT1<>0) then
      begin
        Ncontrolado  := ata.CONT1;
        Barra_CONT := self.I_to_ListaBarras(nil, Ncontrolado, TodasLasBarras);
        if (Barra_CONT.IMP_CERO) then
          ata.CONT1:=Barra_CONT.BarraExtImpCero;
      end;
      if (ata.CONT2<>'')and(StrToInt(ata.CONT2)<>0) then
      begin
        Ncontrolado  := StrToInt(ata.CONT2);
        Barra_CONT := self.I_to_ListaBarras(nil, Ncontrolado, TodasLasBarras);
        if (Barra_CONT.IMP_CERO) then
          ata.CONT2:=IntToStr(Barra_CONT.BarraExtImpCero);
      end;
      if (ata.CONT3<>'')and(StrToInt(ata.CONT3)<>0) then
      begin
        Ncontrolado  := StrToInt(ata.CONT3);
        Barra_CONT := self.I_to_ListaBarras(nil, Ncontrolado, TodasLasBarras);
        if (Barra_CONT.IMP_CERO) then
          ata.CONT3:=IntToStr(Barra_CONT.BarraExtImpCero);
      end;
    end;
   //////////////////////////////////////////////////

  nNodos := barras.Count;
  if MY <> nil then
    MY.Free_destruirsistema;
  MY := TSistema.Create_crearsistema(barras.Count);

  //  GFlieller@2019-11-22: Lo ultimo que se hace en sala.cargue

  for k := 0 to barras.Count - 1 do
  begin
    barra := barras[k];
    barra.cargue;
  end;
  if IiConj = nil then
    IiConj := TVectComplex.Create_Init(nNodos);

end;



procedure TSalaFlucar.ordenar(var Lista: TIntList);
begin

end;



constructor TSalaFlucar.Create;
begin
  inherited Create;

  //  Se declaran todas las listas que se van a usar. Actores
  actores := TList.Create;

  //  Todas las barras contiene todas las barras del .raw. Mantiene las barras
  //  que estan desconectadas y redundantes.
  TodasLasBarras := TList.Create;
  //  En barras quedan solo las barras que estan conectadas. Ademas las barras
  //  que estan conectadas por lineas de impedancia cero se unifiacan en una.
  Barras := TList.Create;

  Impedancias := TList.Create;
  Cuadripolos := TList.Create;
  Generadores := TList.Create;
  Cargas := TList.Create;
  Trafos := TList.Create;
  Lineas := TList.Create;
  LineasImpCero := TList.Create;
  Shunts := TList.Create;
  ShuntsFijos := TList.Create;
  TrafosAdjust := TList.Create;
  TerminalesDC := TList.Create;
  areas := TList.Create;
  ICTRATables := TList.Create;
  TerminalesDCMult := TList.Create;
  LineasSeccion := TList.Create;
  zonas := TList.Create;
  transfareas := TList.Create;
  owners := TList.Create;
  Facts := TList.Create;
  VSC := TList.Create;
  caso:=TList.Create;

  nodos_reguladores := TIntList.CreateEx();
  nodos_regulados := TIntList.CreateEx();

  trafos_reguladores:= Tlist.Create;
  MY := nil;
  ProblemaCPX := nil;
end;

procedure TSalaFlucar.Free;
begin
  if MY <> nil then
    MY.Free_destruirsistema;
  if ProblemaCPX <> nil then
    ProblemaCPX.Free;
  IiConj.Free;

  liberar_lstActores(Actores);

  TodasLasBarras.Free;
  Barras.Free;
  Impedancias.Free;
  Cuadripolos.Free;
  Trafos.Free;
  Generadores.Free;
  Cargas.Free;
  Lineas.Free;
  LineasImpCero.Free;
  Shunts.Free;
  ShuntsFijos.Free;

  liberar(nodos_reguladores);
  liberar(nodos_regulados);
  inherited Free;
end;

function TSalaFlucar.I_to_ListaBarras(Sender: TActorFlucar; I: longint; ListaBarras:TList): pointer;
var
  k: integer;
  barra: TRaw_Bus;
  buscando: boolean;
begin

  buscando := True;
  k := 0;
  while buscando and (k < ListaBarras.Count) do
  begin
    barra := ListaBarras[k];
    if barra.I = I then
      buscando := False
    else
      Inc(k);
  end;
  if buscando then
  begin
    if I <> 0 then
    begin
      if Sender <> nil then
        raise Exception.Create('I_To_ListaBarras; Actor:' +
          Sender.ClassName + '; Nombre: ' + Sender.nombre + '; I:' +
          IntToStr(I) + ' (Barra no encontrada) ')
      else
        raise Exception.Create('I_To_ListaBarras; Actor: NIL; I:' +
          IntToStr(I) + ' (Barra no encontrada) ');
    end;
    Result := nil;
  end
  else
    Result := barra;
end;

function TSalaFlucar.I_to_numeroBarra(Sender: TActorFlucar; I: longint): integer;
var
  k: integer;
  barra: TRaw_Bus;
  buscando: boolean;
begin

  buscando := True;
  k := 0;
  while buscando and (k < TodasLasBarras.Count) do
  begin
    barra := TodasLasBarras[k];
    if barra.I = I then
      buscando := False
    else
      Inc(k);
  end;
  if buscando then
  begin
    if I <> 0 then
    begin
      if Sender <> nil then
        raise Exception.Create('I_To_TodasLasBarras; Actor:' +
          Sender.ClassName + '; Nombre: ' + Sender.nombre + '; I:' +
          IntToStr(I) + ' (Barra no encontrada) ')
      else
        raise Exception.Create('I_To_TodasLasBarras; Actor: NIL; I:' +
          IntToStr(I) + ' (Barra no encontrada) ');
    end;
    Result := -1;
  end
  else
    Result := k + 1;
end;

function TSalaFlucar.I_to_N_Barras(Sender: TActorFlucar; I: longint): integer;
var
  k: integer;
  barra: TRaw_Bus;
  buscando: boolean;
begin
  buscando := True;
  k := 0;

  while buscando and (k < Barras.Count) do
  begin
    barra := Barras[k];
    if (barra.I = I) or (barra.BarraExtImpCero = I) then
      buscando := False
    else
      Inc(k);
  end;
  if buscando then
  begin
    if I <> 0 then
    begin
      if Sender <> nil then
        raise Exception.Create('I_to_N_Barras; Actor:' + Sender.ClassName +
          '; Nombre: ' + Sender.nombre + '; I:' + IntToStr(I) +
          ' (Barra no encontrada) ')
      else
        raise Exception.Create('I_to_N_Barras; Actor: NIL; I:' +
          IntToStr(I) + ' (Barra no encontrada) ');
    end;
    Result := -1;
  end
  else
    Result := k + 1;
end;

function TSalaFlucar.Find_Generador(barra: longint; codigo: string): TActorMonoBarra;
var
  a: TRaw_Generator;
  buscando: boolean;
  k: integer;
  barraaux: TRaw_Bus;
begin
  buscando := True;
  k := 0;

  barraaux := I_to_ListaBarras(nil, barra, Barras);
  if barraaux.IMP_CERO then
    barra := barraaux.BarraExtImpCero;

  while (buscando and (k < self.Generadores.Count)) do
  begin
    a := generadores[k];
    if (a.I = barra) and (a.ID = codigo) then
      buscando := False
    else
      Inc(k);
  end;
  if buscando then
    Result := nil
  else
    Result := a;
end;

function TSalaFlucar.Find_Slack: TBarra;
var
  a: TRaw_Bus;
  buscando: boolean;
  k: integer;

begin
  buscando := True;
  k := 0;

  while (buscando and (k < self.TodasLasBarras.Count)) do
  begin
    a := TodasLasBarras[k];

    if (a.IDE = 3) then
      buscando := False
    else
      Inc(k);
  end;
  if buscando then
    Result := nil
  else
    Result := a;
end;

procedure  TSalaFlucar.LeerRaw(archi: string);

var

  k: integer;
  f: textfile;
  r: string;

begin
  uauxiliares.setSeparadoresGlobales;

  //  GF@ 2019-11-18 lo siguiente no se si es necesario, se supone que archi ya
  //  es el nombre del archivo con extension .raw incluida
  k := pos('.', archi);
  NOmbreArch := copy(archi, 1, k - 1);
  extensionent := '.raw';
  //extensionsal:='.sal';
  NombreArchent := NombreArch + extensionent;
  //NombreArchsal:=NombreArch+extensionsal;

  Assign(f, NombreArchent);
        {$I-}
  Reset(f);
        {$I+}
  if ioresult <> 0 then
  begin
    // si falló, intento buscar el archivo en la ruta local.
    r := extractFileName(NombreArchEnt);
    Assign(f, r);
          {$I-}
    Reset(f);
          {$I+}
    if ioresult <> 0 then
      raise Exception.Create(' Error abriendo archivo ' + NombreArchent);
  end;

  // 1 Se lee el descriptor del caso
  leer_caso(f);

  // 2 Se leen las barras
  leer_barras_raw(f);

  // 3 Se leen las cargas
  leer_cargas_raw(f);

  // 4 si es la version 32 leo los Fixed Shunts
  if RAW_VER >= 32 then
    leer_fixed_shunt_raw(f);

  // 5 Se leen los generadores
  leer_generadores_raw(f);

  // 6 Se leen las lineas
  leer_lineas_raw(f);

  // 7 Se leen los transformadores
  leer_trafos_adjust_raw(f);

  // 8 Se leen las areas
  leer_areas_raw(f);

  // 9 Se leen las terminales DC de 2 vias
  leer_termDC2vias(f);

  // 10 Se leen los VSC. En la 26 se leen los switched shunts
  if RAW_VER < 32 then
    leer_switched_shunts_raw(f)
  else
    leer_VSC_raw(f);

  //11 Se leen las tablas de correccion de las impedancias de los TRAFOS
  leer_TransformerImpedanceCorrectionTables_raw(f);

  //12 Se leen las terminales DC de multiples vias
  leer_MultiTerminal_DCLine_raw(f);

  //13 Se leen las lineas agrupadas por seccion
  leer_MultiSectionLineGrouping_raw(f);

  //14 Se leen las zonas
  leer_Zone_raw(f);

  //15 Se leen los datos de transferencia entre areas
  leer_InterAreaTransfer_raw(f);

  //16 Se leen los owners
  leer_Owner_raw(f);

  //17 Se leen los datos de control de los FACTS
  leer_facts_raw(f);

  //18 Se leen los switched shunts, para la version 32 en adelante los shunts
  //   van al final del raw
  if RAW_VER >= 32 then
    leer_switched_shunts_raw(f);

  //writeln;   writeln('ESTO EL FIN DE LECTURA DE FLUJOS RAW');
  Close(f);
  resolver_referencias;  // GFlieller@2019-11-22: Me parece que el lugar
                         //                       correcto es aca

  uauxiliares.setSeparadoresLocales;
end;

procedure TSalaFlucar.leer_caso( var f: textfile);
var
  caso: TRaw_CaseIdentification;
begin

  caso := TRaw_CaseIdentification.LoadFromtext(self, f);
  self.caso.Add(caso);

  writeln;
  writeln(caso.ic);
  writeln(caso.sbase);
  writeln(caso.ds1);
  writeln(caso.ds2);
  writeln;

//  caso.free;
end;

procedure TSalaFlucar.leer_barras_raw( var f: textfile);
var
  barra: TRaw_Bus;
begin
  barra := TRaw_bus.loadfromtext(self, f);

  while barra.I <> 0 do
  begin
    //Inc(NBARRAS);
    //writeln(barra.Name);
    case barra.IDE of
      // Load Bus
      1: Barra.TIPO := 2;
      // Generation or voltage regulator or fixed MVAR
      2: Barra.TIPO := 3;
      // Swing Bus
      3: Barra.TIPO := 1;
      // Isolated Bus
      4: Barra.TIPO := 4
      else
        raise Exception.Create('leer_barras_raw; tipo IDE desconocido:' + IntToStr(
          barra.IDE));
    end;
    self.TodasLasBarras.Add(barra);
    self.actores.add(barra);
    barra := TRaw_bus.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las BARRAS ', self.barras.Count,
                ' barras completas ', self.TodasLasBarras.Count);
end;

procedure TSalaFlucar.leer_cargas_raw( var f: textfile);
var
  carga: TRaw_Load;
begin
  carga := TRaw_Load.loadfromtext(self, f);
  while carga.I <> 0 do
  begin
    if carga.STATUS<>0 then
    begin
      //writeln(CARGA.I, ' ' + #9, carga.PL: 1: 2, ' ' + #9, carga.QL: 1: 2);
      carga.resolver_referencias;
      self.Cargas.add(carga);
      self.actores.add(carga);
    end;
    carga := TRaw_Load.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las CARGAS: ', self.cargas.Count);

end;

procedure TSalaFlucar.leer_fixed_shunt_raw( var f: textfile);
var
  Fixedshunt: TRaw_FixedShunt;
begin

  Fixedshunt := TRaw_FixedShunt.loadfromtext(self, f);
  while Fixedshunt.I <> 0 do
  begin
    if Fixedshunt.STATUS<>0 then
    begin
      //writeln(Fixedshunt.I);
      Fixedshunt.resolver_referencias;
      self.ShuntsFijos.add(Fixedshunt);
      self.actores.add(FixedShunt);
    end;
    Fixedshunt := TRaw_FixedShunt.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las FIXED SHUNTS: ', self.shuntsfijos.Count);

end;

procedure TSalaFlucar.leer_generadores_raw( var f: textfile);
var
  generador: TRaw_Generator;
begin

  generador := TRaw_Generator.loadfromtext(self, f);
  while generador.I <> 0 do
  begin
    if generador.STAT<>0 then
    begin
      //writeln('Generador: ', generador.I);
      generador.resolver_referencias;
      self.Generadores.add(generador);
      self.actores.add(generador);
    end;
    generador := TRaw_Generator.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las GENERADORES: ', self.Generadores.Count);

end;

procedure TSalaFlucar.leer_lineas_raw(var f: textfile);
var
  linea: TRaw_Branch;
  modulo: NReal;


begin
  linea := TRaw_Branch.loadfromtext(self, f);
  while linea.I <> 0 do
  begin
    if linea.ST = 1 then
    //  6.1 Si la linea esta en servicio
    begin
      //writeln('Linea: ', linea.I, ' ' + #9, linea.J);
      modulo := mod1(numc(linea.RR, linea.X)^);
      if modulo > 1.01E-4 then
      //  6.1.1 Si no es una linea de impedancia cero
      begin
        linea.resolver_referencias;
        linea.IMP_Zero := False;
        self.lineas.add(linea);
        self.actores.add(linea);
      end
      else
      //  Si es una linea de impedancia 0
      begin
        linea.resolver_referencias;
        //linea.Barra_J.IMP_CERO:=True;
        linea.IMP_Zero := True;
        if not (linea.Barra_I.IMP_CERO) and (linea.Barra_J.IMP_CERO) then
        begin
          linea.Barra_I.PrincipalLinImpCero := True;
          linea.Barra_J.BarraExtImpCero := linea.Barra_I.I;
          linea.Barra_J.IMP_CERO := True;
          //linea.Barra_J:=linea.Barra_I;
        end;
        if (linea.Barra_I.IMP_CERO) and not (linea.Barra_J.IMP_CERO) then
        begin
          linea.Barra_J.PrincipalLinImpCero := True;
          linea.Barra_I.BarraExtImpCero := linea.Barra_J.I;
          linea.Barra_I.IMP_CERO := True;
          //linea.Barra_I:=linea.Barra_J;
        end;
        if not (linea.Barra_I.IMP_CERO) and not (linea.Barra_J.IMP_CERO) then
        begin
          if (linea.Barra_I=linea.Barra_J) then
          begin
            linea := TRaw_Branch.loadfromtext(self, f);
            //writeln('Linea de impedancia Cero entre la misma Barra Principal');
            Continue;  //Hay que resolver cuando la linea tiene impedancia cero y esta conectada a la misma barra
          end;
          if linea.Barra_I.PrincipalLinImpCero then
          begin
            linea.Barra_J.BarraExtImpCero := linea.Barra_I.I;
            linea.Barra_J.IMP_CERO := True;
            //linea.Barra_J:=linea.Barra_I;
          end
          else
          if linea.Barra_J.PrincipalLinImpCero then
          begin
            linea.Barra_I.BarraExtImpCero := linea.Barra_J.I;
            linea.Barra_I.IMP_CERO := True;
            //linea.Barra_I:=linea.Barra_J;
          end
          else
          if TRaw_Bus(linea.Barra_J).IDE=3 then
          begin
            linea.Barra_J.PrincipalLinImpCero := True;
            linea.Barra_I.BarraExtImpCero := linea.Barra_J.I;
            linea.Barra_I.IMP_CERO := True;
            //linea.Barra_I:=linea.Barra_J;
          end
          else
          begin
            linea.Barra_I.PrincipalLinImpCero := True;
            linea.Barra_J.BarraExtImpCero := linea.Barra_I.I;
            linea.Barra_J.IMP_CERO := True;
            //linea.Barra_J:=linea.Barra_I;
          end;
        end;
        if linea.Barra_I.IMP_CERO and linea.Barra_J.IMP_CERO then
        begin
          linea.Barra_I.PrincipalLinImpCero := True;
          linea.Barra_J.BarraExtImpCero := linea.Barra_I.BarraExtImpCero;
          linea.Barra_J.IMP_CERO := True;
          //linea.Barra_J:=linea.Barra_I;
        end;
        linea.resolver_referencias;
        self.LineasImpCero.add(linea);
        self.actores.add(linea);
      end;
    end;
    linea := TRaw_Branch.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las LINEAS: '+ IntToStr( self.Lineas.Count) );

end;

procedure TSalaFlucar.leer_trafos_adjust_raw( var f: textfile);
var
  trafoAdjust: TRaw_TransformerAdjust;
begin

  trafoAdjust := TRaw_TransformerAdjust.loadfromtext(self, f);
  while trafoAdjust.I <> 0 do
  begin
 {   if trafoAdjust.STAT <> 0 then  }
      if trafoAdjust.STAT = 1 then
      begin
        // GFlieller@2019-08-01: Agrego el trafo de 3 arrollamientos
        trafoAdjust.resolver_referencias;
        self.trafosAdjust.add(trafoAdjust);
        self.actores.add(trafoAdjust);
      end;
{      else
        raise Exception.Create('FALTA IMPLEMENTAR LA LECTURA DE TRANSFORMADORES EN STAT>1. I='
              + inttostr(trafoAdjust.I) + '; J=' + inttostr(trafoAdjust.J)
              + '; K=' + inttostr(trafoAdjust.K));       }
    trafoAdjust := TRaw_TransformerAdjust.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las TRAFOS: ', self.trafosadjust.Count);
  writeln;

end;

procedure TSalaFlucar.leer_areas_raw( var f: textfile);
var
  area: TRaw_AreaInterchange;
begin

  area := TRaw_AreaInterchange.loadfromtext(self, f);
  while area.I <> 0 do
  begin
    //writeln('Area: ', area.I, ' ' + #9, area.ARNAME);
    self.areas.add(area);
    self.actores.Add(area);
    area := TRaw_AreaInterchange.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las AREAS');

end;

procedure TSalaFlucar.leer_termDC2vias( var f: textfile);
var
  termDC2vias: TRaw_TwoTerminal_DCLine;
begin

  termDC2vias := TRaw_TwoTerminal_DCLine.loadfromtext(self, f);
  while termDC2vias.IDC_LineNumber <> 0 do
  begin
    if termDC2vias.MDC<>0 then
    begin
      //writeln('Terminal DC: ', termDC2vias.IDC_LineNumber);
      termDC2vias.resolver_referencias;
      self.TerminalesDC.add(termDC2vias);
      self.actores.add(termDC2vias);
    end;
    termDC2vias := TRaw_TwoTerminal_DCLine.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de los terminales DC de 2 vias: ', self.TerminalesDC.Count);

end;

procedure TSalaFlucar.leer_switched_shunts_raw( var f: textfile);
var
  shunt: TRaw_SwitchedShunt;
begin

  shunt := TRaw_SwitchedShunt.loadfromtext(self, f);
  while shunt.I <> 0 do
  begin
    //writeln('Shunt: ', shunt.I);
    shunt.resolver_referencias;
    self.Shunts.add(shunt);
    self.actores.add(shunt);
    shunt := TRaw_SwitchedShunt.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las SHUNTS: ', self.Shunts.Count);

end;

procedure TSalaFlucar.leer_VSC_raw( var f: textfile);
var
  vsc: TRaw_VoltageSourceConverter_DCLine;
begin

  vsc := TRaw_VoltageSourceConverter_DCLine.loadfromtext(self, f);
  while vsc.I <> 0 do
  begin
    if vsc.MDC<>0 then
    begin
      //writeln('Voltage Source Converter: ', vsc.I);
      //vsc.resolver_referencias;
      self.VSC.add(vsc);
      self.actores.add(vsc);
    end;
    vsc := TRaw_VoltageSourceConverter_DCLine.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las VSC: ', self.VSC.Count);

end;

procedure TSalaFlucar.leer_TransformerImpedanceCorrectionTables_raw(
                                                         var f: textfile);
var
  ICTable: TRaw_TransformerImpedanceCorrectionTables;
begin

  ICTable := TRaw_TransformerImpedanceCorrectionTables.loadfromtext(self, f);
  while ICTable.I <> 0 do
  begin
    //writeln('ICTable: ', ICTable.I);
    self.ICTRATables.add(ICTable);
    self.actores.add(ICTable);
    ICTable := TRaw_TransformerImpedanceCorrectionTables.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las tablas de correccion de las impedancias de los TRAFOS');

end;

procedure TSalaFlucar.leer_MultiTerminal_DCLine_raw( var f: textfile);
var
  MultiDC: TRaw_MultiTerminal_DCLine;
begin

  MultiDC := TRaw_MultiTerminal_DCLine.loadfromtext(self, f);
  while MultiDC.I <> 0 do
  begin
    if MultiDC.MDC<>0 then
    begin
      //writeln('Terminal MultiDC: ', MultiDC.I);
      self.TerminalesDCMult.add(MultiDC);
      self.actores.Add(MultiDC);
    end;
    MultiDC := TRaw_MultiTerminal_DCLine.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las terminales DC de multiples vias');

end;

procedure TSalaFlucar.leer_MultiSectionLineGrouping_raw( var f: textfile);
var
  Multilinea: TRaw_MultiSectionLineGrouping;
begin

  Multilinea := TRaw_MultiSectionLineGrouping.loadfromtext(self, f);
  while Multilinea.I <> 0 do
  begin
    //writeln('MultiLinea: ', Multilinea.I);
    self.LineasSeccion.add(multiLinea);
    self.actores.Add(multiLinea);
    Multilinea := TRaw_MultiSectionLineGrouping.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las lineas agrupadas por seccion');

end;

procedure TSalaFlucar.leer_Zone_raw( var f: textfile);
var
  zona: TRaw_Zone;
begin

  zona := TRaw_Zone.loadfromtext(self, f);
  while zona.I <> 0 do
  begin
    //writeln('Zona: ', zona.I, ' ', zona.ZONAME);
    self.zonas.add(zona);
    self.actores.Add(zona);
    zona := TRaw_Zone.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las ZONAS');

end;

procedure TSalaFlucar.leer_InterAreaTransfer_raw( var f: textfile);
var
  trasarea: TRaw_InterAreaTransfer;
begin

  trasarea := TRaw_InterAreaTransfer.loadfromtext(self, f);
  while trasarea.ARFROM <> 0 do
  begin
    //writeln('Transferencia entre áreas: ', trasarea.ARFROM);
    self.transfareas.add(trasArea);
    self.actores.Add(trasArea);
    trasarea := TRaw_InterAreaTransfer.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de las transferencia entre AREAS');

end;

procedure TSalaFlucar.leer_Owner_raw( var f: textfile);
var
  dueno: TRaw_Owner;
begin

  dueno := TRaw_Owner.loadfromtext(self, f);
  while dueno.I <> 0 do
  begin
    //writeln(dueno.I);
    self.owners.add(dueno);
    self.actores.Add(dueno);
    dueno := TRaw_Owner.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de los OWNERS:', self.owners.Count);

end;


function TSalaFlucar.BarraConectada( barratemp: TBarra;
                                     var NConexiones : integer): boolean;

var
  MonoBarraConect, kIndice, BiBarraConect, TriBarraConect: Integer;
  es_la_K: Boolean;
  barratemp_: TRaw_Bus;
begin
  barratemp_:= TRaw_Bus(barratemp);
  Result := TRUE;
  //  chequeo cuantas monobarra conectan con barratemp
  MonoBarraConect:=0;
  for kIndice:=0 to Cargas.count-1 do
    if (TRaw_Load(Cargas[kIndice]).STATUS=1) and
      (TRaw_Load(Cargas[kIndice]).I=barratemp_.I) then
    begin
        MonoBarraConect:=MonoBarraConect+1;
    end;

  //  chequeo cuantos generadores conectan con la barratemp
  for kIndice:=0 to Generadores.count-1 do
    if (TRaw_Generator(Generadores[kIndice]).STAT=1) and
      (TRaw_Generator(Generadores[kIndice]).I=barratemp_.I) then
    begin
        MonoBarraConect:=MonoBarraConect+1;
    end;

  //  chequeo cuantos shunt switcheados conectan
  for kIndice:=0 to Shunts.count-1 do
    if (TRaw_SwitchedShunt(Shunts[kIndice]).STAT=1) and
      (TRaw_SwitchedShunt(Shunts[kIndice]).I=barratemp_.I) then
    begin
        MonoBarraConect:=MonoBarraConect+1;
    end;

  //  chequeo cuantos shunt fijos conectan con la barratemp
  for kIndice:=0 to ShuntsFijos.count-1 do
    if (TRaw_FixedShunt(ShuntsFijos[kIndice]).STATUS=1) and
      (TRaw_FixedShunt(shuntsFijos[kIndice]).I=barratemp_.I) then
    begin
        MonoBarraConect:=MonoBarraConect+1;
    end;

  //  chequeo cuantos bibarra conectan con la barratemp
  BiBarraConect:=0;
  for kIndice:=0 to Lineas.count-1 do
    if (TRaw_Branch(Lineas[kIndice]).ST=1) and
      ((TRaw_Branch(Lineas[kIndice]).I=barratemp_.I) or
      (TRaw_Branch(Lineas[kIndice]).J=barratemp_.I)) then
    begin
        BiBarraConect:=BiBarraConect+1;
    end;

  //  chequeo cuantos componentes de TerminalesDC conectan con la barratemp
  for kIndice:=0 to TerminalesDC.count-1 do
    if (TRaw_TwoTerminal_DCLine(TerminalesDC[kIndice]).MDC<>0) and
      ((TRaw_TwoTerminal_DCLine(TerminalesDC[kIndice]).I=barratemp_.I) or
      (TRaw_TwoTerminal_DCLine(TerminalesDC[kIndice]).J=barratemp_.I)) then
    begin
        BiBarraConect:=BiBarraConect+1;
    end;

  //  chequeo cuantos VSC conectan con la barratemp
  for kIndice:=0 to VSC.count-1 do
    if (TRaw_VoltageSourceConverter_DCLine(VSC[kIndice]).MDC<>0) and
      (TRaw_VoltageSourceConverter_DCLine(VSC[kIndice]).I=barratemp_.I) or
      (TRaw_VoltageSourceConverter_DCLine(VSC[kIndice]).J=barratemp_.I) then
    begin
        BiBarraConect:=BiBarraConect+1;
    end;

  //  chequeo cuantos FACTS conectan con la barratemp
  for kIndice:=0 to Facts.count-1 do
    if (TRaw_Facts(Facts[kIndice]).MODE<>0) and
      (TRaw_Facts(Facts[kIndice]).I=barratemp_.I) or
      (TRaw_Facts(Facts[kIndice]).J=barratemp_.I) then
    begin
        BiBarraConect:=BiBarraConect+1;
    end;

  //  chequeo cuantos TriBarra conectan con la barratemp
  TriBarraConect:=0;
  es_la_K:=FALSE;
  for kIndice:=0 to trafosadjust.count-1 do
    if (TRaw_TransformerAdjust(trafosadjust[kIndice]).STAT=1) and
      (TRaw_TransformerAdjust(trafosadjust[kIndice]).I=barratemp_.I) or
      (TRaw_TransformerAdjust(trafosadjust[kIndice]).J=barratemp_.I) or
      (TRaw_TransformerAdjust(trafosadjust[kIndice]).K=barratemp_.I) then
    begin
       TriBarraConect:=TriBarraConect+1;
       if (TRaw_TransformerAdjust(trafosadjust[kIndice]).STAT=1) and
          (TRaw_TransformerAdjust(trafosadjust[kIndice]).K=barratemp_.I) then
          es_la_K:=TRUE;
    end;

  //  chequeo que conecte con al menos dos componentes
  if (MonoBarraConect+BiBarraConect=0) and (TriBarraConect=1) and es_la_K then
     writeln('La barra ' + IntToStr(barratemp_.I) +
     ' se conecta solo a un bobinado K de un trafo');

  NConexiones:= MonoBarraConect+BiBarraConect+TriBarraConect;

  if not(BiBarraConect+TriBarraConect>1) then
     if not(NConexiones>1) then
     begin
        writeln('La barra ' + IntToStr(barratemp_.I) +
        ' tiene: MonoBarras: ' + IntToStr(MonoBarraConect) +
        ' BiBarras: ' + IntToStr(BiBarraConect) +
        ' TriBarras: ' + IntToStr(TriBarraConect) + ' conectados.');
        Result:=FALSE;
     end;
end;







procedure TSalaFlucar.leer_facts_raw( var f: textfile);
var
  fact: TRaw_Facts;
begin

  fact := TRaw_Facts.loadfromtext(self, f);
  while fact.N <> 0 do
  begin
    if fact.MODE<>0 then
    begin
      //writeln('Fact: ', fact.N);
      fact.resolver_referencias;
      self.Facts.add(fact);
      self.actores.Add(fact);
    end;
    fact := TRaw_Facts.loadfromtext(self, f);
  end;
  writeln;
  writeln('ESTO es el fin de los FACTS');

end;

procedure TSalaFlucar.cargarNodoTipo1(var libres, nolibres: integer; Nudos,
  iEcuacion: integer);
var
  Deltamin,Deltamax,Voltmax, Voltmin: NReal;
begin
  //  Si el nodo no es regulado en Voltaje, el modulo y el angulo
  //  puede variar libremente. (Se introducen limites logicos)
  Voltmin := 0.85;
  Voltmax := 1.15;
  Deltamin := -pi;
  Deltamax :=  pi;
  ProblemaCPX.DefinirVariable(iEcuacion,
         CPX_POLAR, Voltmin, Voltmax, TRaw_Bus(Barras[(iEcuacion - 1)]).VM, False,
         Deltamin, Deltamax, TRaw_Bus(Barras[(iEcuacion - 1)]).VA/180*pi, False);

  //  Es PQ entonces el P y el Q son completamente fijos al valor
  //  de la suma de generacion menos demanda.
  ProblemaCPX.DefinirVariable(iEcuacion + Nudos, CPX_RECTANGULAR,
        TRaw_Bus(Barras[(iEcuacion - 1)]).PL / 100, True,
        TRaw_Bus(Barras[(iEcuacion - 1)]).QL / 100, True);

  if TapsVariables then
  begin
    ProblemaCPX.DefinirVariable(iEcuacion + 2 * Nudos, CPX_POLAR,
      1, True, 0, True);
    nolibres := nolibres + 2;

    if (nodos_regulados.Find(TRaw_Bus(Barras[(iEcuacion - 1)]).I) > -1) then
    //  Si el nodo es regulado en Voltaje (modulo y angulo) el
    //  elemento regulador va a establecer los limites entre los que
    //  pueden variar.
    begin
      // Calcular limites de Vmin, Vmax
      // Calcular limites de Deltamin, Deltamax
      WRITELN('¡ATENCION FALTA IMPLEMENTAR CALCULAR LOS LIMITES EN LOS NODOS DE V REGULADO!');
      Voltmin := 0.85;
      Voltmax := 1.15;
      Deltamin := -pi;
      Deltamax := pi;
      ProblemaCPX.DefinirVariable(iEcuacion,
         CPX_POLAR, Voltmin, Voltmax, 1.00, False, Deltamin, Deltamax,
         (Deltamax+Deltamin)/2, False);
    end;

  end;

  libres := libres + 2;
  nolibres := nolibres + 2;

  {$IFDEF DEBUGFLUCAR}
  //writeln('nodo tipo 1 I ', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).I, ' ', g);
  //writeln('nodo tipo 1 NAME ', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).NAME, ' ', g);
  //writeln('nodo tipo 1 v ', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).VM);
  //writeln('nodo tipo 1 arg ', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).VA);
  //writeln('nodo tipo 1 PL', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).PL);
  //writeln('nodo tipo 1 QL', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).QL);
  {$ENDIF}

end;



procedure TSalaFlucar.cargarNodoTipo2(var libres, nolibres,cantNodosGenConTap,
                                          cantNodosGenSinTap: integer;
                                          Nudos, iEcuacion: integer);
var
  Pfija : Nreal;
  RMI_min, RMA_max,Deltamin,Deltamax,Voltmax, Voltmin: NReal;
  jtrafo: Integer;
  ata: TRaw_TransformerAdjust;
  reg1, reg2, reg3: Boolean;

  begin
  //  Es PV entonces el P y el V son completamente fijos, Q es variable.
    ProblemaCPX.DefinirVariable(iEcuacion, CPX_POLAR,
      0.5, 1.5, TRaw_Bus(Barras[(iEcuacion - 1)]).VM, True,
      -pi, pi, TRaw_Bus( Barras[(iEcuacion - 1)]).VA / 180.0 * pi, False);

    Pfija := TRaw_Bus(Barras[(iEcuacion - 1)]).PL / 100;
    ProblemaCPX.DefinirVariable(iEcuacion + Nudos, CPX_RECTANGULAR,
      Pfija, Pfija, Pfija, True,
      TRaw_Bus(Barras[(iEcuacion - 1)]).QMIN / 100,
      TRaw_Bus(Barras[(iEcuacion - 1)]).QMAX / 100,
      TRaw_Bus(Barras[(iEcuacion - 1)]).QL / 100, False);

    libres := libres + 2;
    nolibres := nolibres + 2;

    if (TapsVariables) then
    begin
      if (nodos_reguladores.Find(TRaw_Bus(Barras[(iEcuacion - 1)]).I) > -1) then
      //  Si el nodo es regulador de Voltaje (modulo y angulo). Entonces
      //  el t es variable  y el Delta es variable
      begin

         RMI_min:=0.9;
         RMA_max:=1.1;

         for jtrafo:=0 to trafos_reguladores.count-1 do
         begin
           ata := TRaw_TransformerAdjust(trafos_reguladores[jtrafo]);
           reg1 := ( ata.I = TRaw_Bus(Barras[(iEcuacion - 1)]).I)
                   and ( ata.COD1 = 1 );
           reg2 := ( ata.J = TRaw_Bus(Barras[(iEcuacion - 1)]).I)
                   and ( ata.COD2 = 1 );
           reg3 := ( ata.K = TRaw_Bus(Barras[(iEcuacion - 1)]).I)
                   and ( ata.COD3 = 1 );

           if (reg1) then
           begin
             RMI_min := max(RMI_min,ata.RMI1);
             RMA_max := min(RMA_max,ata.RMA1);
           end;
           if (reg2) then
           begin
             RMI_min := max(RMI_min,ata.RMI2);
             RMA_max := min(RMA_max,ata.RMA2);
           end;
           if (reg3) then
           begin
             RMI_min := max(RMI_min,ata.RMI3);
             RMA_max := min(RMA_max,ata.RMA3);
           end;

         end;

         ProblemaCPX.DefinirVariable(iEcuacion + 2 * Nudos, CPX_POLAR,
               RMI_min, RMA_max, 1.00, False, 0, 0, 0, True);

         //  OJO: Esto es una manganeta
         Pfija := TRaw_Bus(Barras[(iEcuacion - 1)]).PL / 100;
         ProblemaCPX.DefinirVariable(iEcuacion + Nudos, CPX_RECTANGULAR,
           Pfija, Pfija, Pfija, True,
           TRaw_Bus(Barras[(iEcuacion - 1)]).QMIN / 100,
           TRaw_Bus(Barras[(iEcuacion - 1)]).QMAX / 100,
           TRaw_Bus(Barras[(iEcuacion - 1)]).QL / 100, True);

         nolibres := nolibres + 2;

         ////////////////////////////////////////////////////////////////////
         inc(cantNodosGenConTap);
      end
      else
      begin
        //  Si no es nodo regulador o no es una sala de taps variables
        //  entonces t es fijo en modulo y angulo.
        ProblemaCPX.DefinirVariable(iEcuacion + 2 * Nudos, CPX_POLAR,
          1, 1, 1, True, 0, 0, 0, True);
        nolibres := nolibres + 2;
        inc(cantNodosGenSinTap);
      end;
    end
    else
    begin
       inc(cantNodosGenSinTap);
    end;
end;

procedure TSalaFlucar.cargarNodoTipo3(var libres, nolibres: integer;
                                          Nudos, iEcuacion: integer);
begin

  ProblemaCPX.DefinirVariable(iEcuacion, CPX_POLAR,
                 TRaw_Bus(Barras[(iEcuacion - 1)]).VM, True,
                 TRaw_Bus(Barras[(iEcuacion - 1)]).VA / 180.0 * pi, True);
  ProblemaCPX.DefinirVariable(iEcuacion + Nudos, CPX_RECTANGULAR,
                 -9999, 9999,  TRaw_Bus(Barras[(iEcuacion - 1)]).PL/100, False,
                 -9999, 9999, TRaw_Bus( Barras[(iEcuacion - 1)]).QL/100, False);
  libres := libres + 2;
  nolibres := nolibres + 2;

  if (TapsVariables) then
  begin
    ProblemaCPX.DefinirVariable(iEcuacion + 2 * Nudos, CPX_POLAR,
                   1, 1, 1, True, 0, 0, 0, True);
    nolibres := nolibres + 2;
  end;

  {$IFDEF DEBUGFLUCAR}
  //writeln('la generacion de la maquina es ',TRaw_Bus(sala.Barras[(iEcuacion - 1)]).PL: 6: 6 , ' MW');
  //writeln('la max reactiva de la maquina es ',TRaw_Bus(sala.Barras[(iEcuacion - 1)]).QMAX: 6: 6 , ' MVA');
  //writeln('la min reactiva de la maquina es ',TRaw_Bus(sala.Barras[(iEcuacion - 1)]).QMIN: 6: 6 , ' MVA');
  {$ENDIF}

end;



function TSalaFlucar.Find_Demanda(barra: longint; codigo: string): TActorMonoBarra;
var
  a: TRaw_Load;
  buscando: boolean;
  k: integer;
  barraaux: TRaw_Bus;
begin
  buscando := True;
  k := 0;
  barraaux := I_to_ListaBarras(nil, barra, TodasLasBarras);
  if barraaux.IMP_CERO then
    barra := barraaux.BarraExtImpCero;

  while (buscando and (k < Cargas.Count)) do
  begin
    a := Cargas[k];
    if (a.I = barra) and (a.ID = codigo) then
      buscando := False
    else
      Inc(k);
  end;
  if buscando then
    Result := nil
  else
    Result := a;
end;

end.
