#!/usr/bin/perl
# cast2pos.pl         SOURCE    LC    02/02/15
#
# [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
# CHAMPANEY Laurent  Universite de Versailles St Quentin le 15 / 02 / 02
#
# Transfert de fichiers de post-traitement CAST3M vers GMSH
#
#  Usage :
#    cast2pos.pl [-v] [-h] nom
#  
#  lit nom.sauv et le converti en nom.pos
#
#  Utilisation dans gsmh
#    gmsh nom.pos
#
# ======================================================================
#
#use strict;
use Getopt::Long;
my @knownoptions = (
                 "help|h",
                 "verbose|v");
GetOptions (@knownoptions) || exit ;
my $verb1 = 0;
if ($opt_verbose){$verb1=1};
#
if ($opt_help){sortie_usage(); exit();};
#
#
# Info generales
my $generic;
my $generic_ext;
my $line;
my $dime;
# Les tableaux
my @noeuds;
my @points;
my @mail;
my @mchaml;
my @chpo;
my @list_tabl;
my @list_pile;
# Les Tableaux de dimension
my @mail_tyel;
my @mail_nbel;
my @mail_nbno;
my @nb_comp_mchaml;
my @nb_comp_chpo;
#
# Analyse des arguments
if($#ARGV==-1) { sortie_usage(); exit();}
else {
      ($generic , $generic_ext) = ( $ARGV[0] =~ /([-_\/\w]*)\.?(\w*)/ ) ;
}
#
my $fic = "$generic.sauv";
open( FIC, $fic) || die "\n$fic inexistant\n\n";
#
#
# Analyse du fichier de sauvegarde CAST3M et remplissage des Tableaux
#
if ($verb1){print "\nLecture de $fic\n";}
while ($line = <FIC>) {
	if ($line =~ /NIVEAU.*DIMENSION\s*(\d*)/) {
		$dime = $1;
		if ($verb1){print "  Dimension $dime\n";}
	};
	if ($line =~ /PILE NUMERO\s*(\d*)NBRE OBJETS NOMMES\s*(\d*)NBRE OBJETS\s*(\d*)/) {
		my $pile = $1;
		my $nommes1 = $2;
		my $objets1 = $3;
		#print "Pile $pile - objets nommes $nommes1 - objets $objets1\n";
#    PILE des coordonnees des noeuds
		if ($pile == 32) {
			if ($verb1){print "  Lecture de la configurations : ";}
			my $nbsaut1 = int($nommes1 / 8);
			if ( $nommes1 % 8) {$nbsaut1 ++};
			my $nbsaut2 = int($nommes1 / 10);
			if ( $nommes1 % 10) {$nbsaut2 ++};
			my $nbsaut1 = ($nbsaut1 + $nbsaut2) + 1;
			for my $i (1 .. $nbsaut1) {$line = <FIC>};
			#print "$nbsaut1\n";
			my $nblus1 = int($objets1 / 10);
			if ( $objets1 % 10) {$nblus1 ++};
			#print "$nblus1\n";
			my $nbp1 = 0;
			for my $i (1 .. $nblus1) {
			  $line = <FIC>;
                          chomp($line);
			  my @temp1 = unpack ("A8" x (length($line)/8), $line);
			  for my $j (1 .. (length($line)/8)) {
			    my $nn1 = $temp1[$j - 1] + 0;
			    $noeuds[$nbp1] = $nn1;
			    #$noeuds[$nn1] = $nbp1;
			    $nbp1++;
			  };
			};
			if ($verb1){print "$nbp1 points\n";}
		};
#
#    PILE des configurations
		if ($pile == 33) {
			if ($verb1){print "  Lecture des POINTs : ";}
			my $nbsaut1 = int($nommes1 / 8);
			if ( $nommes1 % 8) {$nbsaut1 ++};
			my $nbsaut1 = (2 * $nbsaut1 ) ;
			#print "$nbsaut1\n";
			#
			for my $i (1 .. $nbsaut1) {$line = <FIC>};
			$line = <FIC>;
			chomp($line);
			my $nblus1 = int($line / 3);
			if ( $line % 3) {$nblus1 ++};
			my $nn1 = 0;
			my $incr1 = 0;
			for my $i (1 .. $nblus1) {
			  $line = <FIC>;
                          chomp($line);
			  my @temp1 = unpack ("A22" x (length($line)/22), $line);
			  for my $j (1 .. (length($line)/22)) {
				$points[$nn1][$incr1] = $temp1[$j - 1] * 1.;
				#print "points[$nn1][$iincr1]=$points[$nn1][$incr1] \n";
			   	if (($incr1 + 1) % ($dime + 1)) {$incr1++}
				else { $incr1=0; $nn1++;};
			  };
			};
			if ($verb1){print "$nn1 points lus\n";}
#
		};
#    PILE des maillages
		if ($pile == 1) {
			if ($verb1){print "  Lecture des MAILLAGEs : ";}
			my $nbsaut1 = int($nommes1 / 8);
			if ( $nommes1 % 8) {$nbsaut1 ++};
			#print "$nbsaut1\n";
			for my $i (1 .. $nbsaut1) {$line = <FIC>};
			my $nbsaut1 = int($nommes1 / 10);
			if ( $nommes1 % 10) {$nbsaut1 ++};
			#print "$nbsaut1\n";
			for my $i (1 .. $nbsaut1) {$line = <FIC>};
			for my $k (1 .. $objets1) {
			  $line = <FIC>;
                          chomp($line);
			  my @temp1 = unpack ("A8" x 5, $line);
			  # Info sur le type d'element
			  $mail_tyel[$k-1] = $temp1[0] + 0;
			  my $nbel_el1 = $temp1[4] + 0;
			  $mail_nbel[$k-1] = $nbel_el1;
			  my $nbnd_el1 = $temp1[3] + 0;
			  $mail_nbno[$k-1] = $nbnd_el1;
			  #print "$k : $nbel_el1 - $nbnd_el1\n";
			  # On saute les sous references
			  if (( $temp1[1] + 0) != 0) {$line = <FIC>};
			  if (( $temp1[2] + 0) != 0) {$line = <FIC>};
			  if ($mail_tyel[$k-1] != 0) {
			  	my $nbsaut1 = int($nbel_el1 / 10);
			  	if ( $nbel_el1 % 10) {$nbsaut1 ++};
				  # On saute les couleurs
				  for my $i (1 .. $nbsaut1) {$line = <FIC>};
				  my $nblus1 = int(($nbel_el1*$nbnd_el1)/ 10);
				  if (($nbel_el1*$nbnd_el1) % 10) {$nblus1 ++};
				  # On lit les connectivites
				  my $nd1 = 0;
				  my $el1 = 0;
				  for my $i (1 .. $nblus1) {
				    $line = <FIC>;
				    chomp($line);
				    my @temp1 = unpack ("A8" x (length($line)/8), $line);
				    for my $j (1 .. (length($line)/8)) {
					$mail[$k-1][$el1][$nd1] = $temp1[$j - 1] + 0;
					#print "mail[$k,$el1,$nd1]=$mail[$k][$el1][$nd1] \n";
					if (($nd1 + 1) % ($nbnd_el1)) {$nd1++}
					else { $nd1=0; $el1++}
				    };
				  };
				  #print "Maillage $k : $el1 elements\n";
			  };
			};
			if ($verb1){print "$objets1 maillages\n";}
		};
#    PILE des tables   
		if ($pile == 10) {
			if ($verb1){print "  Lecture des TABLEs : ";}
			my $nbsaut1 = int($nommes1 / 8);
			if ( $nommes1 % 8) {$nbsaut1 ++};
			my $nbsaut1 = (2 * $nbsaut1 ) ;
			for my $i (1 .. $nbsaut1) {$line = <FIC>};
			#for my $j (1 .. $objets1) {
				$line = <FIC>;
				chomp($line);
				my $nblus1 = int($line / 10);
				if ($line % 10) {$nblus1 ++};
				my $k = 0;
				for my $i (1 .. $nblus1) {
				    $line = <FIC>;
				    chomp($line);
				    my @temp1 = unpack ("A8" x (length($line)/8), $line);
				    for my $j (1 .. (length($line)/8)) {
					$list_tabl[$k] = $temp1[$j - 1] + 0;
					#print "list_tabl[$k]=$list_tabl[$k] \n";
					$k++;
				    };
				};
				my $nbvaltemp1 = $k / 4;
				if ($verb1){print "$nbvaltemp1 indice dans la table\n";}
			#};
		};
#    PILE des entiers  
		if ($pile == 26) {
			if ($verb1){print "  Lecture des ENTIERs : ";}
			my $nbsaut1 = int($nommes1 / 8);
			if ( $nommes1 % 8) {$nbsaut1 ++};
			my $nbsaut1 = (2 * $nbsaut1 ) ;
			for my $i (1 .. $nbsaut1) {$line = <FIC>};
			#for my $j (1 .. $objets1) {
				$line = <FIC>;
				chomp($line);
				my $nblus1 = int($line / 7);
				if ($line % 7) {$nblus1 ++};
				my $k = 0;
				for my $i (1 .. $nblus1) {
				    $line = <FIC>;
				    chomp($line);
				    my @temp1 = unpack ("A11" x (length($line)/11), $line);
				    for my $j (1 .. (length($line)/11)) {
					$list_pile[26][$k] = $temp1[$j - 1] * 1.0;
					#print "list_pile[26,$k]=$list_pile[26][$k] \n";
					$k++;
				    };
				};
				my $nbvaltemp1 = $k ;
				if ($verb1){print "$nbvaltemp1 entiers dans la pile\n";}
			#};
		};
#    PILE des flottants
		if ($pile == 25) {
			if ($verb1){print "  Lecture des FLOTTANTs : ";}
			my $nbsaut1 = int($nommes1 / 8);
			if ( $nommes1 % 8) {$nbsaut1 ++};
			my $nbsaut1 = (2 * $nbsaut1 ) ;
			for my $i (1 .. $nbsaut1) {$line = <FIC>};
			#for my $j (1 .. $objets1) {
				$line = <FIC>;
				chomp($line);
				my $nblus1 = int($line / 3);
				if ($line % 3) {$nblus1 ++};
				my $k = 0;
				for my $i (1 .. $nblus1) {
				    $line = <FIC>;
				    chomp($line);
				    my @temp1 = unpack ("A22" x (length($line)/22), $line);
				    for my $j (1 .. (length($line)/22)) {
					$list_pile[25][$k] = $temp1[$j - 1] * 1.0;
					#print "list_pile[25,$k]=$list_pile[25][$k] \n";
					$k++;
				    };
				};
				my $nbvaltemp1 = $k ;
				if ($verb1){print "$nbvaltemp1 flottants dans la pile\n";}
			#};
		};
#    PILE des MCHAMLs
		if ($pile == 39) {
			if ($verb1){print "  Lecture des MCHAMLs : ";}
			my $nbsaut1 = int($nommes1 / 8);
			if ( $nommes1 % 8) {$nbsaut1 ++};
			my $nbsaut1 = (2 * $nbsaut1 ) ;
			for my $i (1 .. $nbsaut1) {$line = <FIC>};
			for my $j (1 .. $objets1) {
				$line = <FIC>;
				$line = <FIC>;
				$line = <FIC>;
				chomp($line);
				my @temp1 = unpack ("A8" x (length($line)/8), $line);
				my $nb_comp1 = $temp1[2];
				$nb_comp_mchaml[$j-1] = $nb_comp1;
				#print "nbre de composantes $nb_comp1\n";
				$line = <FIC>;
				$line = <FIC>;
				$line = <FIC>;
				$line = <FIC>;
				for my $k (1 .. $nb_comp1) {
					$line = <FIC>;
					chomp($line);
					my @temp1 = unpack ("A8" x (length($line)/8), $line);
					my $nb_noeu1 = $temp1[0];
					my $nb_elem1 = $temp1[1];
					#print "$nb_elem1 elts - $nb_noeu1 nds\n";
					my $nblus1 = int(($nb_elem1*$nb_noeu1) / 3);
					if (($nb_elem1*$nb_noeu1) % 3) {$nblus1 ++};
					my $el1 = 0;
					my $no1 = 0;
					for my $ii (1 .. $nblus1) {
					    $line = <FIC>;
					    chomp($line);
					    @temp1 = unpack ("A22" x (length($line)/22), $line);
					    for my $jj (1 .. (length($line)/22)) {
						$mchaml[$j-1][$k-1][$el1][$no1] = $temp1[$jj - 1] * 1.0;
						#print "cham[$j,$k,$el1,$no1]=$mchaml[$j-1][$k-1][$el1][$no1] \n";
						if (($no1 + 1) % ($nb_noeu1)) {$no1++}
						else { $no1=0; $el1++}
					    };
					};
					#my $nbvaltemp1 = $k ;
					#print "$nbvaltemp1 flottants dans la pile\n";
				};
			};
			if ($verb1){print "$objets1 champs lus\n";}
		};
#    PILE des CHPOINTS
		if ($pile == 2) {
			if ($verb1){print "  Lecture des CHPOINTs : ";}
			my $nbsaut1 = int($nommes1 / 8);
			if ( $nommes1 % 8) {$nbsaut1 ++};
			my $nbsaut1 = (2 * $nbsaut1 ) ;
			for my $i (1 .. $nbsaut1) {$line = <FIC>};
			for my $j (1 .. $objets1) {
				$line = <FIC>;
				$line = <FIC>;
				chomp($line);
				my @temp1 = unpack ("A8" x (length($line)/8), $line);
				my $nb_noeu1 = $temp1[1] + 0;
				my $nb_comp1 = $temp1[2] + 0;
				$nb_comp_chpo[$j-1] = $nb_comp1;
				#print "nbre de composantes $nb_comp1\n";
				$line = <FIC>;
				$line = <FIC>;
				$line = <FIC>;
				$line = <FIC>;
				$line = <FIC>;
				my $nblus1 = int(($nb_noeu1*$nb_comp1) / 3);
				if (($nb_comp1*$nb_noeu1) % 3) {$nblus1 ++};
				my $co1 = 0;
				my $el1 = 0;
				for my $ii (1 .. $nblus1) {
				    $line = <FIC>;
				    chomp($line);
				    my @temp1 = unpack ("A22" x (length($line)/22), $line);
				    for my $jj (1 .. (length($line)/22)) {
					$chpo[$j-1][$co1][$el1] = $temp1[$jj - 1] * 1.0;
					#print "chpo[$j,$co1,$el1]=$chpo[$j-1][$co1][$el1] \n";
					if (($el1 + 1) % ($nb_noeu1)) {$el1++}
					else { $el1=0; $co1++}
				    };
				};
			};
			if ($verb1){print "$objets1 champs lus\n";}
		};
	};
		
};
close(FIC);
#
# On a lu le fichier, on peut travailler
#
my $fis = "$generic.pos";
open( FIS, ">$fis");
#
if($verb1){print "\nEcriture de $fis\n";}
print FIS "\$PostFormat /* Gmsh 1.1, ascii */\n";
print FIS "1.1 0 8\n";
print FIS "\$EndPostFormat\n";
print FIS "\$View /* converti depuis cast3m */\n";
#
my $mail1 = 0;
my $cham1 = 0;
my $name = "$generic";
my $typel1 = $mail_tyel[$mail1];
my $nbcomp1;
if ($typel1 != 1) {
	$nbcomp1 = $nb_comp_mchaml[$cham1];
} else {
	$nbcomp1 = $nb_comp_chpo[$cham1];
};
my $nbel1 = $mail_nbel[$mail1];
my $nbno1 = $mail_nbno[$mail1];
my $si_tabl = $list_tabl[0];
print $si_tabl;
#$si_tabl = 1;
my $ipil1 = 0;
my $icha = 1;
if (!$si_tabl) {
	if ($nb_comp_mchaml[0]) {
		if($verb1){print "Pas de TABLE : on traite un MCHAML\n";}
		$ipil1 = 39;
		$icha = 1;
	};
	if ($nb_comp_chpo[0]) {
		if($verb1){print "Pas de TABLE : on traite un CHPOINT\n";}
		$ipil1 = 1;
		$icha = 1;
	};
	if (!$ipil1) {
		die "Je ne sais pas quoi faire...\n";
	};
};
my $ntim1 = ($#list_tabl + 1) / 4;
if (!$ntim1) {$ntim1 = 1; $si_tabl = 0};
#
# les options
if (($typel1 != 1) && ($typel1 != 2) && ($typel1 != 4) && ($typel1 != 23)) {
	die "Type d'element pas implanté\n";
}
if (($typel1 == 1) && ($nbcomp1 == 1)) {
	print FIS "$name $ntim1 $nbel1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
}
if (($typel1 == 1) && ($nbcomp1 >= $dime)) {
	print FIS "$name $ntim1 0 $nbel1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
}
if (($typel1 == 2) && ($nbcomp1 == 1)) {
	print FIS "$name $ntim1 0 0 0 $nbel1 0 0 0 0 0 0 0 0 0 0 0 0\n";
}
if (($typel1 == 2) && ($nbcomp1 >= $dime)) {
	print FIS "$name $ntim1 0 0 0 0 $nbel1 0 0 0 0 0 0 0 0 0 0 0\n";
}
if (($typel1 == 4) && ($nbcomp1 == 1)) {
	print FIS "$name $ntim1 0 0 0 0 0 0 $nbel1 0 0 0 0 0 0 0 0 0\n";
}
if (($typel1 == 4) && ($nbcomp1 >= $dime)) {
	print FIS "$name $ntim1 0 0 0 0 0 0 0 $nbel1 0 0 0 0 0 0 0 0\n";
}
if (($typel1 == 23) && ($nbcomp1 == 1)) {
	print FIS "$name $ntim1 0 0 0 0 0 0 0 0 0 $nbel1 0 0 0 0 0 0\n";
}
if (($typel1 == 23) && ($nbcomp1 >= $dime)) {
	print FIS "$name $ntim1 0 0 0 0 0 0 0 0 0 0 $nbel1 0 0 0 0 0\n";
}
#
# les instants
if ($si_tabl) {
	for my $i (1 .. $ntim1) {
		my $itab = (4 * ($i - 1));
		my $ipil = $list_tabl[$itab];
		my $iind = $list_tabl[$itab + 1] - 1;
		print FIS "$list_pile[$ipil][$iind] ";
	};
}
else {
	print FIS "1. ";
};
#
# les quantites
for my $el1 (1 .. $nbel1){
#
#  Coordonnees des noeuds
	for my $ico1 (1 .. $dime) {
		for my $ino1 (1 .. $nbno1) {
			my $node1 = $mail[$mail1][$el1-1][$ino1-1];
			my $poin1 = $noeuds[$node1 - 1];
			my $coor1 = $points[$poin1 - 1][$ico1 - 1];
			#print "$mail1 - $node1 - $poin1 - $ico1 - $coor1\n";
			print FIS "$coor1 ";
		};
	};
	# si 2D on ajoute zero sur z
	if ($dime == 2) {
		for my $ino1 (1 .. $nbno1) {
			print FIS "0. ";
		};
	}
#
#  Valeurs à chaque instant
	for my $i (1 .. $ntim1) {
		my $val1 ; my $itab ; my $ipil ;
		if ($si_tabl != 0) {
			$itab = (4 * ($i - 1));
			$ipil = $list_tabl[$itab+2];
			$icha = $list_tabl[$itab+3];
			$ipil1 = $ipil;
	        };
		for my $ino1 (1 .. $nbno1) {
			for my $ico1 (1 .. $nbcomp1) {
				if ($ipil1 == 39) {
					$val1 = $mchaml[$icha-1][$ico1-1][$el1-1][$ino1-1];
			#		print "$icha - $ico1 - $el1 - $ino1 - $val1\n";
				} else {
					$val1 = $chpo[$icha-1][$ico1-1][$el1-1];
		#			print "$icha - $ico1 - $el1 \n";
				};
				print FIS "$val1 ";
			};	
			# Si pas assez de composantes on ajoute zero
			if ($nbcomp1 == 2) {
				print FIS "0. ";
			};
		};
		
	};
}
print FIS "\n\$EndView \n";
close(FIS);
print "\nConversion effectuée :\n";
print "  -> Post-traitement dans GMSH :       gmsh $fis\n\n";
exit;
#
sub sortie_usage {
        print "  \n";
        print "cast2pos.pl : convertion CAST3M vers GMSH\n";
        print "Laurent CHAMPANEY                      Fevrier 2002\n";
        print "  \n";
        print "Usage :\n";
        print "  cast2pos.pl nom \n";
        print "  \n";
        print "  lit nom.sauv et le converti en nom.pos  \n";
        print "  \n";
        print "  Restitution dans GMSH\n";
        print "    gmsh nom.pos;\n";
        print "  \n";
        print "  Les quantités qui peuvent être post-traitées dans gmsh sont\n";
        print "   - un CHPOINT\n";
        print "   - un MCHAML de valeur\n";
        print "   - un MCHAML de vecteurs\n";
        print "   - un tableau MCHAML de valeur : chaque indice du\n";
        print "      tableau correspond à un instant\n";
        print "   - un MCHAML de vecteurs : chaque indice du\n";
        print "      tableau correspond à un instant\n";
        print "  \n";
        print "  Nota : il faut faire un fichier .sauv pour chaque type de quantité\n";
        print "  \n";
        print "  Les éléments supports autorisés par GMSH sont :\n";
        print "   - Les points, \n";
        print "   - Les segments à 2 noeuds, \n";
        print "   - Les triangles à 3 noeuds, \n";
        print "   - Les tétraèdres à 4 noeuds, \n";
        print "  \n";
        print "  Attention : vérifier que vous enlever (ENLE LX) les multiplicateurs\n";
        print "              de Lagrange dans les champs solutions de CAST3M.\n";
        print "  \n";
	return;
        };

