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 |
Back to
Craft