namsplit.pl 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #!/usr/bin/env perl
  2. #
  3. # =============================================================================
  4. # namsplit.pl: Splits a OASIS3 namcouple file for the pseudo-parallel mode
  5. #
  6. # UFla, 06/2010
  7. # =============================================================================
  8. use strict;
  9. use warnings;
  10. # Define regular expressions for some important lines of the namcouple file
  11. my $re_fields_sec = '^ \$STRINGS\s+$';
  12. my $re_nfield_sec = '^ \$NFIELDS\s+$';
  13. my $re_field_begin = 'EXPORTED\s+$';
  14. my $re_end_sec = '^ \$END\s+$';
  15. my $re_comment = '^#';
  16. # We need exactly two command line arguments:
  17. # - the number of processors (i.e. the number of files to split into)
  18. # - the namcouple file we want to split
  19. @ARGV == 2 or die "Usage: namsplit.pl <NUM_PROCS> <NAMCOUPLE_FILE>\n";
  20. (my $num_procs,my $namcouple) = @ARGV;
  21. open NAMCOUPLE, "<$namcouple" or die "Can't open file '$namcouple'\n";
  22. # The @header array holds all the header lines of the files, i.e. all
  23. # lines _before_ any couple field definitions. Note that comments are
  24. # stripped.
  25. my @header = ();
  26. # Now fill the @header by reading the namcouple file line-by-line
  27. while (<NAMCOUPLE>)
  28. {
  29. next if (/$re_comment/); # Ignore comments
  30. push @header,$_; # Store current line in @header
  31. <NAMCOUPLE> if (/$re_nfield_sec/); # Ignore the line after the NFIELDS line
  32. # (this line is recreated later for each
  33. # split file)
  34. last if (/$re_fields_sec/); # Stop if end of header found
  35. }
  36. # $num_fields counts the overall number of fields found in the namcouple file
  37. my $num_fields = 0;
  38. # The @fields array holds all the lines for each couple field as one string
  39. my @fields;
  40. # Count fields and fill @fields
  41. while (<NAMCOUPLE>)
  42. {
  43. next if (/$re_comment/); # Ignore comments
  44. last if (/$re_end_sec/); # Stop at $END token
  45. $num_fields++ if (/$re_field_begin/); # Increase the counter each
  46. # time a new field is found
  47. $fields[$num_fields-1] .= $_; # Append the current line to the current
  48. # field string in @fields
  49. }
  50. # Correct if we have more procs than fields
  51. $num_procs = $num_fields if $num_fields<$num_procs;
  52. # First distribution round: Assign equally many fields to each processor
  53. my @fields_per_proc = map int($num_fields/$num_procs),(1..$num_procs);
  54. # Second distribution round: Assign remaining number of fields one by one
  55. foreach (1..$num_fields%$num_procs)
  56. {
  57. $fields_per_proc[$_-1] += 1;
  58. }
  59. # Remember how many fields we have already written out
  60. my $fld_counter = 0;
  61. # Open and fill the split files one-by-one
  62. for (my $i=0;$i<$num_procs;$i++)
  63. {
  64. open OUT,"> $namcouple"."_".$i or die "Can't open output file\n";
  65. # Write the header first (line-by-line)
  66. foreach (@header)
  67. {
  68. print OUT $_;
  69. # Insert the correct number of coupling fields for each file
  70. print OUT " $fields_per_proc[$i] $num_fields\n" if (/$re_nfield_sec/);
  71. }
  72. # Now write the coupling field definitions
  73. print OUT $fields[$fld_counter++] foreach (1..$fields_per_proc[$i]);
  74. # Write $END token and close the file...
  75. print OUT " \$END\n";
  76. close OUT;
  77. }