diff --git a/src/db/db/gsiDeclDbTrans.cc b/src/db/db/gsiDeclDbTrans.cc index f9c579986..27938b0d4 100644 --- a/src/db/db/gsiDeclDbTrans.cc +++ b/src/db/db/gsiDeclDbTrans.cc @@ -521,7 +521,7 @@ struct trans_defs method ("disp", (const vector_type &(C::*) () const) &C::disp, "@brief Gets to the displacement vector\n" "\n" - "Staring with version 0.25 the displacement type is a vector." + "Starting with version 0.25 the displacement type is a vector." ) + method ("rot", &C::rot, "@brief Gets the angle/mirror code\n" @@ -553,7 +553,7 @@ struct trans_defs "@param u The new displacement\n" "\n" "This method was introduced in version 0.20.\n" - "Staring with version 0.25 the displacement type is a vector." + "Starting with version 0.25 the displacement type is a vector." ) + method_ext ("mirror=", &set_mirror, arg ("m"), "@brief Sets the mirror flag\n" diff --git a/src/pex/pex/pexRExtractor.cc b/src/pex/pex/pexRExtractor.cc index db38fc948..02b5dbf59 100644 --- a/src/pex/pex/pexRExtractor.cc +++ b/src/pex/pex/pexRExtractor.cc @@ -52,19 +52,25 @@ RNode::to_string () const std::string RElement::to_string () const { - std::string res = "R "; + std::string na; if (a ()) { - res += a ()->to_string (); + na = a ()->to_string (); } else { - res += "(nil)"; + na = "(nil)"; } - res += " "; + + std::string nb; if (b ()) { - res += b ()->to_string (); + nb = b ()->to_string (); } else { - res += "(nil)"; + nb = "(nil)"; } - res += " "; + + if (nb < na) { + std::swap (na, nb); + } + + std::string res = "R " + na + " " + nb + " "; res += tl::sprintf ("%.6g", resistance ()); return res; } diff --git a/src/pex/pex/pexTriangulationRExtractor.cc b/src/pex/pex/pexTriangulationRExtractor.cc index cce1e4150..5a7a87047 100644 --- a/src/pex/pex/pexTriangulationRExtractor.cc +++ b/src/pex/pex/pexTriangulationRExtractor.cc @@ -42,6 +42,8 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< { rnetwork.clear (); + tl::SelfTimer timer (tl::verbosity () >= m_tri_param.base_verbosity + 1, "Extracting resistor network from polygon (TriangulationRExtractor)"); + db::CplxTrans trans = db::CplxTrans (m_dbu) * db::ICplxTrans (db::Trans (db::Point () - polygon.box ().center ())); db::plc::Graph plc; @@ -55,6 +57,8 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< } else { + tl::SelfTimer timer_tri (tl::verbosity () >= m_tri_param.base_verbosity + 11, "Triangulation step"); + // Subtract the polygon ports from the original polygon and compute the intersection. // Hence we have coincident edges that we can use to identify the nodes that are // connected for the polygon ports @@ -238,7 +242,7 @@ void TriangulationRExtractor::eliminate_all (RNetwork &rnetwork) { if (tl::verbosity () >= m_tri_param.base_verbosity + 10) { - tl::info << "Staring elimination with " << rnetwork.num_internal_nodes () << " internal nodes and " << rnetwork.num_elements () << " resistors"; + tl::info << "Starting elimination with " << rnetwork.num_internal_nodes () << " internal nodes and " << rnetwork.num_elements () << " resistors"; } unsigned int niter = 0; diff --git a/src/pex/unit_tests/pexRExtractorTests.cc b/src/pex/unit_tests/pexRExtractorTests.cc index 1c2de17b7..b0ace9056 100644 --- a/src/pex/unit_tests/pexRExtractorTests.cc +++ b/src/pex/unit_tests/pexRExtractorTests.cc @@ -97,7 +97,7 @@ TEST(network_simplify1) rn.create_element (1, n1, n3); EXPECT_EQ (rn.to_string (), - "R V1 $2 1\n" + "R $2 V1 1\n" "R $2 V3 0\n" "R V1 V3 1" ); @@ -126,7 +126,7 @@ TEST(network_simplify2) rn.create_element (1, n3, n5); EXPECT_EQ (rn.to_string (), - "R V1 $2 1\n" + "R $2 V1 1\n" "R $2 $3 0\n" "R $3 V4 1\n" "R $3 V5 1" @@ -135,9 +135,9 @@ TEST(network_simplify2) rn.simplify (); EXPECT_EQ (rn.to_string (), - "R V1 $2 1\n" - "R V4 $2 1\n" - "R V5 $2 1" + "R $2 V1 1\n" + "R $2 V4 1\n" + "R $2 V5 1" ); } @@ -156,7 +156,7 @@ TEST(network_simplify3) rn.create_element (1, n3, n4); EXPECT_EQ (rn.to_string (), - "R V1 $2 1\n" + "R $2 V1 1\n" "R $2 $3 0\n" "R $3 V4 1" ); @@ -185,7 +185,7 @@ TEST(network_simplify4) EXPECT_EQ (rn.to_string (), "R V1 V4 1\n" "R $2 V1 1\n" - "R V4 $3 1" + "R $3 V4 1" ); rn.simplify (); diff --git a/src/pex/unit_tests/pexSquareCountingRExtractorTests.cc b/src/pex/unit_tests/pexSquareCountingRExtractorTests.cc index 1e4d7e326..77af14a1e 100644 --- a/src/pex/unit_tests/pexSquareCountingRExtractorTests.cc +++ b/src/pex/unit_tests/pexSquareCountingRExtractorTests.cc @@ -98,9 +98,9 @@ TEST(basic) // Same network, but opposite order. $1 and $2 are shorted, hence can be swapped. EXPECT_EQ (rn.to_string (), - "R $3 $1 1\n" + "R $1 $3 1\n" "R $1 $2 0\n" - "R $2 $0 0.390865" + "R $0 $2 0.390865" ); } @@ -135,8 +135,8 @@ TEST(extraction) rex.extract (poly, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R V0 $0 0.0952381\n" + "R $0 V0 0.0952381\n" "R $0 V1 0.166667\n" - "R P0 $0 0.117647" + "R $0 P0 0.117647" ) } diff --git a/src/pex/unit_tests/pexTriangulationRExtractorTests.cc b/src/pex/unit_tests/pexTriangulationRExtractorTests.cc index de2074322..b2bfff50c 100644 --- a/src/pex/unit_tests/pexTriangulationRExtractorTests.cc +++ b/src/pex/unit_tests/pexTriangulationRExtractorTests.cc @@ -64,7 +64,7 @@ TEST(extraction) rex.extract (poly, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R V1 V0 10.0938" + "R V0 V1 10.0938" ) } @@ -94,7 +94,7 @@ TEST(extraction_with_polygon_ports) rex.extract (poly, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R P1 P0 10" + "R P0 P1 10" ) } @@ -124,7 +124,7 @@ TEST(extraction_with_polygon_ports_inside) rex.extract (poly, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R P1 P0 10" + "R P0 P1 10" ) } @@ -155,7 +155,7 @@ TEST(extraction_split_by_ports) rex.extract (poly, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R P2 P0 5\n" + "R P0 P2 5\n" "R P1 P2 5" ) } @@ -187,7 +187,7 @@ TEST(extraction_split_by_butting_port) rex.extract (poly, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R P2 P0 4.84211\n" + "R P0 P2 4.84211\n" "R P1 P2 4.84211\n" "R P0 P1 281.111" ) @@ -220,7 +220,7 @@ TEST(extraction_with_outside_polygon_port) rex.extract (poly, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R P1 P0 11" + "R P0 P1 11" ) } @@ -251,7 +251,65 @@ TEST(extraction_with_polygon_ports_and_vertex_port_inside) rex.extract (poly, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R V0 P0 0\n" // shorted because V0 is inside P0 - "R P1 P0 10" + "R P0 V0 0\n" // shorted because V0 is inside P0 + "R P0 P1 10" ) } + +static db::Polygon ellipse (const db::Box &box, int npoints) +{ + npoints = std::max (3, std::min (10000000, npoints)); + + std::vector pts; + pts.reserve (npoints); + + double da = M_PI * 2.0 / npoints; + for (int i = 0; i < npoints; ++i) { + double x = box.center ().x () - box.width () * 0.5 * cos (da * i); + double y = box.center ().y () + box.height () * 0.5 * sin (da * i); + pts.push_back (db::Point (x, y)); + } + + db::Polygon c; + c.assign_hull (pts.begin (), pts.end (), false); + return c; +} + +TEST(extraction_analytic_disc) +{ + db::Coord r1 = 2000; + db::Coord r2 = 10000; + db::Coord r2pin = 10000 + 1000; + + db::Polygon outer = ellipse (db::Box (-r2pin, -r2pin, r2pin, r2pin), 64); + db::Polygon disc = ellipse (db::Box (-r2, -r2, r2, r2), 64); + db::Polygon inner = ellipse (db::Box (-r1, -r1, r1, r1), 64); + + db::Polygon outer_port = *(db::Region (outer) - db::Region (disc)).nth (0); + + double dbu = 0.001; + + pex::RNetwork rn; + pex::TriangulationRExtractor rex (dbu); + + std::vector vertex_ports; + + std::vector polygon_ports; + polygon_ports.push_back (inner); + polygon_ports.push_back (outer_port); + + rex.extract (disc, vertex_ports, polygon_ports, rn); + + EXPECT_EQ (rn.to_string (), + "R P0 P1 0.245379" // theoretical: 1/(2*PI)*log(r2/r1) = 0.25615 with r2=10000, r1=2000 + ) + + rex.triangulation_parameters ().max_area = 100000 * dbu * dbu; + + rex.extract (disc, vertex_ports, polygon_ports, rn); + + EXPECT_EQ (rn.to_string (), + "R P0 P1 0.255614" // theoretical: 1/(2*PI)*log(r2/r1) = 0.25615 with r2=10000, r1=2000 + ) +} +