Skip to content
Snippets Groups Projects
diffNODE.001_01 8.72 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/usr/bin/perl -w
    
    use strict;
    use FindBin qw ($Bin);
    use lib $Bin;
    use FileHandle;
    
    #Frame was inlined in this script
    #use Tools::Frame;
    
    use Data::Dumper;
    use POSIX qw (floor);
    use Getopt::Long;
    
    my %opts = (
                'spnorms' => 'VORTICITY,DIVERGENCE,TEMPERATURE,KINETIC ENERGY',
                'gpnorms' => '',
                'norm-max-diff' => .050000,
                'jo-max-diff'   => .030000,
               );
    
    
    sub frame
    {
      my ($t, $width, $border) = @_;
      my $len = length ($t);
    
      $border = 1 unless (defined ($border));
    
      my $S = ' ';
    
      my ($C, $V, $H) = ('*', '|', '-');
    
      ($C, $V, $H) = (' ', ' ', ' ')
        unless ($border);
    
      my $df = 3;
      $width ||= $len + 2 * $df;
    
      my $line1 = $C . ($H x ($width-2)) . $C;
      my $line2 = $V . ($S x ($width-2)) . $V;
    
    
      my $TEXT = '';
    
      $TEXT .= "$line1\n";
      for (1 .. ($df-1)/2)
        {
          $TEXT .= "$line2\n";
        }
    
      die ("Cannot frame text: `$t'\n")
        if ($width - 2 * $df <= 0);
      
      while ($t)
        {
          my $s = substr ($t, 0, $width - 2 * $df, '');
    
          my $i = 0;
          while (length ($s) < $width - 2 * $df)
            {
              if ($i % 2)
                {
                  $s = " $s";
                }
              else
                {
                  $s = "$s ";
                }
              $i++;
            }
          my $linet = $V . ($S x ($df-1)) . $s .  ($S x ($df-1)) . $V;
          $TEXT .= "$linet\n";
        }
    
      for (1 .. ($df-1)/2)
        {
          $TEXT .= "$line2\n";
        }
      $TEXT .= "$line1\n";
    }
    
    
    
    sub xave
    {
      my $f = shift;
      my $fh = 'FileHandle'->new ("<$f");
    
      my @gpregs;
    
      if ($opts{gpnorms})
        {
          if ((scalar (@{$opts{gpnorms}}) == 1) && ($opts{gpnorms}[0] eq '*'))
            {
              @gpregs = (qr/^\s*GPNORM\s+\b(\S+)\b/);
            }
          else
            {
              @gpregs = map { qr/^\s*GPNORM\s+\b(\Q$_\E)\b/ } @{$opts{gpnorms}};
            }
        }
    
      my @x;
      MAIN: while (defined (my $line = <$fh>))
        {
          AGAIN:
    
          if ($line =~ m/^\s*GPNORM\s+/o)
            {
              for my $gpreg (@gpregs)
                {
                  if ($line =~ $gpreg)
                    {
                      my $F = $1;
                      $line = <$fh>;
                      next MAIN  unless ($line =~ m/AVE\s+0/o);
                      for ($line)
                        {
                          s/^\s*AVE\s*//o; 
                          s/\s+/\n/go; 
                        }
                      push @x, map { [ $F, $_ ] } split (m/\n/o, $line);
                      next MAIN;
                    }
                }
            }
    
          if ($line =~ s/^\s*SPECTRAL\s+NORMS\s+-\s+//o)
            {
              AGAIN_SPNORMS:
    
    
              goto AGAIN
                unless (($line = <$fh>) =~ s/^\s+LEV\s+//o);
    
              my %index;
              %index = ();
              for my $spnorm (@{$opts{spnorms}})
                {
                  my $index = index ($line, $spnorm);
                  $index{$spnorm} = $index 
                    if ($index >= 0);
                }
    
              my @spnormk = sort { $index{$a} <=> $index{$b} } 
                            grep { defined $index{$_} } 
                            @{$opts{spnorms}};
    
              goto AGAIN
                unless (($line = <$fh>) =~ s/^\s+AVE\s+//o);
    
              my @spnormv = split (m/\s+/o, $line);
    
              while (@spnormk)
                {
                  my $spnormk = shift (@spnormk);
                  my $spnormv = shift (@spnormv);
                  die ("$spnormk, $spnormv\n")
                    unless (defined ($spnormk) && defined ($spnormv));
                  push @x, [ $spnormk, $spnormv ];
                }
    
              goto AGAIN_SPNORMS;
    
            }
        }
    
      return @x;
    }
    
    sub xobstype
    {
      my $f = shift;
      my $fh = 'FileHandle'->new ("<$f");
    
      # keep final value for obs number & JO
    
      my @x;
      while (defined (my $line = <$fh>))
        {
          next unless ($line =~ m/ObsType\s+(\d+)\s+Total:\s*(\d+)\s+(\S+)\s+/o);
          @{$x[$1]}{qw (number JO)} = ($2, $3);
        }
    
      return @x;
    }
    
    sub xjog
    {
      my $f = shift;
      my $fh = 'FileHandle'->new ("<$f");
    
      # keep final value for obs number & JO
    
      my %x;
      while (defined (my $line = <$fh>))
        {
          next unless ($line =~ m/Jo Global\s*:\s*(\d+)\s+(\S+)/o);
          @x{qw (number JO)} = ($1, $2);
        }
    
      return \%x;
    }
    
    sub center
    {
      my ($s, $n) = @_;
      my $i = 0;
      while (length ($s) < $n) 
        {
          $s = $i % 2 ? " $s" : "$s ";
          $i++;
        }
      return $s;
    }
    
    
    
    &GetOptions 
      ('spnorms=s'       => \$opts{'spnorms'},
       'gpnorms=s'       => \$opts{'gpnorms'},
       'norm-max-diff=s' => \$opts{'norm-max-diff'},
       'jo-max-diff=s'   => \$opts{'jo-max-diff'},
      );
    
    $opts{'spnorms'} = [ split (m/,/o, $opts{'spnorms'}) ];
    $opts{'gpnorms'} = [ split (m/,/o, $opts{'gpnorms'}) ];
    
    my ($f1, $f2) = @ARGV;
    
    die ("Usage: $0 NODE.001_01 NODE.001_01.ref\n")
      unless ($f1 && $f2);
    
    my @fx1 = &xave ($f1);
    my @fx2 = &xave ($f2);
    
    print &frame ("NORMS DIFFERENCES", 121);
    
    my @x = ([]);
    my %diff;
    my $zero = 0;
    my $numb = 0;
    
    my $tag1 = "NORMDIFF";
    my $tag2 = "NORMSTAT";
    
    my $nout = 0;
    
    while (defined (my $fx1 = shift (@fx1)) && defined (my $fx2 = shift (@fx2)))
      {
        my ($f1, $x1) = @$fx1;
        my ($f2, $x2) = @$fx2;
    
        die ("Field mismatch $f1 != $f2\n")
          unless ($f1 eq $f2);
    
        chomp ($x1); chomp ($x2);
        if (($x1 !~ m/^\s*$/o) && ($x2 !~ m/^\s*$/o))
          {
            my $dx = $x1 - $x2;
            my $dr = ($x1+$x2 > 0) ? 2*$dx/($x1+$x2) : 0.;
    
            my $sdx = sprintf ('%17.9e', $dx);
            my $sdr = sprintf ('%17.9e', $dr);
    
            $dx = $sdx; $dx = $dx + 0.;
            $dr = $sdr; $dr = $dr + 0.;
    
            push @{$x[-1]},
              sprintf (" $tag1 | %20s | %17.9e  |  %17.9e  |  %17s  |  %17s %s\n", &center ($f1, 20), $x1, $x2, $sdx, $sdr, 
                       $dr > $opts{'norm-max-diff'} ? '*' : '');
    
            $nout++ 
             if ($dr > $opts{'norm-max-diff'});
    
            if (abs ($dr) > 0)
              {
                my $n = &floor ((log (abs ($dr)) / log (10)));
                $diff{$n}++;
    
              }
            else
              {
                $zero++;
              }
    
            $numb++;
          }
        else
          {
            push @x, [];
          }
      }
    
    printf " $tag1 |                      |%-19s | %-19s | %-19s | %-19s\n", 
            &center ("NORM(REF)", 19), &center ("NORM(EXP)", 19), 
            &center ("NORM(REF)-NORM(EXP)", 19), &center ("(NORM(REF)-NORM(EXP))", 19);
    
    printf " $tag1 |                      |%-19s | %-19s | %-19s | %-19s\n", 
            '', '', '', &center ("/NORM(REF)", 19);
    
    for (my $i = 0; $i <= $#x; $i++)
      {
        last unless (@{$x[$i]});
        print @{$x[$i]};
      }
    
    print "\n";
    
    
    my $diff_cumul = 0;
    my $perc_cumul = 0;
    for my $n1 (sort { $a <=> $b } keys (%diff))
      {
        my $n2 = $n1 + 1;
        my $diff = $diff{$n1};
        my $perc = 100 * $diff / $numb;
        $diff_cumul += $diff;
        $perc_cumul += $perc;
        printf (" $tag2 | 1e%+2.2d .. 1e%+2.2d | %3d / %3d | %3d / %3d | %6.2f %%, %6.2f %%\n", $n1, $n2, $diff, $numb, $diff_cumul, $numb, $perc, $perc_cumul);
      }
    
    if ($nout)
      {
        print "\n";
        my $text = sprintf ("WARNING : SOME NORMS DIFFERENCES ARE OUTSIDE ALLOWED LIMIT OF %6.2f %%\n", 100 * $opts{'norm-max-diff'});
        print $text x 5;
      }
    
    print "\n";
    
    my @ot1 = &xobstype ($f1);
    my @ot2 = &xobstype ($f2);
    
    my $not1 = scalar (@ot1);
    my $not2 = scalar (@ot2);
    
    my $not = $not1 > $not2 ? $not1 : $not2;
    
    goto END
      unless ($not > 0);
    
    my $obs_fmtd  = " %10d |  %13.7e ";
    my $obs_fmtds = " %10s |  %13s ";
    my $obs_fmtp  = " %20d |      %9.4f %% ";
    my $obs_fmtps = " %20s |  %15s ";
    
    printf (" OBS_DIFF | %6s | ", 'Type');
    printf ($obs_fmtds, 'NOBS(REF)', 'JO(REF)');
    print " | ";
    printf ($obs_fmtds, 'NOBS(EXP)', 'JO(EXP)');
    print " | ";
    printf ($obs_fmtps, 'NOBS(EXP)-NOBS(REF)', 'JO(EXP)-JO(EXP)');
    printf ("\n");
    
    my $pot = sub 
      {
        my ($ot, $obs_fmt) = @_;
        $obs_fmt ||= $obs_fmtd;
        (my $blank = sprintf ($obs_fmt, 0, 0)) =~ s/\S/ /go;
        if ($ot)
          {
            printf ($obs_fmt, $ot->{number}, $ot->{JO});
          }
        else
          {
            print $blank;
          }
      };
    
    my $dot = sub
      {
        my ($ot1, $ot2) = @_;
    
        my $dot = $ot1 && $ot2 ? { number => abs ($ot1->{number} - $ot2->{number}), 
                                   JO => 100 * 2 * abs ($ot1->{JO} - $ot2->{JO}) / abs ($ot1->{JO} + $ot2->{JO}), } : undef;
        return $dot;
      };
    
    for my $i (1 .. $not-1)
      {
        my $ot1 = $ot1[$i];
        my $ot2 = $ot2[$i];
        my $dot12 = $dot->($ot1, $ot2);
    
        printf (" OBS_DIFF | %6d | ", $i);
    
        $pot->($ot1);
        print " | ";
        $pot->($ot2);
        print " | ";
        $pot->($dot12, $obs_fmtp);
        print "\n";
    
    
      }
    
    my $jog1 = &xjog ($f1);
    my $jog2 = &xjog ($f2);
    
    if ($jog1 || $jog2)
      {
        my $dot12 = $dot->($jog1, $jog2);
        printf (" OBS_DIFF | GLOBAL | ");
        $pot->($jog1);
        print " | ";
        $pot->($jog2);
        print " | ";
        $pot->($dot12, $obs_fmtp);
        print "\n";
    
        
        if ($dot12->{JO} > 100 * $opts{'jo-max-diff'})
          {
            my $text = sprintf ("WARNING : GLOBAL JO DIFFERENCE IS OUTSIDE ALLOWED LIMIT OF %12.6f %%\n", 100 * $opts{'jo-max-diff'});
            print "\n";
            print $text x 5;
          }
    
      }
    
    
    print "\n";
    
    END:
    
    
    
    exit $nout;