#!/usr/bin/perl
#simusol_sceptre.pl
use strict;
use warnings;
BEGIN {
    my $perllibdir = "/usr/local/share/simusol";
    unshift @INC, (split ':', $perllibdir);
}
use Getopt::Long;
use Pod::Usage;
use Data::Dumper;
use Simusol::Ayudas;
use Simusol::Auxiliares;
$0 =~ m!/([^/]+)\s*$!;
$progname = $1;my $curdirori = `pwd`; chomp $curdirori; $curdirori .= '/';
$progr{$progname} = 's';
our $PROPIOSIN;
#print STDERR "Estoy en $progname @ARGV\n";
our %reserv_dir;
my $refs = {'curdirori' => $curdirori};
foreach my $palabra  ('corto','cortosin','basearchcorto','dirarray') {
    $refs->{$palabra} = [];
}; 
impr_todo(__LINE__.' sims',$refs);   
crear_tmp_simusol();
my ($coderr,$mensaje) = interpretar_opciones_s($refs);
impr_debug(__LINE__.' sims',Dumper $refs);
impr_debug(__LINE__.' sim1 opciones',\%opt_hash);  
#----------------------------------------------------------------------------
#($coderr,$mensaje) = crear_reserv_dirs($refs);
$coderr and parars($coderr,$mensaje);
# -----------------------------------------------------------------------------
($coderr,$mensaje,$PROPIOSIN) = atender_argumentos_s();
$coderr and parars($coderr,$mensaje);
# ---------------------------------------------------------------------------
impr_todo(__LINE__.' sims',$refs);
chdir $refs->{outdirfinal} if $refs->{outdirfinal} ne '';
impr_debug(__LINE__.' sims',"\n\n        ya cambiado a \$outdirfinal $refs->{outdirfinal}");
# -----------------------------------------------------------------------------
$coderr  = aprontar('.d',$refs->{PROPIOSIN},$refs->{outdirfinal});
impr_debug(__LINE__.' sims $outdir,$refs->{PROPIOSIN},$dirsal{d}'
  ,[$outdir,$refs->{PROPIOSIN},$dirsal{d}]);
