unit flujoraw;

interface

uses
  Classes,
  SysUtils,
  xMatDefs,
  urawdata,
  usistema, uactoresflucar,
  uConstantesSimSEE,
  AlgebraC,
  ucpxresolvecuacs,
  MatCPX,
  Math,
  uauxiliares;

procedure EscribirRaw(sala: TSalaFlucar; archi: string);
procedure Preparar_sistema(sala: TSalaFlucar);
procedure Cargar_problema(sala: TSalaFlucar);
procedure Cargar_datos_luego_de_resuelto(sala: TSalaFlucar; Convergio: boolean;
  cntiters: Integer);

procedure cargar_taps(sala: TSalaFlucar);
procedure cargar_tap_winding(winding: Integer; ata:TRaw_transformerAdjust;
  var j:Integer; sala:TSalaFlucar);

function RevisarSala(sala: TSalaFlucar):Boolean;
function conectividad(var MatAdmitancias: TMatrizDeAdmitancias;
  var lugar: integer): boolean;

implementation

uses
  ufunciones_flucar;


procedure cargar_tap_winding(winding: Integer; ata:TRaw_transformerAdjust;
  var j:Integer; sala:TSalaFlucar);
var
  NRegulador, NRegulado, windingCOD: integer;
  Barra_REGULADOR, Barra_REGULADA : TBarra;
  windingCONT: LongInt;
begin
  case winding of
  1:
    begin
      windingCOD  := ata.COD1;
      windingCONT := ata.CONT1;
    end;
  2:
    begin
      windingCOD  := ata.COD2;
      windingCONT := StrToInt(ata.CONT2);
    end;
  3:
    begin
      windingCOD  := ata.COD3;
      windingCONT := StrToInt(ata.CONT3);
    end;
  end;

  case abs(windingCOD) of
  0: ;  // SIN CONTROL DE TENSION EN EL NODO "winding"
  1:
    begin
      // CONTROL DE TENSION EN EL NODO "winding"
      NRegulador := ata.I;
      Barra_REGULADOR  := ata.Barra_I;
      if windingCONT = 0 then
      begin
         NRegulado := ata.J;
         Barra_REGULADA  := ata.Barra_J;
      end
      else
      begin
         NRegulado := windingCONT;
         Barra_REGULADA := sala.I_to_ListaBarras(nil, NRegulado, sala.Barras);
      end;
      if (Barra_REGULADA.conectada) and (Barra_REGULADOR.conectada) then
      begin
        if TRaw_Bus(Barra_REGULADOR).IDE <> 2 then
        begin
          sala.nodos_reguladores.Add(NRegulador);
          sala.nodos_regulados.Add(NRegulado);
          sala.trafos_reguladores.Add(ata);
          TRaw_Bus(Barra_REGULADOR).IDE := 2;
          inc(j);
        end;
      end
      else
        raise Exception.Create(
          'flujoraw.cargar_taps. Se está tratando de regular una barra desconectada: ' +
          IntToStr(NRegulador) + ', ' + IntToStr(NRegulado));
    end;
  2:
    begin
        // CONTROL DE Q EN EL NODO "winding"
      raise Exception.Create(
      'flujoraw.cargar_taps. No se implemento la regulacion de tipo 2: ' +
      IntToStr(ata.I) + ', ' + IntToStr(ata.j)+ ',' + IntToStr(ata.K));
    end;
  3:
    begin
        // CONTROL DE P EN EL NODO "winding"
      raise Exception.Create(
      'flujoraw.cargar_taps. No se implemento la regulacion de tipo 3: ' +
      IntToStr(ata.I) + ', ' + IntToStr(ata.j)+ ',' + IntToStr(ata.K));
    end;
  4:
    begin
        // CONTROL EN LINEAS DE DC EN EL NODO "winding"
      raise Exception.Create(
      'flujoraw.cargar_taps. No se implemento la regulacion de tipo 4: ' +
      IntToStr(ata.I) + ', ' + IntToStr(ata.j)+ ',' + IntToStr(ata.K));
    end;
  end;

end;

function RevisarSala(sala: TSalaFlucar): Boolean;
var
  kLinea, kBarra, MonoBarraConect, kIndice, BiBarraConect,
    TriBarraConect, jbarra, cantIslas, knodotemp, kisla, krenglon,
    klista, Ncons: Integer;
  barratemp, BI, BJ: TRaw_Bus;
  suma: NComplex;
  barraSwingPresente, es_la_K, agregada: Boolean;
  listaNodos, nodostemp: Tlist;
  listasIslas : array of TList;
  textdump: TextFile;
