#!/usr/bin/env perl
#!/usr/bin/perl
#
# Albert Danial Mar 19 2005
#
use warnings;
use strict;
use File::Basename;
use vars qw ( $opt_s $opt_m );
use Getopt::Std;
use DBI;
use DBD::SQLite 1.00;

getopts('sm');
my $script = basename $0;
die "$script [options]  <model .db file>

        Writes StaDyn model and driver files from the sofea 
        model database.

        Options
            -s    statics (default)
            -m    modes

        Limitations:
            - triangular elements only
            - all elements have same shell property
            - hardcoded SPC's
            - hardcoded FORCE's
            - no concentrated masses
" unless scalar @ARGV >= 1;
$opt_s = 1 unless $opt_m;

my $model_db_file = shift @ARGV;
$model_db_file .= ".db" unless -r $model_db_file;
(my $outfile = basename $model_db_file) =~ s/db$/stadyn_model/;
die "Cannot read $model_db_file" unless -r $model_db_file;
die "$model_db_file -- expect database file to have .db extension" 
    unless $model_db_file =~ /\.db$/;

my $dbh = DBI->connect("dbi:SQLite:dbname=$model_db_file","","");

my $node_ref = $dbh->selectall_hashref( 
                        "select seq_no,id,coord_in,x1_in,x2_in,x3_in from node",
                        "seq_no");
my $elem_ref = $dbh->selectall_hashref( 
                        "select seq_no,id,type from element",
                        "seq_no");
my $e_n_ref  = $dbh->selectall_arrayref(
                        "select eid,nid from element_node order by seq_no");

unlink $outfile if -e $outfile;
open  OUT, ">$outfile" or die "Could not write $outfile:  $!\n";

chomp(my $timestamp   = `date "+%Y-%m-%d-%H:%M:%S"`);

print  OUT "$outfile created from $model_db_file at $timestamp\n";
print  OUT "32\n";      # 32 = folded plate
print  OUT "1 1 1 1\n"; # echo:  connectivity material numbering loads
print  OUT "end\n";

# elements
my $tri3_ref = $dbh->selectall_hashref( 
                        "select id,shell_prop from tri3", 
                        "id");
my $tri3_node_ref = $dbh->selectall_arrayref(
                        "select E.id,EN.nid from tri3 E, element_node EN 
                         where EN.eid=E.id order by EN.seq_no;");
my $nElem    = scalar keys %{$tri3_ref};

printf OUT "%d\n", $nElem;
for (my $e = 0; $e < scalar @{$tri3_node_ref}; $e += 3) {
    my $eid = $tri3_node_ref->[$e][0];
    printf OUT "%d 4 %3d %3d %3d\n",  # 3=frame   4=plate
            $eid,
            $tri3_node_ref->[$e  ][1]    ,
            $tri3_node_ref->[$e+1][1]    ,
            $tri3_node_ref->[$e+2][1]    ;
}
print  OUT "end\n";

# material properties grouping
print OUT "1\n";             # one material group
print OUT "1 $nElem 1\n";    # all elements belong to material group 1
print OUT "end\n";

# nodes
printf OUT "%d\n", scalar keys %{$node_ref};  # number of nodes
foreach my $seq_no (sort {$a <=> $b} keys %{$node_ref}) {
    printf OUT "%d  % 12.6e % 12.6e % 12.6e\n",
                $node_ref->{$seq_no}{seq_no},   # ideally want {id}
                $node_ref->{$seq_no}{x1_in},
                $node_ref->{$seq_no}{x2_in},
                $node_ref->{$seq_no}{x3_in};
}
print  OUT "end\n";

# boundary conditions
print OUT "1\n";               # number of SPC lines
print OUT "1  0 0 0  0 0 0\n"; # node 1 fully constrained
print OUT "end\n";

# nodal loads and concentrated masses
print OUT "1\n";                                 # number of FORCE/CONM lines
print OUT "2  0.0 0.0 10.0  0.0 0.0 0.0  0.0\n"; # node 2   Fz = 10
print OUT "end\n";

# materials
print OUT "1\n";                            # number of material lines
my $material_ref = $dbh->selectall_hashref( 
                        "select seq_no,id,E,G,nu,rho from material", 
                        "id");
my $shell_prop_ref = $dbh->selectall_hashref( 
                        "select seq_no,id,material_id,thick from shell_prop", 
                        "id");
my $mid = (keys %{$material_ref})[0];
my $pid = (keys %{$shell_prop_ref})[0];
my $nu  = $material_ref->{$mid}{nu};
my $Ip  = $shell_prop_ref->{$pid}{thick}**3 / 12 / (1.0 - $nu**2);
printf OUT "%d %7.2e %12.6e %7.2e %7.2e %3.1f %12.6e %3.1f %3.1f\n",
        $material_ref->{  $mid}{seq_no},
        $material_ref->{  $mid}{E}     ,
        $material_ref->{  $mid}{G}     ,
        $shell_prop_ref->{$pid}{thick} ,
        $material_ref->{  $mid}{rho}   ,
        1.0                            ,  # plane stress
        $Ip                            ,
        1.5                            ,  # in plane drilling parameter alpha
        0.5                            ;  # in plane drilling parameter beta
print  OUT "end\n";

# damping data
print  OUT "0\nend\n";

close  OUT;

my $rc = $dbh->disconnect;

print "Wrote $outfile" if -e $outfile;

# create a driver file
(my $driverfile = $outfile) =~ s/stadyn_model$/driver/;
open  OUT, ">$driverfile" or die "Could not write $driverfile:  $!\n";
if      ($opt_s) {
    print OUT statics_driver($outfile);
} elsif ($opt_m) {
    print OUT modes_driver($outfile);
}
close OUT;
print ", $driverfile" if -e $outfile and -e $driverfile;
print "\n";

print "cat $driverfile | stadyn # to run the job\n";

sub statics_driver {  # {{{1
    my ($model_file, ) = @_;
return " 2 ::MAIN
$model_file                                         ::filename
3 ::MAIN
2   :: 1=BIN 2=ASC
6 ::MAIN
1  :: 1=analysis
0  :: 1=analysis
0 ::MAIN
";
} # 1}}}
sub modes_driver {  # {{{1
    my ($model_file, ) = @_;
return "2 ::MAIN
$model_file                     ::filename
3 ::MAIN
3   :: 1=BIN 2=ASC
41 ::MAIN
3   ::0=deflt 2=ASC
9 ::MAIN
2 2  ::2=vibn  1=jacobi/2=sub  
1  :: 1=analysis
18  ::max modes
2   :: post analysis
12 1 :: 12 modes
12 2 :: 12 mode shapes
0 0  :: quit
0  :: 1=analysis
0 ::MAIN
";
} # 1}}}
