Deleted Files and annotated tests
This commit is contained in:
@@ -164,6 +164,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
def test_edit_unit_toy(self):
|
||||
self.check_edit_unit('toy')
|
||||
|
||||
#FIX
|
||||
def test_edit_unit_full(self):
|
||||
self.check_edit_unit('full')
|
||||
|
||||
@@ -299,6 +300,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
num_drafts = self._get_draft_counts(course)
|
||||
self.assertEqual(num_drafts, 1)
|
||||
|
||||
#FIX
|
||||
def test_import_textbook_as_content_element(self):
|
||||
module_store = modulestore('direct')
|
||||
import_from_xml(module_store, 'common/test/data/', ['full'])
|
||||
@@ -307,6 +309,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
|
||||
self.assertGreater(len(course.textbooks), 0)
|
||||
|
||||
#FIX
|
||||
def test_static_tab_reordering(self):
|
||||
module_store = modulestore('direct')
|
||||
import_from_xml(module_store, 'common/test/data/', ['full'])
|
||||
@@ -331,6 +334,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
|
||||
self.assertEqual(reverse_tabs, course_tabs)
|
||||
|
||||
#FIX
|
||||
def test_import_polls(self):
|
||||
module_store = modulestore('direct')
|
||||
import_from_xml(module_store, 'common/test/data/', ['full'])
|
||||
@@ -342,6 +346,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
# check that there's actually content in the 'question' field
|
||||
self.assertGreater(len(items[0].question), 0)
|
||||
|
||||
#FIX
|
||||
def test_xlint_fails(self):
|
||||
err_cnt = perform_xlint('common/test/data', ['full'])
|
||||
self.assertGreater(err_cnt, 0)
|
||||
@@ -368,6 +373,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
#FIX
|
||||
def test_delete(self):
|
||||
direct_store = modulestore('direct')
|
||||
import_from_xml(direct_store, 'common/test/data/', ['full'])
|
||||
@@ -399,6 +405,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
# make sure the parent no longer points to the child object which was deleted
|
||||
self.assertFalse(sequential.location.url() in chapter.children)
|
||||
|
||||
#FIX
|
||||
def test_about_overrides(self):
|
||||
'''
|
||||
This test case verifies that a course can use specialized override for about data, e.g. /about/Fall_2012/effort.html
|
||||
@@ -413,6 +420,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
effort = module_store.get_item(Location(['i4x', 'edX', 'full', 'about', 'end_date', None]))
|
||||
self.assertEqual(effort.data, 'TBD')
|
||||
|
||||
#FIX
|
||||
def test_remove_hide_progress_tab(self):
|
||||
module_store = modulestore('direct')
|
||||
import_from_xml(module_store, 'common/test/data/', ['full'])
|
||||
@@ -421,6 +429,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
course = module_store.get_item(source_location)
|
||||
self.assertFalse(course.hide_progress_tab)
|
||||
|
||||
#FIX
|
||||
def test_asset_import(self):
|
||||
'''
|
||||
This test validates that an image asset is imported and a thumbnail was generated for a .gif
|
||||
@@ -472,6 +481,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
#
|
||||
# self.assertIsNotNone(thumbnail)
|
||||
|
||||
#FIX
|
||||
def test_asset_delete_and_restore(self):
|
||||
'''
|
||||
This test will exercise the soft delete/restore functionality of the assets
|
||||
@@ -528,6 +538,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
thumbnail = content_store.find(thumbnail_location, throw_on_not_found=False)
|
||||
self.assertIsNotNone(thumbnail)
|
||||
|
||||
#FIX
|
||||
def test_empty_trashcan(self):
|
||||
'''
|
||||
This test will exercise the empting of the asset trashcan
|
||||
@@ -572,6 +583,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
all_thumbnails = trash_store.get_all_content_thumbnails_for_course(course_location)
|
||||
self.assertEqual(len(all_thumbnails), 0)
|
||||
|
||||
#FIX
|
||||
def test_clone_course(self):
|
||||
|
||||
course_data = {
|
||||
@@ -635,6 +647,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
resp = self.client.get('http://localhost:8001/c4x/CDX/123123/asset/&images_circuits_Lab7Solution2.png')
|
||||
self.assertEqual(resp.status_code, 400)
|
||||
|
||||
#FIX
|
||||
def test_delete_course(self):
|
||||
"""
|
||||
This test will import a course, make a draft item, and delete it. This will also assert that the
|
||||
@@ -683,6 +696,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
filesystem = OSFS(root_dir / ('test_export/' + dirname))
|
||||
self.assertTrue(filesystem.exists(item.location.name + filename_suffix))
|
||||
|
||||
#FIX
|
||||
def test_export_course(self):
|
||||
module_store = modulestore('direct')
|
||||
draft_store = modulestore('draft')
|
||||
@@ -802,6 +816,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
|
||||
shutil.rmtree(root_dir)
|
||||
|
||||
#FIX
|
||||
def test_course_handouts_rewrites(self):
|
||||
module_store = modulestore('direct')
|
||||
|
||||
@@ -820,6 +835,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
# note, we know the link it should be because that's what in the 'full' course in the test data
|
||||
self.assertContains(resp, '/c4x/edX/full/asset/handouts_schematic_tutorial.pdf')
|
||||
|
||||
#FIX
|
||||
def test_prefetch_children(self):
|
||||
module_store = modulestore('direct')
|
||||
import_from_xml(module_store, 'common/test/data/', ['full'])
|
||||
@@ -842,6 +858,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
self.assertFalse(Location(['i4x', 'edX', 'full', 'vertical', 'vertical_58', None])
|
||||
in course.system.module_data)
|
||||
|
||||
#FIX
|
||||
def test_export_course_with_unknown_metadata(self):
|
||||
module_store = modulestore('direct')
|
||||
content_store = contentstore()
|
||||
@@ -1200,6 +1217,7 @@ class ContentStoreTest(ModuleStoreTestCase):
|
||||
# make sure we found the item (e.g. it didn't error while loading)
|
||||
self.assertTrue(did_load_item)
|
||||
|
||||
#FIX
|
||||
def test_forum_id_generation(self):
|
||||
module_store = modulestore('direct')
|
||||
import_from_xml(module_store, 'common/test/data/', ['full'])
|
||||
@@ -1214,6 +1232,7 @@ class ContentStoreTest(ModuleStoreTestCase):
|
||||
|
||||
self.assertNotEquals(new_discussion_item.discussion_id, '$$GUID$$')
|
||||
|
||||
#FIX
|
||||
def test_update_modulestore_signal_did_fire(self):
|
||||
module_store = modulestore('direct')
|
||||
import_from_xml(module_store, 'common/test/data/', ['full'])
|
||||
@@ -1239,6 +1258,7 @@ class ContentStoreTest(ModuleStoreTestCase):
|
||||
|
||||
self.assertTrue(self.got_signal)
|
||||
|
||||
#FIX
|
||||
def test_metadata_inheritance(self):
|
||||
module_store = modulestore('direct')
|
||||
import_from_xml(module_store, 'common/test/data/', ['full'])
|
||||
|
||||
@@ -295,6 +295,7 @@ class CourseMetadataEditingTest(CourseTestCase):
|
||||
"""
|
||||
Tests for CourseMetadata.
|
||||
"""
|
||||
#FIX
|
||||
def setUp(self):
|
||||
CourseTestCase.setUp(self)
|
||||
# add in the full class too
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
This is a realistic course, with many different module types and a lot of structure. It is based on 6.002x.
|
||||
@@ -1 +0,0 @@
|
||||
6 hours
|
||||
@@ -1,3 +0,0 @@
|
||||
6.002x (Circuits and Electronics) is designed to serve as a first course in an undergraduate electrical engineering (EE), or electrical engineering and computer science (EECS) curriculum. At MIT, 6.002 is in the core of department subjects required for all undergraduates in EECS.
|
||||
|
||||
The course introduces engineering in the context of the lumped circuit abstraction. Topics covered include: resistive elements and networks; independent and dependent sources; switches and MOS transistors; digital abstraction; amplifiers; energy storage elements; dynamics of first- and second-order networks; design in the time and frequency domains; and analog and digital circuits and applications. Design and lab exercises are also significant components of the course. You should expect to spend approximately 10 hours per week on the course.
|
||||
@@ -1 +0,0 @@
|
||||
12 hours
|
||||
@@ -1 +0,0 @@
|
||||
TBD
|
||||
@@ -1,14 +0,0 @@
|
||||
<ul>
|
||||
<li>What is the format of the class?
|
||||
<p>The course will consist of 24 lectures, each lasting 50 minutes. There will be regular assignments consisting of map tests and short essays.</p>
|
||||
</li>
|
||||
<li>Are there any prerequisites?
|
||||
<p>No - anyone and everyone is welcome to take this course.</p>
|
||||
</li>
|
||||
<li>What textbook should I buy?
|
||||
<p>Although the lectures are designed to be self-contained, we recommend (but do not require) that students refer to the book Worlds Together, Worlds Apart: A History of the World: From 1000 CE to the Present (W W Norton, 3rd edition) — Volume II, which was written specifically for this course.</p>
|
||||
</li>
|
||||
<li>Does Harvard award credentials or reports regarding my work in this course?
|
||||
<p>Princeton does not award credentials or issue reports for student work in this course. However, Coursera could maintain a record of your score on the assessments and, with your permission, verify that score for authorized parties.</p>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -1,9 +0,0 @@
|
||||
<section class="who-should-take">
|
||||
<h3>Who should take this?</h3>
|
||||
<p>If you're one of the many who have a unquenched interest in the worlds history, you'll love this course.</p>
|
||||
</section>
|
||||
|
||||
<section class="who-shouldnt-take">
|
||||
<h3>Who shouldn't take this?</h3>
|
||||
<p>No one. Anyone and everyone is welcome to take this course.</p>
|
||||
</section>
|
||||
@@ -1,2 +0,0 @@
|
||||
<p>In order to succeed in this course, you must have taken an AP level physics course in electricity and magnetism. You must know basic calculus and linear algebra and have some background in differential equations. Since more advanced mathematics will not show up until the second half of the course, the first half of the course will include an optional remedial differential equations component for those who need it.</p>
|
||||
<p>The course web site was developed and tested primarily with Google Chrome. We support current versions of Mozilla Firefox as well. The video player is designed to work with Flash. While we provide a partial non-Flash fallback for the video, as well as partial support for Internet Explorer, other browsers, and tablets, portions of the functionality will be unavailable.</p>
|
||||
@@ -1,17 +0,0 @@
|
||||
<ul>
|
||||
<li><strong>Week 1:</strong> What is World History?</li>
|
||||
<li><strong>Week 2:</strong> Peoples, Plagues and Plunders</li>
|
||||
<li><strong>Week 3:</strong> Warfare and Motion</li>
|
||||
<li><strong>Week 4:</strong> Conquests</li>
|
||||
<li><strong>Week 5:</strong> The Beginnings of Globalization in the Atlantic Worlds</li>
|
||||
<li><strong>Week 6:</strong> The Beginnings of Globalization in the Indian Ocean Worlds</li>
|
||||
<li><strong>Week 7:</strong> The Worlds that Merchants Made</li>
|
||||
<li><strong>Week 8:</strong> The Seventeenth-Century Crisis</li>
|
||||
<li><strong>Week 9:</strong> Empire and Enlightenment</li>
|
||||
<li><strong>Week 10:</strong> The Wealth of Nations</li>
|
||||
<li><strong>Week 11:</strong> The World in Revolution</li>
|
||||
<li><strong>Week 12:</strong> States and Nations</li>
|
||||
<li><strong>Week 13:</strong> Global Frontiers</li>
|
||||
<li><strong>Week 14:</strong> Empires and Nations</li>
|
||||
<li><strong>Week 15:</strong> Back to the Future</li>
|
||||
</ul>
|
||||
@@ -1 +0,0 @@
|
||||
<p>The course uses the textbook Foundations of Analog and Digital Electronic Circuits, by Anant Agarwal and Jeffrey H. Lang. Morgan Kaufmann Publishers, Elsevier, July 2005. While recommended, the book is not required: relevant sections will be provided electronically as part of the online course for personal use in connection with this course only. The copyright for the book is owned by Elsevier. The book can be purchased on <a href="http://www.amazon.com/exec/obidos/ASIN/1558607358/ref=nosim/mitopencourse-20">Amazon</a>.</p>
|
||||
@@ -1 +0,0 @@
|
||||
<iframe width="560" height="315" src="http://www.youtube.com/embed/p2Q6BrNhdh8" frameborder="0" allowfullscreen></iframe>
|
||||
@@ -1,10 +0,0 @@
|
||||
<sequential>
|
||||
<video url_name="welcome"/>
|
||||
<sequential filename="System_Usage_Sequence" slug="System_Usage_Sequence" format="Lecture Sequence" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never" name="System Usage Sequence"/>
|
||||
<vertical slug="Lab0_Using_the_tools" format="Lab" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never" name="Lab0: Using the tools">
|
||||
<html slug="html_19" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never"> See the <a href="/section/labintro"> Lab Introduction </a> or <a href="/static/handouts/schematic_tutorial.pdf">Interactive Lab Usage Handout </a> for information on how to do the lab… </html>
|
||||
<html slug="html_5555" filename="html_5555"/>
|
||||
<problem filename="Lab_0_Using_the_Tools" slug="Lab_0_Using_the_Tools" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="false" name="Lab 0: Using the Tools"/>
|
||||
</vertical>
|
||||
<problem filename="Circuit_Sandbox" slug="Circuit_Sandbox" format="Lab" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="false" name="Circuit Sandbox"/>
|
||||
</sequential>
|
||||
@@ -1,10 +0,0 @@
|
||||
<sequential>
|
||||
<sequential filename="Administrivia_and_Circuit_Elements" slug="Administrivia_and_Circuit_Elements" format="Lecture Sequence" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never" name="Administrivia and Circuit Elements"/>
|
||||
<vertical slug="Basic_Circuit_Analysis" format="Homework" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="closed" rerandomize="per_student" due="March 18" graded="true" name="Basic Circuit Analysis">
|
||||
<problem filename="H1P1_Energy" slug="H1P1_Energy" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="closed" rerandomize="per_student" due="March 18" graded="true" name="H1P1: Energy"/>
|
||||
<problem filename="H1P2_Duality" slug="H1P2_Duality" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="closed" rerandomize="per_student" due="March 18" graded="true" name="H1P2: Duality"/>
|
||||
<problem filename="H1P3_Poor_Workmanship" slug="H1P3_Poor_Workmanship" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="closed" rerandomize="per_student" due="March 18" graded="true" name="H1P3: Poor Workmanship"/>
|
||||
</vertical>
|
||||
<problem filename="Resistor_Divider" slug="Resistor_Divider" format="Lab" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never" due="March 18" graded="true" name="Resistor Divider"/>
|
||||
<html filename="Week_1_Tutorials" slug="Week_1_Tutorials" format="Tutorial Index" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never" name="Week 1 Tutorials"/>
|
||||
</sequential>
|
||||
@@ -1 +0,0 @@
|
||||
<course filename="6.002_Spring_2012" slug="6.002_Spring_2012" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never" name="6.002 Spring 2012" start="2015-07-17T12:00" course="full" org="edX" show_timezone="true" advanced_modules="["videoalpha"]"/>
|
||||
@@ -1,13 +0,0 @@
|
||||
<course>
|
||||
<textbook title="Textbook" book_url="https://s3.amazonaws.com/edx-textbooks/guttag_computation_v3/"/>
|
||||
<chapter filename="Overview" slug="Overview" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never" name="Overview"/>
|
||||
<chapter filename="Week_1" slug="Week_1" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never" name="Week 1"/>
|
||||
<chapter slug="Midterm_Exam" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never" name="Midterm Exam">
|
||||
<sequential slug="Midterm_Exam_1121" format="Midterm" graceperiod="0 day 0 hours 5 minutes 0 seconds" showanswer="attempted" rerandomize="per_student" due="April 30, 12:00" graded="true" name="Midterm Exam">
|
||||
<vertical slug="vertical_1122" graceperiod="0 day 0 hours 5 minutes 0 seconds" showanswer="attempted" rerandomize="per_student" due="April 30, 12:00" graded="true">
|
||||
<html filename="Midterm_Exam_1123" slug="Midterm_Exam_1123" graceperiod="0 day 0 hours 5 minutes 0 seconds" rerandomize="per_student" due="April 30, 12:00" graded="true" name="Midterm Exam"/>
|
||||
</vertical>
|
||||
<vertical filename="vertical_98" slug="vertical_1124" graceperiod="0 day 0 hours 5 minutes 0 seconds" showanswer="attempted" rerandomize="per_student" due="April 30, 12:00" graded="true"/>
|
||||
</sequential>
|
||||
</chapter>
|
||||
</course>
|
||||
@@ -1,35 +0,0 @@
|
||||
{
|
||||
"GRADER" : [
|
||||
{
|
||||
"type" : "Homework",
|
||||
"min_count" : 12,
|
||||
"drop_count" : 2,
|
||||
"short_label" : "HW",
|
||||
"weight" : 0.15
|
||||
},
|
||||
{
|
||||
"type" : "Lab",
|
||||
"min_count" : 12,
|
||||
"drop_count" : 2,
|
||||
"category" : "Labs",
|
||||
"weight" : 0.15
|
||||
},
|
||||
{
|
||||
"type" : "Midterm",
|
||||
"name" : "Midterm Exam",
|
||||
"short_label" : "Midterm",
|
||||
"weight" : 0.3
|
||||
},
|
||||
{
|
||||
"type" : "Final",
|
||||
"name" : "Final Exam",
|
||||
"short_label" : "Final",
|
||||
"weight" : 0.4
|
||||
}
|
||||
],
|
||||
"GRADE_CUTOFFS" : {
|
||||
"A" : 0.87,
|
||||
"B" : 0.7,
|
||||
"C" : 0.6
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
More information given in… <a href="/book/${page}">the text</a>.
|
||||
@@ -1 +0,0 @@
|
||||
<a href='https://6002x.mitx.mit.edu/discussion/questions/scope:all/sort:activity-desc/tags:${tag}/page:1/'> Discussion: ${tag}… </a>
|
||||
@@ -1 +0,0 @@
|
||||
<img src="http://pmitros.csail.mit.edu/tutorial/images/${file}" />
|
||||
@@ -1 +0,0 @@
|
||||
Lecture Slides Handout [<a href="">Clean… </a>][<a href="">Annotated…</a>]
|
||||
@@ -1,3 +0,0 @@
|
||||
<video width="560" height="340" controls>
|
||||
<source src="http://pmitros.csail.mit.edu/tutorial/raw_links/${name}.webm">
|
||||
</video>
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"GRADER" : [
|
||||
{
|
||||
"type" : "Homework",
|
||||
"min_count" : 3,
|
||||
"drop_count" : 1,
|
||||
"short_label" : "HW",
|
||||
"weight" : 0.5
|
||||
},
|
||||
{
|
||||
"type" : "Final",
|
||||
"name" : "Final Question",
|
||||
"short_label" : "Final",
|
||||
"weight" : 0.5
|
||||
}
|
||||
],
|
||||
"GRADE_CUTOFFS" : {
|
||||
"A" : 0.8,
|
||||
"B" : 0.7,
|
||||
"C" : 0.44
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<center>
|
||||
Final Exam
|
||||
</center>
|
||||
<p>This exam covers weeks 1-13. You may use your calculator, your notes, your book, the internet, or any other auxiliary materials that you think can help you. However, you are not allowed to communicate with any person on any topic associated with this course while you are taking this exam.</p>
|
||||
<p>
|
||||
Once you click on the next tab, you will have 24 hours to complete the examination. For each problem you will be allowed exactly three submissions. Your
|
||||
answers to that problem will be checked after each submission, so you
|
||||
can fix mistakes you may have made, within the three-submission limit.
|
||||
Your most recently checked answer is the answer that will contribute to your grade on the exam.
|
||||
</p>
|
||||
<p>
|
||||
Each answer box on the exam contributes equally to your grade on the exam, regardless of how they are grouped as problems.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,8 +0,0 @@
|
||||
Hint…
|
||||
<br/><br/>
|
||||
Remember that the time evolution of any variable \(x(t)\) governed by
|
||||
a first-order system with a time-constant \(\tau\) for a time \(t) between an initial
|
||||
value \(x(t_0)\) and a final value \(x(\infty)\) is the following:
|
||||
<br/><br/>
|
||||
\(x(t) = x(\infty) + (x(t_0) - x(\infty)) e^(-(t-t_0)/\tau)\)
|
||||
<br/><br/>
|
||||
@@ -1,105 +0,0 @@
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#r1_slider").slider({
|
||||
value: 1, min: 1, max: 10, step: 1, slide: schematic.component_slider,
|
||||
schematic: "ctrls", component: "R1", property: "r", analysis: "dc",
|
||||
})
|
||||
|
||||
$("#r2_slider").slider({
|
||||
value: 1, min: 1, max: 10, step: 1, slide: schematic.component_slider,
|
||||
schematic: "ctrls", component: "R2", property: "r", analysis: "dc",
|
||||
})
|
||||
|
||||
$("#r3_slider").slider({
|
||||
value: 1, min: 1, max: 10, step: 1, slide: schematic.component_slider,
|
||||
schematic: "ctrls", component: "R3", property: "r", analysis: "dc",
|
||||
})
|
||||
|
||||
$("#r4_slider").slider({
|
||||
value: 1, min: 1, max: 10, step: 1, slide: schematic.component_slider,
|
||||
schematic: "ctrls", component: "R4", property: "r", analysis: "dc",
|
||||
})
|
||||
|
||||
$("#slider").slider(); });
|
||||
</script>
|
||||
|
||||
<b>Lab 2A: Superposition Experiment</b>
|
||||
|
||||
<br><br><i>Note: This part of the lab is just to develop your intuition about
|
||||
superposition. There are no responses that need to be checked.</i>
|
||||
|
||||
<br/><br/>Circuits with multiple sources can be hard to analyze as-is. For example, what is the voltage
|
||||
between the two terminals on the right of Figure 1?
|
||||
|
||||
<center>
|
||||
<input width="425" type="hidden" height="150" id="schematic1" parts="" analyses="" class="schematic ctrls" name="test2" value="[["w",[160,64,184,64]],["w",[160,16,184,16]],["w",[64,16,112,16]],["w",[112,64,88,64]],["w",[64,64,88,64]],["g",[88,64,0],{},["0"]],["w",[112,64,160,64]],["w",[16,64,64,64]],["r",[160,16,0],{"name":"R4","r":"1"},["1","0"]],["r",[160,16,1],{"name":"R3","r":"1"},["1","2"]],["i",[112,64,6],{"name":"","value":"6A"},["0","2"]],["r",[64,16,0],{"name":"R2","r":"1"},["2","0"]],["r",[64,16,1],{"name":"R1","r":"1"},["2","3"]],["v",[16,16,0],{"name":"","value":"8V"},["3","0"]],["view",-24,0,2]]"/>
|
||||
Figure 1. Example multi-source circuit
|
||||
</center>
|
||||
|
||||
<br/><br/>We can use superposition to make the analysis much easier.
|
||||
The circuit in Figure 1 can be decomposed into two separate
|
||||
subcircuits: one involving only the voltage source and one involving only the
|
||||
current source. We'll analyze each circuit separately and combine the
|
||||
results using superposition. Recall that to decompose a circuit for
|
||||
analysis, we'll pick each source in turn and set all the other sources
|
||||
to zero (i.e., voltage sources become short circuits and current
|
||||
sources become open circuits). The circuit above has two sources, so
|
||||
the decomposition produces two subcircuits, as shown in Figure 2.
|
||||
|
||||
<center>
|
||||
<table><tr><td>
|
||||
<input style="display:inline;" width="425" type="hidden" height="150" id="schematic2" parts="" analyses="" class="schematic ctrls" name="test2" value="[["w",[160,64,184,64]],["w",[160,16,184,16]],["w",[64,16,112,16]],["w",[112,64,88,64]],["w",[64,64,88,64]],["g",[88,64,0],{},["0"]],["w",[112,64,160,64]],["w",[16,64,64,64]],["r",[160,16,0],{"name":"R4","r":"1"},["1","0"]],["r",[160,16,1],{"name":"R3","r":"1"},["1","2"]],["r",[64,16,0],{"name":"R2","r":"1"},["2","0"]],["r",[64,16,1],{"name":"R1","r":"1"},["2","3"]],["v",[16,16,0],{"name":"","value":"8V"},["3","0"]],["view",-24,0,2]]"/>
|
||||
(a) Subcircuit for analyzing contribution of voltage source
|
||||
</td><td>
|
||||
<input width="425" type="hidden" height="150" id="schematic3" parts="" analyses="" class="schematic ctrls" name="test2" value="[["w",[16,16,16,64]],["w",[160,64,184,64]],["w",[160,16,184,16]],["w",[64,16,112,16]],["w",[112,64,88,64]],["w",[64,64,88,64]],["g",[88,64,0],{},["0"]],["w",[112,64,160,64]],["w",[16,64,64,64]],["r",[160,16,0],{"name":"R4","r":"1"},["1","0"]],["r",[160,16,1],{"name":"R3","r":"1"},["1","2"]],["i",[112,64,6],{"name":"","value":"6A"},["0","2"]],["r",[64,16,0],{"name":"R2","r":"1"},["2","0"]],["r",[64,16,1],{"name":"R1","r":"1"},["2","3"]],["view",-24,0,2]]"/>
|
||||
(b) Subcircuit for analyzing contribution of current source
|
||||
</td></tr></table>
|
||||
<br>Figure 2. Decomposition of Figure 1 into subcircuits
|
||||
</center>
|
||||
|
||||
<br/>Let's use the DC analysis capability of the schematic tool to see superposition
|
||||
in action. The sliders below control the resistances of R1, R2, R3 and R4 in all
|
||||
the diagrams. As you move the sliders, the schematic tool will adjust the appropriate
|
||||
resistance, perform a DC analysis and display the node voltages on the diagrams. Here's
|
||||
what you want to observe as you play with the sliders:
|
||||
|
||||
<ul style="margin-left:2em;margin-top:1em;margin-right:2em;margin-bottom:1em;">
|
||||
<i>The voltage for a node in Figure 1 is the sum of the voltages for
|
||||
that node in Figures 2(a) and 2(b), just as predicted by
|
||||
superposition. (Note that due to round-off in the display of the
|
||||
voltages, the sum of the displayed voltages in Figure 2 may only be within
|
||||
.01 of the voltages displayed in Figure 1.)</i>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
<center>
|
||||
<table><tr valign="top">
|
||||
<td>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td>R1</td>
|
||||
<td>
|
||||
<div id="r1_slider" style="width:200px; height:10px; margin-left:15px"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td>R2</td>
|
||||
<td>
|
||||
<div id="r2_slider" style="width:200px; height:10px; margin-left:15px; margin-top:10px;"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td>R3</td>
|
||||
<td>
|
||||
<div id="r3_slider" style="width:200px; height:10px; margin-left:15px; margin-top:10px;"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td>R4</td>
|
||||
<td>
|
||||
<div id="r4_slider" style="width:200px; height:10px; margin-left:15px; margin-top:10px;"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr></table>
|
||||
</center>
|
||||
@@ -1,35 +0,0 @@
|
||||
<center>
|
||||
Midterm Exam
|
||||
</center>
|
||||
|
||||
<p>
|
||||
This is a twenty four hour examination. You can start the exam when it is
|
||||
convenient for you, but you must complete this examination by 12:00pm (noon)
|
||||
GMT on April 30th. Please look up what time this is in your local time zone.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When you open the next page, you will have started the examination.
|
||||
You do not need to start now: you will not be timed until you open the
|
||||
next page. Once you have opened the next page page you must complete
|
||||
the exam and make your final submission within twenty four hours of starting
|
||||
the exam.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You may use any notes, computational, or auxiliary materials that you
|
||||
think can help you. However, you may not communicate with any person
|
||||
about this examination while working on it. Furthermore, you may not
|
||||
communicate about the exam until the exam has been closed for everyone.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For each problem you will be allowed exactly three submissions. Your
|
||||
answers to that problem will be checked after each submission, so you
|
||||
can fix mistakes you may have made, within the three-submission limit.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you want to go back and study some more before starting this
|
||||
exam you can do so. Good Luck!
|
||||
</p>
|
||||
@@ -1,34 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<center>
|
||||
Midterm Exam
|
||||
</center>
|
||||
<p>
|
||||
This is a twenty four hour examination. You can start the exam when it is
|
||||
convenient for you, but you must complete this examination by 12:00pm (noon)
|
||||
GMT on April 30th. Please look up what time this is in your local time zone.
|
||||
</p>
|
||||
<p>
|
||||
When you open the next page, you will have started the examination.
|
||||
You do not need to start now: you will not be timed until you open the
|
||||
next page. Once you have opened the next page page you must complete
|
||||
the exam and make your final submission within twenty four hours of starting
|
||||
the exam.
|
||||
</p>
|
||||
<p>
|
||||
You may use any notes, computational, or auxiliary materials that you
|
||||
think can help you. However, you may not communicate with any person
|
||||
about this examination while working on it. Furthermore, you may not
|
||||
communicate about the exam until the exam has been closed for everyone.
|
||||
</p>
|
||||
<p>
|
||||
For each problem you will be allowed exactly three submissions. Your
|
||||
answers to that problem will be checked after each submission, so you
|
||||
can fix mistakes you may have made, within the three-submission limit.
|
||||
</p>
|
||||
<p>
|
||||
If you want to go back and study some more before starting this
|
||||
exam you can do so. Good Luck!
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,34 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<center>
|
||||
Midterm Exam
|
||||
</center>
|
||||
<p>
|
||||
This is a twenty four hour examination. You can start the exam when it is
|
||||
convenient for you, but you must complete this examination by 12:00pm (noon)
|
||||
GMT on April 30th. Please look up what time this is in your local time zone.
|
||||
</p>
|
||||
<p>
|
||||
When you open the next page, you will have started the examination.
|
||||
You do not need to start now: you will not be timed until you open the
|
||||
next page. Once you have opened the next page page you must complete
|
||||
the exam and make your final submission within twenty four hours of starting
|
||||
the exam.
|
||||
</p>
|
||||
<p>
|
||||
You may use any notes, computational, or auxiliary materials that you
|
||||
think can help you. However, you may not communicate with any person
|
||||
about this examination while working on it. Furthermore, you may not
|
||||
communicate about the exam until the exam has been closed for everyone.
|
||||
</p>
|
||||
<p>
|
||||
For each problem you will be allowed exactly three submissions. Your
|
||||
answers to that problem will be checked after each submission, so you
|
||||
can fix mistakes you may have made, within the three-submission limit.
|
||||
</p>
|
||||
<p>
|
||||
If you want to go back and study some more before starting this
|
||||
exam you can do so. Good Luck!
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<h1>Week 13 Tutorials</h1>
|
||||
<section class="tutorials">
|
||||
<h2> Basic Tutorials </h2>
|
||||
<ul>
|
||||
<li><a href="/section/wk13_solder">Soldering</a> — Steve
|
||||
Finberg, one of the pioneers in from Draper Lab, talks about
|
||||
soldering. </li>
|
||||
</ul>
|
||||
<h2> Bonus Tutorials </h2>
|
||||
<ul>
|
||||
<li><a href="/section/wk13_FreqResp">Frequency Response
|
||||
Curves</a> — We explain several techniques for understanding
|
||||
and approximating Bode plots. </li>
|
||||
</ul>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,47 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<h1>Week 1 Tutorials</h1>
|
||||
<section class="tutorials">
|
||||
<h2> Introduction </h2>
|
||||
<ul>
|
||||
<li><a href="/section/intro"> Welcome! </a> - We introduce
|
||||
ourselves and explain the tutorial format. </li>
|
||||
</ul>
|
||||
<h2>Basic Tutorials </h2>
|
||||
<ul>
|
||||
<li><a href="/section/circuit_abstraction">The Circuit
|
||||
Abstraction</a> - We look at a lightbulb, and see that abstracting
|
||||
away the circuit from the geometry of the wiring has no visible
|
||||
effect. </li>
|
||||
<li><a href="/section/a_real_circuit/">Lightbulb Circuit</a> - We
|
||||
look at the voltage across a lightbulb with a multimeter, and
|
||||
confirm the device is symmetric. In the process, we see reference
|
||||
directions for currents, voltages, and polarity for powers. </li>
|
||||
<li><a href="/section/parallel_resistors">Parallel Resistors</a> -
|
||||
An explanation of equivalent circuits in the context of parallel
|
||||
resistors.</li>
|
||||
<li><a href="/section/series_and_parallel">Combination of Series
|
||||
and Parallel</a> - Slightly more complex networks of resistors
|
||||
simplified with equivalent networks.</li>
|
||||
<li><a href="/section/3r_nodal">Nodal Analysis</a> - A simple
|
||||
example of nodal analysis.</li>
|
||||
<li><a href="/section/floating_voltage_3r">Floating Voltage</a> -
|
||||
Nodal analysis with a floating source.</li>
|
||||
<li><a href="/section/combination_rules">Combination Rules</a> -
|
||||
We show how to apply combination rules to solving simple
|
||||
circuits.</li>
|
||||
</ul>
|
||||
<h2>Worked Problems </h2>
|
||||
<p> For the first week, we work through <a href="http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-002-circuits-and-electronics-spring-2007/assignments/hw1.pdf"> the first problem set from 2007</a></p>
|
||||
<ul>
|
||||
<li><a href="/section/exercise_1_1">OCW Exercise 1-1</a>: Find voltages in a simple series and parallel circuit, and show power is conserved</li>
|
||||
<li><a href="/section/ex_1_2">OCW Exercise 1-2</a> - Synthesize a network of 3/5k and 5/3k from at most four 1k resistors</li>
|
||||
<li><a href="/section/problem_1-1">OCW Problem 1-1/Textbook 2.7</a> - Find the current through a resistor in a network of resistors</li>
|
||||
<li><a href="/section/problem_1-2_part1">OCW Problem 1-2</a> - Analyze long chains of resistors (similar to transmission lines or R1R2 ladders) </li>
|
||||
<li><a href="/section/problem_1_3">OCW Problem 1-3 </a> - Reverse engineer a black-box resistor network</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<p> Since the course has students from a diverse set of backgrounds, the first week's tutorials includes several extra segments, worked out with greater detail, to help bring everyone up to speed. Gratuitous ≥ entity.</p>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
<html slug="html_5555" filename="html_5555> See the <a href="/section/labintro"> Lab Introduction </a> or <a href="/static/handouts/schematic_tutorial.pdf">Interactive Lab Usage Handout </a> for information on how to do the lab. </html>
|
||||
@@ -1,39 +0,0 @@
|
||||
Clarification of the term "Linear"
|
||||
<p>
|
||||
The term "linear" is very clear when applied to a
|
||||
mathematical function. A function F is linear if and only
|
||||
if it obeys homogeneity and superposition:
|
||||
</p><p>
|
||||
Homogeneity: F(cx) = cF(x)
|
||||
<br/>
|
||||
Superposition: F(x+y) = F(x) + F(y)
|
||||
</p><p>
|
||||
In the context of what we have seen so far, the only
|
||||
elements that are linear as mathematical functions are
|
||||
resistors. An independent voltage source or an independent
|
||||
current source is not a linear element. (There are also
|
||||
linear dependent sources, linear capacitors and linear
|
||||
inductors, but we have not yet introduced them in our class.
|
||||
You will see them later.)
|
||||
</p><p>
|
||||
Formally, a circuit composed of only linear elements is a
|
||||
linear circuit. When we add independent sources to a linear
|
||||
circuit as inputs, we get a circuit that is not linear
|
||||
because it has an offset: its v-i characteristic at a pair
|
||||
of exposed terminals may not pass through the origin.
|
||||
However, we can make a Thevenin or Norton equivalent model
|
||||
of such a circuit: the Thevenin resistance summarizes the
|
||||
effect of the linear elements and the Thevenin voltage
|
||||
summarizes the effect of the independent sources.
|
||||
</p><p>
|
||||
However the term "linear," when applied to an electrical
|
||||
circuit often takes on an informal meaning. We often say
|
||||
that a circuit containing only linear elements and
|
||||
independent sources is a "linear circuit." So, in the
|
||||
informal sense, a linear circuit is one where we can apply
|
||||
the Thevenin or Norton theorems to summarize the behavior at
|
||||
a pair of exposed terminals.
|
||||
</p><p>
|
||||
Sorry for the confusion of words — natural language is like
|
||||
that!
|
||||
</p>
|
||||
@@ -1,39 +0,0 @@
|
||||
Clarification of the term "Linear"
|
||||
<p>
|
||||
The term "linear" is very clear when applied to a
|
||||
mathematical function. A function F is linear if and only
|
||||
if it obeys homogeneity and superposition:
|
||||
</p><p>
|
||||
Homogeneity: F(cx) = cF(x)
|
||||
<br/>
|
||||
Superposition: F(x+y) = F(x) + F(y)
|
||||
</p><p>
|
||||
In the context of what we have seen so far, the only
|
||||
elements that are linear as mathematical functions are
|
||||
resistors. An independent voltage source or an independent
|
||||
current source is not a linear element. (There are also
|
||||
linear dependent sources, linear
|
||||
inductors, and other linear elements, but we have not yet introduced them in our class.
|
||||
You will see them later.)
|
||||
</p><p>
|
||||
Formally, a circuit composed of only linear elements is a
|
||||
linear circuit. When we add independent sources to a linear
|
||||
circuit as inputs, we get a circuit that is not linear
|
||||
because it has an offset: its v-i characteristic at a pair
|
||||
of exposed terminals may not pass through the origin.
|
||||
However, we can make a Thevenin or Norton equivalent model
|
||||
of such a circuit: the Thevenin resistance summarizes the
|
||||
effect of the linear elements and the Thevenin voltage
|
||||
summarizes the effect of the independent sources.
|
||||
</p><p>
|
||||
However the term "linear," when applied to an electrical
|
||||
circuit often takes on an informal meaning. We often say
|
||||
that a circuit containing only linear elements and
|
||||
independent sources is a "linear circuit." So, in the
|
||||
informal sense, a linear circuit is one where we can apply
|
||||
the Thevenin or Norton theorems to summarize the behavior at
|
||||
a pair of exposed terminals.
|
||||
</p><p>
|
||||
Sorry for the confusion of words — natural language is like
|
||||
that!
|
||||
</p>
|
||||
@@ -1,75 +0,0 @@
|
||||
<p/><b>Usage Summary:</b>
|
||||
|
||||
<table style="border-spacing:2em; border-collapse: separate;">
|
||||
|
||||
<tr>
|
||||
<td style="width:10em;">Add a component</td>
|
||||
<td>Click on the component in the parts bin (the columns of part icons to
|
||||
the right of the diagram area) and drag it onto the diagram. Release
|
||||
the mouse when the component is in the correct position.
|
||||
</td>
|
||||
</tr>
|
||||
<!-- note that entities like — may be used. -->
|
||||
<tr>
|
||||
<td>Move a component</td>
|
||||
<td>Click to select a component in the diagram (it will turn green)
|
||||
and then drag it to its new location. You can use shift-click to add
|
||||
a component to the current selection. Or you can click somewhere in
|
||||
the diagram that is not on top of a component and drag out a selection
|
||||
rectangle — components intersecting the rectangle will be added to
|
||||
the current selection.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Rotate a component</td>
|
||||
<td>Click to select a component in the diagram (it will turn green)
|
||||
and then type the letter "r" on the keyboard. The component will
|
||||
be rotated 90 degrees. Additional rotations will move the component
|
||||
through its eight possible orientations (4 compass points and their
|
||||
reflections).
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Delete a component</td>
|
||||
<td>Click to select the component in the diagram (shift-click to
|
||||
select multiple components) then type DEL or BACKSPACE on your
|
||||
keyboard.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Change a component's properties</td>
|
||||
<td>Double click on the component. This will bring up an Edit Properties
|
||||
window that has input fields for each of the component's properties.
|
||||
Click OK to change the values. Click CANCEL or the window's close
|
||||
button to abort the changes. Numeric values can be entered using
|
||||
engineeering notation:
|
||||
|
||||
<center><table style="border-collapse:separate; border-spacing:1em;">
|
||||
<tr><th>suffix</th><th>multiplier</th> <th style="width:3em"></th> <th>suffix</th><th>multiplier</th></tr>
|
||||
<tr><td>T</td><td>\(10^{12}\)</td> <td></td> <td>u</td><td>\(10^{-6}\)</td></tr>
|
||||
<tr><td>G</td><td>\(10^{9}\)</td> <td></td> <td>n</td><td>\(10^{-9}\)</td></tr>
|
||||
<tr><td>M</td><td>\(10^{6}\)</td> <td></td> <td>p</td><td>\(10^{-12}\)</td></tr>
|
||||
<tr><td>k</td><td>\(10^{3}\)</td> <td></td> <td>f</td><td>\(10^{-15}\)</td></tr>
|
||||
<tr><td>m</td><td>\(10^{-3}\)</td></tr>
|
||||
</table></center>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Add a wire</td>
|
||||
<td>Wires start at connection points, the open circles that
|
||||
appear at the terminals of components or the ends of wires.
|
||||
Click on a connection point to start a wire — a green wire
|
||||
will appear with one end anchored at the starting point.
|
||||
Drag the mouse and release the mouse button when the other
|
||||
end of the wire is positioned as you wish. Once a wire has
|
||||
been added to the diagram it can be manipulated like any other
|
||||
component.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
@@ -1 +0,0 @@
|
||||
Test file for HTML in data
|
||||
@@ -1,4 +0,0 @@
|
||||
Hint…
|
||||
<br/><br/>
|
||||
Be careful of units here. Make sure you notice multipliers such
|
||||
as u (or μ), k, m, M.
|
||||
@@ -1,8 +0,0 @@
|
||||
<h1> Updates </h1>
|
||||
<ol>
|
||||
<li>
|
||||
<section class="update-description">
|
||||
Welcome to 6002x. Please look around.
|
||||
</section>
|
||||
</li>
|
||||
</ol>
|
||||
@@ -1 +0,0 @@
|
||||
<a href='/static/handouts/schematic_tutorial.pdf'>Schematic Tutorial</a>
|
||||
@@ -1,195 +0,0 @@
|
||||
<h1> Updates </h1>
|
||||
<ol>
|
||||
<li> <h2>May 7</h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li> There is a review of complex numbers available in the Week 10 tutorials, provided by Prof. Jeremy Orloff of the MIT math department. A link has also been provided in the <a href="https://6002x.mitx.mit.edu/wiki/view/MathReview">Math Review</a> section of the wiki. </li>
|
||||
</ul>
|
||||
</li>
|
||||
<li> <h2>May 2 </h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<!-- utf-8 characters are acceptable… as are HTML entities -->
|
||||
<li> We have opened the show-answer button on the midterm… </li>
|
||||
<li> There was a four hour outage in posting ability on the discussion board Monday night… It has been fixed. We apologise for the inconvenience.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li> <h2>April 30 </h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li> The midterm closed early this morning. Staff solutions will be available next week, but you are encouraged to discuss the problems that you thought were particularly hard on the discussion forum. Congratulations on making it halfway through the course! </li>
|
||||
</ul>
|
||||
</li>
|
||||
<li> <h2>April 25 </h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li> The midterm is now available. It will close after midnight on Sunday night has passed in all timezones. Specifically, it will close 12:00pm (noon) GMT, April 30th. It covers the material in weeks one through six. Good Luck!</li>
|
||||
<li> Absolutely no collaboration is allowed on the midterm. Prof. Agarwal has provided a clarification of the collaboration policy on the <a href="https://6002x.mitx.mit.edu/discussion/question/55202/collaboration-guidelines"> discussion forum. </a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
<li> <h2>April 23 </h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li> Reminder: the midterm will be released on Wednesday and close on Sunday. Please see the April 3 and April 9 announcements for more logistical details.</li>
|
||||
<li> Some students have put together extra study materials for the quiz. There are <a href="https://6002x.mitx.mit.edu/discussion/question/45083/how-about-a-course-flashcard-system-as-a-study-aid"> flashcards </a> and <a href="https://6002x.mitx.mit.edu/discussion/question/43696/summaries-for-lectures-1-to-12-more-added-april-19"> summaries </a></li>
|
||||
<li>The grading programs for the sequence 15 exercises have been fixed. Thanks to all of the participants in <a href="https://6002x.mitx.mit.edu/discussion/question/49561/midterm-warning-no-spaces-allowed-in-answer-s15e1"> this thread </a> for pointing out their difficulties. </li>
|
||||
</ul>
|
||||
</li>
|
||||
<li> <h2>April 23 </h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li>There was a bug that caused the Week 6 homework and lab to close early in some timezones. That bug has been fixed, and the due date for Week 6 assignments has been moved to Tuesday night at midnight. We apologize for the inconvenience.</li>
|
||||
<li>In order to help people study for the midterm this week, we will release the Week 6 solutions on their normal release schedule. You will be able to see them later today. Please do not look at the solutions before submitting your Week 6 assignments. We are relying on your honesty and adherence to the Honor Code in this matter.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li> <h2>April 16 </h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li>Weeks 6 and 9 will require more mathematical background than the rest of the course. Please bear with us for those two weeks. This is necessary to understanding the roots of the more intuitive tools that will be developed over the remainder of the course for understanding dynamic systems. </li>
|
||||
</ul>
|
||||
</li>
|
||||
<li> <h2>April 9 </h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li>The wiki now saves circuits as part of the revision history. The format for entering circuits into the wiki is now the keyword "circuit-schematic:". There will be a few minutes of downtime as old circuits are converted into the new format.</li>
|
||||
<li> Although you will have 24 hours to complete the midterm, we do not anticipate that the time limit will be the limiting factor in completing the exam. We hope that it will only take you a couple of hours to finish.</li>
|
||||
<li> In order to clear up some confusion in the format the exam will take, we have posted <a href="/section/MidtermFormatExamples/"> two example exam questions</a>. </li>
|
||||
<li> At least one of the questions on the exam will be strongly inspired by a question from the homeworks, so it would be worth your time to make sure that you understand all of the homework solutions. </li>
|
||||
<li> We have released a review packet for the midterm, <a href="/static/handouts/6002x-MidTermReview-S2012-clean.pdf">without solutions </a>, and <a href="/static/handouts/6002x-MidTermReview-S2012.pdf">with solutions</a>. Note that the exam covers material from weeks one through six. If you have not yet finished going through the material for those weeks, we would encourage going through learning the material in the format that it was initially published before using these review resources.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li> <h2>April 3 </h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li> The exam will be released in the courseware section on Wednesday, April 25th. It will be closed at the end of Sunday, April 29th. See the chart below for release and close times in selected time zones. The exam will consist of two elements in sequence: a cover sheet and the exam itself. Once you click past the cover sheet and open the exam, <strong>you will have twenty-four hours to complete it.</strong> Please be careful to keep track of your own time, as we have no mechanism to warn you when your time is about to expire.
|
||||
<br/>
|
||||
<br/>
|
||||
<table>
|
||||
<tr><td>release</td><td>close</td></tr>
|
||||
<tr><td>10:00pm GMT April 25th  </td> <td>12:00pm GMT April 30th</td></tr>
|
||||
<tr><td>5:00pm EST April 25th</td> <td>7:00am EST April 30th</td></tr>
|
||||
<tr><td>2:00pm PST April 25th</td> <td>4:00am PST April 30th</td></tr>
|
||||
<tr><td>3:30am IST April 26th</td> <td>5:30pm IST April 30th</td></tr>
|
||||
</table>
|
||||
</li>
|
||||
<li> The format of the exam will be very similar to the homeworks, with one exception: you will have a limited number of opportunities to check your answers. You will only be able to check your answers three times before you will no longer be able change your response.</li>
|
||||
<li> There was a short period this morning when the grade plot was showing percentages incorrectly due to a bug in the display code. We apologize for any inconvenience. If you run into any other display issues, please try reloading your browser.</li>
|
||||
</ul>
|
||||
</section>
|
||||
<li> <h2>April 2 </h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li>We will soon start using differential equations in the course material. We have posted a little bit of <a href="/wiki/view/MathReview"> math review </a> on the wiki for people who need a refresher.</li>
|
||||
<li>Please note that we are unable to change the due dates of the assignments for any person for any reason. If something unexpected comes up, we ask that you use one of your allocated two dropped homeworks or two dropped labs.</li>
|
||||
<li>The third week's assignments have been due, so new students who have registered late will not have enough dropped assignments allocated to them to earn all of the points in the course. New students are encouraged to use the course material for their own enrichment, to earn all of the points still available to be earned, or wait until the next offering </li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<li> <h2> March 26 </h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li> Thomas Loch wrote a number of <a href="http://userscripts.org/tags/mitx">scripts</a> that offer
|
||||
enhancements to MITx. These scripts need a Firefox plug-in,
|
||||
<a href="https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/">GreaseMonkey</a>, in order to work.
|
||||
They provide functionality like quality and volume selection for
|
||||
videos, integration with our IRC server, and automatic advance
|
||||
of lecture sequences when a video finishes playing. Note that some sequences
|
||||
-- such as this week's tutorials -- rely on the break between videos.</li>
|
||||
<li> There's an unofficial <a href="http://irc.mitx.mit.edu/webchat/">
|
||||
web client </a> for the IRC channel now available. Please pick a
|
||||
username better than the default. </li>
|
||||
<li> There is a lab experiment this week that requires a recent
|
||||
version of Chrome or Firefox to work. This is the first content that
|
||||
will not work with IE (it processes sound in the browser in a way which
|
||||
is not possible with IE).
|
||||
</ul>
|
||||
</section>
|
||||
<li> <h2> March 19th</h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li> The last update originally listed the wrong name for the creater of the course downloader. Josiah Yan wrote the utility. </li>
|
||||
</ul>
|
||||
</section>
|
||||
</li>
|
||||
<li> <h2>March 15th</h2>
|
||||
<section class="update-description">
|
||||
<ul>
|
||||
<li>We have posted solutions to the ungraded lecture exercises. Solutions
|
||||
to graded assessments will be available after the deadline.</li>
|
||||
<li> Several
|
||||
students asked about how to submit homeworks -- simply hit "check" --
|
||||
your problems are automatically checked, saved, and graded.</li>
|
||||
</ul>
|
||||
<p> As
|
||||
some <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat">IRC</a>
|
||||
users already know, a couple of 6.002x students have put together
|
||||
tools that have been requested in the discussion forums: </p>
|
||||
<ul><li> Jeff Kent created a scrolling textbook viewer. We posted his tool <a href='/static/contrib/xbook.html'> here </a></li>
|
||||
<li> Josiah Yan posted a downloader for the course on his <a href='https://github.com/terriblybored/MITx-6002x-Video-Downloader'> github account. </a> </li>
|
||||
</ul>
|
||||
If you haven't visited the IRC channel
|
||||
(irc.mitx.mit.edu, channel
|
||||
#6002), feel free to download an IRC client, and check it out. Good place
|
||||
to meet other students, and occasionally, the devs.
|
||||
</section>
|
||||
</li>
|
||||
<li>
|
||||
<h2> March 12th </h2>
|
||||
<section class="update-description">
|
||||
Due to student feedback in the forums, we have changed due dates from
|
||||
the beginning of the weekend to the end of the weekend. Enjoy the
|
||||
extra time to complete assignments! Otherwise, we now have better
|
||||
error messages for incorrect inputs, and a slew of other minor
|
||||
fixes. If you experience any problems after the update, please try
|
||||
holding shift and hitting the reload button in your browser.
|
||||
</section>
|
||||
</li>
|
||||
<li>
|
||||
<h2> March 8th </h2>
|
||||
<section class="update-description">
|
||||
It is great to see all the activity in the discussion forum! We recently updated <a href='/wiki/view/QuestionAnswerFAQ'> <strong>the wiki </strong> </a> with more detailed guidance on how to get help from the course staff. We encourage you to check out those guidelines in order to get the most benefit from that resource.
|
||||
</section>
|
||||
</li>
|
||||
<li>
|
||||
<h2> March 6th</h2>
|
||||
<section class="update-description">
|
||||
<p> Several key issues were reported: </p>
|
||||
|
||||
<ul>
|
||||
<li> Tolerance on S1E2 was set a bit too tight -- many
|
||||
solutions (including our own -- we printed more digits at the
|
||||
time these were tested) were marked wrong since we required
|
||||
many digits. This is now corrected.
|
||||
<li> Several students reported (correctly) that our error
|
||||
messages are unclear. A dictionary:
|
||||
<div style="margin-left:50px">
|
||||
<ul> <li> "Unknown error" -- this occurs if you
|
||||
submit non-numeric answers to numeric problems. This most
|
||||
commonly occurs if a comma is used instead of a decimal point,
|
||||
or units are included.
|
||||
<li> "Syntax error" occurs when you type in a
|
||||
formula with an error. E.g. (((
|
||||
<li> "Undefined" means you used an invalid
|
||||
variable in your answer. E.g. if you used 'z' when taking the
|
||||
derivative of e^x (instead of just 'e' and 'x').
|
||||
</ul>
|
||||
</div>
|
||||
<li> Some of the documentation refers to a "save"
|
||||
button. This was eliminated based on user tests prior to
|
||||
release, but we still had references to it in our
|
||||
documentation. Please use the check button instead, which both
|
||||
checks your answers and saves.
|
||||
</ul>
|
||||
</section>
|
||||
</li>
|
||||
<li>
|
||||
<h2> March 5th</h2>
|
||||
<section class="update-description">
|
||||
Welcome to 6.002x!
|
||||
|
||||
You can find a video tutorial for the system tools <a href="/courseware/6.002_Spring_2012/Overview/System_Usage_Sequence/">"System Usage Sequence"</a> in the Overview section of the courseware. There are also several system usage handouts in the handouts section on the side, including the "6.002x At-a-Glance (Calendar)". The System Usage video sequence walks you through the various features of the online learning platform, and the 6.002x At-a-Glance handout provides a detailed week-by-week schedule of course topics, textbook readings, and deadlines. After you familiarize yourself with the various features of the MITx platform, you can jump right into the coursework by working on "Administrivia and Circuit Elements", the first Lecture Sequence in Week 1.
|
||||
|
||||
Enjoy the course!
|
||||
</section>
|
||||
</li>
|
||||
</ol>
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"course/6.002_Spring_2012": {
|
||||
"graceperiod": "1 day 12 hours 59 minutes 59 seconds",
|
||||
"start": "2012-09-21T12:00",
|
||||
"display_name": "Testing",
|
||||
"xqa_key": "5HapHs6tHhu1iN1ZX5JGNYKRkXrXh7NC",
|
||||
"tabs": [
|
||||
{"type": "courseware"},
|
||||
{"type": "course_info", "name": "Course Info"},
|
||||
{"type": "static_tab", "url_slug": "syllabus", "name": "Syllabus"},
|
||||
{"type": "static_tab", "url_slug": "resources", "name": "Resources"},
|
||||
{"type": "discussion", "name": "Discussion"},
|
||||
{"type": "wiki", "name": "Wiki"},
|
||||
{"type": "progress", "name": "Progress"}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
<problem><!-- include ellipses to test non-ascii characters --><startouttext/><p/>Here's a sandbox where you can experiment with all the components
|
||||
we'll discuss in 6.002x. If you click on CHECK below, your diagram
|
||||
will be saved on the server and you can return at some later time…
|
||||
<endouttext/><schematicresponse><p/><center><schematic name="work" value="" width="800" height="600"/></center><answer type="loncapa/python">
|
||||
correct = ['correct']
|
||||
</answer></schematicresponse></problem>
|
||||
@@ -1,32 +0,0 @@
|
||||
<problem><script type="loncapa/python">
|
||||
i = random.randrange(3)
|
||||
M = ["Big Mac", "Angus Bacon and Cheese", "Quarter Pounder with Cheese"][i]
|
||||
C = [540, 790, 510][i]
|
||||
|
||||
BM = C*1000*4.2
|
||||
CB = 50*12*3600
|
||||
</script><startouttext/>
|
||||
According to McDonald's
|
||||
<a href="http://nutrition.mcdonalds.com/getnutrition/nutritionfacts.pdf">nutrition
|
||||
facts</a> a \($M\) provides \($C\) kiloCalories of energy. (1 dietitian's
|
||||
calorie is 1000 physicist's calories.) A typical automobile lead-acid
|
||||
battery can supply 50 Ampere-hours at 12 Volts. We can compare these by
|
||||
converting the energy specifications to common units. The SI unit of
|
||||
energy is the Joule=1 Watt-second. One physicist's calorie is 4.2 Joules.
|
||||
<endouttext/>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
How many Joules are there in a \($M\)?
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$BM"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
How many Joules are there in a car battery?
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$CB"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
Which tastes better? :-)
|
||||
<endouttext/>
|
||||
|
||||
</problem>
|
||||
@@ -1,127 +0,0 @@
|
||||
<problem><script type="loncapa/python">
|
||||
scale = float(random.randrange(1000,2000,10))/1000
|
||||
|
||||
V = 10*scale
|
||||
R1 = 3*scale
|
||||
R2 = 2*scale
|
||||
|
||||
vV = V
|
||||
R1R2S = R1+R2
|
||||
i1 = V/R1R2S
|
||||
i2 = i1
|
||||
iV = -i1
|
||||
v1 = i1*R1
|
||||
v2 = i2*R2
|
||||
|
||||
Ps= vV*iV + v1*i1 + v2*i2
|
||||
|
||||
|
||||
I = V
|
||||
R3 = 1/R1
|
||||
R4 = 1/R2
|
||||
|
||||
iI = -I
|
||||
R3R4P = (R3*R4)/(R3+R4)
|
||||
vI = I*R3R4P
|
||||
v3 = vI
|
||||
v4 = vI
|
||||
i3 = v3/R3
|
||||
i4 = v4/R4
|
||||
|
||||
Pp = vI*iI + v3*i3 + v4*i4
|
||||
</script><startouttext/>
|
||||
In this problem we will investigate a fun idea called "duality."
|
||||
<br/>
|
||||
Consider the series circuit in the diagram shown.
|
||||
<center><img src="/static/circuits/duality.gif"/></center>
|
||||
We are given device parameters \(V=$V\)V, \(R_1=$R1\Omega\), and \(R_2=$R2\Omega\).
|
||||
All of the unknown voltages and currents are labeled in associated reference
|
||||
directions. Solve this circuit for the unknowns and enter them into
|
||||
the boxes given.
|
||||
<br/>
|
||||
The value (in Volts) of \(v_1\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$v1"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The value (in Amperes) of \(i_1\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$i1"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The value (in Volts) of \(v_2\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$v2"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The value (in Amperes) of \(i_2\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$i2"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The value (in Volts) of \(v_V\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$vV"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The value (in Amperes) of \(i_V\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$iV"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The sum of the powers (in Watts) entering all of the elements is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$Ps"><responseparam type="tolerance" default="0.00001" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
|
||||
<startouttext/>
|
||||
<br/> <br/> Now, let's turn our attentions to the parallel circuit.
|
||||
The numerical value of the strength of the current source is set to be
|
||||
the same as the numerical value of the strength of the voltage source:
|
||||
\(I=$I\)A. The resistances are set to be reciprocals of the
|
||||
resistances in the series circuit: \(R_3=$R3\Omega\) and
|
||||
\(R_4=$R4\Omega\).
|
||||
<br/>
|
||||
Solve this circuit for the unknowns and enter them into
|
||||
the boxes given.
|
||||
<br/>
|
||||
The value (in Volts) of \(v_3\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$v3"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The value (in Amperes) of \(i_3\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$i3"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The value (in Volts) of \(v_4\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$v4"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The value (in Amperes) of \(i_4\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$i4"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The value (in Volts) of \(v_I\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$vI"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The value of (in Amperes) \(i_I\) is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$iI"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
The sum of the powers (in Watts) entering all of the elements is:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$Pp"><responseparam type="tolerance" default="0.00001" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
|
||||
<startouttext/>
|
||||
<br/> <br/> Look carefully at the numbers you have derived.
|
||||
Compare the series and parallel circuit. Do you see the pattern?
|
||||
<endouttext/>
|
||||
|
||||
|
||||
</problem>
|
||||
@@ -1,85 +0,0 @@
|
||||
<problem><script type="loncapa/python">
|
||||
V = 240
|
||||
P = float(random.randrange(800,1600,10))
|
||||
Pmax = 3*P
|
||||
Imax = Pmax/V
|
||||
|
||||
Iq = Pmax/120
|
||||
|
||||
R = (V**2)/P
|
||||
|
||||
Rbad = 3*R/2
|
||||
|
||||
Pbad = (V**2)/Rbad
|
||||
|
||||
Ibad = Pbad/V
|
||||
|
||||
PH1 = (Ibad**2)*R
|
||||
PH2 = ((Ibad/2)**2)*R
|
||||
PH3 = PH2
|
||||
</script><startouttext/>
|
||||
Joe wants to heat his 12'X20' workshop with electric heat. He has
|
||||
hired the HACME electrician company to build the system. They propose
|
||||
to use three \($P\)W 240V baseboard heaters to provide a total heating
|
||||
capacity of \($Pmax\)W. (A heater is basically a
|
||||
resistor. This is not quite true, because there is a thermostatic
|
||||
switch incorporated into the heater and because the resistance of a
|
||||
heater varies a bit with its temperature. But we will use a linear
|
||||
resistor as a model of a heater.)
|
||||
<br/>
|
||||
In the proposed system the heaters are connected in parallel with the
|
||||
240V 60Hz AC power line (modeled by a voltage source) as shown in the
|
||||
diagram:
|
||||
<center><img src="/static/circuits/heaters-parallel.gif"/></center>
|
||||
Remember (from exercise S1E3: AC POWER) that AC power-line voltages
|
||||
and currents are specified as RMS values. So 120V AC heats a given
|
||||
resistance exactly as much as 120V DC would heat that same
|
||||
resistance.
|
||||
<endouttext/>
|
||||
|
||||
<startouttext/>
|
||||
<br/>
|
||||
How much current is expected to be drawn from the power line by this
|
||||
heating system when all three heaters are on?
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$Imax"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
If instead, HACME chose to implement the system with 120V heaters, how
|
||||
much current would have been needed?
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$Iq"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
Notice that this would require much heavier and more expensive wire to
|
||||
distribute the power.
|
||||
<br/> <br/>
|
||||
Back to the original plan with 240V power.
|
||||
<br/>
|
||||
Unfortunately, Sparky, who works for HACME, was a little sleepy that
|
||||
day. He accidentally connected the heaters as shown below:
|
||||
<center><img src="/static/circuits/heaters-bad.gif"/></center>
|
||||
<br/>
|
||||
As a consequence, Joe found his workshop too cold. H1 was weak; H2
|
||||
and H3 barely warmed up.
|
||||
<br/>
|
||||
What power was being dissipated in H1?
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$PH1"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
What power was being dissipated in H2 (or in H3)?
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$PH2"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
So the total heating power in Joe's shop was:
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$Pbad"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
<startouttext/>
|
||||
<br/>
|
||||
<!-- add non-ascii utf-8 character here -->
|
||||
No wonder Joe was cold…
|
||||
<endouttext/>
|
||||
|
||||
</problem>
|
||||
@@ -1,115 +0,0 @@
|
||||
<problem><startouttext/><br/>In this first lab, the goal is to familiarize yourself with the
|
||||
interactive tool that will be used to enter and analyze circuits. Here's
|
||||
the example schematic used below:
|
||||
|
||||
<br/><center><input type="hidden" class="schematic" analyses="" parts="" origin_x="50" origin_y="20" width="400" height="350" name="fig1" value="[["w",[120,160,144,160]],["v",[48,64,0],{"name":"Vsupply","value":"dc(3)","_json_":1},["A","D"]],["r",[120,64,0],{"name":"R2","r":"3k","_json_":2},["B","C"]],["r",[120,16,0],{"name":"R1","r":"1k","_json_":3},["A","B"]],["r",[120,112,0],{"name":"R3","r":"2k","_json_":4},["C","D"]],["w",[48,64,48,16]],["w",[48,16,120,16]],["w",[48,112,48,160]],["w",[48,160,120,160]],["w",[120,112,144,112]],["w",[120,64,144,64]],["w",[120,16,144,16]],["L",[144,16,3],{"label":"A","_json_":12},["A"]],["L",[144,64,3],{"label":"B","_json_":13},["B"]],["L",[144,112,3],{"label":"C","_json_":14},["C"]],["g",[48,160,0],{"_json_":15},["D"]],["L",[144,160,3],{"label":"D","_json_":16},["D"]],["view",0,0,2,"5","10","10MEG",null,"100","1"]]"/>
|
||||
Figure 1. Test Circuit for Lab 0
|
||||
</center><br/>And here's the interactive tool to be used in the tasks that follow:
|
||||
|
||||
<endouttext/><schematicresponse><startouttext/><br/><center><schematic analyses="dc,tran" parts="g,L,v,r,s" name="work" value="" width="600" height="400"/></center><endouttext/><answer type="loncapa/python">
|
||||
correct = ['correct']
|
||||
</answer></schematicresponse><startouttext/><br/>Please do the following tasks. When you're done, remember to click CHECK to preserve
|
||||
your work and to verify your answers.
|
||||
|
||||
<ol style="list-style-type:decimal; margin-left: 2em;"><br/><li><b>Enter schematic.</b> Add the voltage source, resistors,
|
||||
wires and ground reference to your diagram, connected as shown
|
||||
in <nobr>Figure 1</nobr>.</li><br/><li><b>Measure voltages.</b> Use the tool to run a DC analysis on
|
||||
the circuit, i.e.., click on the DC button in the toolbar. This will
|
||||
annotate each node/voltage source in the circuit with a
|
||||
voltage/current. If the components are wired correctly, the
|
||||
voltage for node D should be reported as 0V since it's
|
||||
connected to the ground reference and the voltage for node A
|
||||
should be reported as 3V since it is connected directly to the
|
||||
positive terminal of a 3V voltage source whose negative terminal
|
||||
is connected to ground. Please enter the voltages reported for nodes
|
||||
B and C.
|
||||
|
||||
<br/><div style="margin-left: 4em;">
|
||||
Voltage for node B (volts):
|
||||
<numericalresponse answer="2.5"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 4em;">
|
||||
Voltage for node C (volts):
|
||||
<numericalresponse answer="1.0"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
|
||||
</li><br/><li><b>Measure current.</b>
|
||||
|
||||
The DC analysis annotates each voltage source with the current it is
|
||||
providing to the rest of the circuit. The simulator denotes the sign
|
||||
of the source current as positive if the current is flowing out of the
|
||||
positive terminal of the source, through the rest of the circuit, and
|
||||
then back in to the negative terminal. And the source current sign is
|
||||
negative if the current is flowing out of the negative terminal of the
|
||||
source, through the circuit, and into the positive terminal of the
|
||||
source. Please report the total resistance of the path connecting the
|
||||
positive and negative terminals of the source, the signed current
|
||||
flowing from the source into the circuit, and (using the voltage
|
||||
value for the source) verify that Ohm's law is obeyed.
|
||||
|
||||
<br/><div style="margin-left: 4em;">
|
||||
Total resistance between pos and neg terminals (ohms):
|
||||
<numericalresponse answer="6000"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 4em;">
|
||||
Current flowing from source into the circuit (amps, with correct sign):
|
||||
<numericalresponse answer="500e-6"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
|
||||
</li><br/><li><b>Verify KVL.</b> The four components in the schematic form a
|
||||
large loop -- let's verify that Kirchoff's Voltage Law holds by
|
||||
summing the voltage changes across the devices. Starting with node A,
|
||||
travel clockwise around the loop of components, entering the voltage
|
||||
change across each component. Choose the sign of the change for a
|
||||
component using the first terminal you come to in the clockwise
|
||||
traversal as the reference node. Verify that these four values sum
|
||||
to 0.
|
||||
|
||||
<br/>
|
||||
<div style="margin-left: 4em;">
|
||||
Voltage change across R1 (volts, with correct sign):
|
||||
<numericalresponse answer="-0.5"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 4em;">
|
||||
Voltage change across R2 (volts, with correct sign):
|
||||
<numericalresponse answer="-1.5"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 4em;">
|
||||
Voltage change across R3 (volts, with correct sign):
|
||||
<numericalresponse answer="-1.0"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 4em;">
|
||||
Voltage change across Vsupply (volts, with correct sign):
|
||||
<numericalresponse answer="3.0"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
</li><br/><li><b>Transient analysis.</b> Change the waveform produced by
|
||||
the voltage source from a DC value of 3V to a sinusoid with a 1V
|
||||
amplitude, an offset voltage of 1V, and a frequency of 1kHz. Add
|
||||
scope probes to nodes A, B and C and edit their properties so that the
|
||||
plots will be different colors. Now run a transient analysis for 5ms.
|
||||
Move the mouse over the plot until the marker (a vertical dashed line
|
||||
that follows the mouse when it's over the plot) is at approximately
|
||||
1.25ms. Please report the measured voltages for nodes A, B and C…
|
||||
|
||||
<br/>
|
||||
<div style="margin-left: 4em;">
|
||||
Voltage for node A (volts):
|
||||
<numericalresponse answer="1.995"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 4em;">
|
||||
Voltage for node B (volts):
|
||||
<numericalresponse answer="1.662"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 4em;">
|
||||
Voltage for node C (volts):
|
||||
<numericalresponse answer=".665"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
</div>
|
||||
|
||||
</li></ol><endouttext/></problem>
|
||||
@@ -1,59 +0,0 @@
|
||||
<problem><startouttext/><br/><br/>You have a 6-volt battery (assumed ideal) and a 1.5-volt flashlight
|
||||
bulb, which is known to draw \(0.5 A\) when the bulb voltage is \(1.5 V\) (see
|
||||
figure below). Design a network of resistors to go between the battery
|
||||
and the bulb to give \(v_s = 1.5 V\) when the bulb is connected, yet
|
||||
ensures that \(v_s\) does not rise above \(2 V\) when the bulb is disconnected.
|
||||
|
||||
<br/><br/><center><img src="/static/circuits/Lab1_1.png"/></center><br/><br/><i>Hint</i>: use a two-resistor voltage divider to create the voltage for node A. You'll
|
||||
have two unknowns (R1 and R2) which can be determined by solving the two equations for
|
||||
\(v_s\) derived from the constraints above: one involving R1, R2 and Rbulb where \(v_s = 1.5\), and
|
||||
one involving R1 and R2 where \(v_s = 2\).
|
||||
|
||||
<br/><br/>There are two schematic diagrams below. Please enter the network
|
||||
of resistors you've designed into both diagrams. The top diagram is
|
||||
the model when the bulb is connected; the bottom diagram is the model
|
||||
when the bulb is disconnected.
|
||||
|
||||
<br/><br/>Run a DC analysis on both diagrams to
|
||||
show that the node labeled "A" has a voltage of approximately
|
||||
\(1.5 V\) in the top diagram and less than \(2 V\) in the bottom
|
||||
adiagram. Submit your results <i>after</i> the DC analyses have
|
||||
been run (so the results of the analyses will be submitted too).
|
||||
<endouttext/>
|
||||
|
||||
<schematicresponse><startouttext/>
|
||||
Schematic model when bulb is connected:
|
||||
|
||||
<center><schematic height="270" width="400" parts="r" analyses="dc" initial_value="[["w",[48,88,48,112]],["L",[160,16,3],{"label":"A"},["A"]],["g",[48,112,0],{},["0"]],["w",[160,112,136,112]],["w",[160,88,160,112]],["w",[160,16,136,16]],["w",[160,40,160,16]],["r",[160,40,0],{"name":"Bulb","r":"3"},["A","1"]],["w",[48,112,72,112]],["w",[48,16,72,16]],["w",[48,40,48,16]],["v",[48,40,0],{"name":"Battery","value":"6V"},["2","0"]],["view",0,0,2]]"/></center>
|
||||
|
||||
Schematic model when bulb is disconnected:
|
||||
|
||||
<center><schematic height="270" width="400" parts="r" analyses="dc" initial_value="[["w",[48,88,48,112]],["L",[160,16,3],{"label":"A"},["A"]],["g",[48,112,0],{},["0"]],["w",[160,112,136,112]],["w",[160,88,160,112]],["w",[160,16,136,16]],["w",[160,40,160,16]],["w",[48,112,72,112]],["w",[48,16,72,16]],["w",[48,40,48,16]],["v",[48,40,0],{"name":"Battery","value":"6V"},["2","0"]],["view",0,0,2]]"/></center>
|
||||
<endouttext/>
|
||||
|
||||
<answer type="loncapa/python">
|
||||
# for a schematic response, submission[i] is the json representation
|
||||
# of the diagram and analysis results for the i-th schematic tag
|
||||
|
||||
correct = ['incorrect', 'incorrect'] # optimistic default :)
|
||||
|
||||
def get_dc(json):
|
||||
for element in json:
|
||||
if element[0] == 'dc': return element[1]
|
||||
return None
|
||||
|
||||
dc_with_bulb = get_dc(submission[0])
|
||||
if dc_with_bulb:
|
||||
v = dc_with_bulb['A']
|
||||
if v >= 1.4 and v <= 1.6: # want 1.5
|
||||
correct[0] = 'correct'
|
||||
|
||||
dc_without_bulb = get_dc(submission[1])
|
||||
if dc_without_bulb:
|
||||
v = dc_without_bulb['A']
|
||||
if v <= 2.1: # want 2
|
||||
correct[1] = 'correct'
|
||||
|
||||
</answer>
|
||||
</schematicresponse>
|
||||
</problem>
|
||||
@@ -1,40 +0,0 @@
|
||||
<problem><script type="loncapa/python">
|
||||
R = float(random.randrange(100,200,10))
|
||||
|
||||
Vrms = 120
|
||||
Vp = math.sqrt(2)*Vrms
|
||||
Pp = (Vp**2)/R
|
||||
Prms = (Vrms**2)/R
|
||||
</script><startouttext/>
|
||||
The plot shows 1/10 second of the voltage waveform of a 120V 60Hz AC
|
||||
(Alternating Current)
|
||||
power circuit, like that delivered to residences in the United States.
|
||||
<center><img src="/static/circuits/120V60Hz.gif"/></center>
|
||||
The actual voltage is \(120*sqrt(2)*cos(2*\pi*60*t)\)Volts. If we apply
|
||||
this voltage across a resistor of resistance \($R\Omega\) the resistor
|
||||
will dissipate a time-varying power.
|
||||
What is the peak power (in Watts) dissipated by the resistor?
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$Pp"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
|
||||
<startouttext/>
|
||||
<br/> What is the average power (in Watts) dissipated by the resistor? (Hint: you
|
||||
compute the average power by integrating the power over one cycle of
|
||||
the waveform.)
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$Prms"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
|
||||
<startouttext/>
|
||||
<br/> What would be the power (in Watts) dissipated by the resistor if the voltage
|
||||
was a constant value of 120V?
|
||||
<endouttext/>
|
||||
<numericalresponse answer="$Prms"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
|
||||
<startouttext/>
|
||||
<br/> If a time-varying voltage dissipates the same power in a resistor
|
||||
as a constant voltage would dissipate, we say that the time-varying voltage has
|
||||
the RMS value of the constant. RMS is an abbreviation for Root-Mean-Square.
|
||||
<endouttext/>
|
||||
|
||||
|
||||
</problem>
|
||||
@@ -1,13 +0,0 @@
|
||||
<problem><script type="loncapa/python">
|
||||
|
||||
z = "A*x^2 + sqrt(y)"
|
||||
|
||||
</script><startouttext/>
|
||||
Enter the algebraic expression \(A x^2 + \sqrt{y}\) in the box below. The
|
||||
entry is case sensitive. The product must be indicated with an
|
||||
asterisk, and the exponentation with a caret, so you must write
|
||||
"A*x^2 + sqrt(y)"…
|
||||
<endouttext/>
|
||||
<formularesponse type="cs" samples="A,x,y@1,1,1:3,3,3#10" answer="$z"><responseparam description="Numerical Tolerance" type="tolerance" default="0.00001" name="tol"/><textline size="40"/></formularesponse>
|
||||
|
||||
</problem>
|
||||
@@ -1,8 +0,0 @@
|
||||
<problem><startouttext/>
|
||||
Enter the numerical value of the expression \(x + y\) where
|
||||
\(x = 3\) and \(y = 5\)…
|
||||
<endouttext/>
|
||||
|
||||
<numericalresponse answer="8"><responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance"/><textline/></numericalresponse>
|
||||
|
||||
</problem>
|
||||
@@ -1,38 +0,0 @@
|
||||
<problem display_name="S3E2: Lorentz Force">
|
||||
|
||||
<startouttext/>
|
||||
<p>Consider a hypothetical magnetic field pointing out of your computer screen. Now imagine an electron traveling from right to left in the plane of your screen. A diagram of this situation is show below…</p>
|
||||
<center><img width="400" src="/static/images/LSQimages/LSQ_W01_8.png"/></center>
|
||||
|
||||
<p>a. The magnitude of the force experienced by the electron is proportional the product of which of the following? (Select all that apply.)</p>
|
||||
<endouttext/>
|
||||
<choiceresponse>
|
||||
<checkboxgroup>
|
||||
<!-- include ellipses to test non-ascii characters -->
|
||||
<choice correct="true"><text>Magnetic field strength…</text></choice>
|
||||
<choice correct="false"><text>Electric field strength…</text></choice>
|
||||
<choice correct="true"><text>Electric charge of the electron…</text></choice>
|
||||
<choice correct="false"><text>Radius of the electron…</text></choice>
|
||||
<choice correct="false"><text>Mass of the electron…</text></choice>
|
||||
<choice correct="true"><text>Velocity of the electron…</text></choice>
|
||||
|
||||
</checkboxgroup>
|
||||
</choiceresponse>
|
||||
|
||||
<startouttext/>
|
||||
<p>b. The direction of the force experienced by the electron is _______.</p>
|
||||
<endouttext/>
|
||||
<choiceresponse>
|
||||
<checkboxgroup>
|
||||
<choice correct="false"><text>up, in the plane of the screen.</text></choice>
|
||||
<choice correct="true"><text>down, in the plane of the screen.</text></choice>
|
||||
<choice correct="false"><text>into the plane of the screen.</text></choice>
|
||||
<choice correct="false"><text>out of the plane of the screen.</text></choice>
|
||||
<choice correct="false"><text>towards the right, in the plane of the screen.</text></choice>
|
||||
<choice correct="false"><text>towards the left, in the plane of the screen.</text></choice>
|
||||
</checkboxgroup>
|
||||
</choiceresponse>
|
||||
|
||||
|
||||
|
||||
</problem>
|
||||
@@ -1,206 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<problem display_name="L4 Problem 1">
|
||||
<text>
|
||||
<p>
|
||||
<!-- include ellipses to test non-ascii characters -->
|
||||
<b class="bfseries">Part 1: Function Types…</b>
|
||||
</p>
|
||||
<p>
|
||||
For each of the following functions, specify the type of its <b class="bfseries">output</b>. You can assume each function is called with an appropriate argument, as specified by its docstring. </p>
|
||||
<p>
|
||||
If the output can be either an int or a float, select num, which isn't a real Python type, but which we'll use to indicate that either basic numeric type is legal. </p>
|
||||
<p>
|
||||
In fact, in Python, booleans True and False can be operated on as if they were the integers 1 and 0; but it is ugly and confusing to take advantage of this fact, and we will resolutely pretend that it isn't true. </p> <!-- so why even mention it? -->
|
||||
<p>
|
||||
<section class="hints">
|
||||
<div class="collapsible">
|
||||
<header>
|
||||
<a href="#" id="id41">What are those lines under the function definitions?</a>
|
||||
</header>
|
||||
<section id="id41">
|
||||
<p>
|
||||
In this and future problems, you'll see function definitions that look like this: </p>
|
||||
<pre>
|
||||
def a(x):
|
||||
'''
|
||||
x: int or float.
|
||||
'''
|
||||
return x + 1
|
||||
</pre>
|
||||
<p>
|
||||
What are those three lines between <code>def a(x):</code> and <code>return x + 1</code>? These lines are called the <i class="it">docstring</i> of the function. A docstring is a special type of comment that is used to document what your function is doing. Typically, docstrings will explain what the function expects the type(s) of the argument(s) to be, and what the function is returning. </p>
|
||||
<p>
|
||||
In Python, docstrings appear immediately after the <code>def</code> line of a function, before the body. Docstrings start and end with triple quotes - this can be triple single quotes or triple double quotes, it doesn't matter as long as they match. To sum up this general form: </p>
|
||||
<pre>
|
||||
def myFunction(argument):
|
||||
"""
|
||||
Docstring goes here. Explain what type argument(s) should have, and what your function
|
||||
is going to return.
|
||||
"""
|
||||
< Code for your function (the body of the function) goes here >
|
||||
</pre>
|
||||
<p>
|
||||
As you begin coding your own functions, we strongly encourage you to document all your functions by using properly-formatted docstrings! </p>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</p>
|
||||
<ol class="enumerate">
|
||||
<li>
|
||||
<pre>
|
||||
def a(x):
|
||||
'''
|
||||
x: int or float.
|
||||
'''
|
||||
return x + 1
|
||||
</pre>
|
||||
<p>
|
||||
Indicate the type of the output that the function <code>a</code> will yield. <optionresponse><optioninput options="('NoneType','num','int','float','boolean')" correct="num"/></optionresponse> </p>
|
||||
</li>
|
||||
<li>
|
||||
<pre>
|
||||
def b(x):
|
||||
'''
|
||||
x: int or float.
|
||||
'''
|
||||
return x + 1.0
|
||||
</pre>
|
||||
<p>
|
||||
Indicate the type of the output that the function <code>b</code> will yield. <optionresponse><optioninput options="('NoneType','num','int','float','boolean')" correct="float"/></optionresponse> </p>
|
||||
</li>
|
||||
<li>
|
||||
<pre>
|
||||
def c(x, y):
|
||||
'''
|
||||
x: int or float.
|
||||
y: int or float.
|
||||
'''
|
||||
return x + y
|
||||
</pre>
|
||||
<p>
|
||||
Indicate the type of the output that the function <code>c</code> will yield. <optionresponse><optioninput options="('NoneType','num','int','float','boolean')" correct="num"/></optionresponse> </p>
|
||||
</li>
|
||||
<li>
|
||||
<pre>
|
||||
def d(x, y):
|
||||
'''
|
||||
x: Can be of any type.
|
||||
y: Can be of any type.
|
||||
'''
|
||||
return x > y
|
||||
</pre>
|
||||
<p>
|
||||
Indicate the type of the output that the function <code>d</code> will yield. <optionresponse><optioninput options="('NoneType','num','int','float','boolean')" correct="boolean"/></optionresponse> </p>
|
||||
</li>
|
||||
<li>
|
||||
<pre>
|
||||
def e(x, y, z):
|
||||
'''
|
||||
x: Can be of any type.
|
||||
y: Can be of any type.
|
||||
z: Can be of any type.
|
||||
'''
|
||||
return x >= y and x <= z
|
||||
</pre>
|
||||
<p>
|
||||
Indicate the type of the output that the function <code>e</code> will yield. <optionresponse><optioninput options="('NoneType','num','int','float','boolean')" correct="boolean"/></optionresponse> </p>
|
||||
</li>
|
||||
<li>
|
||||
<pre>
|
||||
def f(x, y):
|
||||
'''
|
||||
x: int or float.
|
||||
y: int or float
|
||||
'''
|
||||
x + y - 2
|
||||
</pre>
|
||||
<p>
|
||||
Indicate the type of the output that the function <code>f</code> will yield. <optionresponse><optioninput options="('NoneType','num','int','float','boolean')" correct="NoneType"/></optionresponse> </p>
|
||||
</li>
|
||||
</ol>
|
||||
<p>
|
||||
<b class="bfseries">Part 2: Transcript</b>
|
||||
</p>
|
||||
<p>
|
||||
Below is a transcript of a session with the Python shell. Assume the functions from Part 1 (above) have been defined. Provide the type and value of the expressions being evaluated. If evaluating an expression would cause an error, select NoneType and write 'error' in the box. If the value of an expression is a function, select function as the type and write 'function' in the box. </p>
|
||||
<ol class="enumerate">
|
||||
<li>
|
||||
<p>
|
||||
<code>a(6)</code>
|
||||
<optionresponse>
|
||||
<optioninput options="('NoneType','num','int','float','boolean','function')" correct="int"/>
|
||||
</optionresponse>
|
||||
<stringresponse answer="7">
|
||||
<textline size="50"/>
|
||||
</stringresponse>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<code>a(-5.3)</code>
|
||||
<optionresponse>
|
||||
<optioninput options="('NoneType','num','int','float','boolean','function')" correct="float"/>
|
||||
</optionresponse>
|
||||
<stringresponse answer="-4.3">
|
||||
<textline size="50"/>
|
||||
</stringresponse>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<code>a(a(a(6)))</code>
|
||||
<optionresponse>
|
||||
<optioninput options="('NoneType','num','int','float','boolean','function')" correct="int"/>
|
||||
</optionresponse>
|
||||
<stringresponse answer="9">
|
||||
<textline size="50"/>
|
||||
</stringresponse>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<code>c(a(1), b(1))</code>
|
||||
<optionresponse>
|
||||
<optioninput options="('NoneType','num','int','float','boolean','function')" correct="float"/>
|
||||
</optionresponse>
|
||||
<stringresponse answer="4.0">
|
||||
<textline size="50"/>
|
||||
</stringresponse>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<code>d('apple', 11.1)</code>
|
||||
<optionresponse>
|
||||
<optioninput options="('NoneType','num','int','float','boolean','function')" correct="boolean"/>
|
||||
</optionresponse>
|
||||
<stringresponse answer="True">
|
||||
<textline size="50"/>
|
||||
</stringresponse>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<code>e(a(3), b(4), c(3, 4))</code>
|
||||
<optionresponse>
|
||||
<optioninput options="('NoneType','num','int','float','boolean','function')" correct="boolean"/>
|
||||
</optionresponse>
|
||||
<stringresponse answer="False">
|
||||
<textline size="50"/>
|
||||
</stringresponse>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<code>f</code>
|
||||
<optionresponse>
|
||||
<optioninput options="('NoneType','num','int','float','boolean','function')" correct="function"/>
|
||||
</optionresponse>
|
||||
<stringresponse answer="function">
|
||||
<textline size="50"/>
|
||||
</stringresponse>
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</text>
|
||||
</problem>
|
||||
@@ -1,17 +0,0 @@
|
||||
<problem display_name="S3E3: Deflection of a Proton">
|
||||
<startouttext/>
|
||||
<p>Suppose you were to pass a hydroge ion (H+) through an electric field and measure the deflection of the ion. How would its deflection compare to the deflection of an electron passed through the same electric field? </p>
|
||||
<endouttext/>
|
||||
|
||||
|
||||
<multiplechoiceresponse direction="vertical" randomize="yes">
|
||||
<choicegroup type="MultipleChoice">
|
||||
<choice location="random" correct="false" name="1"><text>The ion would deflect identically as both species have the same charge.</text></choice>
|
||||
<choice location="random" correct="false" name="2"><text>The ion would deflect by an amount identical in magnitude but opposite in direction because the charges are of opposite sign but equal in magnitude.</text></choice>
|
||||
<choice location="random" correct="false" name="3"><text>The deflection will be in the same direction but smaller in magnitude due to the larger mass of the ion.</text></choice>
|
||||
<choice location="random" correct="true" name="4"><text>The deflection will be smaller in magnitude due to the increased mass of the ion, as well as in the opposite direction due to the opposite sign of the charge.</text></choice>
|
||||
|
||||
</choicegroup>
|
||||
</multiplechoiceresponse>
|
||||
|
||||
</problem>
|
||||
@@ -1,31 +0,0 @@
|
||||
<problem display_name="S2E2: Hydrogen Combustion">
|
||||
<text>
|
||||
|
||||
<p>Gaseous hydrogen can be reacted with gaseous oxygen in the presence of a flame to produce water vapor according to the following reaction:</p>
|
||||
[mathjax] \text{ a } \text{H}_{2 } + \text{ b }\text{O}_{2 } = \text{ c }\text{H}_{2 }\text{O }[/mathjax]
|
||||
<p>Balance the equation i.e., specify the values of <i> a, b, </i> and <i>c</i>. Use the lowest whole number coefficients.</p>
|
||||
|
||||
<p>a =</p>
|
||||
<numericalresponse answer="2">
|
||||
<responseparam type="tolerance" default="1%" name="tol" description="Numerical Tolerance" />
|
||||
<textline correct_answer="2" math="1" />
|
||||
</numericalresponse>
|
||||
|
||||
|
||||
<p>b =
|
||||
<numericalresponse answer="1">
|
||||
<responseparam type="tolerance" default="1%" name="tol" description="Numerical Tolerance" />
|
||||
<textline math="1" />
|
||||
</numericalresponse> </p>
|
||||
|
||||
<p>c =
|
||||
<numericalresponse answer="2">
|
||||
<responseparam type="tolerance" default="1%" name="tol" description="Numerical Tolerance" />
|
||||
<textline math="1" />
|
||||
</numericalresponse> </p>
|
||||
|
||||
|
||||
</text>
|
||||
</problem>
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
<problem>
|
||||
<text>
|
||||
<p>Metallothermic production of zirconium (Zr) would involve the reaction of sodium (Na) with zirconium tetrachloride (ZrCl<sub>4</sub>).</p>
|
||||
|
||||
<p><b>(a)</b> Write a balanced chemical equation.</p>
|
||||
|
||||
<!-- chemformularesponse
|
||||
[mathjax] \text{a ZrCl}_{4 } + \text{ b }\text{Na} -> \text{ c }\text{NaCl } + \text{ d } \text{Zr} [/mathjax]
|
||||
ratio of (a, b, c, d) = (1, 4, 4, 1)
|
||||
-->
|
||||
|
||||
<customresponse>
|
||||
<chemicalequationinput size="50"/>
|
||||
<answer type="loncapa/python">
|
||||
|
||||
if chemcalc.chemical_equations_equal(submission[0], 'ZrCl4 + 4 Na -> 4 NaCl + Zr'):
|
||||
correct = ['correct']
|
||||
else:
|
||||
correct = ['incorrect']
|
||||
|
||||
</answer>
|
||||
</customresponse>
|
||||
|
||||
<p><b>(b)</b> Write the balanced chemical equation using lowest whole numbers.</p>
|
||||
|
||||
<!-- chemformularesponse
|
||||
as above, with (a, b, c, d) = (1, 4, 4, 1)
|
||||
-->
|
||||
|
||||
<customresponse>
|
||||
<chemicalequationinput size="50"/>
|
||||
<answer type="loncapa/python">
|
||||
|
||||
if chemcalc.chemical_equations_equal(submission[0], 'ZrCl4 + 4 Na -> 4 NaCl + Zr', exact=True):
|
||||
correct = ['correct']
|
||||
else:
|
||||
correct = ['incorrect']
|
||||
|
||||
</answer>
|
||||
</customresponse>
|
||||
|
||||
|
||||
|
||||
<p><b>(c)</b> Calculate the amount of zirconium produced (in kg) if a reactor were charged with 111 kg [mathjaxinline]\text{ZrCl}_4[/mathjaxinline] and 11.1 kg [mathjaxinline]\text{Na}[/mathjaxinline].
|
||||
<numericalresponse answer="11.0">
|
||||
<responseparam type="tolerance" default="5%" name="tol" description="Numerical Tolerance" />
|
||||
<textline math="1" />
|
||||
</numericalresponse> </p>
|
||||
<br/>
|
||||
<solution>
|
||||
<p><b>SOLUTION:</b></p>
|
||||
<p><b>(b)</b>[mathjax] \text{ZrCl}_{4 } + \mathbf{4 }\text{Na} = \mathbf{4 }\text{NaCl } + \mathbf{1 } \text{Zr} [/mathjax] </p>
|
||||
<p><b>(c)</b></p>
|
||||
<p>[mathjaxinline]111\text{kg ZrCl}_4 = 111000/[91.22 + (4 \times 35.45)] = 476 \text{ moles ZrCl}_4[/mathjaxinline] </p>
|
||||
<p>[mathjaxinline]11.1\text{ kg Na} = 11100/22.99 = 483\text{ moles C}[/mathjaxinline]</p>
|
||||
<p>stoichiometry of reaction further dictates that on a molar basis there needs to be 4 x amount of [mathjaxinline]\text{Na}[/mathjaxinline] as there is [mathjaxinline]\text{ZrCl}_4[/mathjaxinline], but calculations show there to be a shortfall of [mathjaxinline]\text{Na}[/mathjaxinline] </p>
|
||||
<p>[mathjaxinline]\therefore[/mathjaxinline] reaction yield is contrained by [mathjaxinline]\text{Na}[/mathjaxinline] present </p>
|
||||
<p>stoichiometry of reaction further dictates that if [mathjaxinline]\text{Na}[/mathjaxinline] controls the yield, then the amount of [mathjaxinline]\text{Zr}[/mathjaxinline] produced = 1/4 x molar quantity of [mathjaxinline]\text{Na}[/mathjaxinline] = 1/4 x 483 moles = 121 </p>
|
||||
[mathjaxinline]121 \text{ moles Zr} \times 91.22\text{ g / mol } \mathbf{= 11.0 \text{ kg Zr} }[/mathjaxinline]<br/>
|
||||
</solution>
|
||||
</text>
|
||||
</problem>
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
<problem>
|
||||
<choiceresponse>
|
||||
<checkboxgroup>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil One.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Two.<endouttext />
|
||||
</choice>
|
||||
<choice correct="true">
|
||||
<startouttext />This is foil Three.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Four.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Five.<endouttext />
|
||||
</choice>
|
||||
</checkboxgroup>
|
||||
</choiceresponse>
|
||||
<choiceresponse>
|
||||
<checkboxgroup>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil One.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Two.<endouttext />
|
||||
</choice>
|
||||
<choice correct="true">
|
||||
<startouttext />This is foil Three.<endouttext />
|
||||
</choice>
|
||||
<choice correct="true">
|
||||
<startouttext />This is foil Four.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Five.<endouttext />
|
||||
</choice>
|
||||
</checkboxgroup>
|
||||
</choiceresponse>
|
||||
<choiceresponse>
|
||||
<checkboxgroup>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil One.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Two.<endouttext />
|
||||
</choice>
|
||||
<choice correct="true">
|
||||
<startouttext />This is foil Three.<endouttext />
|
||||
</choice>
|
||||
<choice correct="true">
|
||||
<startouttext />This is foil Four.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Five.<endouttext />
|
||||
</choice>
|
||||
</checkboxgroup>
|
||||
</choiceresponse>
|
||||
</problem>
|
||||
@@ -1,40 +0,0 @@
|
||||
<problem>
|
||||
<choiceresponse>
|
||||
<radiogroup>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil One.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Two.<endouttext />
|
||||
</choice>
|
||||
<choice correct="true">
|
||||
<startouttext />This is foil Three.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Four.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Five.<endouttext />
|
||||
</choice>
|
||||
</radiogroup>
|
||||
</choiceresponse>
|
||||
<choiceresponse>
|
||||
<radiogroup>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil One.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Two.<endouttext />
|
||||
</choice>
|
||||
<choice correct="true">
|
||||
<startouttext />This is foil Three.<endouttext />
|
||||
</choice>
|
||||
<choice correct="true">
|
||||
<startouttext />This is foil Four.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Five.<endouttext />
|
||||
</choice>
|
||||
</radiogroup>
|
||||
</choiceresponse>
|
||||
</problem>
|
||||
@@ -1,33 +0,0 @@
|
||||
<problem>
|
||||
<text>
|
||||
<h2>Code response</h2>
|
||||
|
||||
<p>
|
||||
</p>
|
||||
|
||||
<text>
|
||||
Write a program to compute the square of a number
|
||||
<coderesponse tests="repeat:2,generate">
|
||||
<textbox rows="10" cols="70" mode="python"/>
|
||||
<codeparam>
|
||||
<initial_display>def square(x):</initial_display>
|
||||
<answer_display>answer</answer_display>
|
||||
<grader_payload>grader stuff</grader_payload>
|
||||
</codeparam>
|
||||
</coderesponse>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
Write a program to compute the square of a number
|
||||
<coderesponse tests="repeat:2,generate">
|
||||
<textbox rows="10" cols="70" mode="python"/>
|
||||
<codeparam>
|
||||
<initial_display>def square(x):</initial_display>
|
||||
<answer_display>answer</answer_display>
|
||||
<grader_payload>grader stuff</grader_payload>
|
||||
</codeparam>
|
||||
</coderesponse>
|
||||
</text>
|
||||
|
||||
</text>
|
||||
</problem>
|
||||
@@ -1,101 +0,0 @@
|
||||
<problem>
|
||||
<text>
|
||||
<h2>Code response</h2>
|
||||
|
||||
<p>
|
||||
</p>
|
||||
|
||||
<text>
|
||||
Write a program to compute the square of a number
|
||||
<coderesponse tests="repeat:2,generate">
|
||||
<textbox rows="10" cols="70" mode="python"/>
|
||||
<answer><![CDATA[
|
||||
initial_display = """
|
||||
def square(n):
|
||||
"""
|
||||
|
||||
answer = """
|
||||
def square(n):
|
||||
return n**2
|
||||
"""
|
||||
|
||||
preamble = """
|
||||
import sys, time
|
||||
"""
|
||||
|
||||
test_program = """
|
||||
import random
|
||||
import operator
|
||||
|
||||
def testSquare(n = None):
|
||||
if n is None:
|
||||
n = random.randint(2, 20)
|
||||
print 'Test is: square(%d)'%n
|
||||
return str(square(n))
|
||||
|
||||
def main():
|
||||
f = os.fdopen(3,'w')
|
||||
test = int(sys.argv[1])
|
||||
rndlist = map(int,os.getenv('rndlist').split(','))
|
||||
random.seed(rndlist[0])
|
||||
if test == 1: f.write(testSquare(0))
|
||||
elif test == 2: f.write(testSquare(1))
|
||||
else: f.write(testSquare())
|
||||
f.close()
|
||||
|
||||
main()
|
||||
sys.exit(0)
|
||||
"""
|
||||
]]>
|
||||
</answer>
|
||||
</coderesponse>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
Write a program to compute the cube of a number
|
||||
<coderesponse tests="repeat:2,generate">
|
||||
<textbox rows="10" cols="70" mode="python"/>
|
||||
<answer><![CDATA[
|
||||
initial_display = """
|
||||
def cube(n):
|
||||
"""
|
||||
|
||||
answer = """
|
||||
def cube(n):
|
||||
return n**3
|
||||
"""
|
||||
|
||||
preamble = """
|
||||
import sys, time
|
||||
"""
|
||||
|
||||
test_program = """
|
||||
import random
|
||||
import operator
|
||||
|
||||
def testCube(n = None):
|
||||
if n is None:
|
||||
n = random.randint(2, 20)
|
||||
print 'Test is: cube(%d)'%n
|
||||
return str(cube(n))
|
||||
|
||||
def main():
|
||||
f = os.fdopen(3,'w')
|
||||
test = int(sys.argv[1])
|
||||
rndlist = map(int,os.getenv('rndlist').split(','))
|
||||
random.seed(rndlist[0])
|
||||
if test == 1: f.write(testCube(0))
|
||||
elif test == 2: f.write(testCube(1))
|
||||
else: f.write(testCube())
|
||||
f.close()
|
||||
|
||||
main()
|
||||
sys.exit(0)
|
||||
"""
|
||||
]]>
|
||||
</answer>
|
||||
</coderesponse>
|
||||
</text>
|
||||
|
||||
</text>
|
||||
</problem>
|
||||
@@ -1,45 +0,0 @@
|
||||
<problem>
|
||||
<script type="loncapa/python">
|
||||
# from loncapa import *
|
||||
x1 = 4 # lc_random(2,4,1)
|
||||
y1 = 5 # lc_random(3,7,1)
|
||||
|
||||
x2 = 10 # lc_random(x1+1,9,1)
|
||||
y2 = 20 # lc_random(y1+1,15,1)
|
||||
|
||||
m = (y2-y1)/(x2-x1)
|
||||
b = y1 - m*x1
|
||||
answer = "%s*x+%s" % (m,b)
|
||||
answer = answer.replace('+-','-')
|
||||
|
||||
inverted_m = (x2-x1)/(y2-y1)
|
||||
inverted_b = b
|
||||
wrongans = "%s*x+%s" % (inverted_m,inverted_b)
|
||||
wrongans = wrongans.replace('+-','-')
|
||||
</script>
|
||||
|
||||
<text>
|
||||
<p>Hints can be provided to students, based on the last response given, as well as the history of responses given. Here is an example of a hint produced by a Formula Response problem.</p>
|
||||
|
||||
<p>
|
||||
What is the equation of the line which passess through ($x1,$y1) and
|
||||
($x2,$y2)?</p>
|
||||
|
||||
<p>The correct answer is <tt>$answer</tt>. A common error is to invert the equation for the slope. Enter <tt>
|
||||
$wrongans</tt> to see a hint.</p>
|
||||
|
||||
</text>
|
||||
|
||||
<formularesponse samples="x@-5:5#11" id="11" answer="$answer">
|
||||
<responseparam description="Numerical Tolerance" type="tolerance" default="0.001" name="tol" />
|
||||
<text>y = <textline size="25" /></text>
|
||||
<hintgroup>
|
||||
<formulahint samples="x@-5:5#11" answer="$wrongans" name="inversegrad">
|
||||
</formulahint>
|
||||
<hintpart on="inversegrad">
|
||||
<text>You have inverted the slope in the question.</text>
|
||||
</hintpart>
|
||||
</hintgroup>
|
||||
</formularesponse>
|
||||
</problem>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<problem>
|
||||
<text><p>
|
||||
Two skiers are on frictionless black diamond ski slopes.
|
||||
Hello</p></text>
|
||||
|
||||
<imageresponse max="1" loncapaid="11">
|
||||
<imageinput src="/static/Physics801/Figures/Skier-conservation of energy.jpg" width="560" height="388" rectangle="(490,11)-(556,98)"/>
|
||||
<text>Click on the image where the top skier will stop momentarily if the top skier starts from rest.</text>
|
||||
<imageinput src="/static/Physics801/Figures/Skier-conservation of energy.jpg" width="560" height="388" rectangle="(242,202)-(296,276)"/>
|
||||
<text>Click on the image where the lower skier will stop momentarily if the lower skier starts from rest.</text>
|
||||
<imageinput src="/static/Physics801/Figures/Skier-conservation of energy.jpg" width="560" height="388" rectangle="(490,11)-(556,98);(242,202)-(296,276)"/>
|
||||
<text>Click on either of the two positions as discussed previously.</text>
|
||||
<imageinput src="/static/Physics801/Figures/Skier-conservation of energy.jpg" width="560" height="388" rectangle="(490,11)-(556,98);(242,202)-(296,276)"/>
|
||||
<text>Click on either of the two positions as discussed previously.</text>
|
||||
<imageinput src="/static/Physics801/Figures/Skier-conservation of energy.jpg" width="560" height="388" rectangle="(490,11)-(556,98);(242,202)-(296,276)"/>
|
||||
<text>Click on either of the two positions as discussed previously.</text>
|
||||
<hintgroup showoncorrect="no">
|
||||
<text><p>Use conservation of energy.</p></text>
|
||||
</hintgroup>
|
||||
</imageresponse>
|
||||
</problem>
|
||||
@@ -1,13 +0,0 @@
|
||||
<problem>
|
||||
|
||||
<javascriptresponse>
|
||||
<generator src="test_problem_generator.js"/>
|
||||
<grader src="test_problem_grader.js"/>
|
||||
<display class="TestProblemDisplay" src="test_problem_display.js"/>
|
||||
<responseparam name="value" value="4"/>
|
||||
<javascriptinput>
|
||||
</javascriptinput>
|
||||
</javascriptresponse>
|
||||
|
||||
</problem>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<problem>
|
||||
<multiplechoiceresponse>
|
||||
<choicegroup>
|
||||
<choice correct="false" >
|
||||
<startouttext />This is foil One.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false" >
|
||||
<startouttext />This is foil Two.<endouttext />
|
||||
</choice>
|
||||
<choice correct="true" >
|
||||
<startouttext />This is foil Three.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Four.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false">
|
||||
<startouttext />This is foil Five.<endouttext />
|
||||
</choice>
|
||||
</choicegroup>
|
||||
</multiplechoiceresponse>
|
||||
</problem>
|
||||
@@ -1,21 +0,0 @@
|
||||
<problem>
|
||||
<multiplechoiceresponse>
|
||||
<choicegroup>
|
||||
<choice correct="false" name="foil1">
|
||||
<startouttext />This is foil One.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false" name="foil2">
|
||||
<startouttext />This is foil Two.<endouttext />
|
||||
</choice>
|
||||
<choice correct="true" name="foil3">
|
||||
<startouttext />This is foil Three.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false" name="foil4">
|
||||
<startouttext />This is foil Four.<endouttext />
|
||||
</choice>
|
||||
<choice correct="false" name="foil5">
|
||||
<startouttext />This is foil Five.<endouttext />
|
||||
</choice>
|
||||
</choicegroup>
|
||||
</multiplechoiceresponse>
|
||||
</problem>
|
||||
@@ -1,17 +0,0 @@
|
||||
<problem display_name="S3E3: Deflection of a Proton">
|
||||
<startouttext/>
|
||||
<p>Suppose you were to pass a hydroge ion (H+) through an electric field and measure the deflection of the ion. How would its deflection compare to the deflection of an electron passed through the same electric field? </p>
|
||||
<endouttext/>
|
||||
|
||||
|
||||
<multiplechoiceresponse direction="vertical" randomize="yes">
|
||||
<choicegroup type="MultipleChoice">
|
||||
<choice location="random" correct="false" name="1"><text>The ion would deflect identically as both species have the same charge.</text></choice>
|
||||
<choice location="random" correct="false" name="2"><text>The ion would deflect by an amount identical in magnitude but opposite in direction because the charges are of opposite sign but equal in magnitude.</text></choice>
|
||||
<choice location="random" correct="false" name="3"><text>The deflection will be in the same direction but smaller in magnitude due to the larger mass of the ion.</text></choice>
|
||||
<choice location="random" correct="true" name="4"><text>The deflection will be smaller in magnitude due to the increased mass of the ion, as well as in the opposite direction due to the opposite sign of the charge.</text></choice>
|
||||
|
||||
</choicegroup>
|
||||
</multiplechoiceresponse>
|
||||
|
||||
</problem>
|
||||
@@ -1,31 +0,0 @@
|
||||
<problem display_name="S2E2: Hydrogen Combustion">
|
||||
<text>
|
||||
|
||||
<p>Gaseous hydrogen can be reacted with gaseous oxygen in the presence of a flame to produce water vapor according to the following reaction:</p>
|
||||
[mathjax] \text{ a } \text{H}_{2 } + \text{ b }\text{O}_{2 } = \text{ c }\text{H}_{2 }\text{O }[/mathjax]
|
||||
<p>Balance the equation i.e., specify the values of <i> a, b, </i> and <i>c</i>. Use the lowest whole number coefficients.</p>
|
||||
|
||||
<p>a =</p>
|
||||
<numericalresponse answer="2">
|
||||
<responseparam type="tolerance" default="1%" name="tol" description="Numerical Tolerance" />
|
||||
<textline correct_answer="2" math="1" />
|
||||
</numericalresponse>
|
||||
|
||||
|
||||
<p>b =
|
||||
<numericalresponse answer="1">
|
||||
<responseparam type="tolerance" default="1%" name="tol" description="Numerical Tolerance" />
|
||||
<textline math="1" />
|
||||
</numericalresponse> </p>
|
||||
|
||||
<p>c =
|
||||
<numericalresponse answer="2">
|
||||
<responseparam type="tolerance" default="1%" name="tol" description="Numerical Tolerance" />
|
||||
<textline math="1" />
|
||||
</numericalresponse> </p>
|
||||
|
||||
|
||||
</text>
|
||||
</problem>
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
<problem>
|
||||
<text>
|
||||
<p>
|
||||
Why do bicycles benefit from having larger wheels when going up a bump as shown in the picture? <br/>
|
||||
Assume that for both bicycles:<br/>
|
||||
1.) The tires have equal air pressure.<br/>
|
||||
2.) The bicycles never leave the contact with the bump.<br/>
|
||||
3.) The bicycles have the same mass. The bicycle tires (regardless of size) have the same mass.<br/>
|
||||
</p>
|
||||
</text>
|
||||
<optionresponse texlayout="horizontal" max="10" randomize="yes">
|
||||
<ul>
|
||||
<li>
|
||||
<text>
|
||||
<p>The bicycles with larger wheels have more time to go over the bump. This decreases the magnitude of the force needed to lift the bicycle.</p>
|
||||
</text>
|
||||
<optioninput name="Foil1" location="random" options="('True','False')" correct="True">
|
||||
</optioninput>
|
||||
</li>
|
||||
<li>
|
||||
<text>
|
||||
<p>The bicycles with larger wheels always have a smaller vertical displacement regardless of speed.</p>
|
||||
</text>
|
||||
<optioninput name="Foil2" location="random" options="('True','False')" correct="False">
|
||||
</optioninput>
|
||||
</li>
|
||||
<li>
|
||||
<text>
|
||||
<p>The bicycles with larger wheels experience a force backward with less magnitude for the same amount of time.</p>
|
||||
</text>
|
||||
<optioninput name="Foil3" location="random" options="('True','False')" correct="False">
|
||||
</optioninput>
|
||||
</li>
|
||||
<li>
|
||||
<text>
|
||||
<p>The bicycles with larger wheels experience a force backward with less magnitude for a greater amount of time.</p>
|
||||
</text>
|
||||
<optioninput name="Foil4" location="random" options="('True','False')" correct="True">
|
||||
</optioninput>
|
||||
</li>
|
||||
<li>
|
||||
<text>
|
||||
<p>The bicycles with larger wheels have more kinetic energy turned into gravitational potential energy.</p>
|
||||
</text>
|
||||
<optioninput name="Foil5" location="random" options="('True','False')" correct="False">
|
||||
</optioninput>
|
||||
</li>
|
||||
<li>
|
||||
<text>
|
||||
<p>The bicycles with larger wheels have more rotational kinetic energy, so the horizontal velocity of the biker changes less.</p>
|
||||
</text>
|
||||
<optioninput name="Foil6" location="random" options="('True','False')" correct="False">
|
||||
</optioninput>
|
||||
</li>
|
||||
</ul>
|
||||
<hintgroup showoncorrect="no">
|
||||
<text>
|
||||
<br/>
|
||||
<br/>
|
||||
</text>
|
||||
</hintgroup>
|
||||
</optionresponse>
|
||||
</problem>
|
||||
@@ -1,25 +0,0 @@
|
||||
<problem >
|
||||
<text><h2>Example: String Response Problem</h2>
|
||||
<br/>
|
||||
</text>
|
||||
|
||||
<text>Which US state has Lansing as its capital?</text>
|
||||
<stringresponse answer="Michigan" type="ci">
|
||||
<textline size="20" />
|
||||
<hintgroup>
|
||||
<stringhint answer="wisconsin" type="cs" name="wisc">
|
||||
</stringhint>
|
||||
<stringhint answer="minnesota" type="cs" name="minn">
|
||||
</stringhint>
|
||||
<hintpart on="wisc">
|
||||
<text>The state capital of Wisconsin is Madison.</text>
|
||||
</hintpart>
|
||||
<hintpart on="minn">
|
||||
<text>The state capital of Minnesota is St. Paul.</text>
|
||||
</hintpart>
|
||||
<hintpart on="default">
|
||||
<text>The state you are looking for is also known as the 'Great Lakes State'</text>
|
||||
</hintpart>
|
||||
</hintgroup>
|
||||
</stringresponse>
|
||||
</problem>
|
||||
@@ -1,29 +0,0 @@
|
||||
<problem>
|
||||
<text>
|
||||
<h2>Example: Symbolic Math Response Problem</h2>
|
||||
|
||||
<p>
|
||||
A symbolic math response problem presents one or more symbolic math
|
||||
input fields for input. Correctness of input is evaluated based on
|
||||
the symbolic properties of the expression entered. The student enters
|
||||
text, but sees a proper symbolic rendition of the entered formula, in
|
||||
real time, next to the input box.
|
||||
</p>
|
||||
|
||||
<p>This is a correct answer which may be entered below: </p>
|
||||
<p><tt>cos(theta)*[[1,0],[0,1]] + i*sin(theta)*[[0,1],[1,0]]</tt></p>
|
||||
|
||||
<script>
|
||||
from symmath import *
|
||||
</script>
|
||||
<text>Compute [mathjax] U = \exp\left( i \theta \left[ \begin{matrix} 0 & 1 \\ 1 & 0 \end{matrix} \right] \right) [/mathjax]
|
||||
and give the resulting \(2 \times 2\) matrix. <br/>
|
||||
Your input should be typed in as a list of lists, eg <tt>[[1,2],[3,4]]</tt>. <br/>
|
||||
[mathjax]U=[/mathjax] <symbolicresponse cfn="symmath_check" answer="[[cos(theta),i*sin(theta)],[i*sin(theta),cos(theta)]]" options="matrix,imaginary" id="filenamedogi0VpEBOWedxsymmathresponse_1" state="unsubmitted">
|
||||
<textline size="80" math="1" response_id="2" answer_id="1" id="filenamedogi0VpEBOWedxsymmathresponse_2_1"/>
|
||||
</symbolicresponse>
|
||||
<br/>
|
||||
</text>
|
||||
|
||||
</text>
|
||||
</problem>
|
||||
@@ -1,21 +0,0 @@
|
||||
<problem>
|
||||
<truefalseresponse max="10" randomize="yes">
|
||||
<choicegroup>
|
||||
<choice location="random" correct="true" name="foil1">
|
||||
<startouttext />This is foil One.<endouttext />
|
||||
</choice>
|
||||
<choice location="random" correct="true" name="foil2">
|
||||
<startouttext />This is foil Two.<endouttext />
|
||||
</choice>
|
||||
<choice location="random" correct="false" name="foil3">
|
||||
<startouttext />This is foil Three.<endouttext />
|
||||
</choice>
|
||||
<choice location="random" correct="false" name="foil4">
|
||||
<startouttext />This is foil Four.<endouttext />
|
||||
</choice>
|
||||
<choice location="random" correct="false" name="foil5">
|
||||
<startouttext />This is foil Five.<endouttext />
|
||||
</choice>
|
||||
</choicegroup>
|
||||
</truefalseresponse>
|
||||
</problem>
|
||||
@@ -1,37 +0,0 @@
|
||||
<sequential>
|
||||
<vertical filename="vertical_58" slug="vertical_58"
|
||||
graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted"
|
||||
rerandomize="never" />
|
||||
<vertical slug="vertical_66" graceperiod="1 day 12 hours 59 minutes 59 seconds"
|
||||
showanswer="attempted" rerandomize="never">
|
||||
<problem filename="S1E3_AC_power" slug="S1E3_AC_power"
|
||||
name="S1E3: AC power" />
|
||||
<customtag tag="S1E3" slug="discuss_67" impl="discuss" />
|
||||
<!-- utf-8 characters acceptable, but not HTML entities -->
|
||||
<html slug="html_68"> S1E4 has been removed…</html>
|
||||
</vertical>
|
||||
<vertical filename="vertical_89" slug="vertical_89"
|
||||
graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted"
|
||||
rerandomize="never" />
|
||||
<vertical slug="vertical_94" graceperiod="1 day 12 hours 59 minutes 59 seconds"
|
||||
showanswer="attempted" rerandomize="never">
|
||||
<video
|
||||
youtube_id_0_75=""XNh13VZhThQ""
|
||||
youtube_id_1_0=""XbDRmF6J0K0""
|
||||
youtube_id_1_25=""JDty12WEQWk""
|
||||
youtube_id_1_5=""wELKGj-5iyM""
|
||||
slug="What_s_next"
|
||||
name="What's next"/>
|
||||
<html slug="html_95">Minor correction: Six elements (five resistors)…
|
||||
</html>
|
||||
<customtag tag="S1" slug="discuss_96" impl="discuss" />
|
||||
</vertical>
|
||||
<randomize url_name="PS1_Q4" display_name="Problem 4: Read a Molecule">
|
||||
<vertical>
|
||||
<html slug="html_900">
|
||||
<!-- UTF-8 characters are acceptable… HTML entities are not -->
|
||||
<h1>Inline content…</h1>
|
||||
</html>
|
||||
</vertical>
|
||||
</randomize>
|
||||
</sequential>
|
||||
@@ -1,6 +0,0 @@
|
||||
<sequential>
|
||||
<vertical slug="vertical_7" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="never">
|
||||
<problem filename="Sample_Numeric_Problem" slug="Sample_Numeric_Problem" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="false" name="Sample Numeric Problem"/>
|
||||
<problem filename="Sample_Algebraic_Problem" slug="Sample_Algebraic_Problem" graceperiod="1 day 12 hours 59 minutes 59 seconds" showanswer="attempted" rerandomize="false" name="Sample Algebraic Problem"/>
|
||||
</vertical>
|
||||
</sequential>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
@@ -1,1959 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Circuit simulator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Copyright (C) 2011 Massachusetts Institute of Technology
|
||||
|
||||
|
||||
// create a circuit for simulation using "new cktsim.Circuit()"
|
||||
|
||||
// for modified nodal analysis (MNA) stamps see
|
||||
// http://www.analog-electronics.eu/analog-electronics/modified-nodal-analysis/modified-nodal-analysis.xhtml
|
||||
|
||||
cktsim = (function() {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Circuit
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// types of "nodes" in the linear system
|
||||
T_VOLTAGE = 0;
|
||||
T_CURRENT = 1;
|
||||
|
||||
v_newt_lim = 0.3; // Voltage limited Newton great for Mos/diodes
|
||||
v_abstol = 1e-6; // Absolute voltage error tolerance
|
||||
i_abstol = 1e-12; // Absolute current error tolerance
|
||||
eps = 1.0e-12; // A very small number compared to one.
|
||||
dc_max_iters = 1000; // max iterations before giving pu
|
||||
max_tran_iters = 20; // max iterations before giving up
|
||||
time_step_increase_factor = 2.0; // How much can lte let timestep grow.
|
||||
lte_step_decrease_factor = 8; // Limit lte one-iter timestep shrink.
|
||||
nr_step_decrease_factor = 4; // Newton failure timestep shink.
|
||||
reltol = 0.0001; // Relative tol to max observed value
|
||||
lterel = 10; // LTE/Newton tolerance ratio (> 10!)
|
||||
res_check_abs = Math.sqrt(i_abstol); // Loose Newton residue check
|
||||
res_check_rel = Math.sqrt(reltol); // Loose Newton residue check
|
||||
|
||||
function Circuit() {
|
||||
this.node_map = new Array();
|
||||
this.ntypes = [];
|
||||
this.initial_conditions = []; // ic's for each element
|
||||
|
||||
this.devices = []; // list of devices
|
||||
this.device_map = new Array(); // map name -> device
|
||||
this.voltage_sources = []; // list of voltage sources
|
||||
this.current_sources = []; // list of current sources
|
||||
|
||||
this.finalized = false;
|
||||
this.diddc = false;
|
||||
this.node_index = -1;
|
||||
|
||||
this.periods = 1
|
||||
}
|
||||
|
||||
// index of ground node
|
||||
Circuit.prototype.gnd_node = function() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// allocate a new node index
|
||||
Circuit.prototype.node = function(name,ntype,ic) {
|
||||
this.node_index += 1;
|
||||
if (name) this.node_map[name] = this.node_index;
|
||||
this.ntypes.push(ntype);
|
||||
this.initial_conditions.push(ic);
|
||||
return this.node_index;
|
||||
}
|
||||
|
||||
// call to finalize the circuit in preparation for simulation
|
||||
Circuit.prototype.finalize = function() {
|
||||
if (!this.finalized) {
|
||||
this.finalized = true;
|
||||
this.N = this.node_index + 1; // number of nodes
|
||||
|
||||
// give each device a chance to finalize itself
|
||||
for (var i = this.devices.length - 1; i >= 0; --i)
|
||||
this.devices[i].finalize(this);
|
||||
|
||||
// set up augmented matrix and various temp vectors
|
||||
this.matrix = mat_make(this.N, this.N+1);
|
||||
this.Gl = mat_make(this.N, this.N); // Matrix for linear conductances
|
||||
this.G = mat_make(this.N, this.N); // Complete conductance matrix
|
||||
this.C = mat_make(this.N, this.N); // Matrix for linear L's and C's
|
||||
|
||||
this.soln_max = new Array(this.N); // max abs value seen for each unknown
|
||||
this.abstol = new Array(this.N);
|
||||
this.solution = new Array(this.N);
|
||||
this.rhs = new Array(this.N);
|
||||
for (var i = this.N - 1; i >= 0; --i) {
|
||||
this.soln_max[i] = 0.0;
|
||||
this.abstol[i] = this.ntypes[i] == T_VOLTAGE ? v_abstol : i_abstol;
|
||||
this.solution[i] = 0.0;
|
||||
this.rhs[i] = 0.0;
|
||||
}
|
||||
|
||||
// Load up the linear elements once and for all
|
||||
for (var i = this.devices.length - 1; i >= 0; --i) {
|
||||
this.devices[i].load_linear(this)
|
||||
}
|
||||
|
||||
// Check for voltage source loops.
|
||||
n_vsrc = this.voltage_sources.length;
|
||||
if (n_vsrc > 0) { // At least one voltage source
|
||||
var GV = mat_make(n_vsrc, this.N); // Loop check
|
||||
for (var i = n_vsrc - 1; i >= 0; --i) {
|
||||
var branch = this.voltage_sources[i].branch;
|
||||
for (var j = this.N - 1; j >= 0; j--)
|
||||
GV[i][j] = this.Gl[branch][j];
|
||||
}
|
||||
var rGV = mat_rank(GV);
|
||||
if (rGV < n_vsrc) {
|
||||
alert('Warning!!! Circuit has a voltage source loop or a source or current probe shorted by a wire, please remove the source or the wire causing the short.');
|
||||
alert('Warning!!! Simulator might produce meaningless results or no result with illegal circuits.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// load circuit from JSON netlist (see schematic.js)
|
||||
Circuit.prototype.load_netlist = function(netlist) {
|
||||
// set up mapping for all ground connections
|
||||
for (var i = netlist.length - 1; i >= 0; --i) {
|
||||
var component = netlist[i];
|
||||
var type = component[0];
|
||||
if (type == 'g') {
|
||||
var connections = component[3];
|
||||
this.node_map[connections[0]] = this.gnd_node();
|
||||
}
|
||||
}
|
||||
|
||||
// process each component in the JSON netlist (see schematic.js for format)
|
||||
var found_ground = false;
|
||||
for (var i = netlist.length - 1; i >= 0; --i) {
|
||||
var component = netlist[i];
|
||||
var type = component[0];
|
||||
|
||||
// ignore wires, ground connections, scope probes and view info
|
||||
if (type == 'view' || type == 'w' || type == 'g' || type == 's' || type == 'L') {
|
||||
continue;
|
||||
}
|
||||
|
||||
var properties = component[2];
|
||||
var name = properties['name'];
|
||||
if (name==undefined || name=='')
|
||||
name = '_' + properties['_json_'].toString();
|
||||
|
||||
// convert node names to circuit indicies
|
||||
var connections = component[3];
|
||||
for (var j = connections.length - 1; j >= 0; --j) {
|
||||
var node = connections[j];
|
||||
var index = this.node_map[node];
|
||||
if (index == undefined) index = this.node(node,T_VOLTAGE);
|
||||
else if (index == this.gnd_node()) found_ground = true;
|
||||
connections[j] = index;
|
||||
}
|
||||
|
||||
// process the component
|
||||
if (type == 'r') // resistor
|
||||
this.r(connections[0],connections[1],properties['r'],name);
|
||||
else if (type == 'd') // diode
|
||||
this.d(connections[0],connections[1],properties['area'],properties['type'],name);
|
||||
else if (type == 'c') // capacitor
|
||||
this.c(connections[0],connections[1],properties['c'],name);
|
||||
else if (type == 'l') // inductor
|
||||
this.l(connections[0],connections[1],properties['l'],name);
|
||||
else if (type == 'v') // voltage source
|
||||
this.v(connections[0],connections[1],properties['value'],name);
|
||||
else if (type == 'i') // current source
|
||||
this.i(connections[0],connections[1],properties['value'],name);
|
||||
else if (type == 'o') // op amp
|
||||
this.opamp(connections[0],connections[1],connections[2],connections[3],properties['A'],name);
|
||||
else if (type == 'n') // n fet
|
||||
this.n(connections[0],connections[1],connections[2],properties['W/L'],name);
|
||||
else if (type == 'p') // p fet
|
||||
this.p(connections[0],connections[1],connections[2],properties['W/L'],name);
|
||||
else if (type == 'a') // current probe == 0-volt voltage source
|
||||
this.v(connections[0],connections[1],'0',name);
|
||||
}
|
||||
|
||||
if (!found_ground) { // No ground on schematic
|
||||
alert('Please make at least one connection to ground (inverted T symbol)');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// if converges: updates this.solution, this.soln_max, returns iter count
|
||||
// otherwise: return undefined and set this.problem_node
|
||||
// Load should compute -f and df/dx (note the sign pattern!)
|
||||
Circuit.prototype.find_solution = function(load,maxiters) {
|
||||
var soln = this.solution;
|
||||
var rhs = this.rhs;
|
||||
var d_sol = new Array();
|
||||
var abssum_compare;
|
||||
var converged,abssum_old=0, abssum_rhs;
|
||||
var use_limiting = false;
|
||||
var down_count = 0;
|
||||
|
||||
// iteratively solve until values convere or iteration limit exceeded
|
||||
for (var iter = 0; iter < maxiters; iter++) {
|
||||
// set up equations
|
||||
load(this,soln,rhs);
|
||||
|
||||
// Compute norm of rhs, assume variables of v type go with eqns of i type
|
||||
abssum_rhs = 0;
|
||||
for (var i = this.N - 1; i >= 0; --i)
|
||||
if (this.ntypes[i] == T_VOLTAGE)
|
||||
abssum_rhs += Math.abs(rhs[i]);
|
||||
|
||||
if ((iter > 0) && (use_limiting == false) && (abssum_old < abssum_rhs)) {
|
||||
// Old rhsnorm was better, undo last iter and turn on limiting
|
||||
for (var i = this.N - 1; i >= 0; --i)
|
||||
soln[i] -= d_sol[i];
|
||||
iter -= 1;
|
||||
use_limiting = true;
|
||||
}
|
||||
else { // Compute the Newton delta
|
||||
//d_sol = mat_solve(this.matrix,rhs);
|
||||
d_sol = mat_solve_rq(this.matrix,rhs);
|
||||
|
||||
// If norm going down for ten iters, stop limiting
|
||||
if (abssum_rhs < abssum_old)
|
||||
down_count += 1;
|
||||
else
|
||||
down_count = 0;
|
||||
if (down_count > 10) {
|
||||
use_limiting = false;
|
||||
down_count = 0;
|
||||
}
|
||||
|
||||
// Update norm of rhs
|
||||
abssum_old = abssum_rhs;
|
||||
}
|
||||
|
||||
// Update the worst case abssum for comparison.
|
||||
if ((iter == 0) || (abssum_rhs > abssum_compare))
|
||||
abssum_compare = abssum_rhs;
|
||||
|
||||
// Check residue convergence, but loosely, and give up
|
||||
// on last iteration
|
||||
if ( (iter < (maxiters - 1)) &&
|
||||
(abssum_rhs > (res_check_abs+res_check_rel*abssum_compare)))
|
||||
converged = false;
|
||||
else converged = true;
|
||||
|
||||
|
||||
// Update solution and check delta convergence
|
||||
for (var i = this.N - 1; i >= 0; --i) {
|
||||
// Simple voltage step limiting to encourage Newton convergence
|
||||
if (use_limiting) {
|
||||
if (this.ntypes[i] == T_VOLTAGE) {
|
||||
d_sol[i] = (d_sol[i] > v_newt_lim) ? v_newt_lim : d_sol[i];
|
||||
d_sol[i] = (d_sol[i] < -v_newt_lim) ? -v_newt_lim : d_sol[i];
|
||||
}
|
||||
}
|
||||
soln[i] += d_sol[i];
|
||||
thresh = this.abstol[i] + reltol*this.soln_max[i];
|
||||
if (Math.abs(d_sol[i]) > thresh) {
|
||||
converged = false;
|
||||
this.problem_node = i;
|
||||
}
|
||||
}
|
||||
|
||||
//alert(numeric.prettyPrint(this.solution);)
|
||||
if (converged == true) {
|
||||
for (var i = this.N - 1; i >= 0; --i)
|
||||
if (Math.abs(soln[i]) > this.soln_max[i])
|
||||
this.soln_max[i] = Math.abs(soln[i]);
|
||||
|
||||
return iter+1;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// DC analysis
|
||||
Circuit.prototype.dc = function() {
|
||||
|
||||
// Allocation matrices for linear part, etc.
|
||||
if (this.finalize() == false)
|
||||
return undefined;
|
||||
|
||||
// Define -f and df/dx for Newton solver
|
||||
function load_dc(ckt,soln,rhs) {
|
||||
// rhs is initialized to -Gl * soln
|
||||
mat_v_mult(ckt.Gl, soln, rhs, -1.0);
|
||||
// G matrix is initialized with linear Gl
|
||||
mat_copy(ckt.Gl,ckt.G);
|
||||
// Now load up the nonlinear parts of rhs and G
|
||||
for (var i = ckt.devices.length - 1; i >= 0; --i)
|
||||
ckt.devices[i].load_dc(ckt,soln,rhs);
|
||||
// G matrix is copied in to the system matrix
|
||||
mat_copy(ckt.G,ckt.matrix);
|
||||
}
|
||||
|
||||
// find the operating point
|
||||
var iterations = this.find_solution(load_dc,dc_max_iters);
|
||||
|
||||
if (typeof iterations == 'undefined') {
|
||||
// too many iterations
|
||||
if (this.current_sources.length > 0) {
|
||||
alert('Newton Method Failed, do your current sources have a conductive path to ground?');
|
||||
} else {
|
||||
alert('Newton Method Failed, it may be your circuit or it may be our simulator.');
|
||||
}
|
||||
|
||||
return undefined
|
||||
} else {
|
||||
// Note that a dc solution was computed
|
||||
this.diddc = true;
|
||||
// create solution dictionary
|
||||
var result = new Array();
|
||||
// capture node voltages
|
||||
for (var name in this.node_map) {
|
||||
var index = this.node_map[name];
|
||||
result[name] = (index == -1) ? 0 : this.solution[index];
|
||||
}
|
||||
// capture branch currents from voltage sources
|
||||
for (var i = this.voltage_sources.length - 1; i >= 0; --i) {
|
||||
var v = this.voltage_sources[i];
|
||||
result['I('+v.name+')'] = this.solution[v.branch];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Transient analysis (needs work!)
|
||||
Circuit.prototype.tran = function(ntpts, tstart, tstop, probenames, no_dc) {
|
||||
|
||||
// Define -f and df/dx for Newton solver
|
||||
function load_tran(ckt,soln,rhs) {
|
||||
// Crnt is initialized to -Gl * soln
|
||||
mat_v_mult(ckt.Gl, soln, ckt.c,-1.0);
|
||||
// G matrix is initialized with linear Gl
|
||||
mat_copy(ckt.Gl,ckt.G);
|
||||
// Now load up the nonlinear parts of crnt and G
|
||||
for (var i = ckt.devices.length - 1; i >= 0; --i)
|
||||
ckt.devices[i].load_tran(ckt,soln,ckt.c,ckt.time);
|
||||
// Exploit the fact that storage elements are linear
|
||||
mat_v_mult(ckt.C, soln, ckt.q, 1.0);
|
||||
// -rhs = c - dqdt
|
||||
for (var i = ckt.N-1; i >= 0; --i) {
|
||||
var dqdt = ckt.alpha0*ckt.q[i] + ckt.alpha1*ckt.oldq[i] +
|
||||
ckt.alpha2*ckt.old2q[i];
|
||||
//alert(numeric.prettyPrint(dqdt));
|
||||
rhs[i] = ckt.beta0[i]*ckt.c[i] + ckt.beta1[i]*ckt.oldc[i] - dqdt;
|
||||
}
|
||||
// matrix = beta0*G + alpha0*C.
|
||||
mat_scale_add(ckt.G,ckt.C,ckt.beta0,ckt.alpha0,ckt.matrix);
|
||||
}
|
||||
|
||||
var p = new Array(3);
|
||||
function interp_coeffs(t, t0, t1, t2) {
|
||||
// Poly coefficients
|
||||
var dtt0 = (t - t0);
|
||||
var dtt1 = (t - t1);
|
||||
var dtt2 = (t - t2);
|
||||
var dt0dt1 = (t0 - t1);
|
||||
var dt0dt2 = (t0 - t2);
|
||||
var dt1dt2 = (t1 - t2);
|
||||
p[0] = (dtt1*dtt2)/(dt0dt1 * dt0dt2);
|
||||
p[1] = (dtt0*dtt2)/(-dt0dt1 * dt1dt2);
|
||||
p[2] = (dtt0*dtt1)/(dt0dt2 * dt1dt2);
|
||||
return p;
|
||||
}
|
||||
|
||||
function pick_step(ckt, step_index) {
|
||||
var min_shrink_factor = 1.0/lte_step_decrease_factor;
|
||||
var max_growth_factor = time_step_increase_factor;
|
||||
var N = ckt.N;
|
||||
var p = interp_coeffs(ckt.time, ckt.oldt, ckt.old2t, ckt.old3t);
|
||||
var trapcoeff = 0.5*(ckt.time - ckt.oldt)/(ckt.time - ckt.old3t);
|
||||
var maxlteratio = 0.0;
|
||||
for (var i = ckt.N-1; i >= 0; --i) {
|
||||
if (ckt.ltecheck[i]) { // Check lte on variable
|
||||
var pred = p[0]*ckt.oldsol[i] + p[1]*ckt.old2sol[i] + p[2]*ckt.old3sol[i];
|
||||
var lte = Math.abs((ckt.solution[i] - pred))*trapcoeff;
|
||||
var lteratio = lte/(lterel*(ckt.abstol[i] + reltol*ckt.soln_max[i]));
|
||||
maxlteratio = Math.max(maxlteratio, lteratio);
|
||||
}
|
||||
}
|
||||
var new_step;
|
||||
var lte_step_ratio = 1.0/Math.pow(maxlteratio,1/3); // Cube root because trap
|
||||
if (lte_step_ratio < 1.0) { // Shrink the timestep to make lte
|
||||
lte_step_ratio = Math.max(lte_step_ratio,min_shrink_factor);
|
||||
new_step = (ckt.time - ckt.oldt)*0.75*lte_step_ratio;
|
||||
new_step = Math.max(new_step, ckt.min_step);
|
||||
} else {
|
||||
lte_step_ratio = Math.min(lte_step_ratio, max_growth_factor);
|
||||
if (lte_step_ratio > 1.2) /* Increase timestep due to lte. */
|
||||
new_step = (ckt.time - ckt.oldt) * lte_step_ratio / 1.2;
|
||||
else
|
||||
new_step = (ckt.time - ckt.oldt);
|
||||
new_step = Math.min(new_step, ckt.max_step);
|
||||
}
|
||||
return new_step;
|
||||
}
|
||||
|
||||
// Standard to do a dc analysis before transient
|
||||
// Otherwise, do the setup also done in dc.
|
||||
no_dc = false;
|
||||
if ((this.diddc == false) && (no_dc == false)) {
|
||||
if (this.dc() == undefined) { // DC failed, realloc mats and vects.
|
||||
alert('DC failed, trying transient analysis from zero.');
|
||||
this.finalized = false; // Reset the finalization.
|
||||
if (this.finalize() == false)
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.finalize() == false) // Allocate matrices and vectors.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Tired of typing this, and using "with" generates hate mail.
|
||||
var N = this.N;
|
||||
|
||||
// build array to hold list of results for each variable
|
||||
// last entry is for timepoints.
|
||||
var response = new Array(N + 1);
|
||||
for (var i = N; i >= 0; --i) response[i] = new Array();
|
||||
|
||||
// Allocate back vectors for up to a second order method
|
||||
this.old3sol = new Array(this.N);
|
||||
this.old3q = new Array(this.N);
|
||||
this.old2sol = new Array(this.N);
|
||||
this.old2q = new Array(this.N);
|
||||
this.oldsol = new Array(this.N);
|
||||
this.oldq = new Array(this.N);
|
||||
this.q = new Array(this.N);
|
||||
this.oldc = new Array(this.N);
|
||||
this.c = new Array(this.N);
|
||||
this.alpha0 = 1.0;
|
||||
this.alpha1 = 0.0;
|
||||
this.alpha2 = 0.0;
|
||||
this.beta0 = new Array(this.N);
|
||||
this.beta1 = new Array(this.N);
|
||||
|
||||
// Mark a set of algebraic variable (don't miss hidden ones!).
|
||||
this.ar = this.algebraic(this.C);
|
||||
|
||||
// Non-algebraic variables and probe variables get lte
|
||||
this.ltecheck = new Array(this.N);
|
||||
for (var i = N; i >= 0; --i)
|
||||
this.ltecheck[i] = (this.ar[i] == 0);
|
||||
|
||||
for (var name in this.node_map) {
|
||||
var index = this.node_map[name];
|
||||
for (var i = probenames.length; i >= 0; --i) {
|
||||
if (name == probenames[i]) {
|
||||
this.ltecheck[index] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for periodic sources
|
||||
var period = tstop - tstart;
|
||||
for (var i = this.voltage_sources.length - 1; i >= 0; --i) {
|
||||
var per = this.voltage_sources[i].src.period;
|
||||
if (per > 0)
|
||||
period = Math.min(period, per);
|
||||
}
|
||||
for (var i = this.current_sources.length - 1; i >= 0; --i) {
|
||||
var per = this.current_sources[i].src.period;
|
||||
if (per > 0)
|
||||
period = Math.min(period, per);
|
||||
}
|
||||
this.periods = Math.ceil((tstop - tstart)/period);
|
||||
//alert('number of periods ' + this.periods);
|
||||
|
||||
|
||||
this.time = tstart;
|
||||
// ntpts adjusted by numbers of periods in input
|
||||
this.max_step = (tstop - tstart)/(this.periods*ntpts);
|
||||
this.min_step = this.max_step/1e8;
|
||||
var new_step = this.max_step/1e6;
|
||||
this.oldt = this.time - new_step;
|
||||
|
||||
// Initialize old crnts, charges, and solutions.
|
||||
load_tran(this,this.solution,this.rhs)
|
||||
for (var i = N-1; i >= 0; --i) {
|
||||
this.old3sol[i] = this.solution[i];
|
||||
this.old2sol[i] = this.solution[i];
|
||||
this.oldsol[i] = this.solution[i];
|
||||
this.old3q[i] = this.q[i];
|
||||
this.old2q[i] = this.q[i];
|
||||
this.oldq[i] = this.q[i];
|
||||
this.oldc[i] = this.c[i];
|
||||
}
|
||||
|
||||
|
||||
var beta0,beta1;
|
||||
// Start with two pseudo-Euler steps, maximum 50000 steps/period
|
||||
var max_nsteps = this.periods*50000;
|
||||
for(var step_index = -3; step_index < max_nsteps; step_index++) {
|
||||
// Save the just computed solution, and move back q and c.
|
||||
for (var i = this.N - 1; i >= 0; --i) {
|
||||
if (step_index >= 0)
|
||||
response[i].push(this.solution[i]);
|
||||
this.oldc[i] = this.c[i];
|
||||
this.old3sol[i] = this.old2sol[i];
|
||||
this.old2sol[i] = this.oldsol[i];
|
||||
this.oldsol[i] = this.solution[i];
|
||||
this.old3q[i] = this.oldq[i];
|
||||
this.old2q[i] = this.oldq[i];
|
||||
this.oldq[i] = this.q[i];
|
||||
|
||||
}
|
||||
|
||||
if (step_index < 0) { // Take a prestep using BE
|
||||
this.old3t = this.old2t - (this.oldt-this.old2t)
|
||||
this.old2t = this.oldt - (tstart-this.oldt)
|
||||
this.oldt = tstart - (this.time - this.oldt);
|
||||
this.time = tstart;
|
||||
beta0 = 1.0;
|
||||
beta1 = 0.0;
|
||||
} else { // Take a regular step
|
||||
// Save the time, and rotate time wheel
|
||||
response[this.N].push(this.time);
|
||||
this.old3t = this.old2t;
|
||||
this.old2t = this.oldt;
|
||||
this.oldt = this.time;
|
||||
// Make sure we come smoothly in to the interval end.
|
||||
if (this.time >= tstop) break; // We're done.
|
||||
else if(this.time + new_step > tstop)
|
||||
this.time = tstop;
|
||||
else if(this.time + 1.5*new_step > tstop)
|
||||
this.time += (2/3)*(tstop - this.time);
|
||||
else
|
||||
this.time += new_step;
|
||||
|
||||
// Use trap (average old and new crnts.
|
||||
beta0 = 0.5;
|
||||
beta1 = 0.5;
|
||||
}
|
||||
|
||||
// For trap rule, turn off current avging for algebraic eqns
|
||||
for (var i = this.N - 1; i >= 0; --i) {
|
||||
this.beta0[i] = beta0 + this.ar[i]*beta1;
|
||||
this.beta1[i] = (1.0 - this.ar[i])*beta1;
|
||||
}
|
||||
|
||||
// Loop to find NR converging timestep with okay LTE
|
||||
while (true) {
|
||||
// Set the timestep coefficients (alpha2 is for bdf2).
|
||||
this.alpha0 = 1.0/(this.time - this.oldt);
|
||||
this.alpha1 = -this.alpha0;
|
||||
this.alpha2 = 0;
|
||||
|
||||
// If timestep is 1/10,000th of tstop, just use BE.
|
||||
if ((this.time-this.oldt) < 1.0e-4*tstop) {
|
||||
for (var i = this.N - 1; i >= 0; --i) {
|
||||
this.beta0[i] = 1.0;
|
||||
this.beta1[i] = 0.0;
|
||||
}
|
||||
}
|
||||
// Use Newton to compute the solution.
|
||||
var iterations = this.find_solution(load_tran,max_tran_iters);
|
||||
|
||||
// If NR succeeds and stepsize is at min, accept and newstep=maxgrowth*minstep.
|
||||
// Else if Newton Fails, shrink step by a factor and try again
|
||||
// Else LTE picks new step, if bigger accept current step and go on.
|
||||
if ((iterations != undefined) &&
|
||||
(step_index <= 0 || (this.time-this.oldt) < (1+reltol)*this.min_step)) {
|
||||
if (step_index > 0) new_step = time_step_increase_factor*this.min_step;
|
||||
break;
|
||||
} else if (iterations == undefined) { // NR nonconvergence, shrink by factor
|
||||
//alert('timestep nonconvergence ' + this.time + ' ' + step_index);
|
||||
this.time = this.oldt +
|
||||
(this.time - this.oldt)/nr_step_decrease_factor;
|
||||
} else { // Check the LTE and shrink step if needed.
|
||||
new_step = pick_step(this, step_index);
|
||||
if (new_step < (1.0 - reltol)*(this.time - this.oldt)) {
|
||||
this.time = this.oldt + new_step; // Try again
|
||||
}
|
||||
else
|
||||
break; // LTE okay, new_step for next step
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create solution dictionary
|
||||
var result = new Array();
|
||||
for (var name in this.node_map) {
|
||||
var index = this.node_map[name];
|
||||
result[name] = (index == -1) ? 0 : response[index];
|
||||
}
|
||||
// capture branch currents from voltage sources
|
||||
for (var i = this.voltage_sources.length - 1; i >= 0; --i) {
|
||||
var v = this.voltage_sources[i];
|
||||
result['I('+v.name+')'] = response[v.branch];
|
||||
}
|
||||
|
||||
result['_time_'] = response[this.N];
|
||||
return result;
|
||||
}
|
||||
|
||||
// AC analysis: npts/decade for freqs in range [fstart,fstop]
|
||||
// result['_frequencies_'] = vector of log10(sample freqs)
|
||||
// result['xxx'] = vector of dB(response for node xxx)
|
||||
// NOTE: Normalization removed in schematic.js, jkw.
|
||||
Circuit.prototype.ac = function(npts,fstart,fstop,source_name) {
|
||||
|
||||
if (this.dc() == undefined) { // DC failed, realloc mats and vects.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var N = this.N;
|
||||
var G = this.G;
|
||||
var C = this.C;
|
||||
|
||||
// Complex numbers, we're going to need a bigger boat
|
||||
var matrixac = mat_make(2*N, (2*N)+1);
|
||||
|
||||
// Get the source used for ac
|
||||
if (this.device_map[source_name] === undefined) {
|
||||
alert('AC analysis refers to unknown source ' + source_name);
|
||||
return 'AC analysis failed, unknown source';
|
||||
}
|
||||
this.device_map[source_name].load_ac(this,this.rhs);
|
||||
|
||||
// build array to hold list of magnitude and phases for each node
|
||||
// last entry is for frequency values
|
||||
var response = new Array(2*N + 1);
|
||||
for (var i = 2*N; i >= 0; --i) response[i] = new Array();
|
||||
|
||||
// multiplicative frequency increase between freq points
|
||||
var delta_f = Math.exp(Math.LN10/npts);
|
||||
|
||||
var phase_offset = new Array(N);
|
||||
for (var i = N-1; i >= 0; --i) phase_offset[i] = 0;
|
||||
|
||||
var f = fstart;
|
||||
fstop *= 1.0001; // capture that last freq point!
|
||||
while (f <= fstop) {
|
||||
var omega = 2 * Math.PI * f;
|
||||
response[2*N].push(f); // 2*N for magnitude and phase
|
||||
|
||||
// Find complex x+jy that sats Gx-omega*Cy=rhs; omega*Cx+Gy=0
|
||||
// Note: solac[0:N-1]=x, solac[N:2N-1]=y
|
||||
for (var i = N-1; i >= 0; --i) {
|
||||
// First the rhs, replicated for real and imaginary
|
||||
matrixac[i][2*N] = this.rhs[i];
|
||||
matrixac[i+N][2*N] = 0;
|
||||
|
||||
for (var j = N-1; j >= 0; --j) {
|
||||
matrixac[i][j] = G[i][j];
|
||||
matrixac[i+N][j+N] = G[i][j];
|
||||
matrixac[i][j+N] = -omega*C[i][j];
|
||||
matrixac[i+N][j] = omega*C[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the small signal response
|
||||
var solac = mat_solve(matrixac);
|
||||
|
||||
// Save magnitude and phase
|
||||
for (var i = N - 1; i >= 0; --i) {
|
||||
var mag = Math.sqrt(solac[i]*solac[i] + solac[i+N]*solac[i+N]);
|
||||
response[i].push(mag);
|
||||
|
||||
// Avoid wrapping phase, add or sub 180 for each jump
|
||||
var phase = 180*(Math.atan2(solac[i+N],solac[i])/Math.PI);
|
||||
var phasei = response[i+N];
|
||||
var L = phasei.length;
|
||||
// Look for a one-step jump greater than 90 degrees
|
||||
if (L > 1) {
|
||||
var phase_jump = phase + phase_offset[i] - phasei[L-1];
|
||||
if (phase_jump > 90) {
|
||||
phase_offset[i] -= 360;
|
||||
} else if (phase_jump < -90) {
|
||||
phase_offset[i] += 360;
|
||||
}
|
||||
}
|
||||
response[i+N].push(phase + phase_offset[i]);
|
||||
}
|
||||
f *= delta_f; // increment frequency
|
||||
}
|
||||
|
||||
// create solution dictionary
|
||||
var result = new Array();
|
||||
for (var name in this.node_map) {
|
||||
var index = this.node_map[name];
|
||||
result[name] = (index == -1) ? 0 : response[index];
|
||||
result[name+'_phase'] = (index == -1) ? 0 : response[index+N];
|
||||
}
|
||||
result['_frequencies_'] = response[2*N];
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Helper for adding devices to a circuit, warns on duplicate device names.
|
||||
Circuit.prototype.add_device = function(d,name) {
|
||||
// Add device to list of devices and to device map
|
||||
this.devices.push(d);
|
||||
d.name = name;
|
||||
if (name) {
|
||||
if (this.device_map[name] === undefined)
|
||||
this.device_map[name] = d;
|
||||
else {
|
||||
alert('Warning: two circuit elements share the same name ' + name);
|
||||
this.device_map[name] = d;
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
Circuit.prototype.r = function(n1,n2,v,name) {
|
||||
// try to convert string value into numeric value, barf if we can't
|
||||
if ((typeof v) == 'string') {
|
||||
v = parse_number(v,undefined);
|
||||
if (v === undefined) return undefined;
|
||||
}
|
||||
|
||||
if (v != 0) {
|
||||
var d = new Resistor(n1,n2,v);
|
||||
return this.add_device(d, name);
|
||||
} else return this.v(n1,n2,'0',name); // zero resistance == 0V voltage source
|
||||
}
|
||||
|
||||
Circuit.prototype.d = function(n1,n2,area,type,name) {
|
||||
// try to convert string value into numeric value, barf if we can't
|
||||
if ((typeof area) == 'string') {
|
||||
area = parse_number(area,undefined);
|
||||
if (area === undefined) return undefined;
|
||||
}
|
||||
|
||||
if (area != 0) {
|
||||
var d = new Diode(n1,n2,area,type);
|
||||
return this.add_device(d, name);
|
||||
} // zero area diodes discarded.
|
||||
}
|
||||
|
||||
|
||||
Circuit.prototype.c = function(n1,n2,v,name) {
|
||||
// try to convert string value into numeric value, barf if we can't
|
||||
if ((typeof v) == 'string') {
|
||||
v = parse_number(v,undefined);
|
||||
if (v === undefined) return undefined;
|
||||
}
|
||||
var d = new Capacitor(n1,n2,v);
|
||||
return this.add_device(d, name);
|
||||
}
|
||||
|
||||
Circuit.prototype.l = function(n1,n2,v,name) {
|
||||
// try to convert string value into numeric value, barf if we can't
|
||||
if ((typeof v) == 'string') {
|
||||
v = parse_number(v,undefined);
|
||||
if (v === undefined) return undefined;
|
||||
}
|
||||
var branch = this.node(undefined,T_CURRENT);
|
||||
var d = new Inductor(n1,n2,branch,v);
|
||||
return this.add_device(d, name);
|
||||
}
|
||||
|
||||
Circuit.prototype.v = function(n1,n2,v,name) {
|
||||
var branch = this.node(undefined,T_CURRENT);
|
||||
var d = new VSource(n1,n2,branch,v);
|
||||
this.voltage_sources.push(d);
|
||||
return this.add_device(d, name);
|
||||
}
|
||||
|
||||
Circuit.prototype.i = function(n1,n2,v,name) {
|
||||
var d = new ISource(n1,n2,v);
|
||||
this.current_sources.push(d);
|
||||
return this.add_device(d, name);
|
||||
}
|
||||
|
||||
Circuit.prototype.opamp = function(np,nn,no,ng,A,name) {
|
||||
// try to convert string value into numeric value, barf if we can't
|
||||
if ((typeof A) == 'string') {
|
||||
ratio = parse_number(A,undefined);
|
||||
if (A === undefined) return undefined;
|
||||
}
|
||||
var branch = this.node(undefined,T_CURRENT);
|
||||
var d = new Opamp(np,nn,no,ng,branch,A,name);
|
||||
return this.add_device(d, name);
|
||||
}
|
||||
|
||||
Circuit.prototype.n = function(d,g,s, ratio, name) {
|
||||
// try to convert string value into numeric value, barf if we can't
|
||||
if ((typeof ratio) == 'string') {
|
||||
ratio = parse_number(ratio,undefined);
|
||||
if (ratio === undefined) return undefined;
|
||||
}
|
||||
var d = new Fet(d,g,s,ratio,name,'n');
|
||||
return this.add_device(d, name);
|
||||
}
|
||||
|
||||
Circuit.prototype.p = function(d,g,s, ratio, name) {
|
||||
// try to convert string value into numeric value, barf if we can't
|
||||
if ((typeof ratio) == 'string') {
|
||||
ratio = parse_number(ratio,undefined);
|
||||
if (ratio === undefined) return undefined;
|
||||
}
|
||||
var d = new Fet(d,g,s,ratio,name,'p');
|
||||
return this.add_device(d, name);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Support for creating conductance and capacitance matrices associated with
|
||||
// modified nodal analysis (unknowns are node voltages and inductor and voltage
|
||||
// source currents).
|
||||
// The linearized circuit is written as
|
||||
// C d/dt x = G x + rhs
|
||||
// x - vector of node voltages and element currents
|
||||
// rhs - vector of source values
|
||||
// C - Matrix whose values are capacitances and inductances, has many zero rows.
|
||||
// G - Matrix whose values are conductances and +-1's.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// add val component between two nodes to matrix M
|
||||
// Index of -1 refers to ground node
|
||||
Circuit.prototype.add_two_terminal = function(i,j,g,M) {
|
||||
if (i >= 0) {
|
||||
M[i][i] += g;
|
||||
if (j >= 0) {
|
||||
M[i][j] -= g;
|
||||
M[j][i] -= g;
|
||||
M[j][j] += g;
|
||||
}
|
||||
} else if (j >= 0)
|
||||
M[j][j] += g;
|
||||
}
|
||||
|
||||
// add val component between two nodes to matrix M
|
||||
// Index of -1 refers to ground node
|
||||
Circuit.prototype.get_two_terminal = function(i,j,x) {
|
||||
var xi_minus_xj = 0;
|
||||
if (i >= 0) xi_minus_xj = x[i];
|
||||
if (j >= 0) xi_minus_xj -= x[j];
|
||||
return xi_minus_xj
|
||||
}
|
||||
|
||||
Circuit.prototype.add_conductance_l = function(i,j,g) {
|
||||
this.add_two_terminal(i,j,g, this.Gl)
|
||||
}
|
||||
|
||||
Circuit.prototype.add_conductance = function(i,j,g) {
|
||||
this.add_two_terminal(i,j,g, this.G)
|
||||
}
|
||||
|
||||
Circuit.prototype.add_capacitance = function(i,j,c) {
|
||||
this.add_two_terminal(i,j,c,this.C)
|
||||
}
|
||||
|
||||
// add individual conductance to Gl matrix
|
||||
Circuit.prototype.add_to_Gl = function(i,j,g) {
|
||||
if (i >=0 && j >= 0)
|
||||
this.Gl[i][j] += g;
|
||||
}
|
||||
|
||||
// add individual conductance to Gl matrix
|
||||
Circuit.prototype.add_to_G = function(i,j,g) {
|
||||
if (i >=0 && j >= 0)
|
||||
this.G[i][j] += g;
|
||||
}
|
||||
|
||||
// add individual capacitance to C matrix
|
||||
Circuit.prototype.add_to_C = function(i,j,c) {
|
||||
if (i >=0 && j >= 0)
|
||||
this.C[i][j] += c;
|
||||
}
|
||||
|
||||
// add source info to rhs
|
||||
Circuit.prototype.add_to_rhs = function(i,v,rhs) {
|
||||
if (i >= 0) rhs[i] += v;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generic matrix support - making, copying, factoring, rank, etc
|
||||
// Note, Matrices are stored using nested javascript arrays.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Allocate an NxM matrix
|
||||
function mat_make(N,M) {
|
||||
var mat = new Array(N);
|
||||
for (var i = N - 1; i >= 0; --i) {
|
||||
mat[i] = new Array(M);
|
||||
for (var j = M - 1; j >= 0; --j) {
|
||||
mat[i][j] = 0.0;
|
||||
}
|
||||
}
|
||||
return mat;
|
||||
}
|
||||
|
||||
// Form b = scale*Mx
|
||||
function mat_v_mult(M,x,b,scale) {
|
||||
var n = M.length;
|
||||
var m = M[0].length;
|
||||
|
||||
if (n != b.length || m != x.length)
|
||||
throw 'Rows of M mismatched to b or cols mismatch to x.';
|
||||
|
||||
for (var i = 0; i < n; i++) {
|
||||
var temp = 0;
|
||||
for (var j = 0; j < m; j++) temp += M[i][j]*x[j];
|
||||
b[i] = scale*temp; // Recall the neg in the name
|
||||
}
|
||||
}
|
||||
|
||||
// C = scalea*A + scaleb*B, scalea, scaleb eithers numbers or arrays (row scaling)
|
||||
function mat_scale_add(A, B, scalea, scaleb, C) {
|
||||
var n = A.length;
|
||||
var m = A[0].length;
|
||||
|
||||
if (n > B.length || m > B[0].length)
|
||||
throw 'Row or columns of A to large for B';
|
||||
if (n > C.length || m > C[0].length)
|
||||
throw 'Row or columns of A to large for C';
|
||||
if ((typeof scalea == 'number') && (typeof scaleb == 'number'))
|
||||
for (var i = 0; i < n; i++)
|
||||
for (var j = 0; j < m; j++)
|
||||
C[i][j] = scalea*A[i][j] + scaleb*B[i][j];
|
||||
else if ((typeof scaleb == 'number') && (scalea instanceof Array))
|
||||
for (var i = 0; i < n; i++)
|
||||
for (var j = 0; j < m; j++)
|
||||
C[i][j] = scalea[i]*A[i][j] + scaleb*B[i][j];
|
||||
else if ((typeof scaleb instanceof Array) && (scalea instanceof Array))
|
||||
for (var i = 0; i < n; i++)
|
||||
for (var j = 0; j < m; j++)
|
||||
C[i][j] = scalea[i]*A[i][j] + scaleb[i]*B[i][j];
|
||||
else
|
||||
throw 'scalea and scaleb must be scalars or Arrays';
|
||||
}
|
||||
|
||||
// Returns a vector of ones and zeros, ones denote algebraic
|
||||
// variables (rows that can be removed without changing rank(M).
|
||||
Circuit.prototype.algebraic = function(M) {
|
||||
var Nr = M.length
|
||||
Mc = mat_make(Nr, Nr);
|
||||
mat_copy(M,Mc);
|
||||
var R = mat_rank(Mc);
|
||||
|
||||
var one_if_alg = new Array(Nr);
|
||||
for (var row = 0; row < Nr; row++) { // psuedo gnd row small
|
||||
for (var col = Nr - 1; col >= 0; --col)
|
||||
Mc[row][col] = 0;
|
||||
if (mat_rank(Mc) == R) // Zeroing row left rank unchanged
|
||||
one_if_alg[row] = 1;
|
||||
else { // Zeroing row changed rank, put back
|
||||
for (var col = Nr - 1; col >= 0; --col)
|
||||
Mc[row][col] = M[row][col];
|
||||
one_if_alg[row] = 0;
|
||||
}
|
||||
}
|
||||
return one_if_alg;
|
||||
}
|
||||
|
||||
// Copy A -> using the bounds of A
|
||||
function mat_copy(src,dest) {
|
||||
var n = src.length;
|
||||
var m = src[0].length;
|
||||
if (n > dest.length || m > dest[0].length)
|
||||
throw 'Rows or cols > rows or cols of dest';
|
||||
|
||||
for (var i = 0; i < n; i++)
|
||||
for (var j = 0; j < m; j++)
|
||||
dest[i][j] = src[i][j];
|
||||
}
|
||||
|
||||
// Copy and transpose A -> using the bounds of A
|
||||
function mat_copy_transposed(src,dest) {
|
||||
var n = src.length;
|
||||
var m = src[0].length;
|
||||
if (n > dest[0].length || m > dest.length)
|
||||
throw 'Rows or cols > cols or rows of dest';
|
||||
|
||||
for (var i = 0; i < n; i++)
|
||||
for (var j = 0; j < m; j++)
|
||||
dest[j][i] = src[i][j];
|
||||
}
|
||||
|
||||
|
||||
// Uses GE to determine rank.
|
||||
function mat_rank(Mo) {
|
||||
var Nr = Mo.length; // Number of rows
|
||||
var Nc = Mo[0].length; // Number of columns
|
||||
var temp,i,j;
|
||||
// Make a copy to avoid overwriting
|
||||
M = mat_make(Nr, Nc);
|
||||
mat_copy(Mo,M);
|
||||
|
||||
// Find matrix maximum entry
|
||||
var max_abs_entry = 0;
|
||||
for(var row = Nr-1; row >= 0; --row) {
|
||||
for(var col = Nr-1; col >= 0; --col) {
|
||||
if (Math.abs(M[row][col]) > max_abs_entry)
|
||||
max_abs_entry = Math.abs(M[row][col]);
|
||||
}
|
||||
}
|
||||
|
||||
// Gaussian elimination to find rank
|
||||
var the_rank = 0;
|
||||
var start_col = 0;
|
||||
for (var row = 0; row < Nr; row++) {
|
||||
// Search for first nonzero column in the remaining rows.
|
||||
for (var col = start_col; col < Nc; col++) {
|
||||
var max_v = Math.abs(M[row][col]);
|
||||
var max_row = row;
|
||||
for (var i = row + 1; i < Nr; i++) {
|
||||
temp = Math.abs(M[i][col]);
|
||||
if (temp > max_v) { max_v = temp; max_row = i; }
|
||||
}
|
||||
// if max_v non_zero, column is nonzero, eliminate in subsequent rows
|
||||
if (Math.abs(max_v) > eps*max_abs_entry) {
|
||||
start_col = col+1;
|
||||
the_rank += 1;
|
||||
// Swap rows to get max in M[row][col]
|
||||
temp = M[row];
|
||||
M[row] = M[max_row];
|
||||
M[max_row] = temp;
|
||||
|
||||
// now eliminate this column for all subsequent rows
|
||||
for (var i = row + 1; i < Nr; i++) {
|
||||
temp = M[i][col]/M[row][col]; // multiplier for current row
|
||||
if (temp != 0) // subtract
|
||||
for (var j = col; j < Nc; j++) M[i][j] -= M[row][j]*temp;
|
||||
}
|
||||
// Now move on to the next row
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return the rank
|
||||
return the_rank;
|
||||
}
|
||||
|
||||
// Solve Mx=b and return vector x using R^TQ^T factorization.
|
||||
// Multiplication by R^T implicit, should be null-space free soln.
|
||||
// M should have the extra column!
|
||||
// Almost everything is in-lined for speed, sigh.
|
||||
function mat_solve_rq(M, rhs) {
|
||||
|
||||
var Nr = M.length; // Number of rows
|
||||
var Nc = M[0].length; // Number of columns
|
||||
|
||||
// Copy the rhs in to the last column of M if one is given.
|
||||
if (rhs != null) {
|
||||
for (var row = Nr - 1; row >= 0; --row)
|
||||
M[row][Nc-1] = rhs[row];
|
||||
}
|
||||
|
||||
var mat_scale = 0; // Sets the scale for comparison to zero.
|
||||
var max_nonzero_row = Nr-1; // Assumes M nonsingular.
|
||||
for (var row = 0; row < Nr; row++) {
|
||||
// Find largest row with largest 2-norm
|
||||
var max_row = row;
|
||||
var maxsumsq = 0;
|
||||
for (var rowp = row; rowp < Nr; rowp++) {
|
||||
var Mr = M[rowp];
|
||||
var sumsq = 0;
|
||||
for (var col = Nc-2; col >= 0; --col) // Last col=rhs
|
||||
sumsq += Mr[col]*Mr[col];
|
||||
if ((row == rowp) || (sumsq > maxsumsq)) {
|
||||
max_row = rowp;
|
||||
maxsumsq = sumsq;
|
||||
}
|
||||
}
|
||||
if (max_row > row) { // Swap rows if not max row
|
||||
var temp = M[row];
|
||||
M[row] = M[max_row];
|
||||
M[max_row] = temp;
|
||||
}
|
||||
|
||||
// Calculate row norm, save if this is first (largest)
|
||||
row_norm = Math.sqrt(maxsumsq);
|
||||
if (row == 0) mat_scale = row_norm;
|
||||
|
||||
// Check for all zero rows
|
||||
if (row_norm > mat_scale*eps)
|
||||
scale = 1.0/row_norm;
|
||||
else {
|
||||
max_nonzero_row = row - 1; // Rest will be nullspace of M
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Nonzero row, eliminate from rows below
|
||||
var Mr = M[row];
|
||||
for (var col = Nc-1; col >= 0; --col) // Scale rhs also
|
||||
Mr[col] *= scale;
|
||||
for (var rowp = row + 1; rowp < Nr; rowp++) { // Update.
|
||||
var Mrp = M[rowp];
|
||||
var inner = 0;
|
||||
for (var col = Nc-2; col >= 0; --col) // Project
|
||||
inner += Mr[col]*Mrp[col];
|
||||
for (var col = Nc-1; col >= 0; --col) // Ortho (rhs also)
|
||||
Mrp[col] -= inner *Mr[col];
|
||||
}
|
||||
}
|
||||
|
||||
// Last Column of M has inv(R^T)*rhs. Scale rows of Q to get x.
|
||||
var x = new Array(Nc-1);
|
||||
for (var col = Nc-2; col >= 0; --col)
|
||||
x[col] = 0;
|
||||
for (var row = max_nonzero_row; row >= 0; --row) {
|
||||
Mr = M[row];
|
||||
for (var col = Nc-2; col >= 0; --col) {
|
||||
x[col] += Mr[col]*Mr[Nc-1];
|
||||
}
|
||||
}
|
||||
|
||||
// Return solution.
|
||||
return x;
|
||||
}
|
||||
|
||||
// solve Mx=b and return vector x given augmented matrix M = [A | b]
|
||||
// Uses Gaussian elimination with partial pivoting
|
||||
function mat_solve(M,rhs) {
|
||||
var N = M.length; // augmented matrix M has N rows, N+1 columns
|
||||
var temp,i,j;
|
||||
|
||||
// Copy the rhs in to the last column of M if one is given.
|
||||
if (rhs != null) {
|
||||
for (var row = 0; row < N ; row++)
|
||||
M[row][N] = rhs[row];
|
||||
}
|
||||
|
||||
// gaussian elimination
|
||||
for (var col = 0; col < N ; col++) {
|
||||
// find pivot: largest abs(v) in this column of remaining rows
|
||||
var max_v = Math.abs(M[col][col]);
|
||||
var max_col = col;
|
||||
for (i = col + 1; i < N; i++) {
|
||||
temp = Math.abs(M[i][col]);
|
||||
if (temp > max_v) { max_v = temp; max_col = i; }
|
||||
}
|
||||
|
||||
// if no value found, generate a small conductance to gnd
|
||||
// otherwise swap current row with pivot row
|
||||
if (max_v == 0) M[col][col] = eps;
|
||||
else {
|
||||
temp = M[col];
|
||||
M[col] = M[max_col];
|
||||
M[max_col] = temp;
|
||||
}
|
||||
|
||||
// now eliminate this column for all subsequent rows
|
||||
for (i = col + 1; i < N; i++) {
|
||||
temp = M[i][col]/M[col][col]; // multiplier we'll use for current row
|
||||
if (temp != 0)
|
||||
// subtract current row from row we're working on
|
||||
// remember to process b too!
|
||||
for (j = col; j <= N; j++) M[i][j] -= M[col][j]*temp;
|
||||
}
|
||||
}
|
||||
|
||||
// matrix is now upper triangular, so solve for elements of x starting
|
||||
// with the last row
|
||||
var x = new Array(N);
|
||||
for (i = N-1; i >= 0; --i) {
|
||||
temp = M[i][N]; // grab b[i] from augmented matrix as RHS
|
||||
// subtract LHS term from RHS using known x values
|
||||
for (j = N-1; j > i; --j) temp -= M[i][j]*x[j];
|
||||
// now compute new x value
|
||||
x[i] = temp/M[i][i];
|
||||
}
|
||||
|
||||
// return solution
|
||||
return x;
|
||||
}
|
||||
|
||||
// test solution code, expect x = [2,3,-1]
|
||||
//M = [[2,1,-1,8],[-3,-1,2,-11],[-2,1,2,-3]];
|
||||
//x = mat_solve(M);
|
||||
//y = 1; // so we have place to set a breakpoint :)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Device base class
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Device() {
|
||||
}
|
||||
|
||||
// complete initial set up of device
|
||||
Device.prototype.finalize = function() {
|
||||
}
|
||||
|
||||
// Load the linear elements in to Gl and C
|
||||
Device.prototype.load_linear = function(ckt) {
|
||||
}
|
||||
|
||||
// load linear system equations for dc analysis
|
||||
// (inductors shorted and capacitors opened)
|
||||
Device.prototype.load_dc = function(ckt,soln,rhs) {
|
||||
}
|
||||
|
||||
// load linear system equations for tran analysis
|
||||
Device.prototype.load_tran = function(ckt,soln) {
|
||||
}
|
||||
|
||||
// load linear system equations for ac analysis:
|
||||
// current sources open, voltage sources shorted
|
||||
// linear models at operating point for everyone else
|
||||
Device.prototype.load_ac = function(ckt,rhs) {
|
||||
}
|
||||
|
||||
// return time of next breakpoint for the device
|
||||
Device.prototype.breakpoint = function(time) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parse numbers in engineering notation
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// convert first character of argument into an integer
|
||||
function ord(ch) {
|
||||
return ch.charCodeAt(0);
|
||||
}
|
||||
|
||||
// convert string argument to a number, accepting usual notations
|
||||
// (hex, octal, binary, decimal, floating point) plus engineering
|
||||
// scale factors (eg, 1k = 1000.0 = 1e3).
|
||||
// return default if argument couldn't be interpreted as a number
|
||||
function parse_number(s,default_v) {
|
||||
var slen = s.length;
|
||||
var multiplier = 1;
|
||||
var result = 0;
|
||||
var index = 0;
|
||||
|
||||
// skip leading whitespace
|
||||
while (index < slen && s.charAt(index) <= ' ') index += 1;
|
||||
if (index == slen) return default_v;
|
||||
|
||||
// check for leading sign
|
||||
if (s.charAt(index) == '-') {
|
||||
multiplier = -1;
|
||||
index += 1;
|
||||
} else if (s.charAt(index) == '+')
|
||||
index += 1;
|
||||
var start = index; // remember where digits start
|
||||
|
||||
// if leading digit is 0, check for hex, octal or binary notation
|
||||
if (index >= slen) return default_v;
|
||||
else if (s.charAt(index) == '0') {
|
||||
index += 1;
|
||||
if (index >= slen) return 0;
|
||||
if (s.charAt(index) == 'x' || s.charAt(index) == 'X') { // hex
|
||||
while (true) {
|
||||
index += 1;
|
||||
if (index >= slen) break;
|
||||
if (s.charAt(index) >= '0' && s.charAt(index) <= '9')
|
||||
result = result*16 + ord(s.charAt(index)) - ord('0');
|
||||
else if (s.charAt(index) >= 'A' && s.charAt(index) <= 'F')
|
||||
result = result*16 + ord(s.charAt(index)) - ord('A') + 10;
|
||||
else if (s.charAt(index) >= 'a' && s.charAt(index) <= 'f')
|
||||
result = result*16 + ord(s.charAt(index)) - ord('a') + 10;
|
||||
else break;
|
||||
}
|
||||
return result*multiplier;
|
||||
} else if (s.charAt(index) == 'b' || s.charAt(index) == 'B') { // binary
|
||||
while (true) {
|
||||
index += 1;
|
||||
if (index >= slen) break;
|
||||
if (s.charAt(index) >= '0' && s.charAt(index) <= '1')
|
||||
result = result*2 + ord(s.charAt(index)) - ord('0');
|
||||
else break;
|
||||
}
|
||||
return result*multiplier;
|
||||
} else if (s.charAt(index) != '.') { // octal
|
||||
while (true) {
|
||||
if (s.charAt(index) >= '0' && s.charAt(index) <= '7')
|
||||
result = result*8 + ord(s.charAt(index)) - ord('0');
|
||||
else break;
|
||||
index += 1;
|
||||
if (index >= slen) break;
|
||||
}
|
||||
return result*multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
// read decimal integer or floating-point number
|
||||
while (true) {
|
||||
if (s.charAt(index) >= '0' && s.charAt(index) <= '9')
|
||||
result = result*10 + ord(s.charAt(index)) - ord('0');
|
||||
else break;
|
||||
index += 1;
|
||||
if (index >= slen) break;
|
||||
}
|
||||
|
||||
// fractional part?
|
||||
if (index < slen && s.charAt(index) == '.') {
|
||||
while (true) {
|
||||
index += 1;
|
||||
if (index >= slen) break;
|
||||
if (s.charAt(index) >= '0' && s.charAt(index) <= '9') {
|
||||
result = result*10 + ord(s.charAt(index)) - ord('0');
|
||||
multiplier *= 0.1;
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we haven't seen any digits yet, don't check
|
||||
// for exponents or scale factors
|
||||
if (index == start) return default_v;
|
||||
|
||||
// type of multiplier determines type of result:
|
||||
// multiplier is a float if we've seen digits past
|
||||
// a decimal point, otherwise it's an int or long.
|
||||
// Up to this point result is an int or long.
|
||||
result *= multiplier;
|
||||
|
||||
// now check for exponent or engineering scale factor. If there
|
||||
// is one, result will be a float.
|
||||
if (index < slen) {
|
||||
var scale = s.charAt(index);
|
||||
index += 1;
|
||||
if (scale == 'e' || scale == 'E') {
|
||||
var exponent = 0;
|
||||
multiplier = 10.0;
|
||||
if (index < slen) {
|
||||
if (s.charAt(index) == '+') index += 1;
|
||||
else if (s.charAt(index) == '-') {
|
||||
index += 1;
|
||||
multiplier = 0.1;
|
||||
}
|
||||
}
|
||||
while (index < slen) {
|
||||
if (s.charAt(index) >= '0' && s.charAt(index) <= '9') {
|
||||
exponent = exponent*10 + ord(s.charAt(index)) - ord('0');
|
||||
index += 1;
|
||||
} else break;
|
||||
}
|
||||
while (exponent > 0) {
|
||||
exponent -= 1;
|
||||
result *= multiplier;
|
||||
}
|
||||
} else if (scale == 't' || scale == 'T') result *= 1e12;
|
||||
else if (scale == 'g' || scale == 'G') result *= 1e9;
|
||||
else if (scale == 'M') result *= 1e6;
|
||||
else if (scale == 'k' || scale == 'K') result *= 1e3;
|
||||
else if (scale == 'm') result *= 1e-3;
|
||||
else if (scale == 'u' || scale == 'U') result *= 1e-6;
|
||||
else if (scale == 'n' || scale == 'N') result *= 1e-9;
|
||||
else if (scale == 'p' || scale == 'P') result *= 1e-12;
|
||||
else if (scale == 'f' || scale == 'F') result *= 1e-15;
|
||||
}
|
||||
// ignore any remaining chars, eg, 1kohms returns 1000
|
||||
return result;
|
||||
}
|
||||
|
||||
Circuit.prototype.parse_number = parse_number; // make it easy to call from outside
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Sources
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// argument is a string describing the source's value (see comments for details)
|
||||
// source types: dc,step,square,triangle,sin,pulse,pwl,pwl_repeating
|
||||
|
||||
// returns an object with the following attributes:
|
||||
// fun -- name of source function
|
||||
// args -- list of argument values
|
||||
// value(t) -- compute source value at time t
|
||||
// inflection_point(t) -- compute time after t when a time point is needed
|
||||
// dc -- value at time 0
|
||||
// period -- repeat period for periodic sources (0 if not periodic)
|
||||
|
||||
function parse_source(v) {
|
||||
// generic parser: parse v as either <value> or <fun>(<value>,...)
|
||||
var src = new Object();
|
||||
src.period = 0; // Default not periodic
|
||||
src.value = function(t) { return 0; } // overridden below
|
||||
src.inflection_point = function(t) { return undefined; }; // may be overridden below
|
||||
|
||||
// see if there's a "(" in the description
|
||||
var index = v.indexOf('(');
|
||||
var ch;
|
||||
if (index >= 0) {
|
||||
src.fun = v.slice(0,index); // function name is before the "("
|
||||
src.args = []; // we'll push argument values onto this list
|
||||
var end = v.indexOf(')',index);
|
||||
if (end == -1) end = v.length;
|
||||
|
||||
index += 1; // start parsing right after "("
|
||||
while (index < end) {
|
||||
// figure out where next argument value starts
|
||||
ch = v.charAt(index);
|
||||
if (ch <= ' ') { index++; continue; }
|
||||
// and where it ends
|
||||
var arg_end = v.indexOf(',',index);
|
||||
if (arg_end == -1) arg_end = end;
|
||||
// parse and save result in our list of arg values
|
||||
src.args.push(parse_number(v.slice(index,arg_end),undefined));
|
||||
index = arg_end + 1;
|
||||
}
|
||||
} else {
|
||||
src.fun = 'dc';
|
||||
src.args = [parse_number(v,0)];
|
||||
}
|
||||
|
||||
// post-processing for constant sources
|
||||
// dc(v)
|
||||
if (src.fun == 'dc') {
|
||||
var v = arg_value(src.args,0,0);
|
||||
src.args = [v];
|
||||
src.value = function(t) { return v; } // closure
|
||||
}
|
||||
|
||||
// post-processing for impulse sources
|
||||
// impulse(height,width)
|
||||
else if (src.fun == 'impulse') {
|
||||
var h = arg_value(src.args,0,1); // default height: 1
|
||||
var w = Math.abs(arg_value(src.args,2,1e-9)); // default width: 1ns
|
||||
src.args = [h,w]; // remember any defaulted values
|
||||
pwl_source(src,[0,0,w/2,h,w,0],false);
|
||||
}
|
||||
|
||||
// post-processing for step sources
|
||||
// step(v_init,v_plateau,t_delay,t_rise)
|
||||
else if (src.fun == 'step') {
|
||||
var v1 = arg_value(src.args,0,0); // default init value: 0V
|
||||
var v2 = arg_value(src.args,1,1); // default plateau value: 1V
|
||||
var td = Math.max(0,arg_value(src.args,2,0)); // time step starts
|
||||
var tr = Math.abs(arg_value(src.args,3,1e-9)); // default rise time: 1ns
|
||||
src.args = [v1,v2,td,tr]; // remember any defaulted values
|
||||
pwl_source(src,[td,v1,td+tr,v2],false);
|
||||
}
|
||||
|
||||
// post-processing for square wave
|
||||
// square(v_init,v_plateau,freq,duty_cycle)
|
||||
else if (src.fun == 'square') {
|
||||
var v1 = arg_value(src.args,0,0); // default init value: 0V
|
||||
var v2 = arg_value(src.args,1,1); // default plateau value: 1V
|
||||
var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1Hz
|
||||
var duty_cycle = Math.min(100,Math.abs(arg_value(src.args,3,50))); // default duty cycle: 0.5
|
||||
src.args = [v1,v2,freq,duty_cycle]; // remember any defaulted values
|
||||
|
||||
var per = freq == 0 ? Infinity : 1/freq;
|
||||
var t_change = 0.01 * per; // rise and fall time
|
||||
var t_pw = .01 * duty_cycle * 0.98 * per; // fraction of cycle minus rise and fall time
|
||||
pwl_source(src,[0,v1,t_change,v2,t_change+t_pw,
|
||||
v2,t_change+t_pw+t_change,v1,per,v1],true);
|
||||
}
|
||||
|
||||
// post-processing for triangle
|
||||
// triangle(v_init,v_plateua,t_period)
|
||||
else if (src.fun == 'triangle') {
|
||||
var v1 = arg_value(src.args,0,0); // default init value: 0V
|
||||
var v2 = arg_value(src.args,1,1); // default plateau value: 1V
|
||||
var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1s
|
||||
src.args = [v1,v2,freq]; // remember any defaulted values
|
||||
|
||||
var per = freq == 0 ? Infinity : 1/freq;
|
||||
pwl_source(src,[0,v1,per/2,v2,per,v1],true);
|
||||
}
|
||||
|
||||
// post-processing for pwl and pwlr sources
|
||||
// pwl[r](t1,v1,t2,v2,...)
|
||||
else if (src.fun == 'pwl' || src.fun == 'pwl_repeating') {
|
||||
pwl_source(src,src.args,src.fun == 'pwl_repeating');
|
||||
}
|
||||
|
||||
// post-processing for pulsed sources
|
||||
// pulse(v_init,v_plateau,t_delay,t_rise,t_fall,t_width,t_period)
|
||||
else if (src.fun == 'pulse') {
|
||||
var v1 = arg_value(src.args,0,0); // default init value: 0V
|
||||
var v2 = arg_value(src.args,1,1); // default plateau value: 1V
|
||||
var td = Math.max(0,arg_value(src.args,2,0)); // time pulse starts
|
||||
var tr = Math.abs(arg_value(src.args,3,1e-9)); // default rise time: 1ns
|
||||
var tf = Math.abs(arg_value(src.args,4,1e-9)); // default rise time: 1ns
|
||||
var pw = Math.abs(arg_value(src.args,5,1e9)); // default pulse width: "infinite"
|
||||
var per = Math.abs(arg_value(src.args,6,1e9)); // default period: "infinite"
|
||||
src.args = [v1,v2,td,tr,tf,pw,per];
|
||||
|
||||
var t1 = td; // time when v1 -> v2 transition starts
|
||||
var t2 = t1 + tr; // time when v1 -> v2 transition ends
|
||||
var t3 = t2 + pw; // time when v2 -> v1 transition starts
|
||||
var t4 = t3 + tf; // time when v2 -> v1 transition ends
|
||||
|
||||
pwl_source(src,[t1,v1, t2,v2, t3,v2, t4,v1, per,v1],true);
|
||||
}
|
||||
|
||||
// post-processing for sinusoidal sources
|
||||
// sin(v_offset,v_amplitude,freq_hz,t_delay,phase_offset_degrees)
|
||||
else if (src.fun == 'sin') {
|
||||
var voffset = arg_value(src.args,0,0); // default offset voltage: 0V
|
||||
var va = arg_value(src.args,1,1); // default amplitude: -1V to 1V
|
||||
var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1Hz
|
||||
src.period = 1.0/freq;
|
||||
|
||||
var td = Math.max(0,arg_value(src.args,3,0)); // default time delay: 0sec
|
||||
var phase = arg_value(src.args,4,0); // default phase offset: 0 degrees
|
||||
src.args = [voffset,va,freq,td,phase];
|
||||
|
||||
phase /= 360.0;
|
||||
|
||||
// return value of source at time t
|
||||
src.value = function(t) { // closure
|
||||
if (t < td) return voffset + va*Math.sin(2*Math.PI*phase);
|
||||
else return voffset + va*Math.sin(2*Math.PI*(freq*(t - td) + phase));
|
||||
}
|
||||
|
||||
// return time of next inflection point after time t
|
||||
src.inflection_point = function(t) { // closure
|
||||
if (t < td) return td;
|
||||
else return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// object has all the necessary info to compute the source value and inflection points
|
||||
src.dc = src.value(0); // DC value is value at time 0
|
||||
return src;
|
||||
}
|
||||
|
||||
function pwl_source(src,tv_pairs,repeat) {
|
||||
var nvals = tv_pairs.length;
|
||||
if (repeat)
|
||||
src.period = tv_pairs[nvals-2]; // Repeat period of source
|
||||
if (nvals % 2 == 1) npts -= 1; // make sure it's even!
|
||||
|
||||
if (nvals <= 2) {
|
||||
// handle degenerate case
|
||||
src.value = function(t) { return nvals == 2 ? tv_pairs[1] : 0; }
|
||||
src.inflection_point = function(t) { return undefined; }
|
||||
} else {
|
||||
src.value = function(t) { // closure
|
||||
if (repeat)
|
||||
// make time periodic if values are to be repeated
|
||||
t = Math.fmod(t,tv_pairs[nvals-2]);
|
||||
var last_t = tv_pairs[0];
|
||||
var last_v = tv_pairs[1];
|
||||
if (t > last_t) {
|
||||
var next_t,next_v;
|
||||
for (var i = 2; i < nvals; i += 2) {
|
||||
next_t = tv_pairs[i];
|
||||
next_v = tv_pairs[i+1];
|
||||
if (next_t > last_t) // defend against bogus tv pairs
|
||||
if (t < next_t)
|
||||
return last_v + (next_v - last_v)*(t - last_t)/(next_t - last_t);
|
||||
last_t = next_t;
|
||||
last_v = next_v;
|
||||
}
|
||||
}
|
||||
return last_v;
|
||||
}
|
||||
src.inflection_point = function(t) { // closure
|
||||
if (repeat)
|
||||
// make time periodic if values are to be repeated
|
||||
t = Math.fmod(t,tv_pairs[nvals-2]);
|
||||
for (var i = 0; i < nvals; i += 2) {
|
||||
var next_t = tv_pairs[i];
|
||||
if (t < next_t) return next_t;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// helper function: return args[index] if present, else default_v
|
||||
function arg_value(args,index,default_v) {
|
||||
if (index < args.length) {
|
||||
var result = args[index];
|
||||
if (result === undefined) result = default_v;
|
||||
return result;
|
||||
} else return default_v;
|
||||
}
|
||||
|
||||
// we need fmod in the Math library!
|
||||
Math.fmod = function(numerator,denominator) {
|
||||
var quotient = Math.floor(numerator/denominator);
|
||||
return numerator - quotient*denominator;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Sources
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function VSource(npos,nneg,branch,v) {
|
||||
Device.call(this);
|
||||
|
||||
this.src = parse_source(v);
|
||||
this.npos = npos;
|
||||
this.nneg = nneg;
|
||||
this.branch = branch;
|
||||
}
|
||||
VSource.prototype = new Device();
|
||||
VSource.prototype.constructor = VSource;
|
||||
|
||||
// load linear part for source evaluation
|
||||
VSource.prototype.load_linear = function(ckt) {
|
||||
// MNA stamp for independent voltage source
|
||||
ckt.add_to_Gl(this.branch,this.npos,1.0);
|
||||
ckt.add_to_Gl(this.branch,this.nneg,-1.0);
|
||||
ckt.add_to_Gl(this.npos,this.branch,1.0);
|
||||
ckt.add_to_Gl(this.nneg,this.branch,-1.0);
|
||||
}
|
||||
|
||||
// Source voltage added to b.
|
||||
VSource.prototype.load_dc = function(ckt,soln,rhs) {
|
||||
ckt.add_to_rhs(this.branch,this.src.dc,rhs);
|
||||
}
|
||||
|
||||
// Load time-dependent value for voltage source for tran
|
||||
VSource.prototype.load_tran = function(ckt,soln,rhs,time) {
|
||||
ckt.add_to_rhs(this.branch,this.src.value(time),rhs);
|
||||
}
|
||||
|
||||
// return time of next breakpoint for the device
|
||||
VSource.prototype.breakpoint = function(time) {
|
||||
return this.src.inflection_point(time);
|
||||
}
|
||||
|
||||
// small signal model ac value
|
||||
VSource.prototype.load_ac = function(ckt,rhs) {
|
||||
ckt.add_to_rhs(this.branch,1.0,rhs);
|
||||
}
|
||||
|
||||
function ISource(npos,nneg,v) {
|
||||
Device.call(this);
|
||||
|
||||
this.src = parse_source(v);
|
||||
this.npos = npos;
|
||||
this.nneg = nneg;
|
||||
}
|
||||
ISource.prototype = new Device();
|
||||
ISource.prototype.constructor = ISource;
|
||||
|
||||
ISource.prototype.load_linear = function(ckt) {
|
||||
// Current source is open when off, no linear contribution
|
||||
}
|
||||
|
||||
// load linear system equations for dc analysis
|
||||
ISource.prototype.load_dc = function(ckt,soln,rhs) {
|
||||
var is = this.src.dc;
|
||||
|
||||
// MNA stamp for independent current source
|
||||
ckt.add_to_rhs(this.npos,-is,rhs); // current flow into npos
|
||||
ckt.add_to_rhs(this.nneg,is,rhs); // and out of nneg
|
||||
}
|
||||
|
||||
// load linear system equations for tran analysis (just like DC)
|
||||
ISource.prototype.load_tran = function(ckt,soln,rhs,time) {
|
||||
var is = this.src.value(time);
|
||||
|
||||
// MNA stamp for independent current source
|
||||
ckt.add_to_rhs(this.npos,-is,rhs); // current flow into npos
|
||||
ckt.add_to_rhs(this.nneg,is,rhs); // and out of nneg
|
||||
}
|
||||
|
||||
// return time of next breakpoint for the device
|
||||
ISource.prototype.breakpoint = function(time) {
|
||||
return this.src.inflection_point(time);
|
||||
}
|
||||
|
||||
// small signal model: open circuit
|
||||
ISource.prototype.load_ac = function(ckt,rhs) {
|
||||
// MNA stamp for independent current source
|
||||
ckt.add_to_rhs(this.npos,-1.0,rhs); // current flow into npos
|
||||
ckt.add_to_rhs(this.nneg,1.0,rhs); // and out of nneg
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Resistor
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Resistor(n1,n2,v) {
|
||||
Device.call(this);
|
||||
this.n1 = n1;
|
||||
this.n2 = n2;
|
||||
this.g = 1.0/v;
|
||||
}
|
||||
Resistor.prototype = new Device();
|
||||
Resistor.prototype.constructor = Resistor;
|
||||
|
||||
Resistor.prototype.load_linear = function(ckt) {
|
||||
// MNA stamp for admittance g
|
||||
ckt.add_conductance_l(this.n1,this.n2,this.g);
|
||||
}
|
||||
|
||||
Resistor.prototype.load_dc = function(ckt) {
|
||||
// Nothing to see here, move along.
|
||||
}
|
||||
|
||||
Resistor.prototype.load_tran = function(ckt,soln) {
|
||||
}
|
||||
|
||||
Resistor.prototype.load_ac = function(ckt) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Diode
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Diode(n1,n2,v,type) {
|
||||
Device.call(this);
|
||||
this.anode = n1;
|
||||
this.cathode = n2;
|
||||
this.area = v;
|
||||
this.type = type; // 'normal' or 'ideal'
|
||||
this.is = 1.0e-14;
|
||||
this.ais = this.area * this.is;
|
||||
this.vt = (type == 'normal') ? 25.8e-3 : 0.1e-3; // 26mv or .1mv
|
||||
this.exp_arg_max = 50; // less than single precision max.
|
||||
this.exp_max = Math.exp(this.exp_arg_max);
|
||||
}
|
||||
Diode.prototype = new Device();
|
||||
Diode.prototype.constructor = Diode;
|
||||
|
||||
Diode.prototype.load_linear = function(ckt) {
|
||||
// Diode is not linear, has no linear piece.
|
||||
}
|
||||
|
||||
Diode.prototype.load_dc = function(ckt,soln,rhs) {
|
||||
var vd = ckt.get_two_terminal(this.anode, this.cathode, soln);
|
||||
var exp_arg = vd / this.vt;
|
||||
var temp1, temp2;
|
||||
// Estimate exponential with a quadratic if arg too big.
|
||||
var abs_exp_arg = Math.abs(exp_arg);
|
||||
var d_arg = abs_exp_arg - this.exp_arg_max;
|
||||
if (d_arg > 0) {
|
||||
var quad = 1 + d_arg + 0.5*d_arg*d_arg;
|
||||
temp1 = this.exp_max * quad;
|
||||
temp2 = this.exp_max * (1 + d_arg);
|
||||
} else {
|
||||
temp1 = Math.exp(abs_exp_arg);
|
||||
temp2 = temp1;
|
||||
}
|
||||
if (exp_arg < 0) { // Use exp(-x) = 1.0/exp(x)
|
||||
temp1 = 1.0/temp1;
|
||||
temp2 = (temp1*temp2)*temp1;
|
||||
}
|
||||
var id = this.ais * (temp1 - 1);
|
||||
var gd = this.ais * (temp2 / this.vt);
|
||||
|
||||
// MNA stamp for independent current source
|
||||
ckt.add_to_rhs(this.anode,-id,rhs); // current flows into anode
|
||||
ckt.add_to_rhs(this.cathode,id,rhs); // and out of cathode
|
||||
ckt.add_conductance(this.anode,this.cathode,gd);
|
||||
}
|
||||
|
||||
Diode.prototype.load_tran = function(ckt,soln,rhs,time) {
|
||||
this.load_dc(ckt,soln,rhs);
|
||||
}
|
||||
|
||||
Diode.prototype.load_ac = function(ckt) {
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Capacitor
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Capacitor(n1,n2,v) {
|
||||
Device.call(this);
|
||||
this.n1 = n1;
|
||||
this.n2 = n2;
|
||||
this.value = v;
|
||||
}
|
||||
Capacitor.prototype = new Device();
|
||||
Capacitor.prototype.constructor = Capacitor;
|
||||
|
||||
Capacitor.prototype.load_linear = function(ckt) {
|
||||
// MNA stamp for capacitance matrix
|
||||
ckt.add_capacitance(this.n1,this.n2,this.value);
|
||||
}
|
||||
|
||||
Capacitor.prototype.load_dc = function(ckt,soln,rhs) {
|
||||
}
|
||||
|
||||
Capacitor.prototype.load_ac = function(ckt) {
|
||||
}
|
||||
|
||||
Capacitor.prototype.load_tran = function(ckt) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Inductor
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Inductor(n1,n2,branch,v) {
|
||||
Device.call(this);
|
||||
this.n1 = n1;
|
||||
this.n2 = n2;
|
||||
this.branch = branch;
|
||||
this.value = v;
|
||||
}
|
||||
Inductor.prototype = new Device();
|
||||
Inductor.prototype.constructor = Inductor;
|
||||
|
||||
Inductor.prototype.load_linear = function(ckt) {
|
||||
// MNA stamp for inductor linear part
|
||||
// L on diag of C because L di/dt = v(n1) - v(n2)
|
||||
ckt.add_to_Gl(this.n1,this.branch,1);
|
||||
ckt.add_to_Gl(this.n2,this.branch,-1);
|
||||
ckt.add_to_Gl(this.branch,this.n1,-1);
|
||||
ckt.add_to_Gl(this.branch,this.n2,1);
|
||||
ckt.add_to_C(this.branch,this.branch,this.value)
|
||||
}
|
||||
|
||||
Inductor.prototype.load_dc = function(ckt,soln,rhs) {
|
||||
// Inductor is a short at dc, so is linear.
|
||||
}
|
||||
|
||||
Inductor.prototype.load_ac = function(ckt) {
|
||||
}
|
||||
|
||||
Inductor.prototype.load_tran = function(ckt) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Simple Voltage-Controlled Voltage Source Op Amp model
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Opamp(np,nn,no,ng,branch,A,name) {
|
||||
Device.call(this);
|
||||
this.np = np;
|
||||
this.nn = nn;
|
||||
this.no = no;
|
||||
this.ng = ng;
|
||||
this.branch = branch;
|
||||
this.gain = A;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Opamp.prototype = new Device();
|
||||
Opamp.prototype.constructor = Opamp;
|
||||
|
||||
Opamp.prototype.load_linear = function(ckt) {
|
||||
// MNA stamp for VCVS: 1/A(v(no) - v(ng)) - (v(np)-v(nn))) = 0.
|
||||
var invA = 1.0/this.gain;
|
||||
ckt.add_to_Gl(this.no,this.branch,1);
|
||||
ckt.add_to_Gl(this.ng,this.branch,-1);
|
||||
ckt.add_to_Gl(this.branch,this.no,invA);
|
||||
ckt.add_to_Gl(this.branch,this.ng,-invA);
|
||||
ckt.add_to_Gl(this.branch,this.np,-1);
|
||||
ckt.add_to_Gl(this.branch,this.nn,1);
|
||||
}
|
||||
|
||||
Opamp.prototype.load_dc = function(ckt,soln,rhs) {
|
||||
// Op-amp is linear.
|
||||
}
|
||||
|
||||
Opamp.prototype.load_ac = function(ckt) {
|
||||
}
|
||||
|
||||
Opamp.prototype.load_tran = function(ckt) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Simplified MOS FET with no bulk connection and no body effect.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
function Fet(d,g,s,ratio,name,type) {
|
||||
Device.call(this);
|
||||
this.d = d;
|
||||
this.g = g;
|
||||
this.s = s;
|
||||
this.name = name;
|
||||
this.ratio = ratio;
|
||||
if (type != 'n' && type != 'p')
|
||||
{ throw 'fet type is not n or p';
|
||||
}
|
||||
this.type_sign = (type == 'n') ? 1 : -1;
|
||||
this.vt = 0.5;
|
||||
this.kp = 20e-6;
|
||||
this.beta = this.kp * this.ratio;
|
||||
this.lambda = 0.05;
|
||||
}
|
||||
Fet.prototype = new Device();
|
||||
Fet.prototype.constructor = Fet;
|
||||
|
||||
Fet.prototype.load_linear = function(ckt) {
|
||||
// FET's are nonlinear, just like javascript progammers
|
||||
}
|
||||
|
||||
Fet.prototype.load_dc = function(ckt,soln,rhs) {
|
||||
var vds = this.type_sign * ckt.get_two_terminal(this.d, this.s, soln);
|
||||
if (vds < 0) { // Drain and source have swapped roles
|
||||
var temp = this.d;
|
||||
this.d = this.s;
|
||||
this.s = temp;
|
||||
vds = this.type_sign * ckt.get_two_terminal(this.d, this.s, soln);
|
||||
}
|
||||
var vgs = this.type_sign * ckt.get_two_terminal(this.g, this.s, soln);
|
||||
var vgst = vgs - this.vt;
|
||||
with (this) {
|
||||
var gmgs,ids,gds;
|
||||
if (vgst > 0.0 ) { // vgst < 0, transistor off, no subthreshold here.
|
||||
if (vgst < vds) { /* Saturation. */
|
||||
gmgs = beta * (1 + (lambda * vds)) * vgst;
|
||||
ids = type_sign * 0.5 * gmgs * vgst;
|
||||
gds = 0.5 * beta * vgst * vgst * lambda;
|
||||
} else { /* Linear region */
|
||||
gmgs = beta * (1 + lambda * vds);
|
||||
ids = type_sign * gmgs * vds * (vgst - 0.50 * vds);
|
||||
gds = gmgs * (vgst - vds) + beta * lambda * vds * (vgst - 0.5 * vds);
|
||||
gmgs *= vds;
|
||||
}
|
||||
ckt.add_to_rhs(d,-ids,rhs); // current flows into the drain
|
||||
ckt.add_to_rhs(s, ids,rhs); // and out the source
|
||||
ckt.add_conductance(d,s,gds);
|
||||
ckt.add_to_G(s,s, gmgs);
|
||||
ckt.add_to_G(d,s,-gmgs);
|
||||
ckt.add_to_G(d,g, gmgs);
|
||||
ckt.add_to_G(s,g,-gmgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Fet.prototype.load_tran = function(ckt,soln,rhs) {
|
||||
this.load_dc(ckt,soln,rhs);
|
||||
}
|
||||
|
||||
Fet.prototype.load_ac = function(ckt) {
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Module definition
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
var module = {
|
||||
'Circuit': Circuit,
|
||||
'parse_number': parse_number,
|
||||
'parse_source': parse_source,
|
||||
}
|
||||
return module;
|
||||
}());
|
||||
@@ -1,4184 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Simple schematic capture
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Copyright (C) 2011 Massachusetts Institute of Technology
|
||||
|
||||
// add schematics to a document with
|
||||
//
|
||||
// <input type="hidden" class="schematic" name="unique_form_id" value="JSON netlist..." .../>
|
||||
//
|
||||
// other attributes you can add to the input tag:
|
||||
// width -- width in pixels of diagram
|
||||
// height -- height in pixels of diagram
|
||||
// parts -- comma-separated list of parts for parts bin (see parts_map),
|
||||
// parts="" disables editing of diagram
|
||||
|
||||
// JSON schematic representation:
|
||||
// sch := [part, part, ...]
|
||||
// part := [type, coords, properties, connections]
|
||||
// type := string (see parts_map)
|
||||
// coords := [number, ...] // (x,y,rot) or (x1,y1,x2,y2)
|
||||
// properties := {name: value, ...}
|
||||
// connections := [node, ...] // one per connection point in canoncial order
|
||||
// node := string
|
||||
// need a netlist? just use the part's type, properites and connections
|
||||
|
||||
// TO DO:
|
||||
// - wire labels?
|
||||
// - zoom/scroll canvas
|
||||
// - rotate multiple objects around their center of mass
|
||||
// - rubber band wires when moving components
|
||||
|
||||
// set up each schematic entry widget
|
||||
function update_schematics() {
|
||||
// set up each schematic on the page
|
||||
var schematics = document.getElementsByClassName('schematic');
|
||||
for (var i = 0; i < schematics.length; ++i)
|
||||
if (schematics[i].getAttribute("loaded") != "true") {
|
||||
try {
|
||||
new schematic.Schematic(schematics[i]);
|
||||
} catch (err) {
|
||||
var msgdiv = document.createElement('div');
|
||||
msgdiv.style.border = 'thick solid #FF0000';
|
||||
msgdiv.style.margins = '20px';
|
||||
msgdiv.style.padding = '20px';
|
||||
var msg = document.createTextNode('Sorry, there a browser error in starting the schematic tool. The tool is known to be compatible with the latest versions of Firefox and Chrome, which we recommend you use.');
|
||||
msgdiv.appendChild(msg);
|
||||
schematics[i].parentNode.insertBefore(msgdiv,schematics[i]);
|
||||
}
|
||||
schematics[i].setAttribute("loaded","true");
|
||||
}
|
||||
}
|
||||
|
||||
// add ourselves to the tasks that get performed when window is loaded
|
||||
function add_schematic_handler(other_onload) {
|
||||
return function() {
|
||||
// execute othe onload functions first
|
||||
if (other_onload) other_onload();
|
||||
|
||||
update_schematics();
|
||||
}
|
||||
}
|
||||
window.onload = add_schematic_handler(window.onload);
|
||||
|
||||
// ask each schematic input widget to update its value field for submission
|
||||
function prepare_schematics() {
|
||||
var schematics = document.getElementsByClassName('schematic');
|
||||
for (var i = schematics.length - 1; i >= 0; i--)
|
||||
schematics[i].schematic.update_value();
|
||||
}
|
||||
|
||||
schematic = (function() {
|
||||
background_style = 'rgb(220,220,220)';
|
||||
element_style = 'rgb(255,255,255)';
|
||||
thumb_style = 'rgb(128,128,128)';
|
||||
normal_style = 'rgb(0,0,0)'; // default drawing color
|
||||
component_style = 'rgb(64,64,255)'; // color for unselected components
|
||||
selected_style = 'rgb(64,255,64)'; // highlight color for selected components
|
||||
grid_style = "rgb(128,128,128)";
|
||||
annotation_style = 'rgb(255,64,64)'; // color for diagram annotations
|
||||
|
||||
property_size = 5; // point size for Component property text
|
||||
annotation_size = 6; // point size for diagram annotations
|
||||
|
||||
// list of all the defined parts
|
||||
parts_map = {
|
||||
'g': [Ground, 'Ground connection'],
|
||||
'L': [Label, 'Node label'],
|
||||
'v': [VSource, 'Voltage source'],
|
||||
'i': [ISource, 'Current source'],
|
||||
'r': [Resistor, 'Resistor'],
|
||||
'c': [Capacitor, 'Capacitor'],
|
||||
'l': [Inductor, 'Inductor'],
|
||||
'o': [OpAmp, 'Op Amp'],
|
||||
'd': [Diode, 'Diode'],
|
||||
'n': [NFet, 'NFet'],
|
||||
'p': [PFet, 'PFet'],
|
||||
's': [Probe, 'Voltage Probe'],
|
||||
'a': [Ammeter, 'Current Probe'],
|
||||
};
|
||||
|
||||
// global clipboard
|
||||
if (typeof sch_clipboard == 'undefined')
|
||||
sch_clipboard = [];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Schematic = diagram + parts bin + status area
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// setup a schematic by populating the <div> with the appropriate children
|
||||
function Schematic(input) {
|
||||
// set up diagram viewing parameters
|
||||
this.grid = 8;
|
||||
this.scale = 2;
|
||||
this.origin_x = input.getAttribute("origin_x");
|
||||
if (this.origin_x == undefined) this.origin_x = 0;
|
||||
this.origin_y = input.getAttribute("origin_y");
|
||||
if (this.origin_y == undefined) this.origin_y = 0;
|
||||
|
||||
this.window_list = []; // list of pop-up windows in increasing z order
|
||||
|
||||
// use user-supplied list of parts if supplied
|
||||
// else just populate parts bin with all the parts
|
||||
this.edits_allowed = true;
|
||||
var parts = input.getAttribute('parts');
|
||||
if (parts == undefined || parts == 'None') {
|
||||
parts = new Array();
|
||||
for (var p in parts_map) parts.push(p);
|
||||
} else if (parts == '') {
|
||||
this.edits_allowed = false;
|
||||
parts = [];
|
||||
} else parts = parts.split(',');
|
||||
|
||||
// now add the parts to the parts bin
|
||||
this.parts_bin = [];
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var part = new Part(this);
|
||||
var pm = parts_map[parts[i]];
|
||||
part.set_component(new pm[0](0,0,0),pm[1]);
|
||||
this.parts_bin.push(part);
|
||||
}
|
||||
|
||||
// use user-supplied list of analyses, otherwise provide them all
|
||||
// analyses="" means no analyses
|
||||
var analyses = input.getAttribute('analyses');
|
||||
if (analyses == undefined || analyses == 'None')
|
||||
analyses = ['dc','ac','tran'];
|
||||
else if (analyses == '') analyses = [];
|
||||
else analyses = analyses.split(',');
|
||||
|
||||
if (parts.length == 0 && analyses.length == 0) this.diagram_only = true;
|
||||
else this.diagram_only = false;
|
||||
|
||||
// see what we need to submit. Expecting attribute of the form
|
||||
// submit_analyses="{'tran':[[node_name,t1,t2,t3],...],
|
||||
// 'ac':[[node_name,f1,f2,...],...]}"
|
||||
var submit = input.getAttribute('submit_analyses');
|
||||
if (submit && submit.indexOf('{') != -1)
|
||||
this.submit_analyses = JSON.parse(submit);
|
||||
else
|
||||
this.submit_analyses = undefined;
|
||||
|
||||
// toolbar
|
||||
this.tools = new Array();
|
||||
this.toolbar = [];
|
||||
|
||||
if (!this.diagram_only) {
|
||||
this.tools['help'] = this.add_tool(help_icon,'Help: display help page',this.help);
|
||||
this.enable_tool('help',true);
|
||||
this.toolbar.push(null); // spacer
|
||||
}
|
||||
|
||||
if (this.edits_allowed) {
|
||||
this.tools['zoomin'] = this.add_tool(zoomin_icon,'Zoom In: increase display magnification',this.zoomin);
|
||||
this.enable_tool('zoomin',true);
|
||||
this.tools['zoomout'] = this.add_tool(zoomout_icon,'Zoom Out: decrease display magnification',this.zoomout);
|
||||
this.enable_tool('zoomout',true);
|
||||
this.tools['zoomall'] = this.add_tool(zoomall_icon,'Zoom All: show entire diagram',this.zoomall);
|
||||
this.enable_tool('zoomall',true);
|
||||
|
||||
this.tools['cut'] = this.add_tool(cut_icon,'Cut: move selected components from diagram to the clipboard',this.cut);
|
||||
this.tools['copy'] = this.add_tool(copy_icon,'Copy: copy selected components into the clipboard',this.copy);
|
||||
this.tools['paste'] = this.add_tool(paste_icon,'Paste: copy clipboard into the diagram',this.paste);
|
||||
this.toolbar.push(null); // spacer
|
||||
}
|
||||
|
||||
// simulation interface if cktsim.js is loaded
|
||||
if (typeof cktsim != 'undefined') {
|
||||
if (analyses.indexOf('dc') != -1) {
|
||||
this.tools['dc'] = this.add_tool('DC','DC Analysis',this.dc_analysis);
|
||||
this.enable_tool('dc',true);
|
||||
this.dc_max_iters = '1000'; // default values dc solution
|
||||
}
|
||||
|
||||
if (analyses.indexOf('ac') != -1) {
|
||||
this.tools['ac'] = this.add_tool('AC','AC Small-Signal Analysis',this.setup_ac_analysis);
|
||||
this.enable_tool('ac',true);
|
||||
this.ac_npts = '50'; // default values for AC Analysis
|
||||
this.ac_fstart = '10';
|
||||
this.ac_fstop = '1G';
|
||||
this.ac_source_name = undefined;
|
||||
}
|
||||
|
||||
if (analyses.indexOf('tran') != -1) {
|
||||
this.tools['tran'] = this.add_tool('TRAN','Transient Analysis',this.transient_analysis);
|
||||
this.enable_tool('tran',true);
|
||||
this.tran_npts = '100'; // default values for transient analysis
|
||||
this.tran_tstop = '1';
|
||||
}
|
||||
}
|
||||
|
||||
// set up diagram canvas
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.width = input.getAttribute('width');
|
||||
this.width = parseInt(this.width == undefined ? '400' : this.width);
|
||||
this.canvas.width = this.width;
|
||||
this.height = input.getAttribute('height');
|
||||
this.height = parseInt(this.height == undefined ? '300' : this.height);
|
||||
this.canvas.height = this.height;
|
||||
|
||||
// repaint simply draws this buffer and then adds selected elements on top
|
||||
this.bg_image = document.createElement('canvas');
|
||||
this.bg_image.width = this.width;
|
||||
this.bg_image.height = this.height;
|
||||
|
||||
if (!this.diagram_only) {
|
||||
this.canvas.tabIndex = 1; // so we get keystrokes
|
||||
this.canvas.style.borderStyle = 'solid';
|
||||
this.canvas.style.borderWidth = '1px';
|
||||
this.canvas.style.borderColor = grid_style;
|
||||
this.canvas.style.outline = 'none';
|
||||
}
|
||||
|
||||
this.canvas.schematic = this;
|
||||
if (this.edits_allowed) {
|
||||
this.canvas.addEventListener('mousemove',schematic_mouse_move,false);
|
||||
this.canvas.addEventListener('mouseover',schematic_mouse_enter,false);
|
||||
this.canvas.addEventListener('mouseout',schematic_mouse_leave,false);
|
||||
this.canvas.addEventListener('mousedown',schematic_mouse_down,false);
|
||||
this.canvas.addEventListener('mouseup',schematic_mouse_up,false);
|
||||
this.canvas.addEventListener('dblclick',schematic_double_click,false);
|
||||
this.canvas.addEventListener('keydown',schematic_key_down,false);
|
||||
this.canvas.addEventListener('keyup',schematic_key_up,false);
|
||||
}
|
||||
|
||||
// set up message area
|
||||
if (!this.diagram_only) {
|
||||
this.status_div = document.createElement('div');
|
||||
this.status = document.createTextNode('');
|
||||
this.status_div.appendChild(this.status);
|
||||
this.status_div.style.height = status_height + 'px';
|
||||
} else this.status_div = undefined;
|
||||
|
||||
this.connection_points = new Array(); // location string => list of cp's
|
||||
this.components = [];
|
||||
|
||||
this.dragging = false;
|
||||
this.drawCursor = false;
|
||||
this.cursor_x = 0;
|
||||
this.cursor_y = 0;
|
||||
this.draw_cursor = undefined;
|
||||
this.select_rect = undefined;
|
||||
this.wire = undefined;
|
||||
|
||||
this.operating_point = undefined; // result from DC analysis
|
||||
this.dc_results = undefined; // saved analysis results for submission
|
||||
this.ac_results = undefined; // saved analysis results for submission
|
||||
this.transient_results = undefined; // saved analysis results for submission
|
||||
|
||||
// state of modifier keys
|
||||
this.ctrlKey = false;
|
||||
this.shiftKey = false;
|
||||
this.altKey = false;
|
||||
this.cmdKey = false;
|
||||
|
||||
// make sure other code can find us!
|
||||
input.schematic = this;
|
||||
this.input = input;
|
||||
|
||||
// set up DOM -- use nested tables to do the layout
|
||||
var table,tr,td;
|
||||
table = document.createElement('table');
|
||||
table.rules = 'none';
|
||||
if (!this.diagram_only) {
|
||||
table.frame = 'box';
|
||||
table.style.borderStyle = 'solid';
|
||||
table.style.borderWidth = '2px';
|
||||
table.style.borderColor = normal_style;
|
||||
table.style.backgroundColor = background_style;
|
||||
}
|
||||
|
||||
// add tools to DOM
|
||||
if (this.toolbar.length > 0) {
|
||||
tr = document.createElement('tr');
|
||||
table.appendChild(tr);
|
||||
td = document.createElement('td');
|
||||
td.style.verticalAlign = 'top';
|
||||
td.colSpan = 2;
|
||||
tr.appendChild(td);
|
||||
for (var i = 0; i < this.toolbar.length; ++i) {
|
||||
var tool = this.toolbar[i];
|
||||
if (tool != null) td.appendChild(tool);
|
||||
}
|
||||
}
|
||||
|
||||
// add canvas and parts bin to DOM
|
||||
tr = document.createElement('tr');
|
||||
table.appendChild(tr);
|
||||
|
||||
td = document.createElement('td');
|
||||
tr.appendChild(td);
|
||||
var wrapper = document.createElement('div'); // for inserting pop-up windows
|
||||
td.appendChild(wrapper);
|
||||
wrapper.style.position = 'relative'; // so we can position subwindows
|
||||
wrapper.appendChild(this.canvas);
|
||||
|
||||
td = document.createElement('td');
|
||||
td.style.verticalAlign = 'top';
|
||||
tr.appendChild(td);
|
||||
var parts_table = document.createElement('table');
|
||||
td.appendChild(parts_table);
|
||||
parts_table.rules = 'none';
|
||||
parts_table.frame = 'void';
|
||||
parts_table.cellPadding = '0';
|
||||
parts_table.cellSpacing = '0';
|
||||
|
||||
// fill in parts_table
|
||||
var parts_per_column = Math.floor(this.height / (part_h + 5)); // mysterious extra padding
|
||||
for (var i = 0; i < parts_per_column; ++i) {
|
||||
tr = document.createElement('tr');
|
||||
parts_table.appendChild(tr);
|
||||
for (var j = i; j < this.parts_bin.length; j += parts_per_column) {
|
||||
td = document.createElement('td');
|
||||
tr.appendChild(td);
|
||||
td.appendChild(this.parts_bin[j].canvas);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.status_div != undefined) {
|
||||
tr = document.createElement('tr');
|
||||
table.appendChild(tr);
|
||||
td = document.createElement('td');
|
||||
tr.appendChild(td);
|
||||
td.colSpan = 2;
|
||||
td.appendChild(this.status_div);
|
||||
}
|
||||
|
||||
// add to dom
|
||||
// avoid Chrome bug that changes to text cursor whenever
|
||||
// drag starts. Just do this in schematic tool...
|
||||
var toplevel = document.createElement('div');
|
||||
toplevel.onselectstart = function(){ return false; };
|
||||
toplevel.appendChild(table);
|
||||
this.input.parentNode.insertBefore(toplevel,this.input.nextSibling);
|
||||
|
||||
// process initial contents of diagram
|
||||
this.load_schematic(this.input.getAttribute('value'),
|
||||
this.input.getAttribute('initial_value'));
|
||||
}
|
||||
|
||||
part_w = 42; // size of a parts bin compartment
|
||||
part_h = 42;
|
||||
status_height = 18;
|
||||
|
||||
Schematic.prototype.add_component = function(new_c) {
|
||||
this.components.push(new_c);
|
||||
|
||||
// create undoable edit record here
|
||||
}
|
||||
|
||||
Schematic.prototype.remove_component = function(c) {
|
||||
var index = this.components.indexOf(c);
|
||||
if (index != -1) this.components.splice(index,1);
|
||||
}
|
||||
|
||||
Schematic.prototype.find_connections = function(cp) {
|
||||
return this.connection_points[cp.location];
|
||||
}
|
||||
|
||||
// add connection point to list of connection points at that location
|
||||
Schematic.prototype.add_connection_point = function(cp) {
|
||||
var cplist = this.connection_points[cp.location];
|
||||
if (cplist) cplist.push(cp);
|
||||
else {
|
||||
cplist = [cp];
|
||||
this.connection_points[cp.location] = cplist;
|
||||
}
|
||||
|
||||
// return list of conincident connection points
|
||||
return cplist;
|
||||
}
|
||||
|
||||
// remove connection point from the list points at the old location
|
||||
Schematic.prototype.remove_connection_point = function(cp,old_location) {
|
||||
// remove cp from list at old location
|
||||
var cplist = this.connection_points[old_location];
|
||||
if (cplist) {
|
||||
var index = cplist.indexOf(cp);
|
||||
if (index != -1) {
|
||||
cplist.splice(index,1);
|
||||
// if no more connections at this location, remove
|
||||
// entry from array to keep our search time short
|
||||
if (cplist.length == 0)
|
||||
delete this.connection_points[old_location];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// connection point has changed location: remove, then add
|
||||
Schematic.prototype.update_connection_point = function(cp,old_location) {
|
||||
this.remove_connection_point(cp,old_location);
|
||||
return this.add_connection_point(cp);
|
||||
}
|
||||
|
||||
// add a wire to the schematic
|
||||
Schematic.prototype.add_wire = function(x1,y1,x2,y2) {
|
||||
var new_wire = new Wire(x1,y1,x2,y2);
|
||||
new_wire.add(this);
|
||||
new_wire.move_end();
|
||||
return new_wire;
|
||||
}
|
||||
|
||||
Schematic.prototype.split_wire = function(w,cp) {
|
||||
// remove bisected wire
|
||||
w.remove();
|
||||
|
||||
// add two new wires with connection point cp in the middle
|
||||
this.add_wire(w.x,w.y,cp.x,cp.y);
|
||||
this.add_wire(w.x+w.dx,w.y+w.dy,cp.x,cp.y);
|
||||
}
|
||||
|
||||
// see if connection points of component c split any wires
|
||||
Schematic.prototype.check_wires = function(c) {
|
||||
for (var i = 0; i < this.components.length; i++) {
|
||||
var cc = this.components[i];
|
||||
if (cc != c) { // don't check a component against itself
|
||||
// only wires will return non-null from a bisect call
|
||||
var cp = cc.bisect(c);
|
||||
if (cp) {
|
||||
// cc is a wire bisected by connection point cp
|
||||
this.split_wire(cc,cp);
|
||||
this.redraw_background();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// see if there are any existing connection points that bisect wire w
|
||||
Schematic.prototype.check_connection_points = function(w) {
|
||||
for (var locn in this.connection_points) {
|
||||
var cplist = this.connection_points[locn];
|
||||
if (cplist && w.bisect_cp(cplist[0])) {
|
||||
this.split_wire(w,cplist[0]);
|
||||
this.redraw_background();
|
||||
|
||||
// stop here, new wires introduced by split will do their own checks
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// merge collinear wires sharing an end point
|
||||
Schematic.prototype.clean_up_wires = function() {
|
||||
for (var locn in this.connection_points) {
|
||||
var cplist = this.connection_points[locn];
|
||||
if (cplist && cplist.length == 2) {
|
||||
// found a connection with just two connections, see if they're wires
|
||||
var c1 = cplist[0].parent;
|
||||
var c2 = cplist[1].parent;
|
||||
if (c1.type == 'w' && c2.type == 'w') {
|
||||
var e1 = c1.other_end(cplist[0]);
|
||||
var e2 = c2.other_end(cplist[1]);
|
||||
var e3 = cplist[0]; // point shared by the two wires
|
||||
if (collinear(e1,e2,e3)) {
|
||||
c1.remove();
|
||||
c2.remove();
|
||||
this.add_wire(e1.x,e1.y,e2.x,e2.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Schematic.prototype.unselect_all = function(which) {
|
||||
this.operating_point = undefined; // remove annotations
|
||||
|
||||
for (var i = this.components.length - 1; i >= 0; --i)
|
||||
if (i != which) this.components[i].set_select(false);
|
||||
}
|
||||
|
||||
Schematic.prototype.drag_begin = function() {
|
||||
// let components know they're about to move
|
||||
for (var i = this.components.length - 1; i >= 0; --i) {
|
||||
var component = this.components[i];
|
||||
if (component.selected) component.move_begin();
|
||||
}
|
||||
|
||||
// remember where drag started
|
||||
this.drag_x = this.cursor_x;
|
||||
this.drag_y = this.cursor_y;
|
||||
this.dragging = true;
|
||||
}
|
||||
|
||||
Schematic.prototype.drag_end = function() {
|
||||
// let components know they're done moving
|
||||
for (var i = this.components.length - 1; i >= 0; --i) {
|
||||
var component = this.components[i];
|
||||
if (component.selected) component.move_end();
|
||||
}
|
||||
this.dragging = false;
|
||||
|
||||
this.clean_up_wires();
|
||||
this.redraw_background();
|
||||
}
|
||||
|
||||
Schematic.prototype.help = function() {
|
||||
window.open('/static/handouts/schematic_tutorial.pdf');
|
||||
}
|
||||
|
||||
// zoom diagram around current center point
|
||||
Schematic.prototype.rescale = function(nscale) {
|
||||
var cx = this.origin_x + this.width/(2*this.scale);
|
||||
var cy = this.origin_y + this.height/(2*this.scale);
|
||||
|
||||
this.scale = nscale;
|
||||
|
||||
this.origin_x = cx - this.width/(2*this.scale);
|
||||
this.origin_y = cy - this.height/(2*this.scale);
|
||||
|
||||
this.redraw_background();
|
||||
}
|
||||
|
||||
Schematic.prototype.zoomin = function() {
|
||||
this.rescale(this.scale * 1.5);
|
||||
}
|
||||
|
||||
Schematic.prototype.zoomout = function() {
|
||||
this.rescale(this.scale / 1.5);
|
||||
}
|
||||
|
||||
Schematic.prototype.zoomall = function() {
|
||||
// w,h for schematic
|
||||
var sch_w = this.bbox[2] - this.bbox[0];
|
||||
var sch_h = this.bbox[3] - this.bbox[1];
|
||||
|
||||
// compute scales that would make schematic fit, choose smallest
|
||||
var scale_x = this.width/sch_w;
|
||||
var scale_y = this.height/sch_h;
|
||||
this.scale = Math.min(scale_x,scale_y);
|
||||
|
||||
// center the schematic
|
||||
var cx = (this.bbox[2] + this.bbox[0])/2;
|
||||
var cy = (this.bbox[3] + this.bbox[1])/2;
|
||||
this.origin_x = cx - this.width/(2*this.scale);
|
||||
this.origin_y = cy - this.height/(2*this.scale);
|
||||
|
||||
this.redraw_background();
|
||||
}
|
||||
|
||||
Schematic.prototype.cut = function() {
|
||||
// clear previous contents
|
||||
sch_clipboard = [];
|
||||
|
||||
// look for selected components, move them to clipboard.
|
||||
for (var i = this.components.length - 1; i >=0; --i) {
|
||||
var c = this.components[i];
|
||||
if (c.selected) {
|
||||
c.remove();
|
||||
sch_clipboard.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
// update diagram view
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
Schematic.prototype.copy = function() {
|
||||
// clear previous contents
|
||||
sch_clipboard = [];
|
||||
|
||||
// look for selected components, copy them to clipboard.
|
||||
for (var i = this.components.length - 1; i >=0; --i) {
|
||||
var c = this.components[i];
|
||||
if (c.selected)
|
||||
sch_clipboard.push(c.clone(c.x,c.y));
|
||||
}
|
||||
}
|
||||
|
||||
Schematic.prototype.paste = function() {
|
||||
// compute left,top of bounding box for origins of
|
||||
// components in the clipboard
|
||||
var left = undefined;
|
||||
var top = undefined;
|
||||
for (var i = sch_clipboard.length - 1; i >= 0; --i) {
|
||||
var c = sch_clipboard[i];
|
||||
left = left ? Math.min(left,c.x) : c.x;
|
||||
top = top ? Math.min(top,c.y) : c.y;
|
||||
}
|
||||
|
||||
this.message('cursor '+this.cursor_x+','+this.cursor_y);
|
||||
|
||||
// clear current selections
|
||||
this.unselect_all(-1);
|
||||
this.redraw_background(); // so we see any components that got unselected
|
||||
|
||||
// make clones of components on the clipboard, positioning
|
||||
// them relative to the cursor
|
||||
for (var i = sch_clipboard.length - 1; i >= 0; --i) {
|
||||
var c = sch_clipboard[i];
|
||||
var new_c = c.clone(this.cursor_x + (c.x - left),this.cursor_y + (c.y - top));
|
||||
new_c.set_select(true);
|
||||
new_c.add(this);
|
||||
}
|
||||
|
||||
// see what we've wrought
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Netlist and Simulation interface
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// load diagram from JSON representation
|
||||
Schematic.prototype.load_schematic = function(value,initial_value) {
|
||||
// use default value if no schematic info in value
|
||||
if (value == undefined || value.indexOf('[') == -1)
|
||||
value = initial_value;
|
||||
|
||||
if (value && value.indexOf('[') != -1) {
|
||||
// convert string value into data structure
|
||||
var json = JSON.parse(value);
|
||||
|
||||
// top level is a list of components
|
||||
for (var i = json.length - 1; i >= 0; --i) {
|
||||
var c = json[i];
|
||||
if (c[0] == 'view') {
|
||||
// special hack: view component lets us recreate view
|
||||
this.origin_x = c[1];
|
||||
this.origin_y = c[2];
|
||||
this.scale = c[3];
|
||||
//this.ac_npts = c[4];
|
||||
this.ac_fstart = c[5];
|
||||
this.ac_fstop = c[6];
|
||||
this.ac_source_name = c[7];
|
||||
this.tran_npts = c[8];
|
||||
this.tran_tstop = c[9];
|
||||
this.dc_max_iters = c[10];
|
||||
} else if (c[0] == 'w') {
|
||||
// wire
|
||||
this.add_wire(c[1][0],c[1][1],c[1][2],c[1][3]);
|
||||
} else if (c[0] == 'dc') {
|
||||
this.dc_results = c[1];
|
||||
} else if (c[0] == 'transient') {
|
||||
this.transient_results = c[1];
|
||||
} else if (c[0] == 'ac') {
|
||||
this.ac_results = c[1];
|
||||
} else {
|
||||
// ordinary component
|
||||
// c := [type, coords, properties, connections]
|
||||
var type = c[0];
|
||||
var coords = c[1];
|
||||
var properties = c[2];
|
||||
|
||||
// make the part
|
||||
var part = new parts_map[type][0](coords[0],coords[1],coords[2]);
|
||||
|
||||
// give it its properties
|
||||
for (var name in properties)
|
||||
part.properties[name] = properties[name];
|
||||
|
||||
// add component to the diagram
|
||||
part.add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// see what we've got!
|
||||
this.redraw_background();
|
||||
}
|
||||
|
||||
// label all the nodes in the circuit
|
||||
Schematic.prototype.label_connection_points = function() {
|
||||
// start by clearing all the connection point labels
|
||||
for (var i = this.components.length - 1; i >=0; --i)
|
||||
this.components[i].clear_labels();
|
||||
|
||||
// components are in charge of labeling their unlabeled connections.
|
||||
// labels given to connection points will propagate to coincident connection
|
||||
// points and across Wires.
|
||||
|
||||
// let special components like GND label their connection(s)
|
||||
for (var i = this.components.length - 1; i >=0; --i)
|
||||
this.components[i].add_default_labels();
|
||||
|
||||
// now have components generate labels for unlabeled connections
|
||||
this.next_label = 0;
|
||||
for (var i = this.components.length - 1; i >=0; --i)
|
||||
this.components[i].label_connections();
|
||||
}
|
||||
|
||||
// generate a new label
|
||||
Schematic.prototype.get_next_label = function() {
|
||||
// generate next label in sequence
|
||||
this.next_label += 1;
|
||||
return this.next_label.toString();
|
||||
}
|
||||
|
||||
// propagate label to coincident connection points
|
||||
Schematic.prototype.propagate_label = function(label,location) {
|
||||
var cplist = this.connection_points[location];
|
||||
for (var i = cplist.length - 1; i >= 0; --i)
|
||||
cplist[i].propagate_label(label);
|
||||
}
|
||||
|
||||
// update the value field of our corresponding input field with JSON
|
||||
// representation of schematic
|
||||
Schematic.prototype.update_value = function() {
|
||||
// label connection points
|
||||
this.label_connection_points();
|
||||
|
||||
// build JSON data structure, convert to string value for
|
||||
// input field
|
||||
this.input.value = JSON.stringify(this.json_with_analyses());
|
||||
}
|
||||
|
||||
// produce a JSON representation of the diagram
|
||||
Schematic.prototype.json = function() {
|
||||
var json = [];
|
||||
|
||||
// output all the components/wires in the diagram
|
||||
var n = this.components.length;
|
||||
for (var i = 0; i < n; i++)
|
||||
json.push(this.components[i].json(i));
|
||||
|
||||
// capture the current view parameters
|
||||
json.push(['view',this.origin_x,this.origin_y,this.scale,
|
||||
this.ac_npts,this.ac_fstart,this.ac_fstop,
|
||||
this.ac_source_name,this.tran_npts,this.tran_tstop,
|
||||
this.dc_max_iters]);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
// produce a JSON representation of the diagram
|
||||
Schematic.prototype.json_with_analyses = function() {
|
||||
var json = this.json();
|
||||
|
||||
if (this.dc_results != undefined) json.push(['dc',this.dc_results]);
|
||||
if (this.ac_results != undefined) json.push(['ac',this.ac_results]);
|
||||
if (this.transient_results != undefined) json.push(['transient',this.transient_results]);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Simulation interface
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Schematic.prototype.extract_circuit = function() {
|
||||
// give all the circuit nodes a name, extract netlist
|
||||
this.label_connection_points();
|
||||
var netlist = this.json();
|
||||
|
||||
// since we've done the heavy lifting, update input field value
|
||||
// so user can grab diagram if they want
|
||||
this.input.value = JSON.stringify(netlist);
|
||||
|
||||
// create a circuit from the netlist
|
||||
var ckt = new cktsim.Circuit();
|
||||
if (ckt.load_netlist(netlist))
|
||||
return ckt;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
Schematic.prototype.dc_analysis = function() {
|
||||
// remove any previous annotations
|
||||
this.unselect_all(-1);
|
||||
this.redraw_background();
|
||||
|
||||
var ckt = this.extract_circuit();
|
||||
if (ckt === null) return;
|
||||
|
||||
// run the analysis
|
||||
this.operating_point = ckt.dc();
|
||||
|
||||
if (this.operating_point != undefined) {
|
||||
// save a copy of the results for submission
|
||||
this.dc_results = {};
|
||||
for (var i in this.operating_point) this.dc_results[i] = this.operating_point[i];
|
||||
|
||||
// display results on diagram
|
||||
this.redraw();
|
||||
}
|
||||
}
|
||||
|
||||
// return a list of [color,node_label,offset,type] for each probe in the diagram
|
||||
// type == 'voltage' or 'current'
|
||||
Schematic.prototype.find_probes = function() {
|
||||
var result = [];
|
||||
var result = [];
|
||||
for (var i = this.components.length - 1; i >= 0; --i) {
|
||||
var c = this.components[i];
|
||||
var info = c.probe_info();
|
||||
if (info != undefined) result.push(c.probe_info());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// use a dialog to get AC analysis parameters
|
||||
Schematic.prototype.setup_ac_analysis = function() {
|
||||
this.unselect_all(-1);
|
||||
this.redraw_background();
|
||||
|
||||
var npts_lbl = 'Number of points/decade';
|
||||
var fstart_lbl = 'Starting frequency (Hz)';
|
||||
var fstop_lbl = 'Ending frequency (Hz)';
|
||||
var source_name_lbl = 'Name of V or I source for ac'
|
||||
|
||||
if (this.find_probes().length == 0) {
|
||||
alert("AC Analysis: there are no voltage probes in the diagram!");
|
||||
return;
|
||||
}
|
||||
|
||||
var fields = new Array();
|
||||
//fields[npts_lbl] = build_input('text',10,this.ac_npts);
|
||||
fields[fstart_lbl] = build_input('text',10,this.ac_fstart);
|
||||
fields[fstop_lbl] = build_input('text',10,this.ac_fstop);
|
||||
fields[source_name_lbl] = build_input('text',10,this.ac_source_name);
|
||||
|
||||
var content = build_table(fields);
|
||||
content.fields = fields;
|
||||
content.sch = this;
|
||||
|
||||
this.dialog('AC Analysis',content,function(content) {
|
||||
var sch = content.sch;
|
||||
|
||||
// retrieve parameters, remember for next time
|
||||
//sch.ac_npts = content.fields[npts_lbl].value;
|
||||
sch.ac_fstart = content.fields[fstart_lbl].value;
|
||||
sch.ac_fstop = content.fields[fstop_lbl].value;
|
||||
sch.ac_source_name = content.fields[source_name_lbl].value;
|
||||
|
||||
sch.ac_analysis(cktsim.parse_number(sch.ac_npts),
|
||||
cktsim.parse_number(sch.ac_fstart),
|
||||
cktsim.parse_number(sch.ac_fstop),
|
||||
sch.ac_source_name);
|
||||
});
|
||||
}
|
||||
|
||||
// perform ac analysis
|
||||
Schematic.prototype.ac_analysis = function(npts,fstart,fstop,ac_source_name) {
|
||||
// run the analysis
|
||||
var ckt = this.extract_circuit();
|
||||
if (ckt === null) return;
|
||||
var results = ckt.ac(npts,fstart,fstop,ac_source_name);
|
||||
|
||||
if (typeof results == 'string')
|
||||
this.message(results);
|
||||
else {
|
||||
var x_values = results['_frequencies_'];
|
||||
|
||||
// x axis will be a log scale
|
||||
for (var i = x_values.length - 1; i >= 0; --i)
|
||||
x_values[i] = Math.log(x_values[i])/Math.LN10;
|
||||
|
||||
|
||||
if (this.submit_analyses != undefined) {
|
||||
var submit = this.submit_analyses['ac'];
|
||||
if (submit != undefined) {
|
||||
// save a copy of the results for submission
|
||||
this.ac_results = {};
|
||||
|
||||
// save requested values for each requested node
|
||||
for (var j = 0; j < submit.length; j++) {
|
||||
var flist = submit[j]; // [node_name,f1,f2,...]
|
||||
var node = flist[0];
|
||||
var values = results[node];
|
||||
var fvlist = [];
|
||||
// for each requested freq, interpolate response value
|
||||
for (var k = 1; k < flist.length; k++) {
|
||||
var f = flist[k];
|
||||
var v = interpolate(f,x_values,values);
|
||||
// convert to dB
|
||||
fvlist.push([f,v == undefined ? 'undefined' : 20.0 * Math.log(v)/Math.LN10]);
|
||||
}
|
||||
// save results as list of [f,response] paris
|
||||
this.ac_results[node] = fvlist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set up plot values for each node with a probe
|
||||
var y_values = []; // list of [color, result_array]
|
||||
var z_values = []; // list of [color, result_array]
|
||||
var probes = this.find_probes();
|
||||
|
||||
var probe_maxv = [];
|
||||
var probe_color = [];
|
||||
|
||||
// Check for probe with near zero transfer function and warn
|
||||
for (var i = probes.length - 1; i >= 0; --i) {
|
||||
if (probes[i][3] != 'voltage') continue;
|
||||
probe_color[i] = probes[i][0];
|
||||
var label = probes[i][1];
|
||||
var v = results[label];
|
||||
probe_maxv[i] = array_max(v); // magnitudes always > 0
|
||||
}
|
||||
var all_max = array_max(probe_maxv);
|
||||
|
||||
if (all_max < 1.0e-16) {
|
||||
alert('Zero ac response, -infinity on DB scale.');
|
||||
} else {
|
||||
for (var i = probes.length - 1; i >= 0; --i) {
|
||||
if (probes[i][3] != 'voltage') continue;
|
||||
if ((probe_maxv[i] / all_max) < 1.0e-10) {
|
||||
alert('Near zero ac response, remove ' + probe_color[i] + ' probe');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = probes.length - 1; i >= 0; --i) {
|
||||
if (probes[i][3] != 'voltage') continue;
|
||||
var color = probes[i][0];
|
||||
var label = probes[i][1];
|
||||
var offset = cktsim.parse_number(probes[i][2]);
|
||||
|
||||
var v = results[label];
|
||||
// convert values into dB relative to source amplitude
|
||||
var v_max = 1;
|
||||
for (var j = v.length - 1; j >= 0; --j)
|
||||
// convert each value to dB relative to max
|
||||
v[j] = 20.0 * Math.log(v[j]/v_max)/Math.LN10;
|
||||
y_values.push([color,offset,v]);
|
||||
|
||||
var v = results[label+'_phase'];
|
||||
z_values.push([color,0,v]);
|
||||
}
|
||||
|
||||
// graph the result and display in a window
|
||||
var graph2 = this.graph(x_values,'log(Frequency in Hz)',z_values,'degrees');
|
||||
this.window('AC Analysis - Phase',graph2);
|
||||
var graph1 = this.graph(x_values,'log(Frequency in Hz)',y_values,'dB');
|
||||
this.window('AC Analysis - Magnitude',graph1,50);
|
||||
}
|
||||
}
|
||||
|
||||
Schematic.prototype.transient_analysis = function() {
|
||||
this.unselect_all(-1);
|
||||
this.redraw_background();
|
||||
|
||||
var npts_lbl = 'Minimum number of timepoints';
|
||||
var tstop_lbl = 'Stop Time (seconds)';
|
||||
|
||||
var probes = this.find_probes();
|
||||
if (probes.length == 0) {
|
||||
alert("Transient Analysis: there are no probes in the diagram!");
|
||||
return;
|
||||
}
|
||||
|
||||
var fields = new Array();
|
||||
//fields[npts_lbl] = build_input('text',10,this.tran_npts);
|
||||
fields[tstop_lbl] = build_input('text',10,this.tran_tstop);
|
||||
|
||||
var content = build_table(fields);
|
||||
content.fields = fields;
|
||||
content.sch = this;
|
||||
|
||||
this.dialog('Transient Analysis',content,function(content) {
|
||||
var sch = content.sch;
|
||||
var ckt = sch.extract_circuit();
|
||||
if (ckt === null) return;
|
||||
|
||||
// retrieve parameters, remember for next time
|
||||
//sch.tran_npts = content.fields[npts_lbl].value;
|
||||
sch.tran_tstop = content.fields[tstop_lbl].value;
|
||||
|
||||
// gather a list of nodes that are being probed. These
|
||||
// will be added to the list of nodes checked during the
|
||||
// LTE calculations in transient analysis
|
||||
var probe_list = sch.find_probes();
|
||||
var probe_names = new Array(probe_list.length);
|
||||
for (var i = probe_list.length - 1; i >= 0; --i)
|
||||
probe_names[i] = probe_list[i][1];
|
||||
|
||||
// run the analysis
|
||||
var results = ckt.tran(ckt.parse_number(sch.tran_npts), 0,
|
||||
ckt.parse_number(sch.tran_tstop), probe_names, false);
|
||||
|
||||
if (typeof results == 'string')
|
||||
sch.message(results);
|
||||
else {
|
||||
if (sch.submit_analyses != undefined) {
|
||||
var submit = sch.submit_analyses['tran'];
|
||||
if (submit != undefined) {
|
||||
// save a copy of the results for submission
|
||||
sch.transient_results = {};
|
||||
var times = results['_time_'];
|
||||
|
||||
// save requested values for each requested node
|
||||
for (var j = 0; j < submit.length; j++) {
|
||||
var tlist = submit[j]; // [node_name,t1,t2,...]
|
||||
var node = tlist[0];
|
||||
var values = results[node];
|
||||
var tvlist = [];
|
||||
// for each requested time, interpolate waveform value
|
||||
for (var k = 1; k < tlist.length; k++) {
|
||||
var t = tlist[k];
|
||||
var v = interpolate(t,times,values);
|
||||
tvlist.push([t,v == undefined ? 'undefined' : v]);
|
||||
}
|
||||
// save results as list of [t,value] pairs
|
||||
sch.transient_results[node] = tvlist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var x_values = results['_time_'];
|
||||
var x_legend = 'Time';
|
||||
|
||||
// set up plot values for each node with a probe
|
||||
var v_values = []; // voltage values: list of [color, result_array]
|
||||
var i_values = []; // current values: list of [color, result_array]
|
||||
var probes = sch.find_probes();
|
||||
|
||||
for (var i = probes.length - 1; i >= 0; --i) {
|
||||
var color = probes[i][0];
|
||||
var label = probes[i][1];
|
||||
var offset = cktsim.parse_number(probes[i][2]);
|
||||
var v = results[label];
|
||||
if (v == undefined) {
|
||||
alert('The ' + color + ' probe is connected to node ' + '"' + label + '"' + ' which is not an actual circuit node');
|
||||
} else if (probes[i][3] == 'voltage') {
|
||||
if (color == 'x-axis') {
|
||||
x_values = v;
|
||||
x_legend = 'Voltage';
|
||||
} else v_values.push([color,offset,v]);
|
||||
} else {
|
||||
if (color == 'x-axis') {
|
||||
x_values = v;
|
||||
x_legend = 'Current';
|
||||
} else i_values.push([color,offset,v]);
|
||||
}
|
||||
}
|
||||
|
||||
// graph the result and display in a window
|
||||
var graph = sch.graph(x_values,x_legend,v_values,'Voltage',i_values,'Current');
|
||||
sch.window('Results of Transient Analysis',graph);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// t is the time at which we want a value
|
||||
// times is a list of timepoints from the simulation
|
||||
function interpolate(t,times,values) {
|
||||
if (values == undefined) return undefined;
|
||||
|
||||
for (var i = 0; i < times.length; i++)
|
||||
if (t < times[i]) {
|
||||
// t falls between times[i-1] and times[i]
|
||||
var t1 = (i == 0) ? times[0] : times[i-1];
|
||||
var t2 = times[i];
|
||||
|
||||
if (t2 == undefined) return undefined;
|
||||
|
||||
var v1 = (i == 0) ? values[0] : values[i-1];
|
||||
var v2 = values[i];
|
||||
var v = v1;
|
||||
if (t != t1) v += (t - t1)*(v2 - v1)/(t2 - t1);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
// external interface for setting the property value of a named component
|
||||
Schematic.prototype.set_property = function(component_name,property,value) {
|
||||
this.unselect_all(-1);
|
||||
|
||||
for (var i = this.components.length - 1; i >= 0; --i) {
|
||||
var component = this.components[i];
|
||||
if (component.properties['name'] == component_name) {
|
||||
component.properties[property] = value.toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// update diagram
|
||||
this.redraw_background();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Drawing support -- deals with scaling and scrolling of diagrama
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// here to redraw background image containing static portions of the schematic.
|
||||
// Also redraws dynamic portion.
|
||||
Schematic.prototype.redraw_background = function() {
|
||||
var c = this.bg_image.getContext('2d');
|
||||
|
||||
c.lineCap = 'round';
|
||||
|
||||
// paint background color
|
||||
c.fillStyle = element_style;
|
||||
c.fillRect(0,0,this.width,this.height);
|
||||
|
||||
if (!this.diagram_only) {
|
||||
// grid
|
||||
c.strokeStyle = grid_style;
|
||||
var first_x = this.origin_x;
|
||||
var last_x = first_x + this.width/this.scale;
|
||||
var first_y = this.origin_y;
|
||||
var last_y = first_y + this.height/this.scale;
|
||||
|
||||
for (var i = this.grid*Math.ceil(first_x/this.grid); i < last_x; i += this.grid)
|
||||
this.draw_line(c,i,first_y,i,last_y,0.1);
|
||||
|
||||
for (var i = this.grid*Math.ceil(first_y/this.grid); i < last_y; i += this.grid)
|
||||
this.draw_line(c,first_x,i,last_x,i,0.1);
|
||||
}
|
||||
|
||||
// unselected components
|
||||
var min_x = Infinity; // compute bounding box for diagram
|
||||
var max_x = -Infinity;
|
||||
var min_y = Infinity;
|
||||
var max_y = -Infinity;
|
||||
for (var i = this.components.length - 1; i >= 0; --i) {
|
||||
var component = this.components[i];
|
||||
if (!component.selected) {
|
||||
component.draw(c);
|
||||
min_x = Math.min(component.bbox[0],min_x);
|
||||
max_x = Math.max(component.bbox[2],max_x);
|
||||
min_y = Math.min(component.bbox[1],min_y);
|
||||
max_y = Math.max(component.bbox[3],max_y);
|
||||
}
|
||||
}
|
||||
this.unsel_bbox = [min_x,min_y,max_x,max_y];
|
||||
|
||||
this.redraw(); // background changed, redraw on screen
|
||||
}
|
||||
|
||||
// redraw what user sees = static image + dynamic parts
|
||||
Schematic.prototype.redraw = function() {
|
||||
var c = this.canvas.getContext('2d');
|
||||
|
||||
// put static image in the background
|
||||
c.drawImage(this.bg_image, 0, 0);
|
||||
|
||||
// selected components
|
||||
var min_x = this.unsel_bbox[0]; // compute bounding box for diagram
|
||||
var max_x = this.unsel_bbox[2];
|
||||
var min_y = this.unsel_bbox[1];
|
||||
var max_y = this.unsel_bbox[3];
|
||||
var selections = false;
|
||||
for (var i = this.components.length - 1; i >= 0; --i) {
|
||||
var component = this.components[i];
|
||||
if (component.selected) {
|
||||
component.draw(c);
|
||||
selections = true;
|
||||
min_x = Math.min(component.bbox[0],min_x);
|
||||
max_x = Math.max(component.bbox[2],max_x);
|
||||
min_y = Math.min(component.bbox[1],min_y);
|
||||
max_y = Math.max(component.bbox[3],max_y);
|
||||
}
|
||||
}
|
||||
this.enable_tool('cut',selections);
|
||||
this.enable_tool('copy',selections);
|
||||
this.enable_tool('paste',sch_clipboard.length > 0);
|
||||
|
||||
// include a margin for diagram bounding box
|
||||
var dx = (max_x - min_x)/4;
|
||||
var dy = (max_y - min_y)/4;
|
||||
this.bbox = [min_x - dx,min_y - dy,max_x + dx,max_y + dy];
|
||||
|
||||
// connection points: draw one at each location
|
||||
for (var location in this.connection_points) {
|
||||
var cplist = this.connection_points[location];
|
||||
cplist[0].draw(c,cplist.length);
|
||||
}
|
||||
|
||||
// draw new wire
|
||||
if (this.wire) {
|
||||
var r = this.wire;
|
||||
c.strokeStyle = selected_style;
|
||||
this.draw_line(c,r[0],r[1],r[2],r[3],1);
|
||||
}
|
||||
|
||||
// draw selection rectangle
|
||||
if (this.select_rect) {
|
||||
var r = this.select_rect;
|
||||
c.lineWidth = 1;
|
||||
c.strokeStyle = selected_style;
|
||||
c.beginPath();
|
||||
c.moveTo(r[0],r[1]);
|
||||
c.lineTo(r[0],r[3]);
|
||||
c.lineTo(r[2],r[3]);
|
||||
c.lineTo(r[2],r[1]);
|
||||
c.lineTo(r[0],r[1]);
|
||||
c.stroke();
|
||||
}
|
||||
|
||||
// display operating point results
|
||||
if (this.operating_point) {
|
||||
if (typeof this.operating_point == 'string')
|
||||
this.message(this.operating_point);
|
||||
else {
|
||||
// make a copy of the operating_point info so we can mess with it
|
||||
var temp = new Array();
|
||||
for (var i in this.operating_point) temp[i] = this.operating_point[i];
|
||||
|
||||
// run through connection points displaying (once) the voltage
|
||||
// for each electrical node
|
||||
for (var location in this.connection_points)
|
||||
(this.connection_points[location])[0].display_voltage(c,temp);
|
||||
|
||||
// let components display branch current info if available
|
||||
for (var i = this.components.length - 1; i >= 0; --i)
|
||||
this.components[i].display_current(c,temp)
|
||||
}
|
||||
}
|
||||
|
||||
// finally overlay cursor
|
||||
if (this.drawCursor && this.draw_cursor) {
|
||||
//var x = this.cursor_x;
|
||||
//var y = this.cursor_y;
|
||||
//this.draw_text(c,'('+x+','+y+')',x+this.grid,y-this.grid,10);
|
||||
this.draw_cursor(c,this.cursor_x,this.cursor_y);
|
||||
}
|
||||
}
|
||||
|
||||
// draws a cross cursor
|
||||
Schematic.prototype.cross_cursor = function(c,x,y) {
|
||||
this.draw_line(c,x-this.grid,y,x+this.grid,y,1);
|
||||
this.draw_line(c,x,y-this.grid,x,y+this.grid,1);
|
||||
}
|
||||
|
||||
Schematic.prototype.moveTo = function(c,x,y) {
|
||||
c.moveTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale);
|
||||
}
|
||||
|
||||
Schematic.prototype.lineTo = function(c,x,y) {
|
||||
c.lineTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale);
|
||||
}
|
||||
|
||||
Schematic.prototype.draw_line = function(c,x1,y1,x2,y2,width) {
|
||||
c.lineWidth = width*this.scale;
|
||||
c.beginPath();
|
||||
c.moveTo((x1 - this.origin_x) * this.scale,(y1 - this.origin_y) * this.scale);
|
||||
c.lineTo((x2 - this.origin_x) * this.scale,(y2 - this.origin_y) * this.scale);
|
||||
c.stroke();
|
||||
}
|
||||
|
||||
Schematic.prototype.draw_arc = function(c,x,y,radius,start_radians,end_radians,anticlockwise,width,filled) {
|
||||
c.lineWidth = width*this.scale;
|
||||
c.beginPath();
|
||||
c.arc((x - this.origin_x)*this.scale,(y - this.origin_y)*this.scale,radius*this.scale,
|
||||
start_radians,end_radians,anticlockwise);
|
||||
if (filled) c.fill();
|
||||
else c.stroke();
|
||||
}
|
||||
|
||||
Schematic.prototype.draw_text = function(c,text,x,y,size) {
|
||||
c.font = size*this.scale+'pt sans-serif'
|
||||
c.fillText(text,(x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale);
|
||||
}
|
||||
|
||||
// add method to canvas to compute relative coords for event
|
||||
HTMLCanvasElement.prototype.relMouseCoords = function(event){
|
||||
// run up the DOM tree to figure out coords for top,left of canvas
|
||||
var totalOffsetX = 0;
|
||||
var totalOffsetY = 0;
|
||||
var currentElement = this;
|
||||
do {
|
||||
totalOffsetX += currentElement.offsetLeft;
|
||||
totalOffsetY += currentElement.offsetTop;
|
||||
}
|
||||
while (currentElement = currentElement.offsetParent);
|
||||
|
||||
// now compute relative position of click within the canvas
|
||||
this.mouse_x = event.pageX - totalOffsetX;
|
||||
this.mouse_y = event.pageY - totalOffsetY;
|
||||
|
||||
this.page_x = event.pageX;
|
||||
this.page_y = event.pageY;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Event handling
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// process keystrokes, consuming those that are meaningful to us
|
||||
function schematic_key_down(event) {
|
||||
if (!event) event = window.event;
|
||||
var sch = (window.event) ? event.srcElement.schematic : event.target.schematic;
|
||||
var code = event.keyCode;
|
||||
|
||||
// keep track of modifier key state
|
||||
if (code == 16) sch.shiftKey = true;
|
||||
else if (code == 17) sch.ctrlKey = true;
|
||||
else if (code == 18) sch.altKey = true;
|
||||
else if (code == 91) sch.cmdKey = true;
|
||||
|
||||
// backspace or delete: delete selected components
|
||||
else if (code == 8 || code == 46) {
|
||||
// delete selected components
|
||||
for (var i = sch.components.length - 1; i >= 0; --i) {
|
||||
var component = sch.components[i];
|
||||
if (component.selected) component.remove();
|
||||
}
|
||||
sch.clean_up_wires();
|
||||
sch.redraw_background();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// cmd/ctrl x: cut
|
||||
else if ((sch.ctrlKey || sch.cmdKey) && code == 88) {
|
||||
sch.cut();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// cmd/ctrl c: copy
|
||||
else if ((sch.ctrlKey || sch.cmdKey) && code == 67) {
|
||||
sch.copy();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// cmd/ctrl v: paste
|
||||
else if ((sch.ctrlKey || sch.cmdKey) && code == 86) {
|
||||
sch.paste();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 'r': rotate component
|
||||
else if (!sch.ctrlKey && !sch.altKey && !sch.cmdKey && code == 82) {
|
||||
// rotate
|
||||
for (var i = sch.components.length - 1; i >= 0; --i) {
|
||||
var component = sch.components[i];
|
||||
if (component.selected) {
|
||||
component.rotate(1);
|
||||
sch.check_wires(component);
|
||||
}
|
||||
}
|
||||
sch.clean_up_wires();
|
||||
sch.redraw_background();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
else return true;
|
||||
|
||||
// consume keystroke
|
||||
sch.redraw();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
function schematic_key_up(event) {
|
||||
if (!event) event = window.event;
|
||||
var sch = (window.event) ? event.srcElement.schematic : event.target.schematic;
|
||||
var code = event.keyCode;
|
||||
|
||||
if (code == 16) sch.shiftKey = false;
|
||||
else if (code == 17) sch.ctrlKey = false;
|
||||
else if (code == 18) sch.altKey = false;
|
||||
else if (code == 91) sch.cmdKey = false;
|
||||
}
|
||||
|
||||
function schematic_mouse_enter(event) {
|
||||
if (!event) event = window.event;
|
||||
var sch = (window.event) ? event.srcElement.schematic : event.target.schematic;
|
||||
|
||||
// see if user has selected a new part
|
||||
if (sch.new_part) {
|
||||
// grab incoming part, turn off selection of parts bin
|
||||
var part = sch.new_part;
|
||||
sch.new_part = undefined;
|
||||
part.select(false);
|
||||
|
||||
// unselect everything else in the schematic, add part and select it
|
||||
sch.unselect_all(-1);
|
||||
sch.redraw_background(); // so we see any components that got unselected
|
||||
|
||||
// make a clone of the component in the parts bin
|
||||
part = part.component.clone(sch.cursor_x,sch.cursor_y);
|
||||
part.add(sch); // add it to schematic
|
||||
part.set_select(true);
|
||||
|
||||
// and start dragging it
|
||||
sch.drag_begin();
|
||||
}
|
||||
|
||||
sch.drawCursor = true;
|
||||
sch.redraw();
|
||||
sch.canvas.focus(); // capture key strokes
|
||||
return false;
|
||||
}
|
||||
|
||||
function schematic_mouse_leave(event) {
|
||||
if (!event) event = window.event;
|
||||
var sch = (window.event) ? event.srcElement.schematic : event.target.schematic;
|
||||
sch.drawCursor = false;
|
||||
sch.redraw();
|
||||
return false;
|
||||
}
|
||||
|
||||
function schematic_mouse_down(event) {
|
||||
if (!event) event = window.event;
|
||||
else event.preventDefault();
|
||||
var sch = (window.event) ? event.srcElement.schematic : event.target.schematic;
|
||||
|
||||
// determine where event happened in schematic coordinates
|
||||
sch.canvas.relMouseCoords(event);
|
||||
var x = sch.canvas.mouse_x/sch.scale + sch.origin_x;
|
||||
var y = sch.canvas.mouse_y/sch.scale + sch.origin_y;
|
||||
sch.cursor_x = Math.round(x/sch.grid) * sch.grid;
|
||||
sch.cursor_y = Math.round(y/sch.grid) * sch.grid;
|
||||
|
||||
// is mouse over a connection point? If so, start dragging a wire
|
||||
var cplist = sch.connection_points[sch.cursor_x + ',' + sch.cursor_y];
|
||||
if (cplist && !event.shiftKey) {
|
||||
sch.unselect_all(-1);
|
||||
sch.wire = [sch.cursor_x,sch.cursor_y,sch.cursor_x,sch.cursor_y];
|
||||
} else {
|
||||
// give all components a shot at processing the selection event
|
||||
var which = -1;
|
||||
for (var i = sch.components.length - 1; i >= 0; --i)
|
||||
if (sch.components[i].select(x,y,event.shiftKey)) {
|
||||
if (sch.components[i].selected) {
|
||||
sch.drag_begin();
|
||||
which = i; // keep track of component we found
|
||||
}
|
||||
break;
|
||||
}
|
||||
// did we just click on a previously selected component?
|
||||
var reselect = which!=-1 && sch.components[which].was_previously_selected;
|
||||
|
||||
if (!event.shiftKey) {
|
||||
// if shift key isn't pressed and we didn't click on component
|
||||
// that was already selected, unselect everyone except component
|
||||
// we just clicked on
|
||||
if (!reselect) sch.unselect_all(which);
|
||||
|
||||
// if there's nothing to drag, set up a selection rectangle
|
||||
if (!sch.dragging) sch.select_rect = [sch.canvas.mouse_x,sch.canvas.mouse_y,
|
||||
sch.canvas.mouse_x,sch.canvas.mouse_y];
|
||||
}
|
||||
}
|
||||
|
||||
sch.redraw_background();
|
||||
return false;
|
||||
}
|
||||
|
||||
function schematic_mouse_move(event) {
|
||||
if (!event) event = window.event;
|
||||
var sch = (window.event) ? event.srcElement.schematic : event.target.schematic;
|
||||
|
||||
sch.canvas.relMouseCoords(event);
|
||||
var x = sch.canvas.mouse_x/sch.scale + sch.origin_x;
|
||||
var y = sch.canvas.mouse_y/sch.scale + sch.origin_y;
|
||||
sch.cursor_x = Math.round(x/sch.grid) * sch.grid;
|
||||
sch.cursor_y = Math.round(y/sch.grid) * sch.grid;
|
||||
|
||||
if (sch.wire) {
|
||||
// update new wire end point
|
||||
sch.wire[2] = sch.cursor_x;
|
||||
sch.wire[3] = sch.cursor_y;
|
||||
} else if (sch.dragging) {
|
||||
// see how far we moved
|
||||
var dx = sch.cursor_x - sch.drag_x;
|
||||
var dy = sch.cursor_y - sch.drag_y;
|
||||
if (dx != 0 || dy != 0) {
|
||||
// update position for next time
|
||||
sch.drag_x = sch.cursor_x;
|
||||
sch.drag_y = sch.cursor_y;
|
||||
|
||||
// give all components a shot at processing the event
|
||||
for (var i = sch.components.length - 1; i >= 0; --i) {
|
||||
var component = sch.components[i];
|
||||
if (component.selected) component.move(dx,dy);
|
||||
}
|
||||
}
|
||||
} else if (sch.select_rect) {
|
||||
// update moving corner of selection rectangle
|
||||
sch.select_rect[2] = sch.canvas.mouse_x;
|
||||
sch.select_rect[3] = sch.canvas.mouse_y;
|
||||
//sch.message(sch.select_rect.toString());
|
||||
}
|
||||
|
||||
// just redraw dynamic components
|
||||
sch.redraw();
|
||||
//sch.message(sch.canvas.page_x + ',' + sch.canvas.page_y + ';' + sch.canvas.mouse_x + ',' + sch.canvas.mouse_y + ';' + sch.cursor_x + ',' + sch.cursor_y);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function schematic_mouse_up(event) {
|
||||
if (!event) event = window.event;
|
||||
else event.preventDefault();
|
||||
var sch = (window.event) ? event.srcElement.schematic : event.target.schematic;
|
||||
|
||||
// drawing a new wire
|
||||
if (sch.wire) {
|
||||
var r = sch.wire;
|
||||
sch.wire = undefined;
|
||||
|
||||
if (r[0]!=r[2] || r[1]!=r[3]) {
|
||||
// insert wire component
|
||||
sch.add_wire(r[0],r[1],r[2],r[3]);
|
||||
sch.clean_up_wires();
|
||||
sch.redraw_background();
|
||||
} else sch.redraw();
|
||||
}
|
||||
|
||||
// dragging
|
||||
if (sch.dragging) sch.drag_end();
|
||||
|
||||
// selection rectangle
|
||||
if (sch.select_rect) {
|
||||
var r = sch.select_rect;
|
||||
|
||||
// if select_rect is a point, we've already dealt with selection
|
||||
// in mouse_down handler
|
||||
if (r[0]!=r[2] || r[1]!=r[3]) {
|
||||
// convert to schematic coordinates
|
||||
var s = [r[0]/sch.scale + sch.origin_x, r[1]/sch.scale + sch.origin_y,
|
||||
r[2]/sch.scale + sch.origin_x, r[3]/sch.scale + sch.origin_y];
|
||||
canonicalize(s);
|
||||
|
||||
if (!event.shiftKey) sch.unselect_all();
|
||||
|
||||
// select components that intersect selection rectangle
|
||||
for (var i = sch.components.length - 1; i >= 0; --i)
|
||||
sch.components[i].select_rect(s,event.shiftKey);
|
||||
}
|
||||
|
||||
sch.select_rect = undefined;
|
||||
sch.redraw_background();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function schematic_double_click(event) {
|
||||
if (!event) event = window.event;
|
||||
else event.preventDefault();
|
||||
var sch = (window.event) ? event.srcElement.schematic : event.target.schematic;
|
||||
|
||||
// determine where event happened in schematic coordinates
|
||||
sch.canvas.relMouseCoords(event);
|
||||
var x = sch.canvas.mouse_x/sch.scale + sch.origin_x;
|
||||
var y = sch.canvas.mouse_y/sch.scale + sch.origin_y;
|
||||
sch.cursor_x = Math.round(x/sch.grid) * sch.grid;
|
||||
sch.cursor_y = Math.round(y/sch.grid) * sch.grid;
|
||||
|
||||
// see if we double-clicked a component. If so, edit it's properties
|
||||
for (var i = sch.components.length - 1; i >= 0; --i)
|
||||
if (sch.components[i].edit_properties(x,y))
|
||||
break;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Status message and dialogs
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Schematic.prototype.message = function(message) {
|
||||
this.status.nodeValue = message;
|
||||
}
|
||||
|
||||
Schematic.prototype.append_message = function(message) {
|
||||
this.status.nodeValue += ' / '+message;
|
||||
}
|
||||
|
||||
// set up a dialog with specified title, content and two buttons at
|
||||
// the bottom: OK and Cancel. If Cancel is clicked, dialog goes away
|
||||
// and we're done. If OK is clicked, dialog goes away and the
|
||||
// callback function is called with the content as an argument (so
|
||||
// that the values of any fields can be captured).
|
||||
Schematic.prototype.dialog = function(title,content,callback) {
|
||||
// create the div for the top level of the dialog, add to DOM
|
||||
var dialog = document.createElement('div');
|
||||
dialog.sch = this;
|
||||
dialog.content = content;
|
||||
dialog.callback = callback;
|
||||
|
||||
// look for property input fields in the content and give
|
||||
// them a keypress listener that interprets ENTER as
|
||||
// clicking OK.
|
||||
var plist = content.getElementsByClassName('property');
|
||||
for (var i = plist.length - 1; i >= 0; --i) {
|
||||
var field = plist[i];
|
||||
field.dialog = dialog; // help event handler find us...
|
||||
field.addEventListener('keypress',dialog_check_for_ENTER,false);
|
||||
}
|
||||
|
||||
// div to hold the content
|
||||
var body = document.createElement('div');
|
||||
content.style.marginBotton = '5px';
|
||||
body.appendChild(content);
|
||||
body.style.padding = '5px';
|
||||
dialog.appendChild(body);
|
||||
|
||||
// OK button
|
||||
var ok_button = document.createElement('span');
|
||||
ok_button.appendChild(document.createTextNode('OK'));
|
||||
ok_button.dialog = dialog; // for the handler to use
|
||||
ok_button.addEventListener('click',dialog_okay,false);
|
||||
ok_button.style.display = 'inline';
|
||||
ok_button.style.border = '1px solid';
|
||||
ok_button.style.padding = '5px';
|
||||
ok_button.style.margin = '10px';
|
||||
|
||||
// cancel button
|
||||
var cancel_button = document.createElement('span');
|
||||
cancel_button.appendChild(document.createTextNode('Cancel'));
|
||||
cancel_button.dialog = dialog; // for the handler to use
|
||||
cancel_button.addEventListener('click',dialog_cancel,false);
|
||||
cancel_button.style.display = 'inline';
|
||||
cancel_button.style.border = '1px solid';
|
||||
cancel_button.style.padding = '5px';
|
||||
cancel_button.style.margin = '10px';
|
||||
|
||||
// div to hold the two buttons
|
||||
var buttons = document.createElement('div');
|
||||
buttons.style.textAlign = 'center';
|
||||
buttons.appendChild(ok_button);
|
||||
buttons.appendChild(cancel_button);
|
||||
buttons.style.padding = '5px';
|
||||
buttons.style.margin = '10px';
|
||||
dialog.appendChild(buttons);
|
||||
|
||||
// put into an overlay window
|
||||
this.window(title,dialog);
|
||||
}
|
||||
|
||||
// callback when user click "Cancel" in a dialog
|
||||
function dialog_cancel(event) {
|
||||
if (!event) event = window.event;
|
||||
var dialog = (window.event) ? event.srcElement.dialog : event.target.dialog;
|
||||
|
||||
window_close(dialog.win);
|
||||
}
|
||||
|
||||
// callback when user click "OK" in a dialog
|
||||
function dialog_okay(event) {
|
||||
if (!event) event = window.event;
|
||||
var dialog = (window.event) ? event.srcElement.dialog : event.target.dialog;
|
||||
|
||||
window_close(dialog.win);
|
||||
|
||||
// invoke the callback with the dialog contents as the argument
|
||||
if (dialog.callback) dialog.callback(dialog.content);
|
||||
}
|
||||
|
||||
// callback for keypress in input fields: if user typed ENTER, act
|
||||
// like they clicked OK button.
|
||||
function dialog_check_for_ENTER(event) {
|
||||
var key = (window.event) ? window.event.keyCode : event.keyCode;
|
||||
if (key == 13) dialog_okay(event);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Draggable, resizeable, closeable window
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// build a 2-column HTML table from an associative array (keys as text in
|
||||
// column 1, values in column 2).
|
||||
function build_table(a) {
|
||||
var tbl = document.createElement('table');
|
||||
|
||||
// build a row for each element in associative array
|
||||
for (var i in a) {
|
||||
var label = document.createTextNode(i + ': ');
|
||||
var col1 = document.createElement('td');
|
||||
col1.appendChild(label);
|
||||
var col2 = document.createElement('td');
|
||||
col2.appendChild(a[i]);
|
||||
var row = document.createElement('tr');
|
||||
row.appendChild(col1);
|
||||
row.appendChild(col2);
|
||||
row.style.verticalAlign = 'center';
|
||||
tbl.appendChild(row);
|
||||
}
|
||||
|
||||
return tbl;
|
||||
}
|
||||
|
||||
// build an input field
|
||||
function build_input(type,size,value) {
|
||||
var input = document.createElement('input');
|
||||
input.type = type;
|
||||
input.size = size;
|
||||
input.className = 'property'; // make this easier to find later
|
||||
if (value == undefined) input.value = '';
|
||||
else input.value = value.toString();
|
||||
return input;
|
||||
}
|
||||
|
||||
// build a select widget using the strings found in the options array
|
||||
function build_select(options,selected) {
|
||||
var select = document.createElement('select');
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
var option = document.createElement('option');
|
||||
option.text = options[i];
|
||||
select.add(option);
|
||||
if (options[i] == selected) select.selectedIndex = i;
|
||||
}
|
||||
return select;
|
||||
}
|
||||
|
||||
Schematic.prototype.window = function(title,content,offset) {
|
||||
// create the div for the top level of the window
|
||||
var win = document.createElement('div');
|
||||
win.sch = this;
|
||||
win.content = content;
|
||||
win.drag_x = undefined;
|
||||
win.draw_y = undefined;
|
||||
|
||||
// div to hold the title
|
||||
var head = document.createElement('div');
|
||||
head.style.backgroundColor = 'black';
|
||||
head.style.color = 'white';
|
||||
head.style.textAlign = 'center';
|
||||
head.style.padding = '5px';
|
||||
head.appendChild(document.createTextNode(title));
|
||||
head.win = win;
|
||||
win.head = head;
|
||||
|
||||
var close_button = new Image();
|
||||
close_button.src = close_icon;
|
||||
close_button.style.cssFloat = 'right';
|
||||
close_button.addEventListener('click',window_close_button,false);
|
||||
close_button.win = win;
|
||||
head.appendChild(close_button);
|
||||
|
||||
win.appendChild(head);
|
||||
|
||||
// capture mouse events in title bar
|
||||
head.addEventListener('mousedown',window_mouse_down,false);
|
||||
|
||||
// div to hold the content
|
||||
//var body = document.createElement('div');
|
||||
//body.appendChild(content);
|
||||
win.appendChild(content);
|
||||
content.win = win; // so content can contact us
|
||||
|
||||
// compute location relative to canvas
|
||||
if (offset == undefined) offset = 0;
|
||||
win.left = this.canvas.mouse_x + offset;
|
||||
win.top = this.canvas.mouse_y + offset;
|
||||
|
||||
// add to DOM
|
||||
win.style.background = 'white';
|
||||
//win.style.zIndex = '1000';
|
||||
win.style.position = 'absolute';
|
||||
win.style.left = win.left + 'px';
|
||||
win.style.top = win.top + 'px';
|
||||
win.style.border = '2px solid';
|
||||
|
||||
this.canvas.parentNode.insertBefore(win,this.canvas);
|
||||
bring_to_front(win,true);
|
||||
}
|
||||
|
||||
// adjust zIndex of pop-up window so that it is in front
|
||||
function bring_to_front(win,insert) {
|
||||
var wlist = win.sch.window_list;
|
||||
var i = wlist.indexOf(win);
|
||||
|
||||
// remove from current position (if any) in window list
|
||||
if (i != -1) wlist.splice(i,1);
|
||||
|
||||
// if requested, add to end of window list
|
||||
if (insert) wlist.push(win);
|
||||
|
||||
// adjust all zIndex values
|
||||
for (i = 0; i < wlist.length; i += 1)
|
||||
wlist[i].style.zIndex = 1000 + i;
|
||||
}
|
||||
|
||||
// close the window
|
||||
function window_close(win) {
|
||||
// remove the window from the top-level div of the schematic
|
||||
win.parentNode.removeChild(win);
|
||||
|
||||
// remove from list of pop-up windows
|
||||
bring_to_front(win,false);
|
||||
}
|
||||
|
||||
function window_close_button(event) {
|
||||
if (!event) event = window.event;
|
||||
var src = (window.event) ? event.srcElement : event.target;
|
||||
window_close(src.win);
|
||||
}
|
||||
|
||||
// capture mouse events in title bar of window
|
||||
function window_mouse_down(event) {
|
||||
if (!event) event = window.event;
|
||||
var src = (window.event) ? event.srcElement : event.target;
|
||||
var win = src.win;
|
||||
|
||||
bring_to_front(win,true);
|
||||
|
||||
// add handlers to document so we capture them no matter what
|
||||
document.addEventListener('mousemove',window_mouse_move,false);
|
||||
document.addEventListener('mouseup',window_mouse_up,false);
|
||||
document.tracking_window = win;
|
||||
|
||||
// remember where mouse is so we can compute dx,dy during drag
|
||||
win.drag_x = event.pageX;
|
||||
win.drag_y = event.pageY;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function window_mouse_up(event) {
|
||||
var win = document.tracking_window;
|
||||
|
||||
// show's over folks...
|
||||
document.removeEventListener('mousemove',window_mouse_move,false);
|
||||
document.removeEventListener('mouseup',window_mouse_up,false);
|
||||
document.tracking_window = undefined;
|
||||
win.drag_x = undefined;
|
||||
win.drag_y = undefined;
|
||||
return true; // consume event
|
||||
}
|
||||
|
||||
function window_mouse_move(event) {
|
||||
var win = document.tracking_window;
|
||||
|
||||
if (win.drag_x) {
|
||||
var dx = event.pageX - win.drag_x;
|
||||
var dy = event.pageY - win.drag_y;
|
||||
|
||||
// move the window
|
||||
win.left += dx;
|
||||
win.top += dy;
|
||||
win.style.left = win.left + 'px';
|
||||
win.style.top = win.top + 'px';
|
||||
|
||||
// update reference point
|
||||
win.drag_x += dx;
|
||||
win.drag_y += dy;
|
||||
|
||||
return true; // consume event
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Toolbar
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Schematic.prototype.add_tool = function(icon,tip,callback) {
|
||||
var tool;
|
||||
if (icon.search('data:image') != -1) {
|
||||
tool = document.createElement('img');
|
||||
tool.src = icon;
|
||||
} else {
|
||||
tool = document.createElement('span');
|
||||
tool.style.font = 'small-caps small sans-serif';
|
||||
var label = document.createTextNode(icon);
|
||||
tool.appendChild(label);
|
||||
}
|
||||
|
||||
// decorate tool
|
||||
tool.style.borderWidth = '1px';
|
||||
tool.style.borderStyle = 'solid';
|
||||
tool.style.borderColor = background_style;
|
||||
tool.style.padding = '2px';
|
||||
|
||||
// set up event processing
|
||||
tool.addEventListener('mouseover',tool_enter,false);
|
||||
tool.addEventListener('mouseout',tool_leave,false);
|
||||
tool.addEventListener('click',tool_click,false);
|
||||
|
||||
// add to toolbar
|
||||
tool.sch = this;
|
||||
tool.tip = tip;
|
||||
tool.callback = callback;
|
||||
this.toolbar.push(tool);
|
||||
|
||||
tool.enabled = false;
|
||||
tool.style.opacity = 0.2;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
Schematic.prototype.enable_tool = function(tname,which) {
|
||||
var tool = this.tools[tname];
|
||||
|
||||
if (tool != undefined) {
|
||||
tool.style.opacity = which ? 1.0 : 0.2;
|
||||
tool.enabled = which;
|
||||
|
||||
// if disabling tool, remove border and tip
|
||||
if (!which) {
|
||||
tool.style.borderColor = background_style;
|
||||
tool.sch.message('');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// highlight tool button by turning on border, changing background
|
||||
function tool_enter(event) {
|
||||
if (!event) event = window.event;
|
||||
var tool = (window.event) ? event.srcElement : event.target;
|
||||
|
||||
if (tool.enabled) {
|
||||
tool.style.borderColor = normal_style;
|
||||
tool.sch.message(tool.tip);
|
||||
tool.opacity = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
// unhighlight tool button by turning off border, reverting to normal background
|
||||
function tool_leave(event) {
|
||||
if (!event) event = window.event;
|
||||
var tool = (window.event) ? event.srcElement : event.target;
|
||||
|
||||
if (tool.enabled) {
|
||||
tool.style.borderColor = background_style;
|
||||
tool.sch.message('');
|
||||
}
|
||||
}
|
||||
|
||||
// handle click on a tool
|
||||
function tool_click(event) {
|
||||
if (!event) event = window.event;
|
||||
var tool = (window.event) ? event.srcElement : event.target;
|
||||
|
||||
if (tool.enabled) {
|
||||
tool.sch.canvas.relMouseCoords(event); // so we can position pop-up window correctly
|
||||
tool.callback.call(tool.sch);
|
||||
}
|
||||
}
|
||||
|
||||
help_icon = 'data:image/gif;base64,R0lGODlhEAAQAJEAAAAAAP///wAAAAAAACH5BAkAAAIAIf8LSUNDUkdCRzEwMTL/AAAHqGFwcGwCIAAAbW50clJHQiBYWVogB9kAAgAZAAsAGgALYWNzcEFQUEwAAAAAYXBwbAAAAAAAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1hcHBsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALZGVzYwAAAQgAAABvZHNjbQAAAXgAAAVsY3BydAAABuQAAAA4d3RwdAAABxwAAAAUclhZWgAABzAAAAAUZ1hZWgAAB0QAAAAUYlhZWgAAB1gAAAAUclRSQwAAB2wAAAAOY2hhZAAAB3wAAAAsYlRSQwAAB2wAAAAOZ1RS/0MAAAdsAAAADmRlc2MAAAAAAAAAFEdlbmVyaWMgUkdCIFByb2ZpbGUAAAAAAAAAAAAAABRHZW5lcmljIFJHQiBQcm9maWxlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAB4AAAAMc2tTSwAAACgAAAF4aHJIUgAAACgAAAGgY2FFUwAAACQAAAHIcHRCUgAAACYAAAHsdWtVQQAAACoAAAISZnJGVQAAACgAAAI8emhUVwAAABYAAAJkaXRJVAAAACgAAAJ6bmJOTwAAACYAAAKia29LUgAAABYAAP8CyGNzQ1oAAAAiAAAC3mhlSUwAAAAeAAADAGRlREUAAAAsAAADHmh1SFUAAAAoAAADSnN2U0UAAAAmAAAConpoQ04AAAAWAAADcmphSlAAAAAaAAADiHJvUk8AAAAkAAADomVsR1IAAAAiAAADxnB0UE8AAAAmAAAD6G5sTkwAAAAoAAAEDmVzRVMAAAAmAAAD6HRoVEgAAAAkAAAENnRyVFIAAAAiAAAEWmZpRkkAAAAoAAAEfHBsUEwAAAAsAAAEpHJ1UlUAAAAiAAAE0GFyRUcAAAAmAAAE8mVuVVMAAAAmAAAFGGRhREsAAAAuAAAFPgBWAWEAZQBvAGIAZQD/YwBuAP0AIABSAEcAQgAgAHAAcgBvAGYAaQBsAEcAZQBuAGUAcgBpAQ0AawBpACAAUgBHAEIAIABwAHIAbwBmAGkAbABQAGUAcgBmAGkAbAAgAFIARwBCACAAZwBlAG4A6AByAGkAYwBQAGUAcgBmAGkAbAAgAFIARwBCACAARwBlAG4A6QByAGkAYwBvBBcEMAQzBDAEOwRMBD0EOAQ5ACAEPwRABD4ERAQwBDkEOwAgAFIARwBCAFAAcgBvAGYAaQBsACAAZwDpAG4A6QByAGkAcQB1AGUAIABSAFYAQpAadSgAIABSAEcAQgAggnJfaWPPj/AAUAByAG8AZgBp/wBsAG8AIABSAEcAQgAgAGcAZQBuAGUAcgBpAGMAbwBHAGUAbgBlAHIAaQBzAGsAIABSAEcAQgAtAHAAcgBvAGYAaQBsx3y8GAAgAFIARwBCACDVBLhc0wzHfABPAGIAZQBjAG4A/QAgAFIARwBCACAAcAByAG8AZgBpAGwF5AXoBdUF5AXZBdwAIABSAEcAQgAgBdsF3AXcBdkAQQBsAGwAZwBlAG0AZQBpAG4AZQBzACAAUgBHAEIALQBQAHIAbwBmAGkAbADBAGwAdABhAGwA4QBuAG8AcwAgAFIARwBCACAAcAByAG8AZgBpAGxmbpAaACAAUgBHAEIAIGPPj//wZYdO9k4AgiwAIABSAEcAQgAgMNcw7TDVMKEwpDDrAFAAcgBvAGYAaQBsACAAUgBHAEIAIABnAGUAbgBlAHIAaQBjA5MDtQO9A7kDugPMACADwAPBA78DxgOvA7sAIABSAEcAQgBQAGUAcgBmAGkAbAAgAFIARwBCACAAZwBlAG4A6QByAGkAYwBvAEEAbABnAGUAbQBlAGUAbgAgAFIARwBCAC0AcAByAG8AZgBpAGUAbA5CDhsOIw5EDh8OJQ5MACAAUgBHAEIAIA4XDjEOSA4nDkQOGwBHAGUAbgBlAGwAIABSAEcAQgAgAFAAcgBvAGYAaQBsAGkAWQBsAGX/AGkAbgBlAG4AIABSAEcAQgAtAHAAcgBvAGYAaQBpAGwAaQBVAG4AaQB3AGUAcgBzAGEAbABuAHkAIABwAHIAbwBmAGkAbAAgAFIARwBCBB4EMQRJBDgEOQAgBD8EQAQ+BEQEOAQ7BEwAIABSAEcAQgZFBkQGQQAgBioGOQYxBkoGQQAgAFIARwBCACAGJwZEBjkGJwZFAEcAZQBuAGUAcgBpAGMAIABSAEcAQgAgAFAAcgBvAGYAaQBsAGUARwBlAG4AZQByAGUAbAAgAFIARwBCAC0AYgBlAHMAawByAGkAdgBlAGwAcwBldGV4dAAAAABDb3B5cmlnaHQgMjAwrzcgQXBwbGUgSW5jLiwgYWxsIHJpZ2h0cyByZXNlcnZlZC4AWFlaIAAAAAAAAPNSAAEAAAABFs9YWVogAAAAAAAAdE0AAD3uAAAD0FhZWiAAAAAAAABadQAArHMAABc0WFlaIAAAAAAAACgaAAAVnwAAuDZjdXJ2AAAAAAAAAAEBzQAAc2YzMgAAAAAAAQxCAAAF3v//8yYAAAeSAAD9kf//+6L///2jAAAD3AAAwGwALAAAAAAQABAAAAIglI+pwK3XInhSLoZc0oa/7lHRB4bXRJZoaqau+o6ujBQAOw==';
|
||||
|
||||
cut_icon = 'data:image/gif;base64,R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAAcALAAAAAAQABAAAAQu8MhJqz1g5qs7lxv2gRkQfuWomarXEgDRHjJhf3YtyRav0xcfcFgR0nhB5OwTAQA7';
|
||||
|
||||
copy_icon = 'data:image/gif;base64,R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAAcALAAAAAAQABAAAAQ+8MhJ6wE4Wwqef9gmdV8HiKZJrCz3ecS7TikWfzExvk+M9a0a4MbTkXCgTMeoHPJgG5+yF31SLazsTMTtViIAOw==';
|
||||
|
||||
paste_icon = 'data:image/gif;base64,R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAAcALAAAAAAQABAAAARL8MhJqwUYWJnxWp3GDcgAgCdQIqLKXmVLhhnyHiqpr7rME8AgocVDEB5IJHD0SyofBFzxGIQGAbvB0ZkcTq1CKK6z5YorwnR0w44AADs=';
|
||||
|
||||
close_icon = 'data:image/gif;base64,R0lGODlhEAAQAMQAAGtra/f3/62tre/v9+bm787O1pycnHNzc6WlpcXFxd7e3tbW1nt7e7W1te/v74SEhMXFzmNjY+bm5v///87OzgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAQABAAAAVt4DRMZGmSwRQQBUS9MAwRIyQ5Uq7neEFSDtxOF4T8cobIQaE4RAQ5yjHHiCCSD510QtFGvoCFdppDfBu7bYzy+D7WP5ggAgA8Y3FKwi5IAhIweW1vbBGEWy5rilsFi2tGAwSJixAFBCkpJ5ojIQA7';
|
||||
|
||||
zoomall_icon = 'data:image/gif;base64,R0lGODlhEAAQAMT/AAAAAP///zAwYT09bpGRqZ6et5iYsKWlvbi40MzM5cXF3czM5OHh5tTU2fDw84uMom49DbWKcfLy8g0NDcDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABQALAAAAAAQABAAAAVZICWOZFlOwCQF5pg2TDMJbDs1DqI8g2TjOsSC0DMBGEGF4UAz3RQ6wiFRLEkmj8WyUC0FBAMpNdWiBCQD8DWCKq98lEkEAiiTAJB53S7Cz/kuECuAIzWEJCEAIf5PQ29weXJpZ2h0IDIwMDAgYnkgU3VuIE1pY3Jvc3lzdGVtcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLg0KSkxGIEdSIFZlciAxLjANCgA7';
|
||||
|
||||
zoomin_icon = 'data:image/gif;base64,R0lGODlhEAAQAMT/AAAAAP///zAwYT09boSEnIqKopiYsJ6etqurxL+/18XF3dnZ8sXF0OHh5tTU2ePj5piZr2EwAMKXfg0NDcDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABQALAAAAAAQABAAAAVXICWOZFkCE2CWaeMwwLCKQPNMBCQEa/0UAEXiIFhNHKmkYcA7MQgKwMGw2PUgiYkBsWuWBoJpNTWjBATgAECCKgfelHVkUh5NIpJ5XXTP7/kRcH9mgyUhADshACH+T0NvcHlyaWdodCAyMDAwIGJ5IFN1biBNaWNyb3N5c3RlbXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC4NCkpMRiBHUiBWZXIgMS4wDQoAOw==';
|
||||
|
||||
zoomout_icon = 'data:image/gif;base64,R0lGODlhEAAQAMT/AAAAAP///zAwYT09bn19lYSEnJGRqZ6et5iYsJ6etqWlvbi40MzM5cXF3czM5Li4w+Hh5tTU2fDw84uMom49DbWKcQ0NDcDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABcALAAAAAAQABAAAAVX4CWOZFlagGWWaQQ9lrCKViQVxjQEay0RjYXDMFgBIKmkQsA7PQyLhEHB2PUmDoTisGuWBINpNTW7BAbggKWCKgfelzUFUB4BKJV5XXTP7/kUcH9mgyUhADshACH+T0NvcHlyaWdodCAyMDAwIGJ5IFN1biBNaWNyb3N5c3RlbXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC4NCkpMRiBHUiBWZXIgMS4wDQoAOw==';
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Graphing
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// add dashed lines!
|
||||
// from http://davidowens.wordpress.com/2010/09/07/html-5-canvas-and-dashed-lines/
|
||||
CanvasRenderingContext2D.prototype.dashedLineTo = function(fromX, fromY, toX, toY, pattern) {
|
||||
// Our growth rate for our line can be one of the following:
|
||||
// (+,+), (+,-), (-,+), (-,-)
|
||||
// Because of this, our algorithm needs to understand if the x-coord and
|
||||
// y-coord should be getting smaller or larger and properly cap the values
|
||||
// based on (x,y).
|
||||
var lt = function (a, b) { return a <= b; };
|
||||
var gt = function (a, b) { return a >= b; };
|
||||
var capmin = function (a, b) { return Math.min(a, b); };
|
||||
var capmax = function (a, b) { return Math.max(a, b); };
|
||||
|
||||
var checkX = { thereYet: gt, cap: capmin };
|
||||
var checkY = { thereYet: gt, cap: capmin };
|
||||
|
||||
if (fromY - toY > 0) {
|
||||
checkY.thereYet = lt;
|
||||
checkY.cap = capmax;
|
||||
}
|
||||
if (fromX - toX > 0) {
|
||||
checkX.thereYet = lt;
|
||||
checkX.cap = capmax;
|
||||
}
|
||||
|
||||
this.moveTo(fromX, fromY);
|
||||
var offsetX = fromX;
|
||||
var offsetY = fromY;
|
||||
var idx = 0, dash = true;
|
||||
while (!(checkX.thereYet(offsetX, toX) && checkY.thereYet(offsetY, toY))) {
|
||||
var ang = Math.atan2(toY - fromY, toX - fromX);
|
||||
var len = pattern[idx];
|
||||
|
||||
offsetX = checkX.cap(toX, offsetX + (Math.cos(ang) * len));
|
||||
offsetY = checkY.cap(toY, offsetY + (Math.sin(ang) * len));
|
||||
|
||||
if (dash) this.lineTo(offsetX, offsetY);
|
||||
else this.moveTo(offsetX, offsetY);
|
||||
|
||||
idx = (idx + 1) % pattern.length;
|
||||
dash = !dash;
|
||||
}
|
||||
};
|
||||
|
||||
// given a range of values, return a new range [vmin',vmax'] where the limits
|
||||
// have been chosen "nicely". Taken from matplotlib.ticker.LinearLocator
|
||||
function view_limits(vmin,vmax) {
|
||||
// deal with degenerate case...
|
||||
if (vmin == vmax) {
|
||||
if (vmin == 0) { vmin = -0.5; vmax = 0.5; }
|
||||
else {
|
||||
vmin = vmin > 0 ? 0.9*vmin : 1.1*vmin;
|
||||
vmax = vmax > 0 ? 1.1*vmax : 0.9*vmax;
|
||||
}
|
||||
}
|
||||
|
||||
var log_range = Math.log(vmax - vmin)/Math.LN10;
|
||||
var exponent = Math.floor(log_range);
|
||||
//if (log_range - exponent < 0.5) exponent -= 1;
|
||||
var scale = Math.pow(10,-exponent);
|
||||
vmin = Math.floor(scale*vmin)/scale;
|
||||
vmax = Math.ceil(scale*vmax)/scale;
|
||||
|
||||
return [vmin,vmax,1.0/scale];
|
||||
}
|
||||
|
||||
function engineering_notation(n,nplaces,trim) {
|
||||
if (n == 0) return '0';
|
||||
if (n == undefined) return 'undefined';
|
||||
if (trim == undefined) trim = true;
|
||||
|
||||
var sign = n < 0 ? -1 : 1;
|
||||
var log10 = Math.log(sign*n)/Math.LN10;
|
||||
var exp = Math.floor(log10/3); // powers of 1000
|
||||
var mantissa = sign*Math.pow(10,log10 - 3*exp);
|
||||
|
||||
// keep specified number of places following decimal point
|
||||
var mstring = (mantissa + sign*0.5*Math.pow(10,-nplaces)).toString();
|
||||
var mlen = mstring.length;
|
||||
var endindex = mstring.indexOf('.');
|
||||
if (endindex != -1) {
|
||||
if (nplaces > 0) {
|
||||
endindex += nplaces + 1;
|
||||
if (endindex > mlen) endindex = mlen;
|
||||
if (trim) {
|
||||
while (mstring.charAt(endindex-1) == '0') endindex -= 1;
|
||||
if (mstring.charAt(endindex-1) == '.') endindex -= 1;
|
||||
}
|
||||
}
|
||||
if (endindex < mlen)
|
||||
mstring = mstring.substring(0,endindex);
|
||||
}
|
||||
|
||||
switch(exp) {
|
||||
case -5: return mstring+"f";
|
||||
case -4: return mstring+"p";
|
||||
case -3: return mstring+"n";
|
||||
case -2: return mstring+"u";
|
||||
case -1: return mstring+"m";
|
||||
case 0: return mstring;
|
||||
case 1: return mstring+"K";
|
||||
case 2: return mstring+"M";
|
||||
case 3: return mstring+"G";
|
||||
}
|
||||
|
||||
// don't have a good suffix, so just print the number
|
||||
return n.toString();
|
||||
}
|
||||
|
||||
var grid_pattern = [1,2];
|
||||
var cursor_pattern = [5,5];
|
||||
|
||||
// x_values is an array of x coordinates for each of the plots
|
||||
// y_values is an array of [color, value_array], one entry for each plot on left vertical axis
|
||||
// z_values is an array of [color, value_array], one entry for each plot on right vertical axis
|
||||
Schematic.prototype.graph = function(x_values,x_legend,y_values,y_legend,z_values,z_legend) {
|
||||
var pwidth = 400; // dimensions of actual plot
|
||||
var pheight = 300; // dimensions of actual plot
|
||||
var left_margin = (y_values != undefined && y_values.length > 0) ? 55 : 25;
|
||||
var top_margin = 25;
|
||||
var right_margin = (z_values != undefined && z_values.length > 0) ? 55 : 25;
|
||||
var bottom_margin = 45;
|
||||
var tick_length = 5;
|
||||
|
||||
var w = pwidth + left_margin + right_margin;
|
||||
var h = pheight + top_margin + bottom_margin;
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
|
||||
// the graph itself will be drawn here and this image will be copied
|
||||
// onto canvas, where it can be overlayed with mouse cursors, etc.
|
||||
var bg_image = document.createElement('canvas');
|
||||
bg_image.width = w;
|
||||
bg_image.height = h;
|
||||
canvas.bg_image = bg_image; // so we can find it during event handling
|
||||
|
||||
// start by painting an opaque background
|
||||
var c = bg_image.getContext('2d');
|
||||
c.fillStyle = background_style;
|
||||
c.fillRect(0,0,w,h);
|
||||
c.fillStyle = element_style;
|
||||
c.fillRect(left_margin,top_margin,pwidth,pheight);
|
||||
|
||||
// figure out scaling for plots
|
||||
var x_min = array_min(x_values);
|
||||
var x_max = array_max(x_values);
|
||||
var x_limits = view_limits(x_min,x_max);
|
||||
x_min = x_limits[0];
|
||||
x_max = x_limits[1];
|
||||
var x_scale = pwidth/(x_max - x_min);
|
||||
|
||||
function plot_x(x) {
|
||||
return (x - x_min)*x_scale + left_margin;
|
||||
}
|
||||
|
||||
// draw x grid
|
||||
c.strokeStyle = grid_style;
|
||||
c.lineWidth = 1;
|
||||
c.fillStyle = normal_style;
|
||||
c.font = '10pt sans-serif';
|
||||
c.textAlign = 'center';
|
||||
c.textBaseline = 'top';
|
||||
var end = top_margin + pheight;
|
||||
for (var x = x_min; x <= x_max; x += x_limits[2]) {
|
||||
var temp = plot_x(x) + 0.5; // keep lines crisp!
|
||||
|
||||
// grid line
|
||||
c.beginPath();
|
||||
if (x == x_min) {
|
||||
c.moveTo(temp,top_margin);
|
||||
c.lineTo(temp,end);
|
||||
} else
|
||||
c.dashedLineTo(temp,top_margin,temp,end,grid_pattern);
|
||||
c.stroke();
|
||||
|
||||
// tick mark
|
||||
c.beginPath();
|
||||
c.moveTo(temp,end);
|
||||
c.lineTo(temp,end + tick_length);
|
||||
c.stroke();
|
||||
c.fillText(engineering_notation(x,2),temp,end + tick_length);
|
||||
}
|
||||
|
||||
if (y_values != undefined && y_values.length > 0) {
|
||||
var y_min = Infinity;
|
||||
var y_max = -Infinity;
|
||||
var plot;
|
||||
for (plot = y_values.length - 1; plot >= 0; --plot) {
|
||||
var values = y_values[plot][2];
|
||||
if (values == undefined) continue; // no data points
|
||||
var offset = y_values[plot][1];
|
||||
var temp = array_min(values) + offset;
|
||||
if (temp < y_min) y_min = temp;
|
||||
temp = array_max(values) + offset;
|
||||
if (temp > y_max) y_max = temp;
|
||||
}
|
||||
var y_limits = view_limits(y_min,y_max);
|
||||
y_min = y_limits[0];
|
||||
y_max = y_limits[1];
|
||||
var y_scale = pheight/(y_max - y_min);
|
||||
|
||||
function plot_y(y) {
|
||||
return (y_max - y)*y_scale + top_margin;
|
||||
}
|
||||
|
||||
// draw y grid
|
||||
c.textAlign = 'right';
|
||||
c.textBaseline = 'middle';
|
||||
for (var y = y_min; y <= y_max; y += y_limits[2]) {
|
||||
if (Math.abs(y/y_max) < 0.001) y = 0.0; // Just 3 digits
|
||||
var temp = plot_y(y) + 0.5; // keep lines crisp!
|
||||
|
||||
// grid line
|
||||
c.beginPath();
|
||||
if (y == y_min) {
|
||||
c.moveTo(left_margin,temp);
|
||||
c.lineTo(left_margin + pwidth,temp);
|
||||
} else
|
||||
c.dashedLineTo(left_margin,temp,left_margin + pwidth,temp,grid_pattern);
|
||||
c.stroke();
|
||||
|
||||
// tick mark
|
||||
c.beginPath();
|
||||
c.moveTo(left_margin - tick_length,temp);
|
||||
c.lineTo(left_margin,temp);
|
||||
c.stroke();
|
||||
c.fillText(engineering_notation(y,2),left_margin - tick_length -2,temp);
|
||||
}
|
||||
|
||||
// now draw each plot
|
||||
var x,y;
|
||||
var nx,ny;
|
||||
c.lineWidth = 3;
|
||||
c.lineCap = 'round';
|
||||
for (plot = y_values.length - 1; plot >= 0; --plot) {
|
||||
var color = probe_colors_rgb[y_values[plot][0]];
|
||||
if (color == undefined) continue; // no plot color (== x-axis)
|
||||
c.strokeStyle = color;
|
||||
var values = y_values[plot][2];
|
||||
if (values == undefined) continue; // no data points
|
||||
var offset = y_values[plot][1];
|
||||
|
||||
x = plot_x(x_values[0]);
|
||||
y = plot_y(values[0] + offset);
|
||||
c.beginPath();
|
||||
c.moveTo(x,y);
|
||||
for (var i = 1; i < x_values.length; i++) {
|
||||
nx = plot_x(x_values[i]);
|
||||
ny = plot_y(values[i] + offset);
|
||||
c.lineTo(nx,ny);
|
||||
x = nx;
|
||||
y = ny;
|
||||
if (i % 100 == 99) {
|
||||
// too many lineTo's cause canvas to break
|
||||
c.stroke();
|
||||
c.beginPath();
|
||||
c.moveTo(x,y);
|
||||
}
|
||||
}
|
||||
c.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
if (z_values != undefined && z_values.length > 0) {
|
||||
var z_min = Infinity;
|
||||
var z_max = -Infinity;
|
||||
for (plot = z_values.length - 1; plot >= 0; --plot) {
|
||||
var values = z_values[plot][2];
|
||||
if (values == undefined) continue; // no data points
|
||||
var offset = z_values[plot][1];
|
||||
var temp = array_min(values) + offset;
|
||||
if (temp < z_min) z_min = temp;
|
||||
temp = array_max(values) + offset;
|
||||
if (temp > z_max) z_max = temp;
|
||||
}
|
||||
var z_limits = view_limits(z_min,z_max);
|
||||
z_min = z_limits[0];
|
||||
z_max = z_limits[1];
|
||||
var z_scale = pheight/(z_max - z_min);
|
||||
|
||||
function plot_z(z) {
|
||||
return (z_max - z)*z_scale + top_margin;
|
||||
}
|
||||
|
||||
// draw z ticks
|
||||
c.textAlign = 'left';
|
||||
c.textBaseline = 'middle';
|
||||
c.lineWidth = 1;
|
||||
c.strokeStyle = normal_style;
|
||||
var tick_length_half = Math.floor(tick_length/2);
|
||||
var tick_delta = tick_length - tick_length_half;
|
||||
for (var z = z_min; z <= z_max; z += z_limits[2]) {
|
||||
if (Math.abs(z/z_max) < 0.001) z = 0.0; // Just 3 digits
|
||||
var temp = plot_z(z) + 0.5; // keep lines crisp!
|
||||
|
||||
// tick mark
|
||||
c.beginPath();
|
||||
c.moveTo(left_margin + pwidth - tick_length_half,temp);
|
||||
c.lineTo(left_margin + pwidth + tick_delta,temp);
|
||||
c.stroke();
|
||||
c.fillText(engineering_notation(z,2),left_margin + pwidth + tick_length + 2,temp);
|
||||
}
|
||||
|
||||
var z;
|
||||
var nz;
|
||||
c.lineWidth = 3;
|
||||
for (plot = z_values.length - 1; plot >= 0; --plot) {
|
||||
var color = probe_colors_rgb[z_values[plot][0]];
|
||||
if (color == undefined) continue; // no plot color (== x-axis)
|
||||
c.strokeStyle = color;
|
||||
var values = z_values[plot][2];
|
||||
if (values == undefined) continue; // no data points
|
||||
var offset = z_values[plot][1];
|
||||
|
||||
x = plot_x(x_values[0]);
|
||||
z = plot_z(values[0] + offset);
|
||||
c.beginPath();
|
||||
c.moveTo(x,z);
|
||||
for (var i = 1; i < x_values.length; i++) {
|
||||
nx = plot_x(x_values[i]);
|
||||
nz = plot_z(values[i] + offset);
|
||||
c.lineTo(nx,nz);
|
||||
x = nx;
|
||||
z = nz;
|
||||
if (i % 100 == 99) {
|
||||
// too many lineTo's cause canvas to break
|
||||
c.stroke();
|
||||
c.beginPath();
|
||||
c.moveTo(x,z);
|
||||
}
|
||||
}
|
||||
c.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
// draw legends
|
||||
c.font = '12pt sans-serif';
|
||||
c.textAlign = 'center';
|
||||
c.textBaseline = 'bottom';
|
||||
c.fillText(x_legend,left_margin + pwidth/2,h - 5);
|
||||
|
||||
if (y_values != undefined && y_values.length > 0) {
|
||||
c.textBaseline = 'top';
|
||||
c.save();
|
||||
c.translate(5 ,top_margin + pheight/2);
|
||||
c.rotate(-Math.PI/2);
|
||||
c.fillText(y_legend,0,0);
|
||||
c.restore();
|
||||
}
|
||||
|
||||
if (z_values != undefined && z_values.length > 0) {
|
||||
c.textBaseline = 'bottom';
|
||||
c.save();
|
||||
c.translate(w-5 ,top_margin + pheight/2);
|
||||
c.rotate(-Math.PI/2);
|
||||
c.fillText(z_legend,0,0);
|
||||
c.restore();
|
||||
}
|
||||
|
||||
// save info need for interactions with the graph
|
||||
canvas.x_values = x_values;
|
||||
canvas.y_values = y_values;
|
||||
canvas.z_values = z_values;
|
||||
canvas.x_legend = x_legend;
|
||||
canvas.y_legend = y_legend;
|
||||
canvas.z_legend = y_legend;
|
||||
canvas.x_min = x_min;
|
||||
canvas.x_scale = x_scale;
|
||||
canvas.y_min = y_min;
|
||||
canvas.y_scale = y_scale;
|
||||
canvas.z_min = z_min;
|
||||
canvas.z_scale = z_scale;
|
||||
canvas.left_margin = left_margin;
|
||||
canvas.top_margin = top_margin;
|
||||
canvas.pwidth = pwidth;
|
||||
canvas.pheight = pheight;
|
||||
canvas.tick_length = tick_length;
|
||||
|
||||
canvas.cursor1_x = undefined;
|
||||
canvas.cursor2_x = undefined;
|
||||
canvas.sch = this;
|
||||
|
||||
// do something useful when user mouses over graph
|
||||
canvas.addEventListener('mousemove',graph_mouse_move,false);
|
||||
|
||||
// return our masterpiece
|
||||
redraw_plot(canvas);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
function array_max(a) {
|
||||
max = -Infinity;
|
||||
for (var i = a.length - 1; i >= 0; --i)
|
||||
if (a[i] > max) max = a[i];
|
||||
return max;
|
||||
}
|
||||
|
||||
function array_min(a) {
|
||||
min = Infinity;
|
||||
for (var i = a.length - 1; i >= 0; --i)
|
||||
if (a[i] < min) min = a[i];
|
||||
return min;
|
||||
}
|
||||
|
||||
function plot_cursor(c,graph,cursor_x,left_margin) {
|
||||
// draw dashed vertical marker that follows mouse
|
||||
var x = graph.left_margin + cursor_x;
|
||||
var end_y = graph.top_margin + graph.pheight + graph.tick_length;
|
||||
c.strokeStyle = grid_style;
|
||||
c.lineWidth = 1;
|
||||
c.beginPath();
|
||||
c.dashedLineTo(x,graph.top_margin,x,end_y,cursor_pattern);
|
||||
c.stroke();
|
||||
|
||||
// add x label at bottom of marker
|
||||
var graph_x = cursor_x/graph.x_scale + graph.x_min;
|
||||
c.font = '10pt sans-serif';
|
||||
c.textAlign = 'center';
|
||||
c.textBaseline = 'top';
|
||||
c.fillStyle = background_style;
|
||||
c.fillText('\u2588\u2588\u2588\u2588\u2588',x,end_y);
|
||||
c.fillStyle = normal_style;
|
||||
c.fillText(engineering_notation(graph_x,3,false),x,end_y);
|
||||
|
||||
// compute which points marker is between
|
||||
var x_values = graph.x_values;
|
||||
var len = x_values.length;
|
||||
var index = 0;
|
||||
while (index < len && graph_x >= x_values[index]) index += 1;
|
||||
var x1 = (index == 0) ? x_values[0] : x_values[index-1];
|
||||
var x2 = x_values[index];
|
||||
|
||||
if (x2 != undefined) {
|
||||
// for each plot, interpolate and output value at intersection with marker
|
||||
c.textAlign = 'left';
|
||||
var tx = graph.left_margin + left_margin;
|
||||
var ty = graph.top_margin;
|
||||
if (graph.y_values != undefined) {
|
||||
for (var plot = 0; plot < graph.y_values.length; plot++) {
|
||||
var values = graph.y_values[plot][2];
|
||||
var color = probe_colors_rgb[graph.y_values[plot][0]];
|
||||
if (values == undefined || color == undefined) continue; // no data points or x-axis
|
||||
|
||||
// interpolate signal value at graph_x using values[index-1] and values[index]
|
||||
var y1 = (index == 0) ? values[0] : values[index-1];
|
||||
var y2 = values[index];
|
||||
var y = y1;
|
||||
if (graph_x != x1) y += (graph_x - x1)*(y2 - y1)/(x2 - x1);
|
||||
|
||||
// annotate plot with value of signal at marker
|
||||
c.fillStyle = element_style;
|
||||
c.fillText('\u2588\u2588\u2588\u2588\u2588',tx-3,ty);
|
||||
c.fillStyle = color;
|
||||
c.fillText(engineering_notation(y,3,false),tx,ty);
|
||||
ty += 14;
|
||||
}
|
||||
}
|
||||
|
||||
c.textAlign = 'right';
|
||||
if (graph.z_values != undefined) {
|
||||
var tx = graph.left_margin + graph.pwidth - left_margin;
|
||||
var ty = graph.top_margin;
|
||||
for (var plot = 0; plot < graph.z_values.length; plot++) {
|
||||
var values = graph.z_values[plot][2];
|
||||
var color = probe_colors_rgb[graph.z_values[plot][0]];
|
||||
if (values == undefined || color == undefined) continue; // no data points or x-axis
|
||||
|
||||
// interpolate signal value at graph_x using values[index-1] and values[index]
|
||||
var z1 = (index == 0) ? values[0]: values[index-1];
|
||||
var z2 = values[index];
|
||||
var z = z1;
|
||||
if (graph_x != x1) z += (graph_x - x1)*(z2 - z1)/(x2 - x1);
|
||||
|
||||
// annotate plot with value of signal at marker
|
||||
c.fillStyle = element_style;
|
||||
c.fillText('\u2588\u2588\u2588\u2588\u2588',tx+3,ty);
|
||||
c.fillStyle = color;
|
||||
c.fillText(engineering_notation(z,3,false),tx,ty);
|
||||
ty += 14;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function redraw_plot(graph) {
|
||||
var c = graph.getContext('2d');
|
||||
c.drawImage(graph.bg_image,0,0);
|
||||
|
||||
if (graph.cursor1_x != undefined) plot_cursor(c,graph,graph.cursor1_x,4);
|
||||
if (graph.cursor2_x != undefined) plot_cursor(c,graph,graph.cursor2_x,30);
|
||||
|
||||
/*
|
||||
if (graph.cursor1_x != undefined) {
|
||||
// draw dashed vertical marker that follows mouse
|
||||
var x = graph.left_margin + graph.cursor1_x;
|
||||
var end_y = graph.top_margin + graph.pheight + graph.tick_length;
|
||||
c.strokeStyle = grid_style;
|
||||
c.lineWidth = 1;
|
||||
c.beginPath();
|
||||
c.dashedLineTo(x,graph.top_margin,x,end_y,cursor_pattern);
|
||||
c.stroke();
|
||||
|
||||
// add x label at bottom of marker
|
||||
var graph_x = graph.cursor1_x/graph.x_scale + graph.x_min;
|
||||
c.font = '10pt sans-serif';
|
||||
c.textAlign = 'center';
|
||||
c.textBaseline = 'top';
|
||||
c.fillStyle = background_style;
|
||||
c.fillText('\u2588\u2588\u2588\u2588\u2588',x,end_y);
|
||||
c.fillStyle = normal_style;
|
||||
c.fillText(engineering_notation(graph_x,3,false),x,end_y);
|
||||
|
||||
// compute which points marker is between
|
||||
var x_values = graph.x_values;
|
||||
var len = x_values.length;
|
||||
var index = 0;
|
||||
while (index < len && graph_x >= x_values[index]) index += 1;
|
||||
var x1 = (index == 0) ? x_values[0] : x_values[index-1];
|
||||
var x2 = x_values[index];
|
||||
|
||||
if (x2 != undefined) {
|
||||
// for each plot, interpolate and output value at intersection with marker
|
||||
c.textAlign = 'left';
|
||||
var tx = graph.left_margin + 4;
|
||||
var ty = graph.top_margin;
|
||||
for (var plot = 0; plot < graph.y_values.length; plot++) {
|
||||
var values = graph.y_values[plot][1];
|
||||
|
||||
// interpolate signal value at graph_x using values[index-1] and values[index]
|
||||
var y1 = (index == 0) ? values[0] : values[index-1];
|
||||
var y2 = values[index];
|
||||
var y = y1;
|
||||
if (graph_x != x1) y += (graph_x - x1)*(y2 - y1)/(x2 - x1);
|
||||
|
||||
// annotate plot with value of signal at marker
|
||||
c.fillStyle = element_style;
|
||||
c.fillText('\u2588\u2588\u2588\u2588\u2588',tx-3,ty);
|
||||
c.fillStyle = probe_colors_rgb[graph.y_values[plot][0]];
|
||||
c.fillText(engineering_notation(y,3,false),tx,ty);
|
||||
ty += 14;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
function graph_mouse_move(event) {
|
||||
if (!event) event = window.event;
|
||||
var g = (window.event) ? event.srcElement : event.target;
|
||||
|
||||
g.relMouseCoords(event);
|
||||
// not sure yet where the 3,-3 offset correction comes from (borders? padding?)
|
||||
var gx = g.mouse_x - g.left_margin - 3;
|
||||
var gy = g.pheight - (g.mouse_y - g.top_margin) + 3;
|
||||
if (gx >= 0 && gx <= g.pwidth && gy >=0 && gy <= g.pheight) {
|
||||
//g.sch.message('button: '+event.button+', which: '+event.which);
|
||||
g.cursor1_x = gx;
|
||||
} else {
|
||||
g.cursor1_x = undefined;
|
||||
g.cursor2_x = undefined;
|
||||
}
|
||||
|
||||
redraw_plot(g);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts bin
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// one instance will be created for each part in the parts bin
|
||||
function Part(sch) {
|
||||
this.sch = sch;
|
||||
this.component = undefined;
|
||||
this.selected = false;
|
||||
|
||||
// set up canvas
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.canvas.style.borderStyle = 'solid';
|
||||
this.canvas.style.borderWidth = '1px';
|
||||
this.canvas.style.borderColor = background_style;
|
||||
//this.canvas.style.position = 'absolute';
|
||||
this.canvas.style.cursor = 'default';
|
||||
this.canvas.height = part_w;
|
||||
this.canvas.width = part_h;
|
||||
this.canvas.part = this;
|
||||
|
||||
this.canvas.addEventListener('mouseover',part_enter,false);
|
||||
this.canvas.addEventListener('mouseout',part_leave,false);
|
||||
this.canvas.addEventListener('mousedown',part_mouse_down,false);
|
||||
this.canvas.addEventListener('mouseup',part_mouse_up,false);
|
||||
|
||||
// make the part "clickable" by registering a dummy click handler
|
||||
// this should make things work on the iPad
|
||||
this.canvas.addEventListener('click',function(){},false);
|
||||
}
|
||||
|
||||
Part.prototype.set_location = function(left,top) {
|
||||
this.canvas.style.left = left + 'px';
|
||||
this.canvas.style.top = top + 'px';
|
||||
}
|
||||
|
||||
Part.prototype.right = function() {
|
||||
return this.canvas.offsetLeft + this.canvas.offsetWidth;
|
||||
}
|
||||
|
||||
Part.prototype.bottom = function() {
|
||||
return this.canvas.offsetTop + this.canvas.offsetHeight;
|
||||
}
|
||||
|
||||
Part.prototype.set_component = function(component,tip) {
|
||||
component.sch = this;
|
||||
this.component = component;
|
||||
this.tip = tip;
|
||||
|
||||
// figure out scaling and centering of parts icon
|
||||
var b = component.bounding_box;
|
||||
var dx = b[2] - b[0];
|
||||
var dy = b[3] - b[1];
|
||||
this.scale = 0.8; //Math.min(part_w/(1.2*dx),part_h/(1.2*dy));
|
||||
this.origin_x = b[0] + dx/2.0 - part_w/(2.0*this.scale);
|
||||
this.origin_y = b[1] + dy/2.0 - part_h/(2.0*this.scale);
|
||||
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
Part.prototype.redraw = function(part) {
|
||||
var c = this.canvas.getContext('2d');
|
||||
|
||||
// paint background color
|
||||
c.fillStyle = this.selected ? selected_style : background_style;
|
||||
c.fillRect(0,0,part_w,part_h);
|
||||
|
||||
if (this.component) this.component.draw(c);
|
||||
}
|
||||
|
||||
Part.prototype.select = function(which) {
|
||||
this.selected = which;
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
Part.prototype.update_connection_point = function(cp,old_location) {
|
||||
// no connection points in the parts bin
|
||||
}
|
||||
|
||||
Part.prototype.moveTo = function(c,x,y) {
|
||||
c.moveTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale);
|
||||
}
|
||||
|
||||
Part.prototype.lineTo = function(c,x,y) {
|
||||
c.lineTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale);
|
||||
}
|
||||
|
||||
Part.prototype.draw_line = function(c,x1,y1,x2,y2,width) {
|
||||
c.lineWidth = width*this.scale;
|
||||
c.beginPath();
|
||||
c.moveTo((x1 - this.origin_x) * this.scale,(y1 - this.origin_y) * this.scale);
|
||||
c.lineTo((x2 - this.origin_x) * this.scale,(y2 - this.origin_y) * this.scale);
|
||||
c.stroke();
|
||||
}
|
||||
|
||||
Part.prototype.draw_arc = function(c,x,y,radius,start_radians,end_radians,anticlockwise,width,filled) {
|
||||
c.lineWidth = width*this.scale;
|
||||
c.beginPath();
|
||||
c.arc((x - this.origin_x)*this.scale,(y - this.origin_y)*this.scale,radius*this.scale,
|
||||
start_radians,end_radians,anticlockwise);
|
||||
if (filled) c.fill();
|
||||
else c.stroke();
|
||||
}
|
||||
|
||||
Part.prototype.draw_text = function(c,text,x,y,size) {
|
||||
// no text displayed for the parts icon
|
||||
}
|
||||
|
||||
function part_enter(event) {
|
||||
if (!event) event = window.event;
|
||||
var canvas = (window.event) ? event.srcElement : event.target;
|
||||
var part = canvas.part;
|
||||
|
||||
// avoid Chrome bug that changes to text cursor whenever
|
||||
// drag starts. We'll restore the default handler at
|
||||
// the appropriate point so behavior in other parts of
|
||||
// the document are unaffected.
|
||||
//part.sch.saved_onselectstart = document.onselectstart;
|
||||
//document.onselectstart = function () { return false; };
|
||||
|
||||
canvas.style.borderColor = normal_style;
|
||||
part.sch.message(part.tip+': drag onto diagram to insert');
|
||||
return false;
|
||||
}
|
||||
|
||||
function part_leave(event) {
|
||||
if (!event) event = window.event;
|
||||
var canvas = (window.event) ? event.srcElement : event.target;
|
||||
var part = canvas.part;
|
||||
|
||||
if (typeof part.sch.new_part == 'undefined') {
|
||||
// leaving with no part selected? revert handler
|
||||
//document.onselectstart = part.sch.saved_onselectstart;
|
||||
}
|
||||
|
||||
canvas.style.borderColor = background_style;
|
||||
part.sch.message('');
|
||||
return false;
|
||||
}
|
||||
|
||||
function part_mouse_down(event) {
|
||||
if (!event) event = window.event;
|
||||
var part = (window.event) ? event.srcElement.part : event.target.part;
|
||||
|
||||
part.select(true);
|
||||
part.sch.new_part = part;
|
||||
return false;
|
||||
}
|
||||
|
||||
function part_mouse_up(event) {
|
||||
if (!event) event = window.event;
|
||||
var part = (window.event) ? event.srcElement.part : event.target.part;
|
||||
|
||||
part.select(false);
|
||||
part.sch.new_part = undefined;
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Rectangle helper functions
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// rect is an array of the form [left,top,right,bottom]
|
||||
|
||||
// ensure left < right, top < bottom
|
||||
function canonicalize(r) {
|
||||
var temp;
|
||||
|
||||
// canonicalize bounding box
|
||||
if (r[0] > r[2]) {
|
||||
temp = r[0];
|
||||
r[0] = r[2];
|
||||
r[2] = temp;
|
||||
}
|
||||
if (r[1] > r[3]) {
|
||||
temp = r[1];
|
||||
r[1] = r[3];
|
||||
r[3] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
function between(x,x1,x2) {
|
||||
return x1 <= x && x <= x2;
|
||||
}
|
||||
|
||||
function inside(rect,x,y) {
|
||||
return between(x,rect[0],rect[2]) && between(y,rect[1],rect[3]);
|
||||
}
|
||||
|
||||
// only works for manhattan rectangles
|
||||
function intersect(r1,r2) {
|
||||
// look for non-intersection, negate result
|
||||
var result = !(r2[0] > r1[2] ||
|
||||
r2[2] < r1[0] ||
|
||||
r2[1] > r1[3] ||
|
||||
r2[3] < r1[1]);
|
||||
|
||||
// if I try to return the above expression, javascript returns undefined!!!
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Component base class
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Component(type,x,y,rotation) {
|
||||
this.sch = undefined;
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.rotation = rotation;
|
||||
this.selected = false;
|
||||
this.properties = new Array();
|
||||
this.bounding_box = [0,0,0,0]; // in device coords [left,top,right,bottom]
|
||||
this.bbox = this.bounding_box; // in absolute coords
|
||||
this.connections = [];
|
||||
}
|
||||
|
||||
Component.prototype.json = function(index) {
|
||||
this.properties['_json_'] = index; // remember where we are in the JSON list
|
||||
|
||||
var props = {};
|
||||
for (var p in this.properties) props[p] = this.properties[p];
|
||||
|
||||
var conns = [];
|
||||
for (var i = 0; i < this.connections.length; i++)
|
||||
conns.push(this.connections[i].json());
|
||||
|
||||
var json = [this.type,[this.x, this.y, this.rotation],props,conns];
|
||||
return json;
|
||||
}
|
||||
|
||||
Component.prototype.add_connection = function(offset_x,offset_y) {
|
||||
this.connections.push(new ConnectionPoint(this,offset_x,offset_y));
|
||||
}
|
||||
|
||||
Component.prototype.update_coords = function() {
|
||||
var x = this.x;
|
||||
var y = this.y;
|
||||
|
||||
// update bbox
|
||||
var b = this.bounding_box;
|
||||
this.bbox[0] = this.transform_x(b[0],b[1]) + x;
|
||||
this.bbox[1] = this.transform_y(b[0],b[1]) + y;
|
||||
this.bbox[2] = this.transform_x(b[2],b[3]) + x;
|
||||
this.bbox[3] = this.transform_y(b[2],b[3]) + y;
|
||||
canonicalize(this.bbox);
|
||||
|
||||
// update connections
|
||||
for (var i = this.connections.length - 1; i >= 0; --i)
|
||||
this.connections[i].update_location();
|
||||
}
|
||||
|
||||
Component.prototype.rotate = function(amount) {
|
||||
var old_rotation = this.rotation;
|
||||
this.rotation = (this.rotation + amount) % 8;
|
||||
this.update_coords();
|
||||
|
||||
// create an undoable edit record here
|
||||
// using old_rotation
|
||||
}
|
||||
|
||||
Component.prototype.move_begin = function() {
|
||||
// remember where we started this move
|
||||
this.move_x = this.x;
|
||||
this.move_y = this.y;
|
||||
}
|
||||
|
||||
Component.prototype.move = function(dx,dy) {
|
||||
// update coordinates
|
||||
this.x += dx;
|
||||
this.y += dy;
|
||||
this.update_coords();
|
||||
}
|
||||
|
||||
Component.prototype.move_end = function() {
|
||||
var dx = this.x - this.move_x;
|
||||
var dy = this.y - this.move_y;
|
||||
|
||||
if (dx != 0 || dy != 0) {
|
||||
// create an undoable edit record here
|
||||
|
||||
this.sch.check_wires(this);
|
||||
}
|
||||
}
|
||||
|
||||
Component.prototype.add = function(sch) {
|
||||
this.sch = sch; // we now belong to a schematic!
|
||||
sch.add_component(this);
|
||||
this.update_coords();
|
||||
}
|
||||
|
||||
Component.prototype.remove = function() {
|
||||
// remove connection points from schematic
|
||||
for (var i = this.connections.length - 1; i >= 0; --i) {
|
||||
var cp = this.connections[i];
|
||||
this.sch.remove_connection_point(cp,cp.location);
|
||||
}
|
||||
|
||||
// remove component from schematic
|
||||
this.sch.remove_component(this);
|
||||
this.sch = undefined;
|
||||
|
||||
// create an undoable edit record here
|
||||
}
|
||||
|
||||
Component.prototype.transform_x = function(x,y) {
|
||||
var rot = this.rotation;
|
||||
if (rot == 0 || rot == 6) return x;
|
||||
else if (rot == 1 || rot == 5) return -y;
|
||||
else if (rot == 2 || rot == 4) return -x;
|
||||
else return y;
|
||||
}
|
||||
|
||||
Component.prototype.transform_y = function(x,y) {
|
||||
var rot = this.rotation;
|
||||
if (rot == 1 || rot == 7) return x;
|
||||
else if (rot == 2 || rot == 6) return -y;
|
||||
else if (rot == 3 || rot == 5) return -x;
|
||||
else return y;
|
||||
}
|
||||
|
||||
Component.prototype.moveTo = function(c,x,y) {
|
||||
var nx = this.transform_x(x,y) + this.x;
|
||||
var ny = this.transform_y(x,y) + this.y;
|
||||
this.sch.moveTo(c,nx,ny);
|
||||
}
|
||||
|
||||
Component.prototype.lineTo = function(c,x,y) {
|
||||
var nx = this.transform_x(x,y) + this.x;
|
||||
var ny = this.transform_y(x,y) + this.y;
|
||||
this.sch.lineTo(c,nx,ny);
|
||||
}
|
||||
|
||||
Component.prototype.draw_line = function(c,x1,y1,x2,y2) {
|
||||
c.strokeStyle = this.selected ? selected_style :
|
||||
this.type == 'w' ? normal_style : component_style;
|
||||
var nx1 = this.transform_x(x1,y1) + this.x;
|
||||
var ny1 = this.transform_y(x1,y1) + this.y;
|
||||
var nx2 = this.transform_x(x2,y2) + this.x;
|
||||
var ny2 = this.transform_y(x2,y2) + this.y;
|
||||
this.sch.draw_line(c,nx1,ny1,nx2,ny2,1);
|
||||
}
|
||||
|
||||
Component.prototype.draw_circle = function(c,x,y,radius,filled) {
|
||||
if (filled) c.fillStyle = this.selected ? selected_style : normal_style;
|
||||
else c.strokeStyle = this.selected ? selected_style :
|
||||
this.type == 'w' ? normal_style : component_style;
|
||||
var nx = this.transform_x(x,y) + this.x;
|
||||
var ny = this.transform_y(x,y) + this.y;
|
||||
|
||||
this.sch.draw_arc(c,nx,ny,radius,0,2*Math.PI,false,1,filled);
|
||||
}
|
||||
|
||||
rot_angle = [
|
||||
0.0, // NORTH (identity)
|
||||
Math.PI/2, // EAST (rot270)
|
||||
Math.PI, // SOUTH (rot180)
|
||||
3*Math.PI/2, // WEST (rot90)
|
||||
0.0, // RNORTH (negy)
|
||||
Math.PI/2, // REAST (int-neg)
|
||||
Math.PI, // RSOUTH (negx)
|
||||
3*Math.PI/2, // RWEST (int-pos)
|
||||
];
|
||||
|
||||
Component.prototype.draw_arc = function(c,x,y,radius,start_radians,end_radians) {
|
||||
c.strokeStyle = this.selected ? selected_style :
|
||||
this.type == 'w' ? normal_style : component_style;
|
||||
var nx = this.transform_x(x,y) + this.x;
|
||||
var ny = this.transform_y(x,y) + this.y;
|
||||
this.sch.draw_arc(c,nx,ny,radius,
|
||||
start_radians+rot_angle[this.rotation],end_radians+rot_angle[this.rotation],
|
||||
false,1,false);
|
||||
}
|
||||
|
||||
Component.prototype.draw = function(c) {
|
||||
/*
|
||||
for (var i = this.connections.length - 1; i >= 0; --i) {
|
||||
var cp = this.connections[i];
|
||||
cp.draw_x(c);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// result of rotating an alignment [rot*9 + align]
|
||||
aOrient = [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, // NORTH (identity)
|
||||
2, 5, 8, 1, 4, 7, 0, 3, 6, // EAST (rot270)
|
||||
8, 7, 6, 5, 4, 3, 2, 1, 0, // SOUTH (rot180)
|
||||
6, 3, 0, 7, 4, 1, 8, 5, 3, // WEST (rot90)
|
||||
2, 1, 0, 5, 4, 3, 8, 7, 6, // RNORTH (negy)
|
||||
8, 5, 2, 7, 4, 1, 6, 3, 0, // REAST (int-neg)
|
||||
6, 7, 8, 3, 4, 5, 0, 1, 2, // RSOUTH (negx)
|
||||
0, 3, 6, 1, 4, 7, 2, 5, 8 // RWEST (int-pos)
|
||||
];
|
||||
|
||||
textAlign = [
|
||||
'left', 'center', 'right',
|
||||
'left', 'center', 'right',
|
||||
'left', 'center', 'right'
|
||||
];
|
||||
|
||||
textBaseline = [
|
||||
'top', 'top', 'top',
|
||||
'middle', 'middle', 'middle',
|
||||
'bottom', 'bottom', 'bottom'
|
||||
];
|
||||
|
||||
Component.prototype.draw_text = function(c,text,x,y,alignment,size,fill) {
|
||||
var a = aOrient[this.rotation*9 + alignment];
|
||||
c.textAlign = textAlign[a];
|
||||
c.textBaseline = textBaseline[a];
|
||||
if (fill == undefined)
|
||||
c.fillStyle = this.selected ? selected_style : normal_style;
|
||||
else
|
||||
c.fillStyle = fill;
|
||||
this.sch.draw_text(c,text,
|
||||
this.transform_x(x,y) + this.x,
|
||||
this.transform_y(x,y) + this.y,
|
||||
size);
|
||||
}
|
||||
|
||||
Component.prototype.set_select = function(which) {
|
||||
if (which != this.selected) {
|
||||
this.selected = which;
|
||||
// create an undoable edit record here
|
||||
}
|
||||
}
|
||||
|
||||
Component.prototype.select = function(x,y,shiftKey) {
|
||||
this.was_previously_selected = this.selected;
|
||||
if (this.near(x,y)) {
|
||||
this.set_select(shiftKey ? !this.selected : true);
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
Component.prototype.select_rect = function(s) {
|
||||
this.was_previously_selected = this.selected;
|
||||
if (intersect(this.bbox,s))
|
||||
this.set_select(true);
|
||||
}
|
||||
|
||||
// if connection point of component c bisects the
|
||||
// wire represented by this compononent, return that
|
||||
// connection point. Otherwise return null.
|
||||
Component.prototype.bisect = function(c) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// does mouse click fall on this component?
|
||||
Component.prototype.near = function(x,y) {
|
||||
return inside(this.bbox,x,y);
|
||||
}
|
||||
|
||||
Component.prototype.edit_properties = function(x,y) {
|
||||
if (this.near(x,y)) {
|
||||
// make an <input> widget for each property
|
||||
var fields = new Array();
|
||||
for (var i in this.properties)
|
||||
// underscore at beginning of property name => system property
|
||||
if (i.charAt(0) != '_')
|
||||
fields[i] = build_input('text',10,this.properties[i]);
|
||||
|
||||
var content = build_table(fields);
|
||||
content.fields = fields;
|
||||
content.component = this;
|
||||
|
||||
this.sch.dialog('Edit Properties',content,function(content) {
|
||||
for (var i in content.fields)
|
||||
content.component.properties[i] = content.fields[i].value;
|
||||
content.component.sch.redraw_background();
|
||||
});
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
// clear the labels on all connections
|
||||
Component.prototype.clear_labels = function() {
|
||||
for (var i = this.connections.length - 1; i >=0; --i) {
|
||||
this.connections[i].clear_label();
|
||||
}
|
||||
}
|
||||
|
||||
// default action: don't propagate label
|
||||
Component.prototype.propagate_label = function(label) {
|
||||
}
|
||||
|
||||
// give components a chance to generate default labels for their connection(s)
|
||||
// default action: do nothing
|
||||
Component.prototype.add_default_labels = function() {
|
||||
}
|
||||
|
||||
// component should generate labels for all unlabeled connections
|
||||
Component.prototype.label_connections = function() {
|
||||
for (var i = this.connections.length - 1; i >=0; --i) {
|
||||
var cp = this.connections[i];
|
||||
if (!cp.label)
|
||||
cp.propagate_label(this.sch.get_next_label());
|
||||
}
|
||||
}
|
||||
|
||||
// default behavior: no probe info
|
||||
Component.prototype.probe_info = function() { return undefined; }
|
||||
|
||||
// default behavior: nothing to display for DC analysis
|
||||
Component.prototype.display_current = function(c,vmap) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Connection point
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
connection_point_radius = 2;
|
||||
|
||||
function ConnectionPoint(parent,x,y) {
|
||||
this.parent = parent;
|
||||
this.offset_x = x;
|
||||
this.offset_y = y;
|
||||
this.location = '';
|
||||
this.update_location();
|
||||
this.label = undefined;
|
||||
}
|
||||
|
||||
ConnectionPoint.prototype.toString = function() {
|
||||
return '<ConnectionPoint ('+this.offset_x+','+this.offset_y+') '+this.parent.toString()+'>';
|
||||
}
|
||||
|
||||
ConnectionPoint.prototype.json = function() {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
ConnectionPoint.prototype.clear_label = function() {
|
||||
this.label = undefined;
|
||||
}
|
||||
|
||||
ConnectionPoint.prototype.propagate_label = function(label) {
|
||||
// should we check if existing label is the same? it should be...
|
||||
|
||||
if (this.label === undefined) {
|
||||
// label this connection point
|
||||
this.label = label;
|
||||
|
||||
// propagate label to coincident connection points
|
||||
this.parent.sch.propagate_label(label,this.location);
|
||||
|
||||
// possibly label other cp's for this device?
|
||||
this.parent.propagate_label(label);
|
||||
} else if (this.label != '0' && label != '0' && this.label != label)
|
||||
alert("Node has two conflicting labels: "+this.label+", "+label);
|
||||
}
|
||||
|
||||
ConnectionPoint.prototype.update_location = function() {
|
||||
// update location string which we use as a key to find coincident connection points
|
||||
var old_location = this.location;
|
||||
var parent = this.parent;
|
||||
var nx = parent.transform_x(this.offset_x,this.offset_y) + parent.x;
|
||||
var ny = parent.transform_y(this.offset_x,this.offset_y) + parent.y;
|
||||
this.x = nx;
|
||||
this.y = ny;
|
||||
this.location = nx + ',' + ny;
|
||||
|
||||
// add ourselves to the connection list for the new location
|
||||
if (parent.sch)
|
||||
parent.sch.update_connection_point(this,old_location);
|
||||
}
|
||||
|
||||
ConnectionPoint.prototype.coincident = function(x,y) {
|
||||
return this.x==x && this.y==y;
|
||||
}
|
||||
|
||||
ConnectionPoint.prototype.draw = function(c,n) {
|
||||
if (n != 2)
|
||||
this.parent.draw_circle(c,this.offset_x,this.offset_y,connection_point_radius,n > 2);
|
||||
}
|
||||
|
||||
ConnectionPoint.prototype.draw_x = function(c) {
|
||||
this.parent.draw_line(c,this.offset_x-2,this.offset_y-2,this.offset_x+2,this.offset_y+2,grid_style);
|
||||
this.parent.draw_line(c,this.offset_x+2,this.offset_y-2,this.offset_x-2,this.offset_y+2,grid_style);
|
||||
}
|
||||
|
||||
ConnectionPoint.prototype.display_voltage = function(c,vmap) {
|
||||
var v = vmap[this.label];
|
||||
if (v != undefined) {
|
||||
var label = v.toFixed(2) + 'V';
|
||||
|
||||
// first draw some solid blocks in the background
|
||||
c.globalAlpha = 0.85;
|
||||
this.parent.draw_text(c,'\u2588\u2588\u2588',this.offset_x,this.offset_y,
|
||||
4,annotation_size,element_style);
|
||||
c.globalAlpha = 1.0;
|
||||
|
||||
// display the node voltage at this connection point
|
||||
this.parent.draw_text(c,label,this.offset_x,this.offset_y,
|
||||
4,annotation_size,annotation_style);
|
||||
|
||||
// only display each node voltage once
|
||||
delete vmap[this.label];
|
||||
}
|
||||
}
|
||||
|
||||
// see if three connection points are collinear
|
||||
function collinear(p1,p2,p3) {
|
||||
// from http://mathworld.wolfram.com/Collinear.html
|
||||
var area = p1.x*(p2.y - p3.y) + p2.x*(p3.y - p1.y) + p3.x*(p1.y - p2.y);
|
||||
return area == 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Wire
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
near_distance = 2; // how close to wire counts as "near by"
|
||||
|
||||
function Wire(x1,y1,x2,y2) {
|
||||
// arbitrarily call x1,y1 the origin
|
||||
Component.call(this,'w',x1,y1,0);
|
||||
this.dx = x2 - x1;
|
||||
this.dy = y2 - y1;
|
||||
this.add_connection(0,0);
|
||||
this.add_connection(this.dx,this.dy);
|
||||
|
||||
// compute bounding box (expanded slightly)
|
||||
var r = [0,0,this.dx,this.dy];
|
||||
canonicalize(r);
|
||||
r[0] -= near_distance;
|
||||
r[1] -= near_distance;
|
||||
r[2] += near_distance;
|
||||
r[3] += near_distance;
|
||||
this.bounding_box = r;
|
||||
this.update_coords(); // update bbox
|
||||
|
||||
// used in selection calculations
|
||||
this.len = Math.sqrt(this.dx*this.dx + this.dy*this.dy);
|
||||
}
|
||||
Wire.prototype = new Component();
|
||||
Wire.prototype.constructor = Wire;
|
||||
|
||||
Wire.prototype.toString = function() {
|
||||
return '<Wire ('+this.x+','+this.y+') ('+(this.x+this.dx)+','+(this.y+this.dy)+')>';
|
||||
}
|
||||
|
||||
// return connection point at other end of wire from specified cp
|
||||
Wire.prototype.other_end = function(cp) {
|
||||
if (cp == this.connections[0]) return this.connections[1];
|
||||
else if (cp == this.connections[1]) return this.connections[0];
|
||||
else return undefined;
|
||||
}
|
||||
|
||||
Wire.prototype.json = function(index) {
|
||||
var json = ['w',[this.x, this.y, this.x+this.dx, this.y+this.dy]];
|
||||
return json;
|
||||
}
|
||||
|
||||
Wire.prototype.draw = function(c) {
|
||||
this.draw_line(c,0,0,this.dx,this.dy);
|
||||
}
|
||||
|
||||
Wire.prototype.clone = function(x,y) {
|
||||
return new Wire(x,y,x+this.dx,y+this.dy);
|
||||
}
|
||||
|
||||
Wire.prototype.near = function(x,y) {
|
||||
// crude check: (x,y) within expanded bounding box of wire
|
||||
if (inside(this.bbox,x,y)) {
|
||||
// compute distance between x,y and nearst point on line
|
||||
// http://www.allegro.cc/forums/thread/589720
|
||||
var D = Math.abs((x - this.x)*this.dy - (y - this.y)*this.dx)/this.len;
|
||||
if (D <= near_distance) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// selection rectangle selects wire only if it includes
|
||||
// one of the end points
|
||||
Wire.prototype.select_rect = function(s) {
|
||||
this.was_previously_selected = this.selected;
|
||||
if (inside(s,this.x,this.y) || inside(s,this.x+this.dx,this.y+this.dy))
|
||||
this.set_select(true);
|
||||
}
|
||||
|
||||
// if connection point cp bisects the
|
||||
// wire represented by this compononent, return true
|
||||
Wire.prototype.bisect_cp = function(cp) {
|
||||
var x = cp.x;
|
||||
var y = cp.y;
|
||||
|
||||
// crude check: (x,y) within expanded bounding box of wire
|
||||
if (inside(this.bbox,x,y)) {
|
||||
// compute distance between x,y and nearst point on line
|
||||
// http://www.allegro.cc/forums/thread/589720
|
||||
var D = Math.abs((x - this.x)*this.dy - (y - this.y)*this.dx)/this.len;
|
||||
// final check: ensure point isn't an end point of the wire
|
||||
if (D < 1 && !this.connections[0].coincident(x,y) && !this.connections[1].coincident(x,y))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// if some connection point of component c bisects the
|
||||
// wire represented by this compononent, return that
|
||||
// connection point. Otherwise return null.
|
||||
Wire.prototype.bisect = function(c) {
|
||||
if (c == undefined) return;
|
||||
for (var i = c.connections.length - 1; i >= 0; --i) {
|
||||
var cp = c.connections[i];
|
||||
if (this.bisect_cp(cp)) return cp;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Wire.prototype.move_end = function() {
|
||||
// look for wires bisected by this wire
|
||||
this.sch.check_wires(this);
|
||||
|
||||
// look for connection points that might bisect us
|
||||
this.sch.check_connection_points(this);
|
||||
}
|
||||
|
||||
// wires "conduct" their label to the other end
|
||||
Wire.prototype.propagate_label = function(label) {
|
||||
// don't worry about relabeling a cp, it won't recurse!
|
||||
this.connections[0].propagate_label(label);
|
||||
this.connections[1].propagate_label(label);
|
||||
}
|
||||
|
||||
// Wires have no properties to edit
|
||||
Wire.prototype.edit_properties = function(x,y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// some actual component will start the labeling of electrical nodes,
|
||||
// so do nothing here
|
||||
Wire.prototype.label_connections = function() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Ground
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Ground(x,y,rotation) {
|
||||
Component.call(this,'g',x,y,rotation);
|
||||
this.add_connection(0,0);
|
||||
this.bounding_box = [-6,0,6,8];
|
||||
this.update_coords();
|
||||
}
|
||||
Ground.prototype = new Component();
|
||||
Ground.prototype.constructor = Ground;
|
||||
|
||||
Ground.prototype.toString = function() {
|
||||
return '<Ground ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
Ground.prototype.draw = function(c) {
|
||||
Component.prototype.draw.call(this,c); // give superclass a shot
|
||||
this.draw_line(c,0,0,0,8);
|
||||
this.draw_line(c,-6,8,6,8);
|
||||
}
|
||||
|
||||
Ground.prototype.clone = function(x,y) {
|
||||
return new Ground(x,y,this.rotation);
|
||||
}
|
||||
|
||||
// Grounds no properties to edit
|
||||
Ground.prototype.edit_properties = function(x,y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// give components a chance to generate a label for their connection(s)
|
||||
// default action: do nothing
|
||||
Ground.prototype.add_default_labels = function() {
|
||||
this.connections[0].propagate_label('0'); // canonical label for GND node
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Label
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Label(x,y,rotation,label) {
|
||||
Component.call(this,'L',x,y,rotation);
|
||||
this.properties['label'] = label ? label : '???';
|
||||
this.add_connection(0,0);
|
||||
this.bounding_box = [-2,0,2,8];
|
||||
this.update_coords();
|
||||
}
|
||||
Label.prototype = new Component();
|
||||
Label.prototype.constructor = Label;
|
||||
|
||||
Label.prototype.toString = function() {
|
||||
return '<Label'+' ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
Label.prototype.draw = function(c) {
|
||||
Component.prototype.draw.call(this,c); // give superclass a shot
|
||||
this.draw_line(c,0,0,0,8);
|
||||
this.draw_text(c,this.properties['label'],0,9,1,property_size);
|
||||
}
|
||||
|
||||
Label.prototype.clone = function(x,y) {
|
||||
return new Label(x,y,this.rotation,this.properties['label']);
|
||||
}
|
||||
|
||||
// give components a chance to generate a label for their connection(s)
|
||||
// default action: do nothing
|
||||
Label.prototype.add_default_labels = function() {
|
||||
this.connections[0].propagate_label(this.properties['label']);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Voltage Probe
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
probe_colors = ['red','green','blue','cyan','magenta','yellow','black','x-axis'];
|
||||
probe_colors_rgb = {
|
||||
'red': 'rgb(255,64,64)',
|
||||
'green': 'rgb(64,255,64)',
|
||||
'blue': 'rgb(64,64,255)',
|
||||
'cyan': 'rgb(64,255,255)',
|
||||
'magenta' : 'rgb(255,64,255)',
|
||||
'yellow': 'rgb(255,255,64)',
|
||||
'black': 'rgb(0,0,0)',
|
||||
'x-axis': undefined,
|
||||
};
|
||||
|
||||
function Probe(x,y,rotation,color,offset) {
|
||||
Component.call(this,'s',x,y,rotation);
|
||||
this.add_connection(0,0);
|
||||
this.properties['color'] = color ? color : 'cyan';
|
||||
this.properties['offset'] = (offset==undefined || offset=='') ? '0' : offset;
|
||||
this.bounding_box = [0,0,27,-21];
|
||||
this.update_coords();
|
||||
}
|
||||
Probe.prototype = new Component();
|
||||
Probe.prototype.constructor = Probe;
|
||||
|
||||
Probe.prototype.toString = function() {
|
||||
return '<Probe ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
Probe.prototype.draw = function(c) {
|
||||
// draw outline
|
||||
this.draw_line(c,0,0,4,-4);
|
||||
this.draw_line(c,2,-6,6,-2);
|
||||
this.draw_line(c,2,-6,17,-21);
|
||||
this.draw_line(c,6,-2,21,-17);
|
||||
this.draw_line(c,17,-21,21,-17);
|
||||
this.draw_arc(c,19,-11,8,3*Math.PI/2,0);
|
||||
|
||||
// fill body with plot color
|
||||
var color = probe_colors_rgb[this.properties['color']];
|
||||
if (color != undefined) {
|
||||
c.fillStyle = color;
|
||||
c.beginPath();
|
||||
this.moveTo(c,2,-6);
|
||||
this.lineTo(c,6,-2);
|
||||
this.lineTo(c,21,-17);
|
||||
this.lineTo(c,17,-21);
|
||||
this.lineTo(c,2,-6);
|
||||
c.fill();
|
||||
} else {
|
||||
this.draw_text(c,this.properties['color'],27,-11,1,property_size);
|
||||
}
|
||||
}
|
||||
|
||||
Probe.prototype.clone = function(x,y) {
|
||||
return new Probe(x,y,this.rotation,this.properties['color'],this.properties['offset']);
|
||||
}
|
||||
|
||||
Probe.prototype.edit_properties = function(x,y) {
|
||||
if (inside(this.bbox,x,y)) {
|
||||
var fields = new Array();
|
||||
fields['Plot color'] = build_select(probe_colors,this.properties['color']);
|
||||
fields['Plot offset'] = build_input('text',10,this.properties['offset']);
|
||||
|
||||
var content = build_table(fields);
|
||||
content.fields = fields;
|
||||
content.component = this;
|
||||
|
||||
this.sch.dialog('Edit Properties',content,function(content) {
|
||||
var color_choice = content.fields['Plot color'];
|
||||
content.component.properties['color'] = probe_colors[color_choice.selectedIndex];
|
||||
content.component.properties['offset'] = content.fields['Plot offset'].value;
|
||||
content.component.sch.redraw_background();
|
||||
});
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
// return [color, node_label, offset, type] for this probe
|
||||
Probe.prototype.probe_info = function() {
|
||||
var color = this.properties['color'];
|
||||
var offset = this.properties['offset'];
|
||||
if (offset==undefined || offset=="") offset = '0';
|
||||
return [color,this.connections[0].label,offset,'voltage'];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Ammeter Probe
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Ammeter(x,y,rotation,color,offset) {
|
||||
Component.call(this,'a',x,y,rotation);
|
||||
this.add_connection(0,0); // pos
|
||||
this.add_connection(16,0); // neg
|
||||
this.properties['color'] = color ? color : 'magenta';
|
||||
this.properties['offset'] = (offset==undefined || offset=='') ? '0' : offset;
|
||||
this.bounding_box = [-3,0,16,3];
|
||||
this.update_coords();
|
||||
}
|
||||
Ammeter.prototype = new Component();
|
||||
Ammeter.prototype.constructor = Ammeter;
|
||||
|
||||
Ammeter.prototype.toString = function() {
|
||||
return '<Ammeter ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
Ammeter.prototype.move_end = function() {
|
||||
Component.prototype.move_end.call(this); // do the normal processing
|
||||
|
||||
// special for current probes: see if probe has been placed
|
||||
// in the middle of wire, creating three wire segments one
|
||||
// of which is shorting the two terminals of the probe. If
|
||||
// so, auto remove the shorting segment.
|
||||
var e1 = this.connections[0].location;
|
||||
var e2 = this.connections[1].location;
|
||||
var cplist = this.sch.find_connections(this.connections[0]);
|
||||
for (var i = cplist.length - 1; i >= 0; --i) {
|
||||
var c = cplist[i].parent; // a component connected to ammeter terminal
|
||||
// look for a wire whose end points match those of the ammeter
|
||||
if (c.type == 'w') {
|
||||
var c_e1 = c.connections[0].location;
|
||||
var c_e2 = c.connections[1].location;
|
||||
if ((e1 == c_e1 && c2 == c_e2) || (e1 == c_e2 && e2 == c_e1)) {
|
||||
c.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ammeter.prototype.draw = function(c) {
|
||||
this.draw_line(c,0,0,16,0);
|
||||
|
||||
// draw chevron in probe color
|
||||
c.strokeStyle = probe_colors_rgb[this.properties['color']];
|
||||
if (c.strokeStyle != undefined) {
|
||||
c.beginPath();
|
||||
this.moveTo(c,6,-3);
|
||||
this.lineTo(c,10,0);
|
||||
this.lineTo(c,6,3);
|
||||
c.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
Ammeter.prototype.clone = function(x,y) {
|
||||
return new Ammeter(x,y,this.rotation,this.properties['color'],this.properties['offset']);
|
||||
}
|
||||
|
||||
// share code with voltage probe
|
||||
Ammeter.prototype.edit_properties = Probe.prototype.edit_properties;
|
||||
|
||||
Ammeter.prototype.label = function() {
|
||||
var name = this.properties['name'];
|
||||
var label = 'I(' + (name ? name : '_' + this.properties['_json_']) + ')';
|
||||
return label;
|
||||
}
|
||||
|
||||
// display current for DC analysis
|
||||
Ammeter.prototype.display_current = function(c,vmap) {
|
||||
var label = this.label();
|
||||
var v = vmap[label];
|
||||
if (v != undefined) {
|
||||
var i = engineering_notation(v,2) + 'A';
|
||||
this.draw_text(c,i,8,-5,7,annotation_size,annotation_style);
|
||||
|
||||
// only display each current once
|
||||
delete vmap[label];
|
||||
}
|
||||
}
|
||||
|
||||
// return [color, current_label, offset, type] for this probe
|
||||
Ammeter.prototype.probe_info = function() {
|
||||
var color = this.properties['color'];
|
||||
var offset = this.properties['offset'];
|
||||
if (offset==undefined || offset=="") offset = '0';
|
||||
return [color,this.label(),offset,'current'];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Resistor
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Resistor(x,y,rotation,name,r) {
|
||||
Component.call(this,'r',x,y,rotation);
|
||||
this.properties['name'] = name;
|
||||
this.properties['r'] = r ? r : '1';
|
||||
this.add_connection(0,0);
|
||||
this.add_connection(0,48);
|
||||
this.bounding_box = [-5,0,5,48];
|
||||
this.update_coords();
|
||||
}
|
||||
Resistor.prototype = new Component();
|
||||
Resistor.prototype.constructor = Resistor;
|
||||
|
||||
Resistor.prototype.toString = function() {
|
||||
return '<Resistor '+this.properties['r']+' ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
Resistor.prototype.draw = function(c) {
|
||||
Component.prototype.draw.call(this,c); // give superclass a shot
|
||||
this.draw_line(c,0,0,0,12);
|
||||
this.draw_line(c,0,12,4,14);
|
||||
this.draw_line(c,4,14,-4,18);
|
||||
this.draw_line(c,-4,18,4,22);
|
||||
this.draw_line(c,4,22,-4,26);
|
||||
this.draw_line(c,-4,26,4,30);
|
||||
this.draw_line(c,4,30,-4,34);
|
||||
this.draw_line(c,-4,34,0,36);
|
||||
this.draw_line(c,0,36,0,48);
|
||||
if (this.properties['r'])
|
||||
this.draw_text(c,this.properties['r']+'\u03A9',5,24,3,property_size);
|
||||
if (this.properties['name'])
|
||||
this.draw_text(c,this.properties['name'],-5,24,5,property_size);
|
||||
}
|
||||
|
||||
Resistor.prototype.clone = function(x,y) {
|
||||
return new Resistor(x,y,this.rotation,this.properties['name'],this.properties['r']);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Capacitor
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Capacitor(x,y,rotation,name,c) {
|
||||
Component.call(this,'c',x,y,rotation);
|
||||
this.properties['name'] = name;
|
||||
this.properties['c'] = c ? c : '1p';
|
||||
this.add_connection(0,0);
|
||||
this.add_connection(0,48);
|
||||
this.bounding_box = [-8,0,8,48];
|
||||
this.update_coords();
|
||||
}
|
||||
Capacitor.prototype = new Component();
|
||||
Capacitor.prototype.constructor = Capacitor;
|
||||
|
||||
Capacitor.prototype.toString = function() {
|
||||
return '<Capacitor '+this.properties['r']+' ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
Capacitor.prototype.draw = function(c) {
|
||||
Component.prototype.draw.call(this,c); // give superclass a shot
|
||||
this.draw_line(c,0,0,0,22);
|
||||
this.draw_line(c,-8,22,8,22);
|
||||
this.draw_line(c,-8,26,8,26);
|
||||
this.draw_line(c,0,26,0,48);
|
||||
if (this.properties['c'])
|
||||
this.draw_text(c,this.properties['c']+'F',9,24,3,property_size);
|
||||
if (this.properties['name'])
|
||||
this.draw_text(c,this.properties['name'],-9,24,5,property_size);
|
||||
}
|
||||
|
||||
Capacitor.prototype.clone = function(x,y) {
|
||||
return new Capacitor(x,y,this.rotation,this.properties['name'],this.properties['c']);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Inductor
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Inductor(x,y,rotation,name,l) {
|
||||
Component.call(this,'l',x,y,rotation);
|
||||
this.properties['name'] = name;
|
||||
this.properties['l'] = l ? l : '1n';
|
||||
this.add_connection(0,0);
|
||||
this.add_connection(0,48);
|
||||
this.bounding_box = [-4,0,5,48];
|
||||
this.update_coords();
|
||||
}
|
||||
Inductor.prototype = new Component();
|
||||
Inductor.prototype.constructor = Inductor;
|
||||
|
||||
Inductor.prototype.toString = function() {
|
||||
return '<Inductor '+this.properties['l']+' ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
Inductor.prototype.draw = function(c) {
|
||||
Component.prototype.draw.call(this,c); // give superclass a shot
|
||||
this.draw_line(c,0,0,0,14);
|
||||
this.draw_arc(c,0,18,4,6*Math.PI/4,3*Math.PI/4);
|
||||
this.draw_arc(c,0,24,4,5*Math.PI/4,3*Math.PI/4);
|
||||
this.draw_arc(c,0,30,4,5*Math.PI/4,2*Math.PI/4);
|
||||
this.draw_line(c,0,34,0,48);
|
||||
|
||||
if (this.properties['l'])
|
||||
this.draw_text(c,this.properties['l']+'H',6,24,3,property_size);
|
||||
if (this.properties['name'])
|
||||
this.draw_text(c,this.properties['name'],-3,24,5,property_size);
|
||||
}
|
||||
|
||||
Inductor.prototype.clone = function(x,y) {
|
||||
return new Inductor(x,y,this.rotation,this.properties['name'],this.properties['l']);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Diode
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
diode_types = ['normal','ideal'];
|
||||
|
||||
function Diode(x,y,rotation,name,area,type) {
|
||||
Component.call(this,'d',x,y,rotation);
|
||||
this.properties['name'] = name;
|
||||
this.properties['area'] = area ? area : '1';
|
||||
this.properties['type'] = type ? type : 'normal';
|
||||
this.add_connection(0,0); // anode
|
||||
this.add_connection(0,48); // cathode
|
||||
this.bounding_box = (type == 'ideal') ? [-12,0,12,48] : [-8,0,8,48];
|
||||
this.update_coords();
|
||||
}
|
||||
Diode.prototype = new Component();
|
||||
Diode.prototype.constructor = Diode;
|
||||
|
||||
Diode.prototype.toString = function() {
|
||||
return '<Diode '+this.properties['area']+' ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
Diode.prototype.draw = function(c) {
|
||||
Component.prototype.draw.call(this,c); // give superclass a shot
|
||||
this.draw_line(c,0,0,0,16);
|
||||
this.draw_line(c,-8,16,8,16);
|
||||
this.draw_line(c,-8,16,0,32);
|
||||
this.draw_line(c,8,16,0,32);
|
||||
this.draw_line(c,-8,32,8,32);
|
||||
this.draw_line(c,0,32,0,48);
|
||||
|
||||
if (this.properties['type'] == 'ideal') {
|
||||
// put a box around an ideal diode
|
||||
this.draw_line(c,-10,12,10,12);
|
||||
this.draw_line(c,-10,12,-10,36);
|
||||
this.draw_line(c,10,12,10,36);
|
||||
this.draw_line(c,-10,36,10,36);
|
||||
}
|
||||
|
||||
if (this.properties['area'])
|
||||
this.draw_text(c,this.properties['area'],10,24,3,property_size);
|
||||
if (this.properties['name'])
|
||||
this.draw_text(c,this.properties['name'],-10,24,5,property_size);
|
||||
}
|
||||
|
||||
Diode.prototype.clone = function(x,y) {
|
||||
return new Diode(x,y,this.rotation,this.properties['name'],this.properties['area'],this.properties['type']);
|
||||
}
|
||||
|
||||
Diode.prototype.edit_properties = function(x,y) {
|
||||
if (inside(this.bbox,x,y)) {
|
||||
var fields = new Array();
|
||||
fields['name'] = build_input('text',10,this.properties['name']);
|
||||
fields['area'] = build_input('text',10,this.properties['area']);
|
||||
fields['type'] = build_select(diode_types,this.properties['type']);
|
||||
|
||||
var content = build_table(fields);
|
||||
content.fields = fields;
|
||||
content.component = this;
|
||||
|
||||
this.sch.dialog('Edit Properties',content,function(content) {
|
||||
content.component.properties['name'] = content.fields['name'].value;
|
||||
content.component.properties['area'] = content.fields['area'].value;
|
||||
content.component.properties['type'] = diode_types[content.fields['type'].selectedIndex];
|
||||
content.component.sch.redraw_background();
|
||||
});
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// N-channel Mosfet
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function NFet(x,y,rotation,name,w_over_l) {
|
||||
Component.call(this,'n',x,y,rotation);
|
||||
this.properties['name'] = name;
|
||||
this.properties['W/L'] = w_over_l ? w_over_l : '2';
|
||||
this.add_connection(0,0); // drain
|
||||
this.add_connection(-24,24); // gate
|
||||
this.add_connection(0,48); // source
|
||||
this.bounding_box = [-24,0,8,48];
|
||||
this.update_coords();
|
||||
}
|
||||
NFet.prototype = new Component();
|
||||
NFet.prototype.constructor = NFet;
|
||||
|
||||
NFet.prototype.toString = function() {
|
||||
return '<NFet '+this.properties['W/L']+' ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
NFet.prototype.draw = function(c) {
|
||||
Component.prototype.draw.call(this,c); // give superclass a shot
|
||||
this.draw_line(c,0,0,0,16);
|
||||
this.draw_line(c,-8,16,0,16);
|
||||
this.draw_line(c,-8,16,-8,32);
|
||||
this.draw_line(c,-8,32,0,32);
|
||||
this.draw_line(c,0,32,0,48);
|
||||
|
||||
this.draw_line(c,-24,24,-12,24);
|
||||
this.draw_line(c,-12,16,-12,32);
|
||||
|
||||
var dim = this.properties['W/L'];
|
||||
if (this.properties['name']) {
|
||||
this.draw_text(c,this.properties['name'],2,22,6,property_size);
|
||||
this.draw_text(c,dim,2,26,0,property_size);
|
||||
} else
|
||||
this.draw_text(c,dim,2,24,3,property_size);
|
||||
}
|
||||
|
||||
NFet.prototype.clone = function(x,y) {
|
||||
return new NFet(x,y,this.rotation,this.properties['name'],this.properties['W/L']);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// P-channel Mosfet
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function PFet(x,y,rotation,name,w_over_l) {
|
||||
Component.call(this,'p',x,y,rotation);
|
||||
this.properties['name'] = name;
|
||||
this.properties['W/L'] = w_over_l ? w_over_l : '2';
|
||||
this.add_connection(0,0); // drain
|
||||
this.add_connection(-24,24); // gate
|
||||
this.add_connection(0,48); // source
|
||||
this.bounding_box = [-24,0,8,48];
|
||||
this.update_coords();
|
||||
}
|
||||
PFet.prototype = new Component();
|
||||
PFet.prototype.constructor = PFet;
|
||||
|
||||
PFet.prototype.toString = function() {
|
||||
return '<PFet '+this.properties['W/L']+' ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
PFet.prototype.draw = function(c) {
|
||||
Component.prototype.draw.call(this,c); // give superclass a shot
|
||||
this.draw_line(c,0,0,0,16);
|
||||
this.draw_line(c,-8,16,0,16);
|
||||
this.draw_line(c,-8,16,-8,32);
|
||||
this.draw_line(c,-8,32,0,32);
|
||||
this.draw_line(c,0,32,0,48);
|
||||
|
||||
this.draw_line(c,-24,24,-16,24);
|
||||
|
||||
this.draw_circle(c,-14,24,2,false);
|
||||
this.draw_line(c,-12,16,-12,32);
|
||||
|
||||
var dim = this.properties['W/L'];
|
||||
if (this.properties['name']) {
|
||||
this.draw_text(c,this.properties['name'],2,22,6,property_size);
|
||||
this.draw_text(c,dim,2,26,0,property_size);
|
||||
} else
|
||||
this.draw_text(c,dim,2,24,3,property_size);
|
||||
}
|
||||
|
||||
PFet.prototype.clone = function(x,y) {
|
||||
return new PFet(x,y,this.rotation,this.properties['name'],this.properties['W/L']);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Op Amp
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function OpAmp(x,y,rotation,name,A) {
|
||||
Component.call(this,'o',x,y,rotation);
|
||||
this.properties['name'] = name;
|
||||
this.properties['A'] = A ? A : '30000';
|
||||
this.add_connection(0,0); // +
|
||||
this.add_connection(0,16); // -
|
||||
this.add_connection(48,8); // output
|
||||
this.add_connection(24,32); // ground
|
||||
this.bounding_box = [0,-8,48,32];
|
||||
this.update_coords();
|
||||
}
|
||||
OpAmp.prototype = new Component();
|
||||
OpAmp.prototype.constructor = OpAmp;
|
||||
|
||||
OpAmp.prototype.toString = function() {
|
||||
return '<OpAmp'+this.properties['A']+' ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
OpAmp.prototype.draw = function(c) {
|
||||
Component.prototype.draw.call(this,c); // give superclass a shot
|
||||
// triangle
|
||||
this.draw_line(c,8,-8,8,24);
|
||||
this.draw_line(c,8,-8,40,8);
|
||||
this.draw_line(c,8,24,40,8);
|
||||
// inputs and output
|
||||
this.draw_line(c,0,0,8,0);
|
||||
this.draw_line(c,0,16,8,16);
|
||||
this.draw_text(c,'gnd',37,18,property_size);
|
||||
this.draw_line(c,40,8,48,8);
|
||||
this.draw_line(c,24,16,24,32);
|
||||
// + and -
|
||||
this.draw_line(c,10,0,16,0);
|
||||
this.draw_line(c,13,-3,13,3);
|
||||
this.draw_line(c,10,16,16,16);
|
||||
|
||||
if (this.properties['name'])
|
||||
this.draw_text(c,this.properties['name'],32,16,0,property_size);
|
||||
}
|
||||
|
||||
OpAmp.prototype.clone = function(x,y) {
|
||||
return new OpAmp(x,y,this.rotation,this.properties['name'],this.properties['A']);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Source
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
function Source(x,y,rotation,name,type,value) {
|
||||
Component.call(this,type,x,y,rotation);
|
||||
this.properties['name'] = name;
|
||||
if (value == undefined) value = 'dc(1)';
|
||||
this.properties['value'] = value;
|
||||
this.add_connection(0,0);
|
||||
this.add_connection(0,48);
|
||||
this.bounding_box = [-12,0,12,48];
|
||||
this.update_coords();
|
||||
|
||||
this.content = document.createElement('div'); // used by edit_properties
|
||||
}
|
||||
Source.prototype = new Component();
|
||||
Source.prototype.constructor = Source;
|
||||
|
||||
Source.prototype.toString = function() {
|
||||
return '<'+this.type+'source '+this.properties['params']+' ('+this.x+','+this.y+')>';
|
||||
}
|
||||
|
||||
Source.prototype.draw = function(c) {
|
||||
Component.prototype.draw.call(this,c); // give superclass a shot
|
||||
this.draw_line(c,0,0,0,12);
|
||||
this.draw_circle(c,0,24,12,false);
|
||||
this.draw_line(c,0,36,0,48);
|
||||
|
||||
if (this.type == 'v') { // voltage source
|
||||
//this.draw_text(c,'+',0,12,1,property_size);
|
||||
//this.draw_text(c,'\u2013',0,36,7,property_size); // minus sign
|
||||
// draw + and -
|
||||
this.draw_line(c,0,15,0,21);
|
||||
this.draw_line(c,-3,18,3,18);
|
||||
this.draw_line(c,-3,30,3,30);
|
||||
// draw V
|
||||
//this.draw_line(c,-3,20,0,28);
|
||||
//this.draw_line(c,3,20,0,28);
|
||||
} else if (this.type == 'i') { // current source
|
||||
// draw arrow: pos to neg
|
||||
this.draw_line(c,0,15,0,32);
|
||||
this.draw_line(c,-3,26,0,32);
|
||||
this.draw_line(c,3,26,0,32);
|
||||
}
|
||||
|
||||
if (this.properties['name'])
|
||||
this.draw_text(c,this.properties['name'],-13,24,5,property_size);
|
||||
if (this.properties['value'])
|
||||
this.draw_text(c,this.properties['value'],13,24,3,property_size);
|
||||
}
|
||||
|
||||
// map source function name to labels for each source parameter
|
||||
source_functions = {
|
||||
'dc': ['DC value'],
|
||||
|
||||
'impulse': ['Height',
|
||||
'Width (secs)'],
|
||||
|
||||
'step': ['Initial value',
|
||||
'Plateau value',
|
||||
'Delay until step (secs)',
|
||||
'Rise time (secs)'],
|
||||
|
||||
'square': ['Initial value',
|
||||
'Plateau value',
|
||||
'Frequency (Hz)',
|
||||
'Duty cycle (%)'],
|
||||
|
||||
'triangle': ['Initial value',
|
||||
'Plateau value',
|
||||
'Frequency (Hz)'],
|
||||
|
||||
'pwl': ['Comma-separated list of alternating times and values'],
|
||||
|
||||
'pwl_repeating': ['Comma-separated list of alternating times and values'],
|
||||
|
||||
'pulse': ['Initial value',
|
||||
'Plateau value',
|
||||
'Delay until pulse (secs)',
|
||||
'Time for first transition (secs)',
|
||||
'Time for second transition (secs)',
|
||||
'Pulse width (secs)',
|
||||
'Period (secs)'],
|
||||
|
||||
'sin': ['Offset value',
|
||||
'Amplitude',
|
||||
'Frequency (Hz)',
|
||||
'Delay until sin starts (secs)',
|
||||
'Phase offset (degrees)'],
|
||||
}
|
||||
|
||||
// build property editor div
|
||||
Source.prototype.build_content = function(src) {
|
||||
// make an <input> widget for each property
|
||||
var fields = []
|
||||
fields['name'] = build_input('text',10,this.properties['name']);
|
||||
|
||||
if (src == undefined) {
|
||||
fields['value'] = this.properties['value'];
|
||||
} else {
|
||||
// fancy version: add select tag for source type
|
||||
var src_types = [];
|
||||
for (var t in source_functions) src_types.push(t);
|
||||
var type_select = build_select(src_types,src.fun);
|
||||
type_select.component = this;
|
||||
type_select.addEventListener('change',source_type_changed,false)
|
||||
fields['type'] = type_select;
|
||||
|
||||
if (src.fun == 'pwl' || src.run == 'pwl_repeating') {
|
||||
var v = '';
|
||||
var first = true;
|
||||
for (var i = 0; i < src.args.length; i++) {
|
||||
if (first) first = false;
|
||||
else v += ',';
|
||||
v += engineering_notation(src.args[i],3);
|
||||
if (i % 2 == 0) v += 's';
|
||||
}
|
||||
fields[source_functions[src.fun][0]] = build_input('text',30,v);
|
||||
} else {
|
||||
// followed separate input tag for each parameter
|
||||
var labels = source_functions[src.fun];
|
||||
for (var i = 0; i < labels.length; i++) {
|
||||
var v = engineering_notation(src.args[i],3);
|
||||
fields[labels[i]] = build_input('text',10,v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var div = this.content;
|
||||
if (div.hasChildNodes())
|
||||
div.removeChild(div.firstChild); // remove table of input fields
|
||||
div.appendChild(build_table(fields));
|
||||
div.fields = fields;
|
||||
div.component = this;
|
||||
return div;
|
||||
}
|
||||
|
||||
function source_type_changed(event) {
|
||||
if (!event) event = window.event;
|
||||
var select = (window.event) ? event.srcElement : event.target;
|
||||
|
||||
// see where to get source parameters from
|
||||
var type = select.options[select.selectedIndex].value;
|
||||
var src = undefined;
|
||||
if (this.src != undefined && type == this.src.fun)
|
||||
src = this.src;
|
||||
else if (typeof cktsim != 'undefined')
|
||||
src = cktsim.parse_source(type+'()');
|
||||
|
||||
select.component.build_content(src);
|
||||
}
|
||||
|
||||
Source.prototype.edit_properties = function(x,y) {
|
||||
if (this.near(x,y)) {
|
||||
this.src = undefined;
|
||||
if (typeof cktsim != 'undefined')
|
||||
this.src = cktsim.parse_source(this.properties['value']);
|
||||
var content = this.build_content(this.src);
|
||||
|
||||
this.sch.dialog('Edit Properties',content,function(content) {
|
||||
var c = content.component;
|
||||
var fields = content.fields;
|
||||
|
||||
var first = true;
|
||||
var value = '';
|
||||
for (var label in fields) {
|
||||
if (label == 'name')
|
||||
c.properties['name'] = fields['name'].value;
|
||||
else if (label == 'value') {
|
||||
// if unknown source type
|
||||
value = fields['value'].value;
|
||||
c.sch.redraw_background();
|
||||
return;
|
||||
} else if (label == 'type') {
|
||||
var select = fields['type'];
|
||||
value = select.options[select.selectedIndex].value + '(';
|
||||
} else {
|
||||
if (first) first = false;
|
||||
else value += ',';
|
||||
value += fields[label].value;
|
||||
}
|
||||
}
|
||||
c.properties['value'] = value + ')';
|
||||
c.sch.redraw_background();
|
||||
});
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
|
||||
function VSource(x,y,rotation,name,value) {
|
||||
Source.call(this,x,y,rotation,name,'v',value);
|
||||
this.type = 'v';
|
||||
}
|
||||
VSource.prototype = new Component();
|
||||
VSource.prototype.constructor = VSource;
|
||||
VSource.prototype.toString = Source.prototype.toString;
|
||||
VSource.prototype.draw = Source.prototype.draw;
|
||||
VSource.prototype.clone = Source.prototype.clone;
|
||||
VSource.prototype.build_content = Source.prototype.build_content;
|
||||
VSource.prototype.edit_properties = Source.prototype.edit_properties;
|
||||
|
||||
// display current for DC analysis
|
||||
VSource.prototype.display_current = function(c,vmap) {
|
||||
var name = this.properties['name'];
|
||||
var label = 'I(' + (name ? name : '_' + this.properties['_json_']) + ')';
|
||||
var v = vmap[label];
|
||||
if (v != undefined) {
|
||||
// first draw some solid blocks in the background
|
||||
c.globalAlpha = 0.5;
|
||||
this.draw_text(c,'\u2588\u2588\u2588',-8,8,4,annotation_size,element_style);
|
||||
c.globalAlpha = 1.0;
|
||||
|
||||
// display the element current
|
||||
var i = engineering_notation(v,2) + 'A';
|
||||
this.draw_text(c,i,-3,5,5,annotation_size,annotation_style);
|
||||
// draw arrow for current
|
||||
this.draw_line(c,-3,4,0,8);
|
||||
this.draw_line(c,3,4,0,8);
|
||||
// only display each current once
|
||||
delete vmap[label];
|
||||
}
|
||||
}
|
||||
|
||||
VSource.prototype.clone = function(x,y) {
|
||||
return new VSource(x,y,this.rotation,this.properties['name'],this.properties['value']);
|
||||
}
|
||||
|
||||
function ISource(x,y,rotation,name,value) {
|
||||
Source.call(this,x,y,rotation,name,'i',value);
|
||||
this.type = 'i';
|
||||
}
|
||||
ISource.prototype = new Component();
|
||||
ISource.prototype.constructor = ISource;
|
||||
ISource.prototype.toString = Source.prototype.toString;
|
||||
ISource.prototype.draw = Source.prototype.draw;
|
||||
ISource.prototype.clone = Source.prototype.clone;
|
||||
ISource.prototype.build_content = Source.prototype.build_content;
|
||||
ISource.prototype.edit_properties = Source.prototype.edit_properties;
|
||||
|
||||
ISource.prototype.clone = function(x,y) {
|
||||
return new ISource(x,y,this.rotation,this.properties['name'],this.properties['value']);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// JQuery slider support for setting a component value
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function component_slider(event,ui) {
|
||||
var sname = $(this).slider("option","schematic");
|
||||
|
||||
// set value of specified component
|
||||
var cname = $(this).slider("option","component");
|
||||
var pname = $(this).slider("option","property");
|
||||
var suffix = $(this).slider("option","suffix");
|
||||
if (typeof suffix != "string") suffix = "";
|
||||
|
||||
var v = ui.value;
|
||||
$(this).slider("value",v); // move slider's indicator
|
||||
|
||||
var choices = $(this).slider("option","choices");
|
||||
if (choices instanceof Array) v = choices[v];
|
||||
|
||||
// selector may match several schematics
|
||||
$("." + sname).each(function(index,element) {
|
||||
element.schematic.set_property(cname,pname,v.toString() + suffix);
|
||||
})
|
||||
|
||||
// perform requested analysis
|
||||
var analysis = $(this).slider("option","analysis");
|
||||
if (analysis == "dc")
|
||||
$("." + sname).each(function(index,element) {
|
||||
element.schematic.dc_analysis();
|
||||
})
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Module definition
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var module = {
|
||||
'Schematic': Schematic,
|
||||
'component_slider': component_slider,
|
||||
}
|
||||
return module;
|
||||
}());
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"start": [],
|
||||
"end": [],
|
||||
"text": []
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"start": [],
|
||||
"end": [],
|
||||
"text": []
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"start": [],
|
||||
"end": [],
|
||||
"text": []
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"start": [],
|
||||
"end": [],
|
||||
"text": []
|
||||
}
|
||||
@@ -1,275 +0,0 @@
|
||||
{
|
||||
"start": [
|
||||
0,
|
||||
410,
|
||||
2390,
|
||||
5510,
|
||||
7110,
|
||||
10400,
|
||||
13120,
|
||||
15150,
|
||||
18850,
|
||||
20800,
|
||||
25570,
|
||||
27950,
|
||||
32870,
|
||||
36560,
|
||||
38920,
|
||||
40850,
|
||||
43130,
|
||||
46690,
|
||||
48640,
|
||||
50910,
|
||||
54260,
|
||||
56872,
|
||||
59590,
|
||||
63370,
|
||||
66290,
|
||||
68000,
|
||||
71320,
|
||||
74130,
|
||||
77880,
|
||||
80860,
|
||||
81900,
|
||||
85380,
|
||||
89890,
|
||||
93550,
|
||||
97980,
|
||||
100960,
|
||||
104010,
|
||||
105450,
|
||||
107320,
|
||||
110600,
|
||||
114310,
|
||||
116940,
|
||||
118800,
|
||||
122550,
|
||||
124950,
|
||||
127000,
|
||||
129479,
|
||||
131740,
|
||||
133570,
|
||||
137170,
|
||||
141410,
|
||||
143740,
|
||||
146820,
|
||||
148870,
|
||||
152620,
|
||||
157640,
|
||||
162970,
|
||||
164060,
|
||||
167630,
|
||||
168680,
|
||||
171890,
|
||||
173700,
|
||||
177560,
|
||||
181850,
|
||||
185390,
|
||||
189290,
|
||||
191550,
|
||||
196470,
|
||||
197780,
|
||||
202150,
|
||||
204550,
|
||||
208200,
|
||||
210910,
|
||||
213870,
|
||||
218830,
|
||||
222090,
|
||||
225070,
|
||||
229290,
|
||||
233580,
|
||||
236700,
|
||||
239510,
|
||||
242110,
|
||||
243770,
|
||||
246990,
|
||||
247950,
|
||||
251740,
|
||||
255340,
|
||||
256500,
|
||||
258759
|
||||
],
|
||||
"end": [
|
||||
410,
|
||||
2390,
|
||||
5510,
|
||||
7109,
|
||||
10400,
|
||||
13120,
|
||||
15149,
|
||||
18850,
|
||||
20800,
|
||||
25570,
|
||||
27950,
|
||||
32870,
|
||||
36559,
|
||||
38920,
|
||||
40850,
|
||||
43130,
|
||||
46690,
|
||||
48640,
|
||||
50910,
|
||||
54260,
|
||||
56872,
|
||||
59590,
|
||||
63370,
|
||||
66289,
|
||||
68000,
|
||||
71320,
|
||||
74130,
|
||||
77880,
|
||||
80860,
|
||||
81900,
|
||||
85380,
|
||||
89890,
|
||||
93550,
|
||||
97979,
|
||||
100960,
|
||||
104009,
|
||||
105450,
|
||||
107320,
|
||||
110600,
|
||||
114309,
|
||||
116940,
|
||||
118800,
|
||||
122550,
|
||||
124950,
|
||||
127000,
|
||||
129479,
|
||||
131740,
|
||||
133570,
|
||||
137170,
|
||||
141410,
|
||||
143740,
|
||||
146820,
|
||||
148870,
|
||||
152620,
|
||||
157640,
|
||||
162970,
|
||||
164060,
|
||||
167630,
|
||||
168680,
|
||||
171890,
|
||||
173700,
|
||||
177560,
|
||||
181850,
|
||||
185390,
|
||||
189290,
|
||||
191549,
|
||||
196470,
|
||||
197780,
|
||||
202150,
|
||||
204550,
|
||||
208200,
|
||||
210910,
|
||||
213870,
|
||||
218830,
|
||||
222090,
|
||||
225070,
|
||||
229290,
|
||||
233579,
|
||||
236700,
|
||||
239510,
|
||||
242109,
|
||||
243770,
|
||||
246990,
|
||||
247950,
|
||||
251739,
|
||||
255340,
|
||||
256500,
|
||||
258759,
|
||||
260009
|
||||
],
|
||||
"text": [
|
||||
null,
|
||||
"Let us summarize what we've\nlearned so far.",
|
||||
"So we started out with building\nthis playground, this",
|
||||
"EECS playground.",
|
||||
"And within this playground,\nwe've all decided that we will",
|
||||
"abide by the lumped matter\ndiscipline, the LMD.",
|
||||
"And these are simply constraints\nthat we impose",
|
||||
"upon ourselves to simplify\nour analysis.",
|
||||
"Notice that, you really\ndon't have to do that.",
|
||||
"You are welcome to hang out here\nand do whatever you want.",
|
||||
"But you might have a\nlot of fun as well.",
|
||||
"But, you will not be able to\nbuild things as simply as you",
|
||||
"would if you were inside\nthe EECS playground.",
|
||||
"But, Within this playground\nyou have promised that you",
|
||||
"will follow the lumped\nmatter discipline.",
|
||||
"Lumped matter discipline has\nthree components to it.",
|
||||
"One is that the elements will\nhave del phi b by del t equals",
|
||||
"zero, outside the elements.",
|
||||
"In other words, when you build\ncircuits, you want to make",
|
||||
"sure that the del phi b by del\nt is going to be zero.",
|
||||
"And inside the elements, we are\ngoing to make sure that",
|
||||
"when you define something--\ndescribe something as a lumped",
|
||||
"element, del q by del t,\nfor that element--",
|
||||
"the net del q by del t for\nthat element inside the",
|
||||
"element is going to be zero.",
|
||||
"And that's going to be true\nfor all your elements,",
|
||||
"registers, sources,\nwires, and so on.",
|
||||
"And the third element is that\nyou will only focus on signal",
|
||||
"speeds of interest that\nwill be way lower than",
|
||||
"the speed of light.",
|
||||
"Now one of the interesting facts\nof life is that as our",
|
||||
"microprocessors get faster and\nfaster, some of the chips",
|
||||
"inside your iPhones, and your\ndesktops, and so on, are",
|
||||
"clocking at speeds in excess\nof three to four gigahertz.",
|
||||
"When signal speeds are that\nfast, we are now getting to a",
|
||||
"point where the signal speeds\ninside our chips are",
|
||||
"approaching the speed\nof light.",
|
||||
"So they're not all\nthat far off.",
|
||||
"And so therefore, over the next\ndecade, as people try to",
|
||||
"push speeds to even higher\nvalues, various things are",
|
||||
"going to start breaking unless\nwe change things",
|
||||
"dramatically somehow.",
|
||||
"What this does is these\ndiscipline elements, the",
|
||||
"lumped matter discipline,\nenables us to create the",
|
||||
"lumped circuit abstraction.",
|
||||
"Look at our lumped elements.",
|
||||
"Lumped elements will\nbe described",
|
||||
"by their v-i relation.",
|
||||
"So each of these lumped elements\nof that sum i, that",
|
||||
"would be sum function of\nv, the v-i relation.",
|
||||
"The relation could be linear,\ncould be non-linear.",
|
||||
"Could be, in general, could be\nanything, just that they have",
|
||||
"some v-i relation.",
|
||||
"For the register you saw that\ni was v divided by R.",
|
||||
"For some other element, it could\nbe that i is 6.7 times v",
|
||||
"squared plus v divided by\n2 plus some constant 1.",
|
||||
"I mean, who knows.",
|
||||
"That could be some function of\nv. Could be linear, could be",
|
||||
"non-linear.",
|
||||
"And for this element, the power\nconsumed by the element",
|
||||
"is given by vi.",
|
||||
"Finally, we showed that when\nyou make the lumped matter",
|
||||
"discipline assumptions,\nMaxwell's equations simplify",
|
||||
"to extremely simple\nKVL and KCL.",
|
||||
"So, for example, KVL simply\nsays that the sum of the",
|
||||
"voltages around a\nloop is zero.",
|
||||
"While KCL says that the sum of\nthe current that go into a",
|
||||
"node is zero.",
|
||||
"You can also say the currents\ncoming out of a node are zero",
|
||||
"by the same principle.",
|
||||
"What is amazing about this is\nthat by making the lumped",
|
||||
"matter discipline, by abiding\nby the lumped matter",
|
||||
"discipline, we have been able\nto convert the use of",
|
||||
"Maxwell's equation into the use\nof very simple algebra.",
|
||||
"So we replaced our del phi's and\ndel t's, and all of that",
|
||||
"stuff, with extremely\nsimple algebra.",
|
||||
"And in the next set of segments\nI'm going to show you",
|
||||
"how we can simplify and analyze\ncircuits extremely",
|
||||
"easily using very, very\nsimple algebra.",
|
||||
"And, in fact, for the first half\nof this course, you are",
|
||||
"not going to see any\nsquigglies at all.",
|
||||
"It's going to be very,\nvery simple.",
|
||||
"And even later, we're not going\nto be seeing any partial",
|
||||
"differential equations.",
|
||||
"We will see some fairly simple\ndifferential equations, but by",
|
||||
"making the LMD assumptions, we\nhave really gotten rid of a",
|
||||
"lot of the complexity.",
|
||||
"And things are going to be\nreally, really, really simple.",
|
||||
null
|
||||
]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"start": [],
|
||||
"end": [],
|
||||
"text": []
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"start": [],
|
||||
"end": [],
|
||||
"text": []
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
{
|
||||
"start": [
|
||||
0,
|
||||
1800,
|
||||
2440,
|
||||
7270,
|
||||
11690,
|
||||
13030,
|
||||
17060,
|
||||
21240,
|
||||
24980,
|
||||
29930,
|
||||
33740,
|
||||
37930,
|
||||
40340,
|
||||
46830,
|
||||
50200,
|
||||
52890,
|
||||
56355,
|
||||
59450,
|
||||
60430,
|
||||
66640,
|
||||
69640,
|
||||
72148,
|
||||
73398,
|
||||
77730,
|
||||
83080,
|
||||
84330,
|
||||
99630,
|
||||
103660,
|
||||
110800,
|
||||
114250,
|
||||
118220,
|
||||
121940,
|
||||
131580,
|
||||
134300,
|
||||
137730,
|
||||
140540,
|
||||
143860,
|
||||
146050,
|
||||
147300,
|
||||
149850,
|
||||
157140,
|
||||
161820,
|
||||
164460,
|
||||
165600,
|
||||
169520,
|
||||
174040,
|
||||
176290,
|
||||
178310,
|
||||
181070,
|
||||
182920,
|
||||
184160,
|
||||
189960,
|
||||
192630,
|
||||
193480,
|
||||
199020,
|
||||
201540,
|
||||
204520,
|
||||
208180,
|
||||
211470,
|
||||
217120,
|
||||
220790,
|
||||
224490,
|
||||
227200,
|
||||
229150,
|
||||
232940,
|
||||
236320,
|
||||
239070,
|
||||
242480
|
||||
],
|
||||
"end": [
|
||||
1800,
|
||||
2440,
|
||||
7270,
|
||||
11690,
|
||||
13030,
|
||||
17060,
|
||||
21240,
|
||||
24979,
|
||||
29930,
|
||||
33740,
|
||||
37930,
|
||||
40340,
|
||||
46830,
|
||||
50199,
|
||||
52890,
|
||||
56355,
|
||||
59449,
|
||||
60430,
|
||||
66640,
|
||||
69640,
|
||||
72148,
|
||||
73398,
|
||||
77729,
|
||||
83080,
|
||||
84330,
|
||||
99630,
|
||||
103660,
|
||||
110800,
|
||||
114250,
|
||||
118220,
|
||||
121940,
|
||||
131579,
|
||||
134300,
|
||||
137730,
|
||||
140540,
|
||||
143859,
|
||||
146050,
|
||||
147300,
|
||||
149850,
|
||||
157140,
|
||||
161820,
|
||||
164459,
|
||||
165600,
|
||||
169519,
|
||||
174040,
|
||||
176290,
|
||||
178310,
|
||||
181070,
|
||||
182920,
|
||||
184160,
|
||||
189960,
|
||||
192630,
|
||||
193480,
|
||||
199019,
|
||||
201540,
|
||||
204519,
|
||||
208180,
|
||||
211470,
|
||||
217120,
|
||||
220790,
|
||||
224489,
|
||||
227200,
|
||||
229149,
|
||||
232940,
|
||||
236320,
|
||||
239070,
|
||||
242480,
|
||||
243730
|
||||
],
|
||||
"text": [
|
||||
"SPEAKER 1: So I want to show\nyou a simple circuit that",
|
||||
"looks like this.",
|
||||
"And let's go ahead and measure\nsome voltages and currents.",
|
||||
"In terms of terminology,\nremember",
|
||||
"this is called a loop.",
|
||||
"So if I start from the point\nC, and I travel through the",
|
||||
"voltage source, come to the node\nA, down through R1 and",
|
||||
"all the way down through R2\nback to C, that's a loop.",
|
||||
"Similarly, this point A is a\nnode where the register R1,",
|
||||
"the voltage source V0 and\nR4 are connected.",
|
||||
"Just make sure your terminology\nis correct.",
|
||||
"So what I'll do is let me make\nsome quick measurements for",
|
||||
"you, and show you that these KVL\nand KCL are indeed true.",
|
||||
"So the circuit's up there.",
|
||||
"So let me take some\nmeasurements.",
|
||||
"And why don't you write down\nwhat I measure on the board.",
|
||||
null,
|
||||
"Let me borrow another\npiece of chalk here.",
|
||||
"What I'll do is focus on this\nloop here and focus on this",
|
||||
"node and make some\nmeasurements.",
|
||||
"So you see the circuit\nup there.",
|
||||
"[INAUDIBLE]",
|
||||
null,
|
||||
"So I get three volts for the\nvoltage from C to A. So why",
|
||||
"don't you write down\nthree volts.",
|
||||
null,
|
||||
"OK, so the next one\nis minus 1.6.",
|
||||
null,
|
||||
"And so that will be\nI'm doing AB, VAB.",
|
||||
null,
|
||||
"And then let me do\nthe last one.",
|
||||
"And it is minus 1.37.",
|
||||
"Within the bonds of experimental\nerror, notice",
|
||||
"that if I add up these\nthree voltages, they",
|
||||
"nicely sum up to zero.",
|
||||
"OK, next let me focus\non this node here.",
|
||||
"And at this node, let\nme go ahead and",
|
||||
"measure some currents.",
|
||||
null,
|
||||
"What I'll do now is change to an\nAC voltage so that I can go",
|
||||
"ahead and measure the current\nwithout breaking my circuit.",
|
||||
"This time around, you'll get to\nsee the measurements that",
|
||||
"I'm taking as well.",
|
||||
"What I have here is three wires\nthat I have pulled out",
|
||||
"from D. And this is the node D.\nSo three wires coming into",
|
||||
"the node D just to make it a\nlittle bit easier for me to",
|
||||
"measure stuff.",
|
||||
"So everybody keep your fingers\ncrossed so I don't",
|
||||
"look like a fool here.",
|
||||
"Hope this works out.",
|
||||
"So it's about 10 millivolts\npeak to peak out there.",
|
||||
"Let's say that if the wave form\nrises on the left hand",
|
||||
"side, it's positive.",
|
||||
"So it's positive\n10 millivolts.",
|
||||
"And another positive\n10 millivolts.",
|
||||
"So that's 20 millivolts.",
|
||||
"And this time it's a negative,\nroughly 20, I",
|
||||
"guess, negative 20.",
|
||||
"So I'm getting, in terms of\ncurrents, I have a positive",
|
||||
"10, a positive 10 and a negative\n20 that adds up to 0.",
|
||||
"But more interestingly, I can\nshow you the same thing by",
|
||||
"holding this current\nmeasuring probe",
|
||||
"directly across that node.",
|
||||
"And notice that the net current\nthat is entering into",
|
||||
"this node here is zero.",
|
||||
"So that should just show you\nthat KCL does indeed hold in",
|
||||
"practice, and it is not just a\nfigment of our imaginations.",
|
||||
null
|
||||
]
|
||||
}
|
||||
@@ -1,266 +0,0 @@
|
||||
{
|
||||
"start": [
|
||||
0,
|
||||
3780,
|
||||
5290,
|
||||
9590,
|
||||
13370,
|
||||
13735,
|
||||
15275,
|
||||
16740,
|
||||
19790,
|
||||
23420,
|
||||
26470,
|
||||
28560,
|
||||
31630,
|
||||
33770,
|
||||
35320,
|
||||
36750,
|
||||
38390,
|
||||
41660,
|
||||
43720,
|
||||
46740,
|
||||
47805,
|
||||
49920,
|
||||
52170,
|
||||
53540,
|
||||
56530,
|
||||
59350,
|
||||
63350,
|
||||
66470,
|
||||
68440,
|
||||
69220,
|
||||
71320,
|
||||
72870,
|
||||
78300,
|
||||
79890,
|
||||
82470,
|
||||
85670,
|
||||
90720,
|
||||
93660,
|
||||
97005,
|
||||
98280,
|
||||
102090,
|
||||
103460,
|
||||
107090,
|
||||
108040,
|
||||
110700,
|
||||
112510,
|
||||
117400,
|
||||
121890,
|
||||
124450,
|
||||
130229,
|
||||
133180,
|
||||
140010,
|
||||
142500,
|
||||
143580,
|
||||
150010,
|
||||
152720,
|
||||
159180,
|
||||
161330,
|
||||
165510,
|
||||
171270,
|
||||
173750,
|
||||
177000,
|
||||
179340,
|
||||
181273,
|
||||
182400,
|
||||
188140,
|
||||
189210,
|
||||
192730,
|
||||
199620,
|
||||
206460,
|
||||
208220,
|
||||
211810,
|
||||
214510,
|
||||
219790,
|
||||
221440,
|
||||
223910,
|
||||
224950,
|
||||
226060,
|
||||
231860,
|
||||
232940,
|
||||
237990,
|
||||
240450,
|
||||
242470,
|
||||
244760,
|
||||
246470,
|
||||
248420
|
||||
],
|
||||
"end": [
|
||||
3780,
|
||||
5290,
|
||||
9590,
|
||||
13370,
|
||||
13735,
|
||||
15275,
|
||||
16740,
|
||||
19790,
|
||||
23420,
|
||||
26470,
|
||||
28560,
|
||||
31630,
|
||||
33770,
|
||||
35320,
|
||||
36750,
|
||||
38390,
|
||||
41660,
|
||||
43720,
|
||||
46740,
|
||||
47805,
|
||||
49920,
|
||||
52170,
|
||||
53540,
|
||||
56530,
|
||||
59350,
|
||||
63350,
|
||||
66470,
|
||||
68440,
|
||||
69220,
|
||||
71320,
|
||||
72870,
|
||||
78300,
|
||||
79890,
|
||||
82470,
|
||||
85670,
|
||||
90720,
|
||||
93660,
|
||||
97005,
|
||||
98280,
|
||||
102090,
|
||||
103460,
|
||||
107090,
|
||||
108040,
|
||||
110700,
|
||||
112510,
|
||||
117400,
|
||||
121890,
|
||||
124450,
|
||||
130229,
|
||||
133180,
|
||||
140010,
|
||||
142500,
|
||||
143580,
|
||||
150010,
|
||||
152720,
|
||||
159180,
|
||||
161330,
|
||||
165510,
|
||||
171270,
|
||||
173750,
|
||||
177000,
|
||||
179340,
|
||||
181273,
|
||||
182400,
|
||||
188140,
|
||||
189210,
|
||||
192730,
|
||||
196700,
|
||||
206460,
|
||||
208220,
|
||||
211810,
|
||||
214510,
|
||||
219790,
|
||||
221440,
|
||||
223910,
|
||||
224950,
|
||||
226060,
|
||||
231860,
|
||||
232940,
|
||||
237990,
|
||||
240450,
|
||||
242470,
|
||||
244760,
|
||||
246470,
|
||||
248420,
|
||||
249670
|
||||
],
|
||||
"text": [
|
||||
"SPEAKER 1: We just learned the fundamental rules of",
|
||||
"electrical circuits.",
|
||||
"For example, if we have a circuit like this, which is",
|
||||
"called a bridge and which has a voltage source and five",
|
||||
"resistors--",
|
||||
"SPEAKER 2: And I'll show the circuit in lecture.",
|
||||
"SPEAKER 1: That's right.",
|
||||
"We had a bunch of voltage current constraints, one for",
|
||||
"each of the branches, each of the elements in the network.",
|
||||
"For example, this one, the voltage across it is the",
|
||||
"voltage intrinsic to it.",
|
||||
"And we have Kirchoff's Current Laws, one for each of the",
|
||||
"possible nodes in the network.",
|
||||
"So that's four of them here.",
|
||||
"It turns out one of them is redundant.",
|
||||
"It can be derived from the others.",
|
||||
"And we have Kirchoff Voltage Laws, which are some of the",
|
||||
"voltages around the loop is zero.",
|
||||
"And I have four of them written down here, and only",
|
||||
"three of them are independent.",
|
||||
"But we can have many more because there's a loop I",
|
||||
"didn't show, which is the one that looks like this, for",
|
||||
"example, OK?",
|
||||
"And the other thing we have is that some of the powers on the",
|
||||
"network entering each the elements is zero.",
|
||||
"So there's no power gained or lost. This is a general method",
|
||||
"of solving all circuit problems. Unfortunately, even",
|
||||
"for a simple circuit like this, we have a mess of",
|
||||
"equations here.",
|
||||
"This is not a good idea.",
|
||||
"SPEAKER 2: So in the next lecture, what Anant will show",
|
||||
"you is a much more coherent, a much better organized",
|
||||
"technique for solving these circuits.",
|
||||
"So again, if we circle this circuit--",
|
||||
"this is the same brood circuit Anant showed in the lecture--",
|
||||
"we have six resistors, one, two, three, four nodes.",
|
||||
"And what we do is we take each of these nodes and for those",
|
||||
"nodes we'll write Kirchoff's Current Law.",
|
||||
"And that's called nodal analysis.",
|
||||
"So step zero is we pick one of these nodes and we label that",
|
||||
"node as ground.",
|
||||
"And labeling it ground just says the voltage on",
|
||||
"that node is zero.",
|
||||
"SPEAKER 1: The potential on that node is zero.",
|
||||
"Voltages are differences of potential.",
|
||||
"SPEAKER 2: Then we take a node, such as b.",
|
||||
"And for that node, b, we write down an equation that says the",
|
||||
"currents going into that node are o0.",
|
||||
"So IR1 is plus IR2 plus IR3 is equal to zero.",
|
||||
"We take this node, d, where we also write down Kirchoff's",
|
||||
"Current Law, IR3 plus IR4 plus IR5 is equal to zero.",
|
||||
"And at that point, we substitute",
|
||||
"in for those voltages.",
|
||||
"So when we have IR3, that's just b minus d over R3.",
|
||||
"That's the current going into it.",
|
||||
"For R5 over here, we have just d--",
|
||||
"IS is 0 minus d.",
|
||||
"So that's just minus d over R5.",
|
||||
"And for IR4, we have a minus d over R4.",
|
||||
"So we have an equation like this.",
|
||||
"SPEAKER 1: So these labels, a, b and d, are within node",
|
||||
"potentials, OK?",
|
||||
"SPEAKER 2: We do the same thing over here for--",
|
||||
"SPEAKER 1: Right, yes.",
|
||||
"SPEAKER 2: We do the same thing over here for IR2 is--",
|
||||
"SPEAKER 1: It's IR1.",
|
||||
"SPEAKER 2: IR1 is a minus b over R1.",
|
||||
"IR3 is d minus b over R3.",
|
||||
"And finally, IR2 is minus b over R2.",
|
||||
"So now we have two equations.",
|
||||
"And the last thing that we do is we label this node a to",
|
||||
"have the voltage v. We say a is equal to v.",
|
||||
"Since this is a zero, instead of a, it's v, we make that",
|
||||
"substitution everywhere here.",
|
||||
"We have two equations, two unknowns.",
|
||||
"We solve it.",
|
||||
"And that gives us our answer.",
|
||||
"SPEAKER 1: So the equations are b and d because all the",
|
||||
"A's are substituted for.",
|
||||
"And all of the KCLs that were written with the KCLs for some",
|
||||
"of the currents entering the node is zero.",
|
||||
"You could have equally written them as some of the currents",
|
||||
"leaving the node as zero and get the same answer because",
|
||||
"that would just multiply everything by minus 1.",
|
||||
"SPEAKER 2: So you'll see this next week.",
|
||||
"That's just a preview of coming attractions."
|
||||
]
|
||||
}
|
||||
@@ -1,335 +0,0 @@
|
||||
{
|
||||
"start": [
|
||||
0,
|
||||
430,
|
||||
3070,
|
||||
5680,
|
||||
9120,
|
||||
12590,
|
||||
13280,
|
||||
17280,
|
||||
20200,
|
||||
23630,
|
||||
26720,
|
||||
29450,
|
||||
32700,
|
||||
35920,
|
||||
39280,
|
||||
43310,
|
||||
44850,
|
||||
46400,
|
||||
48270,
|
||||
52110,
|
||||
54140,
|
||||
57570,
|
||||
61600,
|
||||
63040,
|
||||
64410,
|
||||
66980,
|
||||
69920,
|
||||
72490,
|
||||
75110,
|
||||
77540,
|
||||
80680,
|
||||
84430,
|
||||
87190,
|
||||
91790,
|
||||
94420,
|
||||
97830,
|
||||
101030,
|
||||
104180,
|
||||
106960,
|
||||
108320,
|
||||
110885,
|
||||
113180,
|
||||
115630,
|
||||
119930,
|
||||
122740,
|
||||
129590,
|
||||
131000,
|
||||
134200,
|
||||
138470,
|
||||
142200,
|
||||
145410,
|
||||
150500,
|
||||
153590,
|
||||
158000,
|
||||
160290,
|
||||
164600,
|
||||
167370,
|
||||
169272,
|
||||
173420,
|
||||
176650,
|
||||
180460,
|
||||
183390,
|
||||
185200,
|
||||
188940,
|
||||
190750,
|
||||
194040,
|
||||
196510,
|
||||
198060,
|
||||
202670,
|
||||
206860,
|
||||
209980,
|
||||
213620,
|
||||
219130,
|
||||
221760,
|
||||
222700,
|
||||
227050,
|
||||
230340,
|
||||
234810,
|
||||
236930,
|
||||
239030,
|
||||
241390,
|
||||
246630,
|
||||
248200,
|
||||
252220,
|
||||
255370,
|
||||
257160,
|
||||
258709,
|
||||
263370,
|
||||
264280,
|
||||
266840,
|
||||
270190,
|
||||
275640,
|
||||
277790,
|
||||
280880,
|
||||
282680,
|
||||
283930,
|
||||
285990,
|
||||
287870,
|
||||
290740,
|
||||
294140,
|
||||
299760,
|
||||
305270,
|
||||
308230,
|
||||
310160,
|
||||
311540,
|
||||
314150,
|
||||
316160,
|
||||
316440,
|
||||
318500
|
||||
],
|
||||
"end": [
|
||||
430,
|
||||
3070,
|
||||
5680,
|
||||
9120,
|
||||
12590,
|
||||
13280,
|
||||
17280,
|
||||
20200,
|
||||
23630,
|
||||
26720,
|
||||
29450,
|
||||
32700,
|
||||
35920,
|
||||
39280,
|
||||
43310,
|
||||
44850,
|
||||
46400,
|
||||
48269,
|
||||
52110,
|
||||
54140,
|
||||
57570,
|
||||
61600,
|
||||
63040,
|
||||
64410,
|
||||
66979,
|
||||
69920,
|
||||
72490,
|
||||
75110,
|
||||
77540,
|
||||
80680,
|
||||
84430,
|
||||
87190,
|
||||
91789,
|
||||
94420,
|
||||
97830,
|
||||
101030,
|
||||
104180,
|
||||
106960,
|
||||
108320,
|
||||
110884,
|
||||
113180,
|
||||
115630,
|
||||
119929,
|
||||
122740,
|
||||
129590,
|
||||
131000,
|
||||
134200,
|
||||
138470,
|
||||
142200,
|
||||
145410,
|
||||
150500,
|
||||
153590,
|
||||
158000,
|
||||
160290,
|
||||
164600,
|
||||
167370,
|
||||
169272,
|
||||
173420,
|
||||
176649,
|
||||
180460,
|
||||
183390,
|
||||
185200,
|
||||
188940,
|
||||
190750,
|
||||
194040,
|
||||
196510,
|
||||
198060,
|
||||
202670,
|
||||
206859,
|
||||
209980,
|
||||
213619,
|
||||
219130,
|
||||
221760,
|
||||
222700,
|
||||
227049,
|
||||
230340,
|
||||
234810,
|
||||
236930,
|
||||
239030,
|
||||
241390,
|
||||
246630,
|
||||
248200,
|
||||
252220,
|
||||
255370,
|
||||
257160,
|
||||
258709,
|
||||
263370,
|
||||
264280,
|
||||
266840,
|
||||
270190,
|
||||
275640,
|
||||
277789,
|
||||
280880,
|
||||
282680,
|
||||
283930,
|
||||
285990,
|
||||
287870,
|
||||
290740,
|
||||
294140,
|
||||
299760,
|
||||
305270,
|
||||
308229,
|
||||
310160,
|
||||
311540,
|
||||
314150,
|
||||
316159,
|
||||
316440,
|
||||
318500,
|
||||
319750
|
||||
],
|
||||
"text": [
|
||||
null,
|
||||
"SPEAKER 1: In this sequence, are\ngoing to look at a whole",
|
||||
"bunch of techniques for\nanalyzing circuits.",
|
||||
"Think of these as your tool\nchest. So you are embarking on",
|
||||
"6.002 and going on to build\nlots of useful electronic",
|
||||
"systems.",
|
||||
"But before we go and build these\nsystems, much like a",
|
||||
"carpenter who needs to go build\na house, much like a",
|
||||
"carpenter has to go and buy a\nset of tools from the local",
|
||||
"store, we need to go and make\nsure that you have the tools",
|
||||
"in your tool chest to analyze\nthese circuits.",
|
||||
"This tool chest will include\nthings like the KVL KCL",
|
||||
"method, the Node method\nand so on.",
|
||||
"But before I begin talking about\nthese techniques for",
|
||||
"your tool chest, I'd like to do\na extremely quick review--",
|
||||
"as is my usual practice--",
|
||||
"of what you've covered so far.",
|
||||
"So remember our EECS\nplayground.",
|
||||
"We've gotten into this place by\npromising that we are going",
|
||||
"to observe the lumped\nmatter discipline.",
|
||||
"By observing the discipline\nrecall that the complexities",
|
||||
"of Maxwell's equations and the\ndifferential equations that",
|
||||
"you have to solve-- the\npartial differential",
|
||||
"equations-- goes away.",
|
||||
"And you're left with very\nsimple linear equations.",
|
||||
"And you will see a lot\nof that today.",
|
||||
"As you make the lumped matter\ndiscipline, you end up with",
|
||||
"these lumped elements, like\nresistors and voltage",
|
||||
"sources and so on.",
|
||||
"And what you do with these\nlumped elements is we can",
|
||||
"label what are called the\nbranch variables or the",
|
||||
"terminal variables for these\nlumped elements, OK?",
|
||||
"So for example, v is the voltage\nacross the element.",
|
||||
"And i is the current through\nthe element.",
|
||||
"The power consumed by the\nelement is given by vi.",
|
||||
"Continuing with our review, the\nlumped matter discipline",
|
||||
"enables us to create the lumped\ncircuit abstraction.",
|
||||
"So you take these lumped\nelements and you connect them",
|
||||
"with ideal wires.",
|
||||
"So in this case, I have a\nresistor which is a lumped",
|
||||
"element, a voltage source.",
|
||||
"And I connect them with\nthese ideal wires.",
|
||||
"And what you end up with is\ncalled a lumped circuit.",
|
||||
"But this is your lumped\ncircuit abstraction.",
|
||||
"Well as we made the transition\nfrom physics to EECS by",
|
||||
"adhering to the lumped\nmatter discipline.",
|
||||
"I had discussed in the last\nsequence that Maxwell's",
|
||||
"equations turn into very simple\nalgebraic equations.",
|
||||
"And these are captured by\nKirchoff's voltage and current",
|
||||
"laws, called KVL and KCL.",
|
||||
"So KVL says that for all loops\nin your circuit, the sum of",
|
||||
"the voltages around the\nloops add up to zero.",
|
||||
"Similarly for all the nodes in\nthe circuit, the currents that",
|
||||
"enter into a node\nadd up to zero.",
|
||||
"And in the same matter, if I\njust summed the currents",
|
||||
"leaving a node, they also\nadd up to zero.",
|
||||
"So whether you sum the currents\nentering the node or",
|
||||
"currents leaving a node, they\nwould add up to zero by KCL.",
|
||||
"And the beauty of this was by\nadhering to lump matter",
|
||||
"discipline, recall the\ncomplexities Maxwell's",
|
||||
"equations whether an\nintegral form or",
|
||||
"differential form went away.",
|
||||
"And we were now left with\nextremely simple algebraic",
|
||||
"expressions of the sort.",
|
||||
"And you will see shortly that\nyou will end up solving",
|
||||
"extremely simple linear\nequations",
|
||||
"as we analyze circuits.",
|
||||
"So as one example here\nis a linear circuit.",
|
||||
"It has one, two, three, four,\nfive, six elements.",
|
||||
"It's got a voltage source\nof a voltage v zero.",
|
||||
"It's got a resistor, r one\nand so on and so forth.",
|
||||
"So for this circuit according\nto our abstraction and the",
|
||||
"laws of KVL and KCL,\nthe following",
|
||||
"are going to be true.",
|
||||
"So for instance if I look at\nnode a, then according to KCL,",
|
||||
"the currents entering the\nnode must be zero.",
|
||||
"So in other words, the\ncurrent here is ica.",
|
||||
"And I can sum to that\nthe current",
|
||||
"entering from the d direction.",
|
||||
"So that would be plus ida.",
|
||||
"And then there is a current from\nthe ba direction and iba.",
|
||||
"Those are going to\nsum to zero.",
|
||||
"Now I can multiply the whole\nthing by minus 1.",
|
||||
"And that would give me the sum\nof the currents leaving the",
|
||||
"node are also going\nto be zero.",
|
||||
"So that is KCL.",
|
||||
"Now I can also write KVL in this\ncase for this loop, for",
|
||||
"instance, here.",
|
||||
"For this loop I can add up the\nvoltages around the loop.",
|
||||
"And by KVL they must\nadd up to zero.",
|
||||
"So for example if I look at\nthe voltage vca, I can add",
|
||||
"that to the next voltage here.",
|
||||
"That is to vab and then\nadd that to the",
|
||||
"final voltage, vbc.",
|
||||
"And by KCL--",
|
||||
null,
|
||||
"so all of those must\nadd up to be zero.",
|
||||
"Now if you go back to our\ncircuit here that you see on",
|
||||
"the left hand side, I am going\nto show you a little demo that",
|
||||
"will look at these currents,\nica, ida, and iba, and also",
|
||||
"look at the voltages, vcabab\nand bbc and actually go and",
|
||||
"look at the circuit, make the\nmeasurements, and show that",
|
||||
"they indeed sum up to zero.",
|
||||
"Not surprising.",
|
||||
"KVL and KCL really work.",
|
||||
"And so the demo should\nalso work.",
|
||||
"OK.",
|
||||
"So let's go and do our demo.",
|
||||
null
|
||||
]
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
{
|
||||
"start": [
|
||||
0,
|
||||
6830,
|
||||
9040,
|
||||
11810,
|
||||
15030,
|
||||
19420,
|
||||
21690,
|
||||
24880,
|
||||
29850,
|
||||
32409,
|
||||
35430,
|
||||
37550,
|
||||
40240,
|
||||
44050,
|
||||
47470,
|
||||
50910,
|
||||
52750,
|
||||
55340,
|
||||
57870,
|
||||
59920,
|
||||
62450,
|
||||
66320,
|
||||
70470,
|
||||
72100,
|
||||
82700,
|
||||
84820,
|
||||
86550,
|
||||
88890,
|
||||
93560,
|
||||
94810,
|
||||
98620,
|
||||
100040,
|
||||
102740,
|
||||
105880,
|
||||
108470,
|
||||
111550,
|
||||
112830,
|
||||
116190,
|
||||
117410,
|
||||
120620,
|
||||
122310,
|
||||
125810,
|
||||
129720,
|
||||
132900,
|
||||
135170,
|
||||
138020,
|
||||
141350,
|
||||
143230,
|
||||
144480
|
||||
],
|
||||
"end": [
|
||||
6830,
|
||||
9040,
|
||||
11809,
|
||||
15030,
|
||||
19419,
|
||||
21690,
|
||||
24880,
|
||||
29849,
|
||||
32409,
|
||||
35430,
|
||||
37550,
|
||||
40239,
|
||||
44050,
|
||||
47470,
|
||||
50910,
|
||||
52750,
|
||||
55340,
|
||||
57870,
|
||||
59919,
|
||||
62450,
|
||||
66320,
|
||||
70470,
|
||||
72100,
|
||||
82699,
|
||||
84820,
|
||||
86550,
|
||||
88890,
|
||||
93560,
|
||||
94810,
|
||||
98620,
|
||||
100040,
|
||||
102740,
|
||||
105880,
|
||||
108470,
|
||||
111550,
|
||||
112830,
|
||||
116190,
|
||||
117410,
|
||||
120619,
|
||||
122310,
|
||||
125810,
|
||||
129720,
|
||||
132900,
|
||||
135170,
|
||||
138019,
|
||||
141350,
|
||||
143230,
|
||||
144480,
|
||||
152786
|
||||
],
|
||||
"text": [
|
||||
null,
|
||||
"PROFESSOR ANANT AGARWAL:\nWelcome to MITx, MIT's",
|
||||
"worldwide online learning\ninitiative.",
|
||||
"We are delighted to have you\njoin us for 6.002x: Circuits",
|
||||
"and Electronics, the inaugural\ncourse of MITx.",
|
||||
"OK, welcome to 6.002.",
|
||||
"6.002x is the same as Electronic\nCircuits course",
|
||||
"taken by MIT students as the\nfirst course in an EE or EECS",
|
||||
"major at MIT.",
|
||||
"This course will help you make\nthe transition from physics to",
|
||||
"electrical engineering.",
|
||||
"In this course, you will learn\nabout a lot of fun things,",
|
||||
"including the foundations behind\nmany cool devices, such",
|
||||
"as the smartphone.",
|
||||
"The course will be hard and we\nwant you to stick with us.",
|
||||
"It is our hope that you\nwill have a lot",
|
||||
"of fun in this course.",
|
||||
"Let me start by introducing\nyou to our team.",
|
||||
"I am Anant Agarwal.",
|
||||
"I am the director of MIT's\nComputer Science and",
|
||||
"Artificial Intelligence\nLaboratory or CSAIL.",
|
||||
"Like most MIT faculty, I have\na wide range of interests,",
|
||||
"including a fascination\naround chainsaws.",
|
||||
null,
|
||||
"GERRY SUSSMAN: Hello, I'm Gerry\nSussman, professor of",
|
||||
"electrical engineering at MIT.",
|
||||
"Been a faculty member\nhere since 1973.",
|
||||
"I build electronics, optics,\ncomputer software, and I",
|
||||
"repair watches as a hobby.",
|
||||
null,
|
||||
"PIOTR MITROS: I'm\nPiotr Mitros.",
|
||||
"I'm a research scientist at MIT,\nand I was in charge of",
|
||||
"developing the software\ninfrastructure for MITx.",
|
||||
"As a graduate student, I spent a\nlot of time traveling around",
|
||||
"India, Nigeria, and China,\nmostly as part of educational",
|
||||
"technology projects.",
|
||||
"So I'm very excited to be\nhelping out with this course.",
|
||||
"PROFESSOR ANANT AGARWAL: Whether\nwe like chainsaws or",
|
||||
"watches, we are all passionate\neducators.",
|
||||
"This course is free.",
|
||||
"You will have the opportunity\nto earn an MITx pilot",
|
||||
"certificate with your grade\nat the end of this course.",
|
||||
"In this experimental first\ncourse of MITx, the",
|
||||
"certificates are also free.",
|
||||
"Now, this is a prototype course\nand we welcome your",
|
||||
"participation and any feedback\nyou might have to improving",
|
||||
"the learning experience.",
|
||||
"Let's get started.",
|
||||
null
|
||||
]
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
{
|
||||
"start": [
|
||||
0,
|
||||
360,
|
||||
2460,
|
||||
6080,
|
||||
11270,
|
||||
12700,
|
||||
16210,
|
||||
18460,
|
||||
22750,
|
||||
26140,
|
||||
30360,
|
||||
31480,
|
||||
35370,
|
||||
37170,
|
||||
40710,
|
||||
43190,
|
||||
46980,
|
||||
49050,
|
||||
52590,
|
||||
55170,
|
||||
57100,
|
||||
59330,
|
||||
60950,
|
||||
65450,
|
||||
69710,
|
||||
73480,
|
||||
75100,
|
||||
77600,
|
||||
78790,
|
||||
81330,
|
||||
82580
|
||||
],
|
||||
"end": [
|
||||
360,
|
||||
2460,
|
||||
6080,
|
||||
11270,
|
||||
12700,
|
||||
16210,
|
||||
18460,
|
||||
22750,
|
||||
26140,
|
||||
30360,
|
||||
31480,
|
||||
35370,
|
||||
37169,
|
||||
40710,
|
||||
43190,
|
||||
46980,
|
||||
49050,
|
||||
52589,
|
||||
55170,
|
||||
57100,
|
||||
59330,
|
||||
60949,
|
||||
65450,
|
||||
69710,
|
||||
73479,
|
||||
75100,
|
||||
77600,
|
||||
78789,
|
||||
81330,
|
||||
82580,
|
||||
83340
|
||||
],
|
||||
"text": [
|
||||
null,
|
||||
"SPEAKER 1: In this next segment,\nI'd like to show you",
|
||||
"a little demo of a set of lumped\nelements that you will",
|
||||
"find in 6002x and in building\nelectronic circuits and",
|
||||
"systems in general.",
|
||||
"And these lumped elements have\nbehavior that is completely",
|
||||
"captured by their V-I\nrelationship.",
|
||||
"I also want to point out that\nthe behavior of these lumped",
|
||||
"elements is captured by the\nV-I relationship only for",
|
||||
"those sorts of questions that\nwe, as electrical engineers,",
|
||||
"would like to ask.",
|
||||
"Understand that the V-I relation\ndoesn't capture all",
|
||||
"the possible behaviors\nof the element.",
|
||||
"It only captures those possible\nbehaviors that we, as",
|
||||
"EEs, generally like to ask.",
|
||||
"Once I've shown you these basic\nV-I relationships, we",
|
||||
"will do some other fun stuff.",
|
||||
"I'm going to show you some\nexamples of behavior that the",
|
||||
"V-I relationship will\nnot capture.",
|
||||
"We'll show you what\nwe can predict.",
|
||||
"For example, we'll\nshow you how the",
|
||||
"resistors don't work sometimes.",
|
||||
"And sometimes we will show you\nanother example of a cucumber",
|
||||
"pickle that may behave in ways\nthat you don't quite expect",
|
||||
"and whose behavior need not\nnecessarily be captured by",
|
||||
"your V-I relationship.",
|
||||
"So I don't want you to go around\nsaying that you don't",
|
||||
"have any fun in this course.",
|
||||
"So hopefully, you will\nenjoy what you are",
|
||||
"going to see ahead.",
|
||||
null
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<p>This is another sample tab</p>
|
||||
@@ -1 +0,0 @@
|
||||
<h1>This is a sample tab</h1>
|
||||
@@ -1,339 +0,0 @@
|
||||
chapter/Week_10
|
||||
chapter/Week_11
|
||||
chapter/Week_12
|
||||
chapter/Week_4
|
||||
chapter/Week_5
|
||||
chapter/Week_6
|
||||
chapter/Week_7
|
||||
chapter/Week_8
|
||||
chapter/Week_9
|
||||
html/Lab_10B_RC_Filters_Experiment
|
||||
html/Lab_5B_Mosfet_Amplifier_Experiment
|
||||
html/Week_10_Tutorials
|
||||
html/Week_11_Tutorials
|
||||
html/Week_12_Tutorials
|
||||
html/Week_4_Tutorials
|
||||
html/Week_5_Tutorials
|
||||
html/Week_6_Tutorials
|
||||
html/Week_7_Tutorials
|
||||
html/Week_8_Tutorials
|
||||
html/Week_9_Tutorials
|
||||
problem/Capacitors_and_Energy_Storage
|
||||
problem/Curve_Tracer
|
||||
problem/H10P1_Magnitude_and_Angle
|
||||
problem/H10P2_Impedances
|
||||
problem/H10P3_An_L_Network
|
||||
problem/H11P1_LC_Tank
|
||||
problem/H11P2_Scope_Probe
|
||||
problem/H11P3_A_Step_in_Time
|
||||
problem/H12P1_Current_Source
|
||||
problem/H12P2_Measuring_Light_
|
||||
problem/H12P3_Opamps_and_Filter_Design
|
||||
problem/H4P0_Vacuum_Diode
|
||||
problem/H4P1_Zener_Regulator
|
||||
problem/H5P1_Source_Follower_Large_Signal
|
||||
problem/H5P2_Source_Follower_Small_Signal
|
||||
problem/H6P1_The_NewFET_device
|
||||
problem/H6P2_Phase_Inverter
|
||||
problem/H6P3_Series_and_Parallel_Capacitors
|
||||
problem/H6P4_Switched_RC
|
||||
problem/H7P1_Series_and_Parallel_Inductors
|
||||
problem/H7P2_The_Curse_of_Lead_Inductance
|
||||
problem/H8P1_Charging_an_Inductor
|
||||
problem/H8P2_Physiological_Model
|
||||
problem/H8P3_Memory
|
||||
problem/H9P1_Response_to_a_Delayed_Impulse
|
||||
problem/H9P2_An_L_Network
|
||||
problem/H9P3_Designing_a_Shock_Absorber
|
||||
problem/Impedance_Frequency_Response
|
||||
problem/Mosfet_Amplifier
|
||||
problem/Op_Amps
|
||||
problem/Propagation_Delay
|
||||
problem/Resonance
|
||||
problem/S10E1_Incremental_Voltage
|
||||
problem/S10E2_two_terminal_connection
|
||||
problem/S10E3_Small_Signal_Amplifier
|
||||
problem/S14E1_Response_to_step_down
|
||||
problem/S14E2_Rise_Time
|
||||
problem/S14E3_Fall_Time_Constant
|
||||
problem/S14E4_Fall_Time
|
||||
problem/S15E1_Review_A_Step_Up
|
||||
problem/S15E2_Review_A_Step_Down
|
||||
problem/S15E3_Review_A_Pulse_is_Step_Up_then_Step_Down
|
||||
problem/S15E4_Area
|
||||
problem/S15E5_Initial_Conditions
|
||||
problem/S16E1_Charging_and_Discharging
|
||||
problem/S16E2_Time_to_Decay
|
||||
problem/S19E1_Trigonometry_Isn_t_So_Bad
|
||||
problem/S19E2_Exponentials_are_Nice
|
||||
problem/S19E3_Complex_Numbers
|
||||
problem/S19E4_Magnitudes_and_Angles
|
||||
problem/S20E1_Inductor_Impedance
|
||||
problem/S20E2_RC_voltage_divider
|
||||
problem/S20E3_LCR_voltage_divider
|
||||
problem/S20E4_LCR_voltage_divider_frequency_limits
|
||||
problem/S21E2_LR_filter
|
||||
problem/S21E3_Thevenin_Tank
|
||||
problem/S21E4_AM_Radio_Tuning
|
||||
problem/S22E1_Which_output_
|
||||
problem/S22E2_The_filter_is_ringing
|
||||
problem/S23E2_Inverting_Amplifier_analysis
|
||||
problem/S23E3_L23AmplifierInputResistance
|
||||
problem/S24E1_Summing_Amplifier
|
||||
problem/S24E2_Difference_Amplifier
|
||||
problem/S24E3_Inverting_Amplifier_Generalized
|
||||
problem/S24E4_Generalization_to_impedances
|
||||
problem/S24E5_Generalization_to_nonlinear_elements
|
||||
problem/S7E1_Linearization
|
||||
problem/S7E2_Graphs
|
||||
problem/S7E3_Linearization
|
||||
problem/S8E0_Dependent_Source
|
||||
problem/S8E1_Dependent_Current_Source
|
||||
problem/S8E2_Dependent_Voltage_Source
|
||||
problem/S9E1_MOSFET_model
|
||||
problem/S9E2_Amplifier_1
|
||||
problem/S9E3_MOSFET_Amplifier_2
|
||||
sequential/Dependent_Sources_and_Amplifiers
|
||||
sequential/Filters
|
||||
sequential/Incremental_Analysis
|
||||
sequential/MOSFET_Amplifiers_Small_signal_model
|
||||
sequential/MOSFETs_Large_Signals
|
||||
sequential/Operational_Amplifier_Circuits
|
||||
sequential/Ramps_Steps_and_Impulses
|
||||
sequential/Sinusoidal_Steady_State
|
||||
sequential/Speed_of_Digital_Circuits
|
||||
sequential/State_and_Memory
|
||||
sequential/The_Impedance_Model
|
||||
sequential/The_Operational_Amplifier_Abstraction
|
||||
sequential/Time_Domain_Versus_Frequency_Domain_Analysis
|
||||
vertical/vertical_1002
|
||||
vertical/vertical_1006
|
||||
vertical/vertical_1010
|
||||
vertical/vertical_1014
|
||||
vertical/vertical_1018
|
||||
vertical/vertical_1022
|
||||
vertical/vertical_1026
|
||||
vertical/vertical_1030
|
||||
vertical/vertical_1034
|
||||
vertical/vertical_1038
|
||||
vertical/vertical_1042
|
||||
vertical/vertical_1046
|
||||
vertical/vertical_1050
|
||||
vertical/vertical_1054
|
||||
vertical/vertical_1058
|
||||
vertical/vertical_1062
|
||||
vertical/vertical_1069
|
||||
vertical/vertical_1073
|
||||
vertical/vertical_1077
|
||||
vertical/vertical_1081
|
||||
vertical/vertical_1085
|
||||
vertical/vertical_1089
|
||||
vertical/vertical_1093
|
||||
vertical/vertical_1097
|
||||
vertical/vertical_1100
|
||||
vertical/vertical_1104
|
||||
vertical/vertical_1108
|
||||
vertical/vertical_1112
|
||||
vertical/vertical_1320
|
||||
vertical/vertical_1324
|
||||
vertical/vertical_1328
|
||||
vertical/vertical_1332
|
||||
vertical/vertical_1336
|
||||
vertical/vertical_1340
|
||||
vertical/vertical_1344
|
||||
vertical/vertical_1348
|
||||
vertical/vertical_1352
|
||||
vertical/vertical_1356
|
||||
vertical/vertical_1360
|
||||
vertical/vertical_1364
|
||||
vertical/vertical_1368
|
||||
vertical/vertical_1373
|
||||
vertical/vertical_1377
|
||||
vertical/vertical_1381
|
||||
vertical/vertical_1385
|
||||
vertical/vertical_1389
|
||||
vertical/vertical_1393
|
||||
vertical/vertical_1403
|
||||
vertical/vertical_1407
|
||||
vertical/vertical_1411
|
||||
vertical/vertical_1415
|
||||
vertical/vertical_1419
|
||||
vertical/vertical_1423
|
||||
vertical/vertical_1427
|
||||
vertical/vertical_1431
|
||||
vertical/vertical_1435
|
||||
vertical/vertical_1439
|
||||
vertical/vertical_1443
|
||||
vertical/vertical_1447
|
||||
vertical/vertical_1451
|
||||
vertical/vertical_1455
|
||||
vertical/vertical_1459
|
||||
vertical/vertical_1463
|
||||
vertical/vertical_1467
|
||||
vertical/vertical_1471
|
||||
vertical/vertical_1479
|
||||
vertical/vertical_1483
|
||||
vertical/vertical_1487
|
||||
vertical/vertical_1491
|
||||
vertical/vertical_1495
|
||||
vertical/vertical_1499
|
||||
vertical/vertical_1503
|
||||
vertical/vertical_1507
|
||||
vertical/vertical_1511
|
||||
vertical/vertical_1515
|
||||
vertical/vertical_1519
|
||||
vertical/vertical_1523
|
||||
vertical/vertical_1527
|
||||
vertical/vertical_1531
|
||||
vertical/vertical_1535
|
||||
vertical/vertical_1539
|
||||
vertical/vertical_1543
|
||||
vertical/vertical_1547
|
||||
vertical/vertical_1551
|
||||
vertical/vertical_1555
|
||||
vertical/vertical_1559
|
||||
vertical/vertical_1563
|
||||
vertical/vertical_1566
|
||||
vertical/vertical_1570
|
||||
vertical/vertical_1574
|
||||
vertical/vertical_1578
|
||||
vertical/vertical_1582
|
||||
vertical/vertical_1586
|
||||
vertical/vertical_1590
|
||||
vertical/vertical_1594
|
||||
vertical/vertical_1598
|
||||
vertical/vertical_1603
|
||||
vertical/vertical_1607
|
||||
vertical/vertical_1611
|
||||
vertical/vertical_1615
|
||||
vertical/vertical_1619
|
||||
vertical/vertical_1623
|
||||
vertical/vertical_1627
|
||||
vertical/vertical_1631
|
||||
vertical/vertical_1635
|
||||
vertical/vertical_1639
|
||||
vertical/vertical_1643
|
||||
vertical/vertical_1647
|
||||
vertical/vertical_1651
|
||||
vertical/vertical_1655
|
||||
vertical/vertical_1659
|
||||
vertical/vertical_1663
|
||||
vertical/vertical_1667
|
||||
vertical/vertical_1671
|
||||
vertical/vertical_1675
|
||||
vertical/vertical_1679
|
||||
vertical/vertical_1683
|
||||
vertical/vertical_1687
|
||||
vertical/vertical_1691
|
||||
vertical/vertical_1695
|
||||
vertical/vertical_1699
|
||||
vertical/vertical_1703
|
||||
vertical/vertical_1707
|
||||
vertical/vertical_1711
|
||||
vertical/vertical_1715
|
||||
vertical/vertical_1719
|
||||
vertical/vertical_1723
|
||||
vertical/vertical_1727
|
||||
vertical/vertical_1731
|
||||
vertical/vertical_1735
|
||||
vertical/vertical_1739
|
||||
vertical/vertical_1743
|
||||
vertical/vertical_1747
|
||||
vertical/vertical_1751
|
||||
vertical/vertical_1755
|
||||
vertical/vertical_1759
|
||||
vertical/vertical_1763
|
||||
vertical/vertical_1767
|
||||
vertical/vertical_431
|
||||
vertical/vertical_435
|
||||
vertical/vertical_439
|
||||
vertical/vertical_443
|
||||
vertical/vertical_447
|
||||
vertical/vertical_451
|
||||
vertical/vertical_455
|
||||
vertical/vertical_459
|
||||
vertical/vertical_463
|
||||
vertical/vertical_469
|
||||
vertical/vertical_475
|
||||
vertical/vertical_479
|
||||
vertical/vertical_483
|
||||
vertical/vertical_487
|
||||
vertical/vertical_491
|
||||
vertical/vertical_495
|
||||
vertical/vertical_504
|
||||
vertical/vertical_508
|
||||
vertical/vertical_512
|
||||
vertical/vertical_516
|
||||
vertical/vertical_520
|
||||
vertical/vertical_524
|
||||
vertical/vertical_530
|
||||
vertical/vertical_534
|
||||
vertical/vertical_538
|
||||
vertical/vertical_542
|
||||
vertical/vertical_546
|
||||
vertical/vertical_550
|
||||
vertical/vertical_554
|
||||
vertical/vertical_558
|
||||
vertical/vertical_562
|
||||
vertical/vertical_566
|
||||
vertical/vertical_570
|
||||
vertical/vertical_577
|
||||
vertical/vertical_581
|
||||
vertical/vertical_585
|
||||
vertical/vertical_589
|
||||
vertical/vertical_593
|
||||
vertical/vertical_597
|
||||
vertical/vertical_601
|
||||
vertical/vertical_605
|
||||
vertical/vertical_609
|
||||
vertical/vertical_613
|
||||
vertical/vertical_617
|
||||
vertical/vertical_621
|
||||
vertical/vertical_625
|
||||
vertical/vertical_629
|
||||
vertical/vertical_633
|
||||
vertical/vertical_637
|
||||
vertical/vertical_641
|
||||
vertical/vertical_645
|
||||
vertical/vertical_649
|
||||
vertical/vertical_653
|
||||
vertical/vertical_660
|
||||
vertical/vertical_664
|
||||
vertical/vertical_668
|
||||
vertical/vertical_672
|
||||
vertical/vertical_676
|
||||
vertical/vertical_680
|
||||
vertical/vertical_684
|
||||
vertical/vertical_688
|
||||
vertical/vertical_692
|
||||
vertical/vertical_696
|
||||
vertical/vertical_700
|
||||
vertical/vertical_704
|
||||
vertical/vertical_886
|
||||
vertical/vertical_890
|
||||
vertical/vertical_894
|
||||
vertical/vertical_898
|
||||
vertical/vertical_902
|
||||
vertical/vertical_906
|
||||
vertical/vertical_910
|
||||
vertical/vertical_914
|
||||
vertical/vertical_918
|
||||
vertical/vertical_922
|
||||
vertical/vertical_926
|
||||
vertical/vertical_930
|
||||
vertical/vertical_938
|
||||
vertical/vertical_942
|
||||
vertical/vertical_946
|
||||
vertical/vertical_950
|
||||
vertical/vertical_954
|
||||
vertical/vertical_958
|
||||
vertical/vertical_962
|
||||
vertical/vertical_966
|
||||
vertical/vertical_970
|
||||
vertical/vertical_974
|
||||
vertical/vertical_978
|
||||
vertical/vertical_982
|
||||
vertical/vertical_986
|
||||
vertical/vertical_990
|
||||
vertical/vertical_994
|
||||
vertical/vertical_998
|
||||
@@ -1,20 +0,0 @@
|
||||
<vertical display_name="Test problems">
|
||||
<problem url_name="test_files:numericalresponse_demo"/>
|
||||
<problem url_name="test_files:choiceresponse_checkbox"/>
|
||||
<problem url_name="test_files:choiceresponse_radio"/>
|
||||
<problem url_name="test_files:coderesponse"/>
|
||||
<problem url_name="test_files:coderesponse_externalresponseformat"/>
|
||||
<problem url_name="test_files:formularesponse_with_hint"/>
|
||||
<problem url_name="test_files:imageresponse"/>
|
||||
<problem url_name="test_files:javascriptresponse"/>
|
||||
<problem url_name="test_files:multi_bare"/>
|
||||
<problem url_name="test_files:multichoice"/>
|
||||
<problem url_name="test_files:multiplechoicelresponse_demo"/>
|
||||
<problem url_name="test_files:numericalresponse_demo"/>
|
||||
<problem url_name="test_files:optionresponse"/>
|
||||
<problem url_name="test_files:stringresponse_with_hint"/>
|
||||
<problem url_name="test_files:symbolicresponse"/>
|
||||
<problem url_name="test_files:truefalse"/>
|
||||
<problem url_name="test_files:chemicalequationresponse"/>
|
||||
<problem url_name="test_files:filesubmission"/>
|
||||
</vertical>
|
||||
@@ -1,6 +0,0 @@
|
||||
<sequential>
|
||||
<video youtube_id_1_5=""8kARlsUt9lM"" youtube_id_1_25=""4cLA-IME32w"" youtube_id_1_0=""pFOrD8k9_p4"" youtube_id_0_75=""CcgAYu0n0bg"" slug="S1V9_Demo_Setup_-_Lumped_Elements" name="S1V9: Demo Setup - Lumped Elements"/>
|
||||
<customtag tag="S1" slug="discuss_59" impl="discuss"/>
|
||||
<customtag page="29" slug="book_60" impl="book"/>
|
||||
<customtag lecnum="1" slug="slides_61" impl="slides"/>
|
||||
</sequential>
|
||||
@@ -1,15 +0,0 @@
|
||||
<sequential>
|
||||
<html slug="html_90">
|
||||
<!-- UTF-8 characters are acceptable… HTML entities are not -->
|
||||
<h1>Inline content…</h1>
|
||||
</html>
|
||||
<video youtube_id_1_5=""vl9xrfxcr38"" youtube_id_1_25=""qxNX4REGqx4"" youtube_id_1_0=""BGU1poJDgOY"" youtube_id_0_75=""8rK9vnpystQ"" slug="S1V14_Summary" name="S1V14: Summary"/>
|
||||
<customtag tag="S1" slug="discuss_91" impl="discuss"/>
|
||||
<customtag page="70" slug="book_92" impl="book"/>
|
||||
<customtag lecnum="1" slug="slides_93" impl="slides"/>
|
||||
<poll_question name="T1_changemind_poll_foo" display_name="Change your answer" reset="false">
|
||||
<p>Have you changed your mind?</p>
|
||||
<answer id="yes">Yes</answer>
|
||||
<answer id="no">No</answer>
|
||||
</poll_question>
|
||||
</sequential>
|
||||
@@ -1,6 +0,0 @@
|
||||
<sequential>
|
||||
<video youtube_id_0_75=""3NIegrCmA5k"" youtube_id_1_0=""eLAyO33baQ8"" youtube_id_1_25=""m1zWi_sh4Aw"" youtube_id_1_5=""EG-fRTJln_E"" slug="S2V1_Review_KVL_KCL" name="S2V1: Review KVL, KCL"/>
|
||||
<customtag tag="S2" slug="discuss_95" impl="discuss"/>
|
||||
<customtag page="54" slug="book_96" impl="book"/>
|
||||
<customtag lecnum="2" slug="slides_97" impl="slides"/>
|
||||
</sequential>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user