begin
  Result:=TRUE;
  barraSwingPresente:=FALSE;
  listaNodos:=TList.Create;
  nodostemp:=TList.Create;
  setlength(listasIslas,0);

  cantIslas:=0;
  kBarra:=0;

  AssignFile(textdump,GetUserDir+DirectorySeparator+'lsdjifh.txt');
  Rewrite(textdump);

  while (kBarra<sala.Barras.count) do
  begin
    inc(cantIslas);

    //listaNodos.Clear;
    barratemp:=sala.Barras[kBarra];
    listaNodos.add(barratemp);

    kIndice:=0;
    while (kIndice<listaNodos.Count) do
    begin
      barratemp:= listaNodos[kIndice];
      nodostemp:=barratemp.NodosConLosQueConecta();
      for knodotemp:=0 to nodostemp.Count-1 do
          if (listaNodos.IndexOf(nodostemp[knodotemp])=-1) then
             listaNodos.add(nodostemp[knodotemp]);

      inc(kIndice);
    end;

    setlength(listasIslas, length(listasIslas) +1);
    listasIslas[high(listasIslas)]:=TList.Create;
    listasIslas[high(listasIslas)].AddList(listaNodos);
    listaNodos.Clear;
    for krenglon:=0 to listasIslas[high(listasIslas)].count-1 do
        writeln(textdump,IntToStr(TRaw_Bus(listasIslas[high(listasIslas)][krenglon]).I));
    writeln(textdump);

    agregada:=TRUE;
    while ((kBarra<sala.Barras.Count) and (agregada)) do
    begin
      agregada:=False;
      for klista:=0 to High(listasIslas) do
        agregada:=agregada or (listasIslas[klista].IndexOf(sala.Barras[kBarra])<>-1);
      if agregada then
         inc(kBarra);
    end;
  end;

  CloseFile(textdump);
  writeln('Cantidad de Islas: ' + IntToStr(cantIslas));


  //Chequeo de las lineas activas no conecten nodos activos a diferente tension
  for kLinea:=0 to sala.Lineas.count-1 do
  begin
    if TRaw_Branch(sala.Lineas[kLinea]).ST=0 then
       Continue;
    BI:=sala.I_to_ListaBarras(nil,TRaw_Branch(sala.Lineas[kLinea]).I, sala.Barras);
    BJ:=sala.I_to_ListaBarras(nil,TRaw_Branch(sala.Lineas[kLinea]).J, sala.Barras);
    if IntToBool(TRaw_Branch(sala.Lineas[kLinea]).ST) then
      if (BI.IDE<>4) and (BJ.IDE<>4) and (BI.BASKV<>BJ.BASKV) then
      begin
         writeln('Una linea conecta los nodos ' + IntToStr(BI.I) +
                 ' y '+ IntToStr(BJ.I) +' que tienen diferente tensión');
         Result:=FALSE;
      end;
  end;
  for kLinea:=0 to sala.LineasImpCero.count-1 do
  begin
    if TRaw_Branch(sala.LineasImpCero[kLinea]).ST=0 then
       Continue;
    BI:=sala.I_to_ListaBarras(nil,TRaw_Branch(sala.LineasImpCero[kLinea]).I, sala.Barras);
    BJ:=sala.I_to_ListaBarras(nil,TRaw_Branch(sala.LineasImpCero[kLinea]).J, sala.Barras);
    if IntToBool(TRaw_Branch(sala.LineasImpCero[kLinea]).ST) then
      if (BI.IDE<>4) and (BJ.IDE<>4) and (BI.BASKV<>BJ.BASKV) then
      begin
         writeln('Una linea conecta los nodos ' + IntToStr(BI.I) +
                 ' y '+ IntToStr(BJ.I) +' que tienen diferente tensión');
         Result:=FALSE;
      end;
  end;


  //Se recorren todas las barras activas para ver si estan conectadas a por lo
  //menos dos elementos
  for kbarra:=0 to sala.Barras.count-1 do
  begin
    barratemp:=TRaw_Bus(sala.Barras[kbarra]);

    //  Barras de tipo 4 no se chequean
    if barratemp.IDE=4 then
       continue;
    //  Si es de tipo 3 se agrega a las swing
    if barratemp.IDE=3 then
       barraSwingPresente:=TRUE;

    Result:= sala.BarraConectada(barratemp, Ncons);

  end;

  //Se chequea que no hayan barras aisladas en la matriz de admitancias
  for kbarra:=0 to sala.Barras.count-1 do
  begin
    suma := complex_NULO;
    for jbarra:=0 to sala.Barras.count-1 do
    begin
      suma.r:= suma.r + abs(sala.MY.e(kbarra+1,jbarra+1).r);
      suma.i:= suma.i + abs(sala.MY.e(kbarra+1,jbarra+1).i);
    end;
    if ((suma.r=0) and (suma.i=0)) then
    begin
      writeln('La barra ' + IntToStr(TRaw_Bus(sala.Barras[kbarra]).I) +' esta aislada');
      Result:=FALSE;
    end;
  end;

  if not barraSwingPresente then
  begin
    writeln('No hay barra Swing');
    Result:=FALSE;
  end;


