1: #!/usr/bin/perl
2: use strict;
3: use warnings;
4:
5: # Perl solving a physics / electrodynamics problem involving
6: # symbolic mathematics, derivatives and complex numbers:
7:
8: use Math::Symbolic qw/:all/;
9: use Math::Complex;
10:
11: # Given the following simple circuit:
12: #
13: # ----|||||-----/\/\/\---- (R = resistor,
14: # | R L | L = solenoid,
15: # | | U = alternating voltage)
16: # ---------O ~ O----------
17: # U(t)
18: #
19: # Question: What's the current in this circuit?
20: #
21: # We'll need some physics before letting the computer do the
22: # math:
23: # Applying Kirchhoff's rules, one quickly ends up with the
24: # following differential equation for the current:
25: # (L * dI/dt) + (R * I) = U
26:
27: my $left = parse_from_string('L * total_derivative(I(t), t) + R * I(t)');
28: my $right = parse_from_string('U(t)');
29:
30:
31: # If we understand current and voltage to be complex functions,
32: # we'll be able to derive. ("'" denoting complex here)
33: # I'(t) = I'_max * e^(i*omega*t)
34: # U'(t) = U_max * e^(i*omega*t)
35: # (Please note that omega is the frequency of the alternating voltage.
36: # For example, the voltage from German outlets has a frequency of 50Hz.)
37:
38: my $argument = parse_from_string('e^(i*omega*t)');
39: my $current = parse_from_string('I_max') * $argument;
40: my $voltage = parse_from_string('U_max') * $argument;
41:
42: # Putting it into the equation:
43: $left->implement( I => $current );
44: $right->implement( U => $voltage );
45:
46: $left = $left->apply_derivatives()->simplify();
47:
48: # Now, we can solve the equation to get a complex function for
49: # the current:
50:
51: $left /= $argument;
52: $right /= $argument;
53: my $quotient = parse_from_string('R + i*omega*L');
54: $left /= $quotient;
55: $right /= $quotient;
56:
57: # Now we have:
58: # $left = $right
59: # I_max(t) = U_max / (R + i*omega*L)
60: # But I_max(t) is still complex and so is the right-hand-side of the
61: # equation!
62:
63: # Making the symbolic i a "literal" Math::Complex i
64: $right->implement(
65: e => Math::Symbolic::Constant->euler(),
66: i => Math::Symbolic::Constant->new(i), # Math::Complex magic
67: );
68:
69: print <<'HERE';
70: Sample of complex maximum current with the following values:
71: U_max => 100
72: R => 10
73: L => 10
74: omega => 1
75: HERE
76:
77: print "Computed to: "
78: . $right->value(
79: U_max => 100,
80: R => 10,
81: L => 10,
82: omega => 1,
83: ),
84: "\n\n";
85:
86: # Now, we're dealing with alternating current and voltage.
87: # So let's make a generator that generates nice current
88: # functions of time!
89: # I(t) = Re(I_max(t)) * cos(omega*t - phase);
90:
91: # Usage: generate_current(U_Max, R, L, omega, phase)
92: sub generate_current {
93: my $current = $right->new(); # cloning
94:
95: $current *= parse_from_string('cos(omega*t - phase)');
96:
97: $current->implement(
98: U_max => $_[0],
99: R => $_[1],
100: L => $_[2],
101: omega => $_[3],
102: phase => $_[4],
103: );
104: $current = $current->simplify();
105: return sub { Re( $current->value( t => $_[0] ) ) };
106: }
107:
108: print "Sample current function with: 230V, 2Ohms, 0.1H, 50Hz, PI/4\n";
109: my $current_of_time = generate_current( 230, 2, 0.1, 50, PI / 4 );
110:
111: print "The current at 0 seconds: " . $current_of_time->(0) . "\n";
112: print "The current at 0.1 seconds: " . $current_of_time->(0.1) . "\n";
113: print "The current at 1 second: " . $current_of_time->(1) . "\n";
114:
115: </readmore>
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Solving electronics problems with Perl
by blue_cowdawg (Monsignor) on Feb 01, 2013 at 16:02 UTC | |
|
Re: Solving electronics problems with Perl
by Anonymous Monk on Feb 01, 2013 at 15:38 UTC | |
by blue_cowdawg (Monsignor) on Feb 01, 2013 at 16:00 UTC | |
|
Re: Solving electronics problems with Perl
by wolfger (Deacon) on Sep 08, 2003 at 15:53 UTC | |
by tsee (Curate) on Sep 08, 2003 at 16:18 UTC |