def test_square_mesh(corner_x, corner_y, width, height, _): assume(width > 1e-3) assume(height > 1e-3) # todo limit aspect ratio bg = Rectangle.from_center([0, 0], 2e6, 2e6) r = Rectangle([corner_x, corner_y], width, height) mg = ModelGeometry(allow_overlaps=True) mg.add_domain("bg", bg) mg.add_domain("r", r) points = [ (-1e6, -1e6), (1e-6, -1e6), (1e6, 1e6), (-1e6, 1e6), (corner_x, corner_y), (corner_x + width, corner_y), (corner_x + width, corner_y + height), (corner_x, corner_y + height), ] mesh = create_mesh(mg) coordinates = mesh.coordinates() for p in points: err = coordinates - p assert np.any(np.isclose(err, 0, atol=1e-6))
def test_create_rectangle_center(center_x, center_y, width, height, use_height): if use_height: r = Rectangle.from_center([center_x, center_y], width, height) else: r = Rectangle.from_center([center_x, center_y], width) assert np.isclose(r.center[0], center_x) assert np.isclose(r.center[1], center_y) assert np.isclose(width, r.width) if use_height: assert np.isclose(height, r.height) if use_height: check_represented_area(r, width * height) else: check_represented_area(r, width * width)
def test_domain_single(): mg = ModelGeometry() bg = Rectangle.from_center([0, 0], 1) mg.add_domain("bg", bg) mesh = create_mesh(mg) domains = mark_domains(mesh, mg).array() assert np.all(domains == mg.domain_names["bg"])
def test_domain_nested(): mg = ModelGeometry() bg = Rectangle.from_center([0, 0], 1) r = Rectangle.from_center([0, 0], 0.5) mg.add_domain("bg", bg) mg.add_domain("r", r) mesh = create_mesh(mg) domains = mark_domains(mesh, mg).array() checker = r.expand(1e-3)._shapely_representation xy = mesh.coordinates() tri_f = tri.Triangulation(xy[:, 0], xy[:, 1], mesh.cells()) triangles = tri_f.get_masked_triangles() verts = np.stack((tri_f.x[triangles], tri_f.y[triangles]), axis=-1) for ix, (v1, v2, v3) in enumerate(verts): if (checker.contains(shp.Point(v1)) and checker.contains(shp.Point(v2)) and checker.contains(shp.Point(v3))): assert domains[ix] == mg.domain_names["r"] else: assert domains[ix] == mg.domain_names["bg"]
def make_square_in_square_in_square(complex=False): """Make a complex nested square structure. Default behaviour is a nested square Complex behaviour will nest two other squares inside the center square :param complex: If the complex regime will be used :return: Model geometry of the nested squares """ sq1 = Rectangle.from_center([0, 0], 6) sq2 = Rectangle.from_center([0, 0], 4) mg = ModelGeometry(allow_overlaps=True) mg.add_domain("bg", sq1) mg.add_domain("fg", sq2) if complex: sq3 = Rectangle.from_center([0, 0], 2) sq4 = Rectangle.from_center([0, 0], 0.5) # not labeled mg.add_domain("fg2", sq3) mg.add_domain("fake", sq4) mesh = create_mesh(mg) domains = mark_domains(mesh, mg) return domains, mg
def create_geometry( self, fish_x: Sequence[float], fish_y: Sequence[float], species: str = "APTERONOTUS", **kwargs, ): """Create the model geometry by making a fish, tank and ground and adding any additional user geometry. :param fish_x: x coordinates (head->tail) for the fish :param fish_y: y coordinates (head->tail) for the fish :param species: Name of the species :param kwargs: Catchall for the remaining parameters """ self.setup_fish(fish_x, fish_y, species) ground = Circle(self.GROUND_LOCATION, self.GROUND_RADIUS) tank = Rectangle.from_center([0, 0], self.TANK_SIZE) self.model_geometry.add_domain( self.WATER_NAME, tank, sigma=self.WATER_CONDUCTIVITY, ) self.model_geometry.add_domain( self.GROUND_NAME, ground, sigma=self.GROUND_CONDUCTIVITY ) self.add_geometry(**kwargs) # iterate over (possible) multiple fish and add them for ix, (outer_body, body, organ, skin_cond) in enumerate( zip( self.fish_container.outer_body, self.fish_container.body, self.fish_container.organ, self.fish_container.skin_conductance, ) ): self.model_geometry.add_domain( f"{self.SKIN_NAME}_{ix}", outer_body, sigma=skin_cond ) self.model_geometry.add_domain( f"{self.BODY_NAME}_{ix}", body, sigma=self.BODY_CONDUCTIVITY ) self.model_geometry.add_domain( f"{self.ORGAN_NAME}_{ix}", organ, sigma=self.ORGAN_CONDUCTIVITY )
import pytest from fish2eod.geometry.primitives import Circle, Rectangle from fish2eod.mesh.model_geometry import ModelGeometry overlaps_c1 = Circle([0, 0], 0.5) not_on_bg = Circle([15, 15], 1) bg = Rectangle.from_center([0, 0], 10) c1 = Circle([0, 0], 1) c2 = Circle([2, 2], 1) @pytest.mark.quick def test_create_only_bg(): ModelGeometry() @pytest.mark.quick def test_create_seperate_domains(): mg = ModelGeometry() mg.add_domain("bg", bg) mg.add_domain("c1", c1) mg.add_domain("c2", c2) @pytest.mark.quick def test_not_on_bg(): mg = ModelGeometry() mg.add_domain("bg", bg) with pytest.raises(ValueError) as _: mg.add_domain("off", not_on_bg)
def test_rotate(angle, degrees, center): r = Rectangle.from_center([0, 0], 5, 5) re_done = r.rotate(angle, degrees, center).rotate(-angle, degrees, center) check_overlap_equal(r, re_done)
def create_geometry(self, **kwargs): sq = Rectangle.from_center([0, 0], 3) circ = Circle([0, 0], 0.5) self.model_geometry.add_domain("bg", sq, sigma=1) self.model_geometry.add_domain("act", circ, sigma=2)