# -----------------------------------------------------------------------------
$coderr and parars($coderr);
# -----------------------------------------------------------------------------
impr_todo(__LINE__.' sims',$refs);
my $rcodes = simular();
#chdir $outdir; ya se hizo el cambio dentro de simular
#impr_debug(__LINE__.' sims ',"\n\n          ya cambiado a \$outdir $outdir");
if ($rcodes) {
    parars(30);
} else {
   parars(0);
};
#termina el principal
#----------------------------------------------------------------------------
#----------------------------------------------------------------------------
#----------------------------------------------------------------------------
sub ac{
  comfin('comS ac', @_);
  my ($refvaloresls2) = @_;
  while (<ENTRADAls2>) {
     last if /RUN\/RERUN NUMBER\D+(\d+)/;
  };
  # en lo anterior no queda asignado $1;
  my ($rerun) = /RUN\/RERUN NUMBER\D+(\d+)/;
  my $refval = $refvaloresls2->[$rerun] = {};
  while (<ENTRADAls2>) {
      last if /^0S C E P T R E\s*post/; 
      if (/^\s*$/) {
          $_ = <ENTRADls2>;
          next;
      };    
      my ($key,$value) = /^.(.{33})(.+)$/;
      $refval->{$key} = $value;
      $_ = <ENTRADls2>;
  };#while
  comfin('finS ac');
  return $_; 
}#ac
#----------------------------------------------------------------------------
sub analizar_error2{
  comfin('coms analizar_error2', @_);
  my $cosa  = $_[0]; my $textosal = '';
  if ($cosa =~ /(IMPLICIT integration cancelled)/i) {
     $textosal .= "El metodo de integración IMPLICIT fue cancelado;\n"
           . "(podría deberse a circuito con sólo resistencias)\n"  
	   . "   Pruebe a agregar en un cuadro CONTROLES\n"
	   . "       INTEGRATION ROUTINE = TRAP\n";
  } elsif ($cosa =~ /(SMALLER MINIMUM STEP SIZE REQUIRED)/i) { 
      $textosal .=  "    Pruebe a agregar en un cuadro CONTROLES\n"
	            . "        INTEGRATION ROUTINE = IMPLICIT\n"
	            . "          o bien \n"
	            . "        MINIMUM STEP SIZE = ....\n"
		    . "      o bien pida un tiempo de simulación más pequeño\n"
                    . "      o que sus variables varíen menos bruscamente\n";
  };
  comfin('fins analizar_error2');
  return  $cosa,$textosal;
} #analizar_error2
# -----------------------------------------------------------------------------
sub atender_argumentos_s{#no tiene argumentos 
  #fija $outdir y determina, $dirdeseada (a partir de outdir) y $PROPIOSIN
  comfin('coms atender_argumentos',@_);
  my $coderr = ''; 
  my $largo = 60 - length($progname); 
  my $opc_arg = paraimpr3puntos($largo,@ARGV);
# -----------------------------------------------------------------------------
  impr_debug(__LINE__.' sims @ARGV',\@ARGV);  
# -----------------------------------------------------------------------------
  my $textoARGV = $ARGV[0];
  if (defined $textoARGV and $textoARGV =~ /[\*\?\ ]/ or @ARGV >1) {
      $mensaje =  " Debe concretar mas su pedido";
      parars(250," Debe concretar mejor su pedido");
  };
# -----------------------------------------------------------------------------
  if (@ARGV == 1) {
      $refs->{dirarray} = [$ARGV[0]];
      ($coderr,$mensaje) = interpretar_outdir($refs);
      if ($coderr) {parars($coderr,$mensaje) } else { $PROPIOSIN = $refs->{PROPIOSIN}};
  } elsif (@ARGV == 0)  {
      $mensaje = "Debe indicar un archivo .d (con o sin su extension"; $coderr = 60;
#      impr_debug(__LINE__.' sims $dirsal{d}',$dirsal{d});
  } else {# $@ARGV > 1
      $mensaje =" Debe pedir un solo archivo .d y no 
         @ARGV";
      $coderr = 250;
  };
  impr_debug(__LINE__.' sims $outdirfinal,$PROPIOSIN', [$refs->{outdirfinal},$PROPIOSIN]);
  
  not $PROPIOSIN and $coderr = 254;
  comfin('fins atender_argumentos_s',$coderr,$mensaje);
  return $coderr,$mensaje,$PROPIOSIN;
}#atender_argumentos_s
# -----------------------------------------------------------------------------
sub escr_res{
  comfin('coms escr_res', @_);
  my ($refls2,$refsim,$tiempostop,$refprograf) = @_; my $coderr = '';
  my $archsim =  $dirsalida{'sim'} . "$PROPIOSIN.sim";
  -e $archsim or parars(250," No existe $archsim");
  $fechamarcas{sim} = scalar localtime((stat $archsim)[9]);
  my  $archparaplot = $dirsalida{'paraplot'} . "$PROPIOSIN.paraplot";
  my @lista;
  foreach my $palabra ('sim','paraplot') { 
      my $arch = "$dirsal{$palabra}$PROPIOSIN.$palabra";
      if (-e $arch) {
          my $fecha =   scalar localtime((stat $arch)[9]);
          push @lista, sprintf "#     %-24s  de fecha %30s"
            ,"$mutuodir$dirsal{$palabra}$PROPIOSIN.$palabra",$fecha;
      };
  };
  my $resto = "#   a partir de archivos calculados por Sceptre y Simusol:\n"
      . join ("\n",@lista) ."\n";
  my $formato = "%4s%18s%14s%14s%13s%13s\n";
  my @inicialestime;
  my $cuantosrerun = @{$refsim->{archress}};
  open SALIDAcache, ">>$dirsal{cache}$PROPIOSIN.cache" 
    or die " No pude escribir $dirsal{cache}$PROPIOSIN.cache";
  print SALIDAcache
    "Archivos numéricos resumen producidos en $mutuodir$dirsalida{res}/:\n";
#  impr_debug(__LINE__.' sims $ref_arch',Dumper $ref_arch);
  for(my $rerun = 0; $rerun < $cuantosrerun; $rerun ++) {
      my $rr = $refsim->{res}->[$rerun]->{marcarerun};
      open SALIDAres, ">$dirsal{res}$refsim->{archress}->[$rerun]" or
      parars(230,"No puedo abrir $dirsal{res}$refsim->{archress}->[$rerun]"); 
      print SALIDAres 
"# Archivo $refsim->{archress}->[$rerun] $marca_Simusol ($progname)\n";
      print SALIDAres 
         "# Resumen de simulacion de $mutuodir$dirsal{d}$PROPIOSIN.d "
           ."de fecha $fechamarcas{d}\n";
      print SALIDAres $resto;
      if ($cuantosrerun >1) {
          print SALIDAres " -  RERUN $rerun/",($cuantosrerun-1);
          print SALIDAres " $refprograf->{variaciones}->[$rerun]";
          print SALIDAres "\n";
      };
      printf SALIDAres $formato,
'No.',  ,'variable ','val. inicial ','val. final ','val.minimo ','val maximo ';
      my $id = $refls2->{cual}->[$rerun]-1;
      for(my $i = 0; $i < @{$refsim->{nsceptres}}; $i++) {
	  my $varcomp = $refprograf->{varcomps}->[$i];  
          my $sceptre = $refsim->{nsceptres}->[$i];
          $id ++;
#          impr_debug(__LINE__.' sims $sceptre,$varcomp',[$sceptre,$varcomp]);
          my @lista = @{$refsim->{res}->[$rerun]->{$sceptre}}
            {'ini','fin','min','max'};
          push @lista,$id;
          map(do{defined $_ or $_ = ' '},@lista);
          printf SALIDAres "%3s%18s%14s%14s%13s%13s (%2s)\n"
            ,$i+1, $varcomp,$lista[0] ,$lista[1], $lista[2], $lista[3], $lista[4];      
      };#foreach
      print SALIDAres "    $refsim->{points}->[$rerun]";
      print SALIDAres " puntos de la solucion calculados; ";
      my $termcond = $refls2->{termconds}->[$rerun];
      print SALIDAres "$termcond\n";
      $termcond !~ /NORMAL STOP/
        and explicar_mensaje_res($refls2,$rerun,$tiempostop,$termcond); 
      close SALIDAres;
      system "cat $dirsal{res}$PROPIOSIN$rr.res" if $opt_hash{d};
      print SALIDAcache "  $refsim->{archress}->[$rerun]\n"; 
  };#for my $rerun
  close SALIDAcache;
  comfin('fins escr_res', $coderr);
  return $coderr;
}#escr_res
# -----------------------------------------------------------------------------
sub escr_simul{
  comfin('coms escr_simul', @_);
  my ($refsim,$refprograf) = @_; my $coderr = '';
  my $cuantosrerun = @{$refsim->{archress}}; my $cuantossimul = $cuantosrerun;
  my $juntarsimuls = '';
  if ($refprograf->{arch_var}) {
      $cuantossimul = @{$refprograf->{arch_var}};
      $cuantossimul < $cuantosrerun and $juntarsimuls = 1;
  } else {
      $refprograf->{arch_var} = ["$PROPIOSIN.simul"];
  };   
  impr_debug(__LINE__.' sims $refprograf',Dumper $refprograf); 
  impr_debug(__LINE__.' sims $cuantosrerun,$cuantossimul,$juntarsimuls'
    ,[$cuantosrerun,$cuantossimul,$juntarsimuls]);  
  my @lista;
  foreach my $palabra ('sim','paraplot') { 
      my $arch = "$dirsal{$palabra}$PROPIOSIN.$palabra";
      if (-e $arch) {
          my $fecha =   scalar localtime((stat $arch)[9]);
          push @lista, sprintf "#     %-24s  de fecha %30s"
            ,"$mutuodir$dirsal{$palabra}$PROPIOSIN.$palabra",$fecha;
      };
  };
  my $resto = "#   a partir de archivos calculados por Sceptre y Simusol:\n"
      . join ("\n",@lista) ."\n";
  my @renglones;
  my $textoparasimusol = '#  para Simusol: ';
  #  impr_debug(__LINE__.' sims $ref_arch',Dumper $ref_arch);
  my @palabras = qw (sceptrevars variables magnitudes unidades);
  my @palabrashay;
  map(do{$refprograf->{$_} and push @palabrashay,$_},@palabras); 
  $textoparasimusol .= "@palabrashay";
  foreach my $palabra (@palabras) {
      $refprograf->{$palabra} or next;
      push @renglones, $refprograf->{$palabra};
  };
  impr_debug(__LINE__.' sims @renglones',\@renglones);
  $resto .= $textoparasimusol;
  foreach my  $ref   (@renglones) {
      $resto .= "\n#"; map(do{$resto .= sprintf("%12s ",$_)}, @$ref);
  };
  open SALIDAcache, ">>$dirsal{cache}$PROPIOSIN.cache" or
      die " No pude escribir $dirsal{cache}$PROPIOSIN.cache";
  print SALIDAcache 
"Archivos numéricos completos producidos en $mutuodir$dirsalida{simul}/ :\n";
  open ENTRADAsim,"$dirsal{d}$PROPIOSIN.sim" 
    or die "No pude abrir $PROPIOSIN.sim";
  my @listasimul = @{$refprograf->{"arch_var"}};
  impr_debug(__LINE__.' sims $refprograf',Dumper $refprograf);
  my $rerun = 0;
  impr_debug(__LINE__.' sims $cuantosrerun,$cuantossimul,$juntarsimuls'
    ,[$cuantosrerun,$cuantossimul,$juntarsimuls]);  
  while (@listasimul) { 
      my $archsimul = shift @listasimul;   
      (my $propioarchsimul = $archsimul) =~ s/^.*\/([^\/]+)$/$1/;
      impr_debug(__LINE__.' sims',"                     $archsimul $juntarsimuls");
      open SALIDAsimul,">$archsimul" or
          die "No pude abrir para escritura $archsimul"; 
      print SALIDAsimul "#   Archivo $propioarchsimul; $marca_Simusol; ($progname)\n";
      $cuantossimul > 1
        and print SALIDAsimul "\#         $refprograf->{variaciones}->[$rerun]\n";
      $rerun ++;
      print SALIDAsimul "$resto\n";
      while (my $renglon =<ENTRADAsim>) { 
          if ($renglon =~ /^#RUN\/RERUN NUMBER\s+(\d+)$/) {
	      $juntarsimuls and next  or last;
          } else {
              if ($renglon !~ /^#/) {
                  my @listavalores = split /\s+/,$renglon;
                  @listavalores = grep ($_ ne '',@listavalores);
                  my $aimprimir = '';
                  for (my $i= 0; $i < @listavalores; $i ++) {
                      my $valor = $listavalores[$i];
                      $aimprimir .= sprintf " %12.5g", $valor;
                  }; #for   
                  print SALIDAsimul "$aimprimir\n"; 
              };
          };
      };#while my $renglon
      close SALIDAsimul;
      print SALIDAcache "  $archsimul\n";
  };#while @listasimul
  comfin('fins escr_simul');
}#escr_simul
#----------------------------------------------------------------------------
sub explicar_errores_sceptre{
  comfin('coms explicar_errores_sceptre',@_);
  my ($rcode,$coderr,@condiciones) = $_[0];
  if (not -f "$PROPIOSIN.ls1") {
      mensajear ('No se pudo ejecutar sceptre, primera parte');
      return $coderr;
  };
  if ($coderr eq '5') {
      my $archls1 = $PROPIOSIN . '.ls1';
      print "   Tres ultimos renglones del archivo $archls1:
            @condiciones" unless $opt_hash{noverb};
      $coderr = 30;
      return $coderr;
  };
  if ($rcode == 256) {
      mensajear(" Ejecución de Sceptre (${PROPIOSIN}_run) interrumpida");
      return $coderr;    
  };
  $coderr = 30;
  if (not -s "$PROPIOSIN.for") {
      mensajear(" sceptre no pudo generar un buen programa simulador
          para el circuito dado en $PROPIOSIN.d");
       return $coderr;
  };
  if (-s "$PROPIOSIN.ls2") {
      if (not system "grep  IMPLICIT.integration.cancelled $PROPIOSIN.ls2") {
          mensajear(" El método de integración IMPLICIT no sirve para este circuito");
      } elsif ((not -f "$PROPIOSIN.dirac" and not -f "$PROPIOSIN.sim")
        or system "grep 'TRANSIENT SOLUTION' $PROPIOSIN.ls2 2>/dev/null >/dev/null") {
          mensajear(" Sceptre no ha calculado transitorio para $PROPIOSIN.d");
      };
      return $coderr;
  };
  if (not -e "${PROPIOSIN}_run") {
      my @renglones = `grep undefined ${PROPIOSIN}.ls4`; chomp @renglones;
      impr_debug(__LINE__.' sims @renglones', \@renglones);
      my @renglonesundef = @renglones;
      map (do {$_ =~ s/^.+undefined reference to .(\w+)_.$/$1/},@renglonesundef);
      map (do {not $_ =~ /^.+undefined reference to .(\w+)_.$/},@renglones);
      if (@renglonesundef) {
           mensajear("Hay referencias indefinidas en el programa FORTRAN:\n      ".
               join (" ",@renglonesundef));
      } else {
           mensajear("Hay problemas en el programa FORTRAN generado por Sceptre:
             " .join (' ',@renglones));
      }; 
      mensajear(' El programa simulador resulto con errores');
      return $coderr;
  };
}#explicar_errores_sceptre
#----------------------------------------------------------------------------
sub explicar_mensaje_res{
  comfin('coms explicar_mensaje_res',@_);
  my ($refls2,$rerun,$tiempostop,$termcond) = @_;
  if ($termcond =~ /OPTIONAL TERMINATION/) {
      my $refterna = shift @{$refls2->{opt_code}};
#          impr_debug(__LINE__.' sims $refterna',$refterna);
      print SALIDAres "      Condicion:  $refterna->[2]\n";
  } else {
      my $numero = sprintf ("%G",$refls2->{times}->[$rerun]);
      print SALIDAres "    Tiempo pedido: $tiempostop; alcanzado $numero s\n";
      $numero = sprintf ("%G",$refls2->{stepsizes}->[$rerun]);
      print SALIDAres "    Ultimo paso (last step size): $numero s\n";
      $numero = sprintf ("%G",$refls2->{passcounters}->[$rerun]);
      print SALIDAres "    Pasos de integracion: $numero\n";
      print SALIDAres "    Rutina de integracion: $refls2->{intes}->[$rerun]\n";
  };
  comfin('fins explicar_mensaje_res');
  return '';
}#explicar_mensaje_res
#----------------------------------------------------------------------------
sub extraer_sim{
  comfin('coms extraer_sim',@_);
  my ($refls2) = @_; my $coderr = '';
  my $refsim = {}; my $refprograf = {};
  my @palabras = ('nam','ini','fin','min','max','no. of solution points:');
  my @abrs = ('nam','ini','fin','min','max','points'); 
  foreach my $abr (@abrs) {
      my $palabra = shift @palabras;
      my @algos = `grep  "\#$palabra" $dirsal{d}$PROPIOSIN.sim`;chomp @algos;
#      impr_debug(__LINE__.' sims @algo',\@algos);
      my $rerun = 0;
      foreach (@algos) {
          s/^#$palabra\s*(.*\w)\s*$/$1/;
#          impr_debug(__LINE__.' sims $algo',$_);
          if ($abr ne 'points') {
              $refsim->{$abr}->[$rerun] = [split /\s+/,$_];
	  } else {
              s/$palabra\s+//;
              $refsim->{$abr}->[$rerun] = $_;
          };
          $rerun ++;
      };
  };
  $refsim->{nsceptres} = $refsim->{nam}->[0];
#  impr_debug(__LINE__.' sims $refsim',Dumper $refsim);
  my $cuantosrerun = scalar @{$refsim->{nam}};
  my $marcarerun = '';
  for (my $rerun = 0; $rerun < $cuantosrerun; $rerun++) { 
      my $i = 0; $rerun and $marcarerun = "_$rerun";
      $refsim->{res}->[$rerun]->{marcarerun} = $marcarerun;
      push @{$refsim->{archress}},"$PROPIOSIN$marcarerun.res";
#      push @{$refsim->{archsimuls}},"$PROPIOSIN$marcarerun.simul"
#	  if $rerun < $cuantossimul;
      for my $nombre (@{$refsim->{nam}->[0]}) {
          for my $palabra ('ini','fin') {
              $refsim->{res}->[$rerun]->{$nombre}->{$palabra}
                 = $refsim->{$palabra}->[$rerun]->[$i];
          };
          for my $palabra ('min','max') {
              my $valor
                = sprintf ("%10.4E", $refsim->{$palabra}->[$rerun]->[$i]);
              $refsim->{res}->[$rerun]->{$nombre}->{$palabra} = $valor;
          };
          $i ++;
      };
  };
  $refprograf->{sceptrevars} = $refsim->{nsceptres};
  @{$refprograf->{varcomps}} = @{$refsim->{nsceptres}};
  impr_debug(__LINE__.' sims varcomps',$refprograf->{varcomps});
  #si se puede leer .paraplot, $refprograf->{varcomps} tiene sceptrevar y propia
  @{$refprograf->{variaciones}} = @{$refls2->{intes}};
#  $refprograf->{arch_var} = ["$PROPIOSIN.simul"];
  @{$refprograf->{variaciones}} > 1 or @{$refprograf->{variaciones}} = ();
#  impr_debug(__LINE__.' sims $refsim',Dumper $refsim);
  comfin('fins extraer_sim $coderr',$coderr);
  return $coderr,$refsim,$refprograf;
}#extraer_sim
#----------------------------------------------------------------------------
sub identificar_terminate{
  comfin('coms identificar_terminate',@_);
  my $code = $_[0];
#  my $renglon =  `grep OPTIONAL.TERMINATION.CODE $PROPIOSIN.ls2`;chomp $renglon;
#  my @lista = split /\s+/,$renglon; my $code = $lista[-1];
  my @terminates =  `grep TERMINATE $dirsal{d}$PROPIOSIN.d`;chomp @terminates;
  impr_debug(__LINE__.' sims @terminates',Dumper \@terminates);
  my $textoterminate = $terminates[$code-1]; 
  comfin('fins identificar_terminate',$textoterminate);
  return $textoterminate;
}#identificar_terminate  
#----------------------------------------------------------------------------
sub interpretar_opciones_s{
  my $refs = $_[0];
  GetOptions(\%opt_hash, 'help','noclas','d','version','adsim' 
    ,'nopausa','noverb','outdir=s')
    or pod2usage(2);
  help() if defined $opt_hash{help};
  version() if defined $opt_hash{version};
  print STDERR ".....  coms interpretar_opciones_s($refs) \n" if $opt_hash{d};
  #----------------------------------------------------------------------------
  parars(200,' Pidio no simular') if $opt_hash{nosim};
  #----------------------------------------------------------------------------
  $debug = $opt_hash{d}; #$debug está definida con our en Ayudas.pm
  if ($opt_hash{noclas}) {
      foreach my $key (keys %dirsalida) {
          substr($dirsalida{$key},0,1) ne 'c' and
            $dirsalida{$key} = '';
      };
  };
  resolver_outdir($refs);
  calcular_dirsal();
  comfin('fins interpretar_opiones_s');
  return ''
}#interpretar_opiones_s    
#----------------------------------------------------------------------------
sub leer_paraplot_s{
  comfin('coms leer_paraplot_s',@_);
  my ($archparaplot,$refprograf) = @_;my $coderr= '';
  open ENTRADAparaplot,$archparaplot or do {
      mensajear(" No pude abrir $archparaplot"); $coderr = 20; 
  };
  my (@sceptres,@propias,@magns,@unis,@indices,@varcomps);
  my @palabras =  ('sceptrevars','variables','unidades','magnitudes','indices',
    'arch_var','variaciones'); 
  if (not $coderr) {
      my @renglones = <ENTRADAparaplot>;chomp @renglones;
      close ENTRADAparaplot;
      while (@renglones) {
          my $renglon = shift @renglones;
          if ($renglon =~ /^\s*(\w+)\s+SIMULADO\s*=\s*(.*)$/) {
              my $cosastring = $1; my $listastring = $2;
              if (grep (/$cosastring/,@palabras) ){
                  $refprograf->{$cosastring} = [split /\s*,\s*/,$listastring];
              } elsif ($cosastring eq 'archivo') {
                 $refprograf->{$cosastring} = $listastring;
              };     
          };
      };	  
 #     impr_debug(__LINE__.' sims $refprograf',Dumper $refprograf);
     (@indices == 0)  or (@propias == @indices and @propias >= @sceptres) 
         or (do {mensajear(" errores en el archivo paraplot,
         $archparaplot"); $coderr = 70});
  };
  if (not $coderr) {
      $refprograf->{indices} and @indices = @{$refprograf->{indices}};
      @sceptres = @{$refprograf->{sceptrevars}};
      @propias = @{$refprograf->{variables}};
      @indices == 0 and @{$refprograf->{indices}} = @indices = (1 .. @propias);
      my @palabras =  ('sceptrevars','variables','unidades','magnitudes','indices'); 
      foreach my $palabra (@palabras) {
	  impr_debug(__LINE__.' sims',[$palabra,@{$refprograf->{$palabra}}]);
      }; 
      my ($indiceant) = (0);#$sceptres[0],$propias[0]);    
      for(my $i = 1; $i <= @indices; $i ++) {
	  my $indice = $indices[$i-1];
#          impr_debug(__LINE__.' sims $i,$indiceant,$indice',[$i,$indiceant,$indice]);
          if ($indiceant < $indice) {
#	      impr_debug(__LINE__.' sims $i,$indiceant,$sceptres[$indiceant]
#                ,$propias[$indice-1]'
#                ,[$i,$indiceant,$sceptres[$indiceant],$propias[$i-1]]);
              push @varcomps,"$sceptres[$indiceant],$propias[$i-1]";
#              impr_debug(__LINE__.' sims $varcoms[-1]',$varcomps[-1]);
              $indiceant++;
	  };
      };
      $refprograf->{varcomps} = \@varcomps;
  };    
  comfin('fins leer_paraplot_s @varcomps',$coderr,$refprograf);
  return $coderr;	     
}#leer_paraplot_s;
#----------------------------------------------------------------------------
sub parars{
  comfin('coms parars',@_);
  my ($codigo,$mensaje) = @_;
  if ($mensaje) {
      explic( ' '.'=' x 70);mensajear($mensaje);
  };
  explic( ' '.'=' x 70) if $codigo;
  system "rm $gnusdir/* 2>/dev/null; rmdir $gnusdir 2>/dev/null" if -d $gnusdir;
  if ($debug) {
      if ($PROPIOSIN) { 
          mensajear(
           " código sc: $codigo para $PROPIOSIN.d $curdirori, desde $outdir");
      } else {
          mensajear(" codigo sc: $codigo,en $curdirori, desde $outdir");
      };
  } else {
      mensajear (" codigo sc: $codigo");
  };
  exit $codigo; 
}#parars
#----------------------------------------------------------------------------
sub parars_ver{
  comfin('coms parars_ver', @_);
  my ($cod,$archls,$mens) = @_;
  exit $cod if $opt_hash{nopausa}; 
  mensajear($mens) if $mens;
  explic("   Puede ver todos los mensajes del Sceptre 
          en el archivo $archls; 
       vealos ahora, pulsando ENTER-RETURN
          (y  avance con barra espaciadora y salga con q)
       o interrumpa el procesamiento de este archivo pulsando q");
  my $dummy = <STDIN>; 
  if (defined $dummy and $dummy =~ /q/) {
      parars($cod) if $dummy eq 'q';
  } elsif (-e $archls) {
      impr_debug(__LINE__.' sims $archls',$archls);
      system "less $archls";
  } else {
      mensajear(" Pero el archivo $archls no existe!");
  };
  comfin('fins parars_ver');
  return '';; 
}
#----------------------------------------------------------------------------
sub revisar_ls1{
  # si no ha habido problemas, devuelve tiempos; si hubo problemas..parars_ver
  comfin('coms revisar_ls1 ', @_);
  my $PROPIOSIN = $_[0]; my $rcode = '';
  my $archls1 = $PROPIOSIN . '.ls1';
  my @lista = `cat $archls1`; chomp @lista;
  my @listiempo = grep (/STOP\s*TIME/, @lista);
  map (s/\s*STOP\s*TIME\s*=\s*(\S.*\S)\s*$/$1/i, @listiempo);
  my $tiempostop = join '    ',@listiempo;
  @listiempo = grep (/START\s*TIME/, @lista);
  map (s/\s*START\s*TIME\s*=\s*(\S.*\S)\s*$/$1/i, @listiempo);
  my $tiempostart = join '    ',@listiempo;
  my @listawarning = grep /WARNING/,@lista;
  if (@listawarning) {
      my $texto = join "\n",@listawarning; 
      mensajear("- - - Aviso de Sceptre de posibles problemas:\n$texto");
  };
  my @listarefer = grep /0\'(\w+)\s*\'\s*IS REFERENCED BY/ ,@lista;
  if (@listarefer) {
      my $texto = join "\n",@listarefer; 
      mensajear("- - - Aviso de Sceptre de problema serio:\n$texto");
      avgrav("Variable o función no definida para Sceptre");
      comfin('fins revisar_ls1 ',66);
      parars(66);
  };
  my @condiciones =  `tail -n3 $archls1`; 
  my $condicionls1 = $condiciones[-1];
  if ($condicionls1 =~ /SYSTEM NOW ENTERING SIMULATION/) {
      print "SYSTEM NOW ENTERING SIMULATION\n" if $opt_hash{noverb};
      my @condiciones =  `tail -n3 $archls1`; 
      if ($condiciones[1] !~ /\s+END/ and $condiciones[1] =~ /\w/) {
          avgrav(" sceptre no aceptó todo el archivo $PROPIOSIN.d");
          $rcode = 5;
      };
      comfin('fins revisar_ls1 $tiempostart,$tiempostop '
        ,$tiempostart,$tiempostop);
      return ($rcode,$tiempostart,$tiempostop,@condiciones);
  };
  my ($antant,$ant,$pres) = ('0','0','0');
  avgrav(" sceptre no aceptó el archivo $PROPIOSIN.d");
  explic ("........ Selección de mensajes de Sceptre; 
                  (todos están en $archls1)");
  my $raras = 0;
  foreach (@lista) {
      if (/PRECEDING UNRECOGNIZABLE CARD IGNORED/
           or /INCORRECT DELIMITER/ 
           or /VARIABLE NAME EXCEEDS/){
          $raras ++;last if $raras >5;
      };
      ($antant,$ant,$pres) = ($ant, $pres, $_);
      ($antant =~ /^0/  or $ant !~ /^0\S/) and next;
      print "$antant\n" 
        unless ($antant =~ /^\s*$/ or $antant =~ /^\s*END\s*/); 
      if ($ant =~ /ERROR MESSAGE/) {
          $pres =~ s/^0//; 
          print "$pres\n";$pres = '';
      } else {
          $ant =~ s/^0//; 
          print "$ant\n";$ant = '';
      };
  };
  $pres =~ s/^0//;
  mensajear("$pres") if $pres ne '';
  #impr_debug(__LINE__.' sims $pres', $pres);
  my $ultima = $lista[-1];
  my $mensparar='';
  if ($raras) {
      # $mensparar = " El archivo $CORTOSIND.d no parece adecuado\n";
      $rcode = 249; 
  };
  if ($ultima =~ /E\/C loop/) {
      $mensparar .= "====== Sceptre no acepta ciclos con solo 
          elementos E o C"; 
      $rcode = 252;
  } elsif ($lista[-2] =~ /AN ILLEGAL PROCESSING SEQUENCE HAS BEEN REQUESTED/){
      $mensparar = 
            "===== Error de sintaxis en $PROPIOSIN.d; quizás muy incompleto";
      $rcode = 250;
  } elsif ($ultima =~ /CURRENT SOURCE CUT SET/) {
      $mensparar = "===== No es posible un elemento J fuera de un ciclo,
                    ni dos elementos J en serie";
      $rcode = 251;
  } elsif ($ultima =~ /PROGRAM CAPACITY HAS BEEN EXCEEDED/) {
      $mensparar = "$lista[-3]\n$lista[-2]
       Se agotó la memoria para Sceptre; si es
          por tablas dependientes del tiempo puede conseguir partir 
          la ejecucion en dos o más intervalos";
      $rcode = 253;
  };
  comfin('fins revisar_ls1 ');
  impr_debug(__LINE__. ' sims $rcode, $archls1,$mensparar'
    ,[$rcode, $archls1,$mensparar]);
  parars_ver($rcode,$archls1,$mensparar);
}#revisar_ls1
#----------------------------------------------------------------------------
sub simular{
  comfin('coms simular',@_);
# ----------------------------------------------------------------------------
  my ($outdirfinal,$PROPIOSIN) = @$refs{'outdirfinal','PROPIOSIN'};
  my $lugar = "$outdirfinal$dirsal{d}"; 
  chdir $lugar unless $lugar eq '';
  my $FC = 'gfortran -fno-automatic'; # para compilar FORTRAN
  my $BINDIR = "/usr/local/bin";
  my $LIBDIR = "/usr/local/lib";
  my $LIBX2 = "$LIBDIR/libsceptre.a";
  my $LIBX3 = "$LIBDIR/libsceptreaux.a";
  my $SCEPTRE = "$BINDIR/sceptre";
  if ( ! -d "$HOME/lib") {mkdir "$HOME/lib"};
  if ( ! -e "$HOME/lib/modellib.dat") {
      system "cp $LIBDIR/modellib.dat $HOME/lib/modellib.dat"
  }; 
  if (! -e "$HOME/lib/usrlib.a") {
      system "cp $LIBDIR/usrlib.a  $HOME/lib/usrlib.a"
  }; 
  my $USRLIB = "$HOME/lib/usrlib.a";
  my $MODELLIB = "$HOME/lib/modellib.dat";
  if (-e "modellib.dat") {system "rm modellib.dat 2>/dev/null"};
  system "ln -s ${MODELLIB} modellib.dat 2>/dev/null"; 
  explic(
    "======= Si parece que se \"quedó\" el Sceptre, interrumpa con CTRL_C");
  my $rcode ='';
  system "cp funciones.for  $dirsal{d}funciones.for" if $dirsal{d} ne '';
  if ($noverb) {
      $rcode = system "$SCEPTRE $PROPIOSIN >/dev/null" 
  } else {
      $rcode =   system "$SCEPTRE $PROPIOSIN";
  };
#  impr_debug(__LINE__.' sims $rcode,$rcode/256',[$rcode,$rcode/256]);
#  puede haber aparecido un cat de $PROPIOSIN.lso
  print "error code $SCEPTRE ",$rcode/256,"\n" if $rcode;
  my ($tiempostart,$tiempostop,@condiciones);
  if (-e "$PROPIOSIN.ls1") {
      ($coderr,$tiempostart,$tiempostop,@condiciones) = revisar_ls1($PROPIOSIN);
  };
  if ($rcode or $coderr) {
      explicar_errores_sceptre($rcode,$coderr,@condiciones);   
  };    
  system("rm -f pri.o exec2 acsave.dat datasave.dat 2>/dev/null");
  if (not -e "$PROPIOSIN.ls2") { 
      mensajear(" Sceptre no dejo rastros de la ejecución de la segunda parte;
        puede haber habido violacion de segmento");
      $coderr = 28;
      comfin('fins simular',$coderr);
      return $coderr;
  };    
  my $refls2 = {};
  $refls2 = revisar_ls2($PROPIOSIN,$tiempostart,$tiempostop);
  ($rcodes,my $refsim,my $refprograf) = extraer_sim($refls2);
  if ($rcodes) {
      mensajear(" Hubo problemas para extraer_sim");
  };
  if (not $rcodes) {
      my $archparaplot = "$dirsal{paraplot}$PROPIOSIN.paraplot";
      if (-e $archparaplot) {
          $fechamarcas{paraplot} = scalar localtime((stat "$archparaplot")[9]);   
          $coderr = leer_paraplot_s($archparaplot,$refprograf);
      } else {
          mensajear("No existe $archparaplot");
      };
      ($rcodes) = escr_res($refls2,$refsim,$tiempostop,$refprograf);
      if ($rcodes) {
          mensajear (" Hubo problemas para preparar $PROPIOSIN.res");
      } else {
          if ($opt_hash{adsim}) {
              system "scripts/adsim";
          }; 
          $rcodes = escr_simul($refsim,$refprograf);
          if ($rcodes) {
              mensajear("Hubo problemas para preparar $PROPIOSIN.simul");
	  } else {
	      if ($opt_hash{d}) {
                  my @archres = @{$refsim->{archress}};
                  my $archres = join ("  ",@archres);
                  my @archsimul = @{$refprograf->{arch_var}};
                  my $archsimul = join ("  ",@archsimul);
                  explic(
        "Resumen de resultados de la simulación en: \n" 
           .' 'x12 ."$dirsal{res}$archres
           y resultados completos en: \n"
           .' 'x12 ."$dirsal{simul}$archsimul"); 
              };
          };    
      };
  };
    impr_debug(__LINE__.' sims $outdir',$outdir);
  chdir $refs->{outdir} if $refs->{outdir} ne ''; 
  if (not $opt_hash{noclas}) { 
      impr_debug(__LINE__.' sims ',"\n\n      ya cambiado a outdir\n");
  };

  comfin('fins simular',$rcodes);
  return $rcodes
}#simular
# ---------------------------------------------------------------------------
sub revisar_ls2{
  comfin('coms revisar_ls2', @_);
  my ($propio,$tiempostart,$tiempostop) = @_;
  my $archls2 = "$dirsal{d}$propio.ls2";
  if (not system("grep 'INITIAL CONDITION SOLUTION' $archls2 >/dev/null")) { 
      system "less $archls2";
      parars(0);
  };
  open ENTRADAls2,"<$archls2" or die "No existe el archivo $propio.ls2";

  my ($condicionls2,$menserror) = ('','');
  my $refls2 = {};
  my $rerun = 0;
  while (<ENTRADAls2>) {     
      chomp;
      if (/^0RUN.RERUN NUMBER \s*(\d+)$/) {
	  push @{$refls2->{reruns}},$1;$rerun = $1; 
      } elsif (/^0INTEGRATION ROUTINE \s*(\w+)\s*$/) {
	  $refls2->{intes}->[$rerun] = $1;
      } elsif (/^0LAST STEP SIZE \s*([\d\.]+)D([\+\-])(\d+)/) {
          $refls2->{stepsizes}->[$rerun] = "$1D$2$3";
      } elsif (/^0LAST STEP SIZE \s*([\d\.]+)([\+\-])(\d+)/) {
          $refls2->{stepsizes}->[$rerun] = "$1D$2$3";
      } elsif (/^0CURRENT SIMULATION TIME \s*(.+)$/) {
          $refls2->{times}->[$rerun] = $1;
      } elsif (/^0INTEGRATION STEP COUNTER \s*(.+)$/) {
          $refls2->{stepcounters}->[$rerun] = $1;
      } elsif (/^0INTEGRATION PASS COUNTER \s*(.+)$/) {
          $refls2->{passcounters}->[$rerun] = $1;
      } elsif (/^0TERMINATION CONDITION \s*(.+\S)\s*$/) {
          $refls2->{termconds}->[$rerun] = $1;
      } elsif (/^0OPTIONAL TERMINATION CODE IS\s*(\d+)/) {
          my $code = $1;
          my $terminate = identificar_terminate($code);
          $refls2->{opt_code}->[$rerun] = [$rerun,$code,$terminate];
      } elsif (/^0directory of/) {
          last;
      };
  };
  foreach my $palabra (qw(passcounters stepcounters stepsizes times)) {
      my $numero = $refls2->{$palabra}->[$rerun];
      $numero =~ s/D/E/; 
      $refls2->{$palabra}->[$rerun] = $numero
  };

  if (/^0directory of/) {
      while (<ENTRADAls2>) {
          if(/_0\s+\d\s+\d+\s+(\d)/) {
              $refls2->{cual}->[$rerun] = $1;last;
          };
      };
  };
  while (<ENTRADAls2>) {
      if (/^0(.+)/) {
          $refls2->{condicionls2} = $1;
      };
  };	  
  impr_debug(__LINE__.' sims $refls2',Dumper $refls2);
  comfin('fins revisar_ls2');
  return $refls2;
}#revisar_ls2
#----------------------------------------------------------------------------
sub help{
    pod2usage({-verbose => 0
           ,-exit => 0
	   ,-message => "   $progname  $version
       es parte del conjunto de scripts de S I M U S O L
            más ayuda con   
	       man $progname
	    y luego salga con   q\n"   
            })
}
#----------------------------------------------------------------------------
sub version{
   print "\n       $progname  $version\n\n";
   exit 0  
}