end;

function conectividad(var MatAdmitancias: TMatrizDeAdmitancias;
  var lugar: integer): boolean;
var
  i, n, k: integer;
  resultado: NComplex;
  arbol: array of boolean;
begin
  n := MatAdmitancias.numeroDeEcuaciones;
  setlength(arbol, n + 1);
  Result := True;
  lugar := 1;
  resultado := complex_NULO;
  for i := 1 to n do
    arbol[i] := False;

  for i := 1 to n do
    for k := 1 to n do
    begin
      if i <> k then
      begin
        if MatAdmitancias.ValCoef(resultado, i, k) and not
          EsCero(resultado) then
        begin
          arbol[k] := True;
        end;
      end;
    end;
  for i := 1 to n do
  begin
    writeln(arbol[i]);
    if not arbol[i] then
    begin
      Result := False;
      lugar := i;
    end;
  end;

end;

procedure dump_barras_to_txt(sala: TSalaFlucar; archi: string);
var
  f: textfile;
  i: integer;
  ab: TRaw_Bus;
begin
  assignfile(f, archi);
  rewrite(f);
  writeln(f, 'NBarras: ', #9, sala.Barras.Count);
  writeln(f, 'Name', #9, 'AREA', #9, 'I', #9, 'IDE', #9, 'IMP Cero');
  for i := 0 to sala.Barras.Count - 1 do
  begin
    ab := sala.Barras[i];
    writeln(f, ab.Name, #9, ab.AREA, #9, ab.I, #9, ab.IDE, #9, ab.IMP_CERO);
  end;
  closefile(f);
end;



procedure dump_cargas_to_txt(sala: TSalaFlucar; archi: string);
var
  f: textfile;
  i: integer;
  a: TRaw_Load;
begin
  assignfile(f, archi);
  rewrite(f);
  writeln(f, 'NCargas: ', #9, sala.Cargas.Count);
  writeln(f, 'ID', #9, 'AREA', #9, 'I', #9, 'PL', #9, 'QL');
  for i := 0 to sala.Cargas.Count - 1 do
  begin
    a := sala.Cargas[i];
    writeln(f, a.ID, #9, a.AREA, #9, a.I, #9, a.PL, #9, a.QL);
  end;
  closefile(f);
end;

procedure dump_MY_to_txt(sala: TSalaFlucar; archi: string);
var
  f: textfile;
  i, j: integer;
  a: NComplex;
  ab1, ab2: TRaw_Bus;
begin
  assignfile(f, archi);
  rewrite(f);
  //writeln( f, 'NCargas: ',#9, sala.Cargas.Count );
  //writeln( f, 'ID', #9, 'AREA', #9,  'I' );
  for i := 1 to sala.Barras.Count do
  begin
    for j := 1 to sala.Barras.Count do
    begin
      ab1 := sala.Barras[i - 1];
      ab2 := sala.Barras[j - 1];
      a := sala.MY.e(i, j);
      writeln(f, a.r, #9, a.i, #9); //ab1.I, #9,ab2.I, #9
    end;
    //writeln(f,' ');
  end;
  closefile(f);
end;

procedure EscribirRaw(sala: TSalaFlucar; archi: string);
var
  kIndice, k, nodo, desde, hasta: Integer;
  NOmbreArch, extensionent, NombreArchent: string;
  Texto: TextFile;
  {$IFDEF WRITE_RESULT}
  Grafos: TextFile;
  {$ENDIF}
  Nodes, Trafos, Sources, Targets: TDAofString;

begin
  uauxiliares.setSeparadoresGlobales;

  k := pos('.', archi);
  NOmbreArch := copy(archi, 1, k - 1);
  extensionent := '.raw';
  NombreArchent := NombreArch + '_proc' + extensionent;

  Assign(Texto, NombreArchent);
  Rewrite(Texto);

  {$IFDEF WRITE_RESULT}
  Assign(Grafos, NOmbreArch+'_grafos.csv');
  Rewrite(Grafos);
  {$ENDIF}
  SetLength(Nodes, sala.Barras.count);
  SetLength(Trafos, sala.TrafosAdjust.Count);
  SetLength(Sources, sala.Lineas.Count + sala.TerminalesDC.Count + sala.VSC.Count +
                     sala.Facts.Count + 2*sala.TrafosAdjust.Count);
  SetLength(Targets, sala.Lineas.Count + sala.TerminalesDC.Count + sala.VSC.Count +
                     sala.Facts.Count + 2*sala.TrafosAdjust.Count);
  nodo:=0;
  desde:=0;
  hasta:=0;

  //1 Se escribe el encabezado que está en el caso
  TRaw_CaseIdentification(sala.caso[0]).WriteToText(Texto);

  //2 Se escriben las Barras
  for kIndice:=0 to sala.Barras.count-1 do
  begin
    TRaw_Bus(sala.Barras[kIndice]).WriteToText(Texto);
    Nodes[nodo]:=IntToStr(TRaw_Bus(sala.Barras[kIndice]).I);
    inc(nodo);
  end;

  writeln(Texto,'0 / END OF BUS DATA, BEGIN LOAD DATA');
  // 3 Se escriben las cargas
  for kIndice:=0 to sala.Cargas.count-1 do
  begin
    TRaw_Load(sala.Cargas[kIndice]).WriteToText(Texto);
  end;

  writeln(Texto,'0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA');
  //4 Se escriben Fixed Shunt
  for kIndice:=0 to sala.ShuntsFijos.count-1 do
  begin
    TRaw_FixedShunt(sala.ShuntsFijos[kIndice]).WriteToText(Texto);
  end;

  writeln(Texto,'0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA');
  //5 Se escriben los Generdores
  for kIndice:=0 to sala.Generadores.count-1 do
  begin
    TRaw_Generator(sala.Generadores[kIndice]).WriteToText(Texto);
  end;

  writeln(Texto,'0 / END OF GENERATOR DATA, BEGIN BRANCH DATA');
  // 6 Se escriben las lineas
  for kIndice:=0 to sala.Lineas.count-1 do
  begin
    TRaw_Branch(sala.Lineas[kIndice]).WriteToText(Texto);
    Sources[desde]:=IntToStr(TRaw_Branch(sala.Lineas[kIndice]).I);
    Targets[hasta]:=IntToStr(TRaw_Branch(sala.Lineas[kIndice]).J);
    inc(desde);
    inc(hasta);
  end;

  writeln(Texto,'0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA');
  // 7 Se escriben los transformadores
  for kIndice:=0 to sala.trafosadjust.count-1 do
  begin
    TRaw_TransformerAdjust(sala.trafosadjust[kIndice]).WriteToText(Texto);
    Trafos[kIndice]:='-1' + IntToStr(kIndice);
    inc(nodo);

    Sources[desde]:=IntToStr(TRaw_TransformerAdjust(sala.trafosadjust[kIndice]).I);
    Targets[hasta]:=Trafos[kIndice];
    inc(desde);
    inc(hasta);
    Sources[desde]:=IntToStr(TRaw_TransformerAdjust(sala.trafosadjust[kIndice]).J);
    Targets[hasta]:=Trafos[kIndice];
    inc(desde);
    inc(hasta);
    if TRaw_TransformerAdjust(sala.trafosadjust[kIndice]).K<>0 then
    begin
      SetLength(Sources, Length(Sources)+1);
      SetLength(Targets, Length(Targets)+1);
      Sources[desde]:=IntToStr(TRaw_TransformerAdjust(sala.trafosadjust[kIndice]).K);
      Targets[hasta]:=Trafos[kIndice];
      inc(desde);
      inc(hasta);
    end;

  end;

  writeln(Texto,'0 / END OF TRANSFORMER DATA, BEGIN AREA DATA');
  // 8 Se escriben las areas
  for kIndice:=0 to sala.areas.count-1 do
  begin
    TRaw_AreaInterchange(sala.areas[kIndice]).WriteToText(Texto);
  end;

  writeln(Texto,'0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA');
  // 9 Se escriben los two-terminal
  for kIndice:=0 to sala.TerminalesDC.count-1 do
  begin
    TRaw_TwoTerminal_DCLine(sala.TerminalesDC[kIndice]).WriteToText(Texto);
    Sources[desde]:=IntToStr(TRaw_TwoTerminal_DCLine(sala.TerminalesDC[kIndice]).I);
    Targets[hasta]:=IntToStr(TRaw_TwoTerminal_DCLine(sala.TerminalesDC[kIndice]).J);
    inc(desde);
    inc(hasta);
  end;

  writeln(Texto,'0 / END OF TWO-TERMINAL DC DATA, BEGIN VSC DC LINE DATA');
  // 10 Se escriben los VSC.
  for kIndice:=0 to sala.VSC.count-1 do
  begin
    TRaw_VoltageSourceConverter_DCLine(sala.VSC[kIndice]).WriteToText(Texto);
    Sources[desde]:=IntToStr(TRaw_VoltageSourceConverter_DCLine(sala.VSC[kIndice]).I);
    Targets[hasta]:=IntToStr(TRaw_VoltageSourceConverter_DCLine(sala.VSC[kIndice]).J);
    inc(desde);
    inc(hasta);
  end;

  writeln(Texto,'0 / END OF VSC DC LINE DATA, BEGIN IMPEDANCE CORRECTION DATA');
  // 11 Se escriben las Tablas de Correccion de impedancia.
  for kIndice:=0 to sala.ICTRATables.count-1 do
  begin
    TRaw_TransformerImpedanceCorrectionTables(sala.ICTRATables[kIndice]).WriteToText(Texto);
  end;

  writeln(Texto,'0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA');
  // 12 Se escriben los Multi-Terminal.
  for kIndice:=0 to sala.TerminalesDCMult.count-1 do
  begin
    TRaw_MultiTerminal_DCLine(sala.TerminalesDCMult[kIndice]).WriteToText(Texto);
  end;

 writeln(Texto,'0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA');
  // 13 Se escriben las Multi Section Line.
  for kIndice:=0 to sala.LineasSeccion.count-1 do
  begin
    TRaw_MultiSectionLineGrouping(sala.LineasSeccion[kIndice]).WriteToText(Texto);
  end;

  writeln(Texto,'0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA');
  // 14 Se escriben las Zonas.
  for kIndice:=0 to sala.zonas.count-1 do
  begin
    TRaw_Zone(sala.zonas[kIndice]).WriteToText(Texto);
  end;

  writeln(Texto,'0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA');
  // 15 Se escriben las Inter-Area de transferencia.
  for kIndice:=0 to sala.transfareas.count-1 do
  begin
    TRaw_InterAreaTransfer(sala.transfareas[kIndice]).WriteToText(Texto);
  end;

  writeln(Texto,'0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA');
  // 16 Se escriben los Owners.
  for kIndice:=0 to sala.owners.count-1 do
  begin
    TRaw_Owner(sala.owners[kIndice]).WriteToText(Texto);
  end;

  writeln(Texto,'0 / END OF OWNER DATA, BEGIN FACTS DEVICE DATA');
  // 17 Se escriben los Facts Device.
  for kIndice:=0 to sala.facts.count-1 do
  begin
    TRaw_Facts(sala.facts[kIndice]).WriteToText(Texto);
    Sources[desde]:=IntToStr(TRaw_Facts(sala.facts[kIndice]).I);
    Targets[hasta]:=IntToStr(TRaw_Facts(sala.facts[kIndice]).J);
    inc(desde);
    inc(hasta);
  end;

  writeln(Texto,'0 / END OF FACTS DEVICE DATA, BEGIN SWITCHED SHUNT DATA');
  // 18 Se escriben los Switched Shunt.
  for kIndice:=0 to sala.Shunts.count-1 do
  begin
    TRaw_SwitchedShunt(sala.Shunts[kIndice]).WriteToText(Texto);
  end;

  writeln(Texto,'0 / END OF SWITCHED SHUNT DATA, BEGIN GNE DATA');
  // 19 Se escriben los GNE

  writeln(Texto,'0 / END OF GNE DATA');
  writeln(Texto,'Q');


  CloseFile(Texto);
  {$IFDEF WRITE_RESULT}
  for kIndice:=0 to Length(Nodes)-1 do
  begin
    write(Grafos,Nodes[kIndice]);
    if (kIndice<>Length(Nodes)-1) then
       write(Grafos,',')
    else
        writeln(Grafos);
  end;

  for kIndice:=0 to Length(Trafos)-1 do
  begin
    write(Grafos,Trafos[kIndice]);
    if (kIndice<>Length(Trafos)-1) then
       write(Grafos,',')
    else
        writeln(Grafos);
  end;

  for kIndice:=0 to Length(Sources)-1 do
  begin
    write(Grafos,Sources[kIndice]);
    if (kIndice<>Length(Sources)-1) then
       write(Grafos,',')
    else
        writeln(Grafos);
  end;

  for kIndice:=0 to Length(Targets)-1 do
  begin
    write(Grafos,Targets[kIndice]);
    if (kIndice<>Length(Targets)-1) then
       write(Grafos,',')
    else
        writeln(Grafos);
  end;


  CloseFile(Grafos);
  {$ENDIF}
end;

procedure Preparar_sistema(sala: TSalaFlucar);
var
  i: integer;
begin

  //dump_barras_to_txt( sala, 'lst_barras1.xlt' );
  //dump_cargas_to_txt(sala,  'lst_cargas.xlt' );
  //dump_MY_to_txt(sala,  'sistema2.xlt' );

  //Barras
  for i := 0 to sala.Barras.Count - 1 do
  begin
    TRaw_Bus(sala.Barras[i]).cargue;
  end;

  //ShuntFijos
  if RAW_VER >= 32 then
  begin
    for i := 0 to sala.ShuntsFijos.Count - 1 do
    begin
      TRaw_FixedShunt(sala.ShuntsFijos[i]).cargue;
    end;
  end;

  //Lineas
  for i := 0 to sala.lineas.Count - 1 do
  begin
    TRaw_Branch(sala.lineas[i]).cargue;
  end;

  //TrafosAdjust
  if RAW_VER >= 32 then
  begin
    for i := 0 to sala.trafosAdjust.Count - 1 do
    begin
      TRaw_TransformerAdjust(sala.trafosAdjust[i]).cargue;
    end;
  end;

  //ShuntSwitched
  for i := 0 to sala.shunts.Count - 1 do
  begin
    TRaw_SwitchedShunt(sala.shunts[i]).cargue;
  end;

  //Cargas
  for i := 0 to sala.Cargas.Count - 1 do
  begin
    TRaw_Load(sala.Cargas[i]).cargue;
  end;

  //Generadores
  for i := 0 to sala.generadores.Count - 1 do
  begin
    TRaw_Generator(sala.generadores[i]).cargue;
  end;

  //TerminalesDC
  for i:=0 to sala.TerminalesDC.Count - 1 do
  begin
    TRaw_TwoTerminal_DCLine(sala.TerminalesDC[i]).cargue;
  end;

  //VoltageSourceConverterDCLine
  for i:=0 to sala.VSC.Count - 1 do
  begin
    TRaw_VoltageSourceConverter_DCLine(sala.VSC[i]).cargue;
  end;

end;

procedure cargar_taps(sala: TSalaFlucar);
var
  i, j: integer;
  ata: TRaw_TransformerAdjust;
begin
  j := 0;
  for i := 0 to sala.trafosAdjust.Count - 1 do
  begin
    ata := sala.trafosAdjust[i];
    ata.resolver_referencias;

    if (ata.STAT = 1) then     // EN SERVICIO
    begin
       cargar_tap_winding(1, ata, j, sala);
       if (ata.K <> 0) then         // TRES BOBINADOS
       begin
         cargar_tap_winding(2, ata, j, sala);
         cargar_tap_winding(3, ata, j, sala);
       end;
    end
    else if (ata.STAT=2) or (ata.STAT=3) then
           raise Exception.Create(
              'Trafo con bobinado 2 o 3 desconectado:' +
              IntToStr(ata.I) + ', ' + IntToStr(ata.j)+ ',' + IntToStr(ata.K));
  end;
  writeln('ESTO ES EL FIN DE CARGAR LOS REGULADORES');
  writeln('Numero de reguladores ', j);

end;

procedure Cargar_problema(sala: TSalaFlucar);
var

  iEcuacion, Nudos, kkvar: integer;
  reg2, reg1, reg3: boolean;
  libres, nolibres, g, jtrafo, cantNodosCargas, cantNodosSwing,
    cantNodosGenSinTap, cantNodosGenConTap, nolibre: Integer;
  ata: TRaw_TransformerAdjust;
  RMI_min, RMA_max: Double;
begin

  ufunciones_flucar.salaActiva := sala;
  Nudos := sala.nNodos;
  libres := 0;
  nolibres := 0;
  g := 0;

  cantNodosCargas:=0;
  cantNodosGenSinTap:=0;
  cantNodosGenConTap:=0;
  cantNodosSwing:=0;

  for iEcuacion := 1 to Nudos do
    sala.problemaCPX.InscribirEcuacion(fi, iEcuacion);

  for iEcuacion := 1 to Nudos do
  begin
    case TRaw_Bus(sala.Barras[(iEcuacion - 1)]).IDE of
      1:     // BusType 1: load bus (no generator boundary condition)
      begin  // barra PQ o de carga
        sala.cargarNodoTipo1(libres,nolibres,Nudos,iEcuacion);
        inc(cantNodosCargas);
      end;

      2:    //  2: generator or plan bus (either voltage regulator or fixed MVAR)
      begin //  barra PV o de generacion o voltaje controlado
        sala.cargarNodoTipo2( libres,nolibres,cantNodosGenConTap,
                              cantNodosGenSinTap,Nudos,iEcuacion);

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

      end;

      3:    //         3: swing bus
      begin  // barra Slack (Flotante)
        sala.cargarNodoTipo3(libres,nolibres,Nudos,iEcuacion);

        {$IFDEF DEBUGFLUCAR}
        writeln('nodo tipo 3, I=', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).I, ' ', g);
        //writeln('nodo tipo 3 NAME ', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).NAME, ' ', g);
        writeln('nodo tipo 3 v ', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).VM);
        writeln('nodo tipo 3 arg ', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).VA);
        writeln('nodo tipo 3 PL', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).PL);
        writeln('nodo tipo 3 QL', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).QL);
        {$ENDIF}
        inc(cantNodosSwing);
      end;
      4:   //         4: disconnected (isolated ) bus
      begin
        // nada
      end;
    end;



    ////si el nodo es regulador, agregar tm variable, de lo contrario agregar un tm fijo
//    if sala.TapsVariables then
//    begin
//      if (sala.nodos_reguladores.Find(TRaw_Bus(sala.Barras[(iEcuacion - 1)]).I) > -1) then
//      begin
//
//           RMI_min:=0.9;
//           RMA_max:=1.1;
//
//           for jtrafo:=0 to sala.trafos_reguladores.count-1 do
//           begin
//             ata := TRaw_TransformerAdjust(sala.trafos_reguladores[jtrafo]);
//             reg1 := ( ata.I = TRaw_Bus(sala.Barras[(iEcuacion - 1)]).I)
//                     and ( ata.COD1 = 1 );
//             reg2 := ( ata.J = TRaw_Bus(sala.Barras[(iEcuacion - 1)]).I)
//                     and ( ata.COD2 = 1 );
//             reg3 := ( ata.K = TRaw_Bus(sala.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;
//
//           sala.ProblemaCPX.DefinirVariable(iEcuacion + 2 * Nudos, CPX_POLAR,
//                 RMI_min, RMA_max, 1.00, False, 0, 0, 0, True);
//
//           libres := libres + 1;
//           nolibres := nolibres + 1;
//
//           ////////////////////////////////////////////////////////////////////
//         //end;
//         inc(cantNodosGenConTap);
//      end
//      else
//      begin
//        sala.ProblemaCPX.DefinirVariable(iEcuacion + 2 * Nudos, CPX_POLAR,
//          1, 1, 1, True, 0, 0, 0, True);
//        nolibres := nolibres + 2;
//      end;
//    end
//    else
//    begin
//      // cargo tm fijo
//      {$IFDEF TM_FIJO}
//      sala.ProblemaCPX.DefinirVariable(iEcuacion + 2 * Nudos, CPX_POLAR,
//        1, True, 0, True);
//      nolibres := nolibres + 2;
//      {$ENDIF}
//    end;
//
  end;

  {$IFDEF DEBUGFLUCAR}
  writeln();
  writeln('Total Nodos: '+ IntToStr(Nudos));
  writeln('Nodos Carga: '+ IntToStr(cantNodosCargas));
  writeln('Nodos Generador s/TAP: '+ IntToStr(cantNodosGenSinTap));
  writeln('Nodos Generador c/TAP: '+ IntToStr(cantNodosGenConTap));
  writeln('Nodos Swing: '+ IntToStr(cantNodosSwing));
  writeln();
  writeln('Variables Libres  ', libres);
  writeln('Variables NO Libres  ', nolibres);
  writeln();
  {$ENDIF}

  for iEcuacion := 1 to Nudos do
    for kkvar := 1 to Nudos do
    begin
      sala.ProblemaCPX.InscribirDerivada(dfidro_V, iEcuacion, kkvar, 1);
      sala.ProblemaCPX.InscribirDerivada(dfidalfa_V, iEcuacion, kkvar, 2);
      sala.ProblemaCPX.InscribirDerivada(dfidP, iEcuacion, kkvar + Nudos, 1);
      sala.ProblemaCPX.InscribirDerivada(dfidQ, iEcuacion, kkvar + Nudos, 2);
      if sala.TapsVariables then
      begin
        sala.ProblemaCPX.InscribirDerivada(dfidtm, iEcuacion,
          kkvar + 2 * Nudos, 1);
        sala.ProblemaCPX.InscribirDerivada(dfidargtm, iEcuacion,
          kkvar + 2 * Nudos, 2);
      end;
    end;

  //  sala.MY.writetoTXT('sistema.xlt');

  // dump_MY_to_txt(sala,  'sistema2.xlt' );

end;


procedure Cargar_datos_luego_de_resuelto(sala: TSalaFlucar; Convergio: boolean;
  cntiters: Integer);
var
  iEcuacion, Nudos: integer;
  i, h: integer;
  S_12, S_21, S_CON, I_I: NComplex;

begin
  Nudos := sala.nNodos;
  if not Convergio then
  begin
    writeln('No CONVERGIO ' + sala.ProblemaCPX.errMsg);
    writeln('.... PRESINE ENTER PARA CONTINUAR....');
    system.readln;
    for iEcuacion := 1 to Nudos do
    begin
      TRaw_Bus(sala.Barras[(iEcuacion - 1)]).VM :=
        mod1(sala.ProblemaCPX.zvalores.v[iEcuacion]);
      TRaw_Bus(sala.Barras[(iEcuacion - 1)]).VA :=
        fase(sala.ProblemaCPX.zvalores.v[iEcuacion]);

     {$IFDEF DEBUGFLUCAR}
      writeln('nudo ', iEcuacion, '   ');
      writeln('|V|= ', mod1(sala.ProblemaCPX.zvalores.v[iEcuacion]): 6: 6);
      writeln('arg(V)= ', fase(sala.ProblemaCPX.zvalores.v[iEcuacion]) *
        180.0 / pi: 6: 6);
      //writeln(p.zvalores.v[iEcuacion].r: 6:6);
      //writeln(p.zvalores.v[iEcuacion].i: 6:6);

      writeln('P= ', sala.ProblemaCPX.zvalores.v[iEcuacion + Nudos].r * 100: 6: 6);
      writeln('Q= ', sala.ProblemaCPX.zvalores.v[iEcuacion + Nudos].i * 100: 6: 6);
      if sala.TapsVariables then
      begin
        writeln('tm= ', 1 / sala.ProblemaCPX.zvalores.v[iEcuacion + 2 * Nudos].r: 6: 6);
        writeln('Im(tm)= ', sala.ProblemaCPX.zvalores.v[iEcuacion + 2 * Nudos].i: 6: 6);
      end;
     {$ENDIF}

    end;
    writeln('Nro de iteraciones  ', cntiters);
  end
  else
  begin
    {$IFDEF DEBUGFLUCAR}
    writeln(' FELICITACIONES CONVERGIO ' + sala.ProblemaCPX.errMsg);
    {$ENDIF}
    //readln;
    for iEcuacion := 1 to Nudos do
    begin
      TRaw_Bus(sala.Barras[(iEcuacion - 1)]).VM :=
        mod1(sala.ProblemaCPX.zvalores.v[iEcuacion]);
      //*TRaw_Bus(sala.Barras[(iEcuacion - 1)]).BASKV;
      TRaw_Bus(sala.Barras[(iEcuacion - 1)]).VA :=
        fase(sala.ProblemaCPX.zvalores.v[iEcuacion]) * 180.0 / pi;

      {$IFDEF DEBUGFLUCAR}
      Writeln('nudo ', iecuacion, '  N: ', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).I,
        ' ', TRaw_Bus(sala.Barras[(iEcuacion - 1)]).Name, ' ',
        '|V|= ', mod1(sala.ProblemaCPX.zvalores.v[iEcuacion]): 3: 3, ' < ',
        fase(sala.ProblemaCPX.zvalores.v[iEcuacion]) * 180.0 / pi: 6: 6, ' ',
        'P= ', sala.ProblemaCPX.zvalores.v[iEcuacion + Nudos].r *
        100: 3: 3, ' Q= ', sala.ProblemaCPX.zvalores.v[iEcuacion + Nudos].i * 100: 3: 3);
      {$ENDIF}

      if not (sala.nodos_reguladores.IntCount = 0) then
        writeln('tm= ', 1/sala.ProblemaCPX.zvalores.v[iEcuacion+2*Nudos].r: 4: 4,
                ' < ', sala.ProblemaCPX.zvalores.v[iEcuacion+2*Nudos].i: 4: 4);

    end;
    {$IFDEF DEBUGFLUCAR}
    //readln;
    writeln('Nro de iteraciones  ', cntiters);
    writeln('');
    {$ENDIF}
    for i := 0 to sala.lineas.Count - 1 do
    begin
      if (sala.nodos_reguladores.Find(TRaw_Branch(sala.lineas[i]).I) > -1) then
      begin
        h := TRaw_Branch(sala.lineas[i]).Barra_I.jcol;
        TRaw_Branch(sala.lineas[i]).RATIO :=
          1 / (sala.ProblemaCPX.zvalores.v[h + 2 * Nudos].r);
        // TRaw_Branch(sala.lineas[i]).RATIO/(sala.ProblemaCPX.zvalores.v[h + 2 * Nudos].r);    //   1/sala.ProblemaCPX.zvalores.v[h + 2 * Nudos].r;
      end;
      TRaw_Branch(sala.lineas[i]).Calculo_potencias(S_12, S_21, S_CON, I_I);

      {$IFDEF DEBUGFLUCAR}
      writeln(' linea ', TRaw_Branch(sala.lineas[i]).I, ' ',
        TRaw_Branch(sala.lineas[i]).J, '  ', ' P12 = ', S_12.r * 100: 6: 2,
        ' Q12 = ', S_12.i * 100: 6: 2, ' P21=', S_21.r * 100: 6: 2,
        ' Q21=', S_21.i * 100: 6: 2, ' PCON = ', S_CON.r * 100: 6: 2,
        ' QCON = ', S_CON.i * 100: 6: 2, ' ratio ',
        TRaw_Branch(sala.lineas[i]).RATIO: 6: 3);
      {$ENDIF}
    end;
  end;
  {$IFDEF DEBUGFLUCAR}
  //sala.MY.muestrasistema;
  {$ENDIF}
end;

end.

