File Coverage

blib/lib/Physics/Springs/Friction.pm
Criterion Covered Total %
statement 21 54 38.8
branch 0 8 0.0
condition n/a
subroutine 7 8 87.5
pod 1 1 100.0
total 29 71 40.8


line stmt bran cond sub pod time code
1             package Physics::Springs::Friction;
2              
3 2     2   12488 use 5.006;
  2         6  
  2         63  
4 2     2   10 use strict;
  2         4  
  2         59  
5 2     2   9 use warnings;
  2         4  
  2         67  
6              
7 2     2   11 use Carp;
  2         4  
  2         146  
8 2     2   11 use base 'Physics::Springs';
  2         3  
  2         1820  
9              
10 2     2   38233 use constant FFORCES => '_PhSpringsFriction_friction_forces';
  2         6  
  2         158  
11 2     2   10 use Sub::Assert;
  2         7  
  2         1379  
12              
13             our $VERSION = '1.01';
14              
15             sub new {
16             my $proto = shift;
17             my $class = ref($proto) || $proto;
18              
19             my $self = $class->SUPER::new();
20             $self->{FFORCES} = [];
21             return $self;
22             }
23              
24             assert
25             context => 'novoid',
26             pre => '@PARAM == 1',
27             post => '@RETURN == 1',
28             sub => 'new';
29              
30              
31             sub add_friction {
32             my $self = shift;
33              
34             my $impl = shift;
35             my $magn = shift;
36              
37             my $friction = {
38             implementation => 'stokes',
39             magnitude => 0.1,
40             };
41             if (defined $impl) {
42             unless (ref($impl) eq 'CODE' or
43             $impl eq 'stokes' or
44             $impl eq 'newton'
45             ) {
46              
47             $impl = <
48             sub {
49             my \$P = shift;
50             my \$M = shift;
51             my \$F = [0, 0, 0];
52             $impl
53             return \@\$F;
54             }
55             ENDIMPL
56             local $@;
57             my $closure = eval $impl;
58             croak "Error while evaluating friction " .
59             "implementation.\n ($@)" if $@;
60             $impl = $closure;
61             }
62             $friction->{implementation} = $impl;
63             }
64              
65             $friction->{magnitude} = $magn if defined $magn;
66              
67             push @{$self->{FFORCES}}, $friction;
68             return $#{$self->{FFORCES}};
69             }
70              
71             assert
72             pre => [
73             '@PARAM <= 3 && @PARAM > 0',
74             '@PARAM == 1 ? 1 : defined($PARAM[1])',
75             '@PARAM != 3 ? 1 : defined($PARAM[2])',
76             ],
77             post => '$VOID || (@RETURN == 1 and $RETURN >= 0)',
78             sub => 'add_friction';
79            
80              
81              
82             sub iterate_step {
83 0     0 1   my $self = shift;
84 0           my @params = @_;
85 0           my $time_diff = $params[0];
86 0           foreach my $friction (@{$self->{FFORCES}}) {
  0            
87 0           my $magnitude = $friction->{magnitude};
88 0           my $func = $friction->{implementation};
89 0 0         if ($func eq 'stokes') {
    0          
90             # F = 6*PI*eta*r*v
91             # magnitude = 6*PI*eta*r
92 0           foreach my $P (@{$self->{p}}) {
  0            
93 0           my ($vx, $vy, $vz) = (
94             $P->{vx}, $P->{vy}, $P->{vz}
95             );
96            
97 0           my $v = sqrt(
98             $vx**2 +
99             $vy**2 +
100             $vz**2
101             );
102            
103 0 0         next if $v == 0;
104              
105 0           my $f = $magnitude * $v;
106              
107 0           $P->{_fx} -= $f * ($vx/$v);
108 0           $P->{_fy} -= $f * ($vy/$v);
109 0           $P->{_fz} -= $f * ($vz/$v);
110             }
111             }
112             elsif ($func eq 'newton') {
113             # F = 0.5*c*rho*A*v^2
114             # magnitude = c*rho*A
115 0           foreach my $P (@{$self->{p}}) {
  0            
116 0           my ($vx, $vy, $vz) = (
117             $P->{vx}, $P->{vy}, $P->{vz}
118             );
119            
120 0           my $v = sqrt(
121             $vx**2 +
122             $vy**2 +
123             $vz**2
124             );
125            
126 0 0         next if $v == 0;
127            
128 0           my $f = 0.5 * $magnitude * $v**2;
129              
130 0           $P->{_fx} -= $f * ($vx/$v);
131 0           $P->{_fy} -= $f * ($vy/$v);
132 0           $P->{_fz} -= $f * ($vz/$v);
133             }
134             }
135             else {
136 0           foreach my $particle (@{$self->{p}}) {
  0            
137 0           my @this_f = $func->({%$particle}, $magnitude);
138 0           $particle->{_fx} += $this_f[0];
139 0           $particle->{_fy} += $this_f[1];
140 0           $particle->{_fz} += $this_f[2];
141             }
142             }
143             }
144             # use Data::Dumper;
145             # print Dumper $self->{p};
146 0           $self->SUPER::iterate_step(@params);
147             }
148            
149             1;
150             __END__