├── .gitignore ├── .pytest_cache ├── README.md └── v │ └── cache │ ├── lastfailed │ └── nodeids ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.org ├── blockmeshdict.txt ├── pyblockmesh ├── __init__.py ├── edge.py ├── face.py ├── hexahedron.py └── vertex.py ├── pytest.ini ├── requirements.txt ├── script └── test ├── setup.cfg ├── setup.py └── tests ├── __init__.py ├── helpers ├── __init__.py └── my_helper.py ├── test_edge_operations.py ├── test_face_operations.py ├── test_hexahedron_operations.py ├── test_vertex_operations.py └── tests_helper.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | .python-version 3 | 4 | # C extensions 5 | *.so 6 | 7 | # Packages 8 | *.egg 9 | *.egg-info 10 | dist 11 | build 12 | eggs 13 | parts 14 | bin 15 | var 16 | sdist 17 | develop-eggs 18 | .installed.cfg 19 | lib 20 | lib64 21 | .cache 22 | 23 | # Installer logs 24 | pip-log.txt 25 | 26 | # Unit test / coverage reports 27 | .coverage 28 | coverage.* 29 | .tox 30 | nosetests.xml 31 | htmlcov 32 | 33 | # Translations 34 | *.mo 35 | 36 | # Mr Developer 37 | .mr.developer.cfg 38 | .project 39 | .pydevproject 40 | -------------------------------------------------------------------------------- /.pytest_cache/README.md: -------------------------------------------------------------------------------- 1 | # pytest cache directory # 2 | 3 | This directory contains data from the pytest's cache plugin, 4 | which provides the `--lf` and `--ff` options, as well as the `cache` fixture. 5 | 6 | **Do not** commit this to version control. 7 | 8 | See [the docs](https://docs.pytest.org/en/latest/cache.html) for more information. 9 | -------------------------------------------------------------------------------- /.pytest_cache/v/cache/lastfailed: -------------------------------------------------------------------------------- 1 | { 2 | "pyblockmesh/edge.py": true, 3 | "pyblockmesh/face.py": true, 4 | "pyblockmesh/hexahedron.py": true, 5 | "pyblockmesh/vertex.py": true, 6 | "tests/edge/test_operations.py::TestInitialization::test_expansionRatio": true, 7 | "tests/edge/test_operations.py::TestInitialization::test_keyword": true, 8 | "tests/vertex/test_operations.py::TestInitialization::test_iter": true, 9 | "tests/vertex/test_operations.py::TestInitialization::test_len": true, 10 | "tests/vertex/test_operations.py::TestOperation::test_add": true, 11 | "tests/vertex/test_operations.py::TestOperation::test_equal": true, 12 | "tests/vertex/test_operations.py::TestOperation::test_mult": true, 13 | "tests/vertex/test_operations.py::TestOperation::test_sub": true 14 | } -------------------------------------------------------------------------------- /.pytest_cache/v/cache/nodeids: -------------------------------------------------------------------------------- 1 | [ 2 | "tests/test_edge_operations.py::TestInitialization::test_expansionRatio", 3 | "tests/test_edge_operations.py::TestInitialization::test_keyword", 4 | "tests/test_vertex_operations.py::TestInitialization::test_del", 5 | "tests/test_vertex_operations.py::TestInitialization::test_initialization", 6 | "tests/test_vertex_operations.py::TestInitialization::test_iter", 7 | "tests/test_vertex_operations.py::TestInitialization::test_len", 8 | "tests/test_vertex_operations.py::TestInitialization::test_repr", 9 | "tests/test_vertex_operations.py::TestOperation::test_add", 10 | "tests/test_vertex_operations.py::TestOperation::test_equal", 11 | "tests/test_vertex_operations.py::TestOperation::test_gt", 12 | "tests/test_vertex_operations.py::TestOperation::test_lt", 13 | "tests/test_vertex_operations.py::TestOperation::test_mult", 14 | "tests/test_vertex_operations.py::TestOperation::test_sub" 15 | ] -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "3.3" 5 | - "3.4" 6 | - "3.5" 7 | script: 8 | - py.test 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2016-02-13 2 | 3 | * Update requirements to latest versions 4 | * Add oss related files 5 | * Add require.io badge for requirements to README 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Adding features or fixing bugs 4 | 5 | * Fork the repo 6 | * Check out a feature or bug branch 7 | * Add your changes 8 | * Update README when needed 9 | * Submit a pull request to upstream repo 10 | * Add description of your changes 11 | * Ensure tests are passing 12 | * Ensure branch is mergeable 13 | 14 | ## Testing 15 | 16 | * Please make sure tests pass with `./script/test` 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Vishakh Kumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+TITLE: pyblockmesh 2 | #+AUTHOR: Vishakh Pradeep Kumar 3 | #+EMAIL: grokkingStuff@gmail.com 4 | 5 | Python Library 6 | 7 | #+BEGIN_SRC sh :exports results 8 | . 9 | ├── CHANGELOG.md 10 | ├── CONTRIBUTING.md 11 | ├── index.org 12 | ├── LICENSE 13 | ├── pyblockmesh 14 | │   ├── edge.py 15 | │   ├── face.py 16 | │   ├── hexahedron.py 17 | │   ├── __init__.py 18 | │   └── vertex.py 19 | ├── pytest.ini 20 | ├── README.md 21 | ├── README.org 22 | ├── requirements.txt 23 | ├── script 24 | │   └── test 25 | ├── setup.py 26 | └── tests 27 | ├── helpers 28 | │   ├── __init__.py 29 | │   └── my_helper.py 30 | ├── __init__.py 31 | ├── tests_helper.py 32 | └── unit 33 | ├── __init__.py 34 | ├── test_example.py 35 | └── test_version.py 36 | 37 | 5 directories, 22 files 38 | #+END_SRC 39 | 40 | * Example 41 | 42 | 43 | #+BEGIN_SRC python 44 | import pyblockmesh as pbm 45 | 46 | 47 | v0 = pbm.Vertex(-1,-1,-1) 48 | v1 = pbm.Vertex( 1,-1,-1) 49 | v2 = pbm.Vertex( 1, 1,-1) 50 | v3 = pbm.Vertex(-1, 1,-1) 51 | v4 = pbm.Vertex(-1,-1, 1) 52 | v5 = pbm.Vertex( 1,-1, 1) 53 | v6 = pbm.Vertex( 1, 1, 1) 54 | v7 = pbm.Vertex(-1, 1, 1) 55 | 56 | h1 = pbm.Hexahedron([v0,v1,v2,v3,v4,v5,v6,v7],numberOfCells=[3,3,3]) 57 | h1.add_edge(v0,v1,'line') 58 | h1.add_face([v0,v1,v2,v3],name='inlet',patchType='wall') 59 | 60 | string = pbm.buildBlockMesh() 61 | 62 | print(string) 63 | blockMeshDict = open("blockmeshdict.txt", "w") 64 | blockMeshDict.write(string) 65 | blockMeshDict.close() 66 | #+END_SRC 67 | 68 | #+RESULTS: 69 | : None 70 | 71 | #+BEGIN_EXAMPLE 72 | vertices 73 | ( 74 | (-1 -1 -1) 75 | (1 -1 -1) 76 | (1 1 -1) 77 | (-1 1 -1) 78 | (-1 -1 1) 79 | (1 -1 1) 80 | (1 1 1) 81 | (-1 1 1) 82 | ) 83 | 84 | blocks 85 | ( 86 | hex 0 1 2 3 4 5 6 7 ( 3 3 3 ) 87 | ) 88 | 89 | edges 90 | ( 91 | line 0 1 92 | ) 93 | 94 | boundary 95 | ( 96 | inlet 97 | { 98 | type wall; 99 | faces 100 | ( 101 | ( 0 3 2 1 ) 102 | ); 103 | } 104 | ) 105 | #+END_EXAMPLE 106 | 107 | 108 | 109 | * Requirements 110 | 111 | Package requirements are handled using pip. To install them do 112 | 113 | #+BEGIN_SRC sh 114 | pip install -r requirements.txt 115 | #+END_SRC 116 | 117 | -------------------------------------------------------------------------------- /blockmeshdict.txt: -------------------------------------------------------------------------------- 1 | 2 | vertices 3 | ( 4 | (-1 -1 -1) 5 | (1 -1 -1) 6 | (1 1 -1) 7 | (-1 1 -1) 8 | (-1 -1 1) 9 | (1 -1 1) 10 | (1 1 1) 11 | (-1 1 1) 12 | ) 13 | 14 | blocks 15 | ( 16 | hex 0 1 2 3 4 5 6 7 ( 3 3 3 ) 17 | ) 18 | 19 | edges 20 | ( 21 | line 0 1 22 | ) 23 | 24 | boundary 25 | ( 26 | inlet 27 | { 28 | type wall; 29 | faces 30 | ( 31 | ( 0 3 2 1 ) 32 | ); 33 | } 34 | ) -------------------------------------------------------------------------------- /pyblockmesh/__init__.py: -------------------------------------------------------------------------------- 1 | from pyblockmesh.vertex import Vertex 2 | from pyblockmesh.hexahedron import Hexahedron 3 | from pyblockmesh.edge import Edge 4 | from pyblockmesh.face import Face 5 | 6 | def buildBlockMesh(): 7 | v = Vertex.list_all() 8 | b = Hexahedron.list_all() 9 | e = Edge.list_all() 10 | f = Face.list_all() 11 | return "\n".join([v,b,e,f]) 12 | -------------------------------------------------------------------------------- /pyblockmesh/edge.py: -------------------------------------------------------------------------------- 1 | from collections.abc import Mapping, MutableMapping 2 | 3 | from enum import Enum # for enum34, or the stdlib version 4 | # from aenum import Enum # for the aenum version 5 | 6 | 7 | 8 | class Edge(MutableMapping): 9 | instances = [] 10 | edgeTypes = Enum('edgeType', 'arc spline polyLine BSpline line') 11 | 12 | def __init__(self, 13 | vertices, 14 | expansionRatio = None, 15 | keyword = None, 16 | interpolationPoints = [], 17 | *args,**kwargs): 18 | 19 | self._storage = dict(vertices = vertices, 20 | expansionRatio = expansionRatio, 21 | keyword = keyword, 22 | *args,**kwargs) 23 | 24 | # Assign expansionRatio 25 | if expansionRatio is None: 26 | self["expansionRatio"] = 1 27 | else: 28 | self["expansionRatio"] = expansionRatio 29 | 30 | # Default keyword is 'line' 31 | # The interpolation points are vertices 32 | if keyword is None: 33 | self["keyword"] = Edge.edgeTypes.line.name 34 | self["interpolationPoints"] = [] 35 | elif keyword not in Edge.edgeTypes._member_names_: 36 | raise ValueError("keyword must be a valid edge type") 37 | else: 38 | self["keyword"] = Edge.edgeTypes[keyword].name 39 | self["interpolationPoints"] = interpolationPoints 40 | 41 | Edge.instances.append(self) 42 | 43 | def __getitem__(self, key): 44 | return self._storage[key] 45 | def __iter__(self): 46 | return iter(self["vertices"]) 47 | def __setitem__(self, key, value): 48 | self._storage[key] = value 49 | def __delitem__(self, key): 50 | del self._storage[key] 51 | def __len__(self): 52 | return 2 53 | def __repr__(self): 54 | edge = self["keyword"] 55 | v1Name = self["vertices"][0]["name"] 56 | v2Name = self["vertices"][1]["name"] 57 | 58 | if v1Name == None or v2Name == None: 59 | raise ValueError("vertices must have names before they can be represented") 60 | 61 | v1Name = str(v1Name) 62 | v2Name = str(v2Name) 63 | 64 | if isinstance(self["interpolationPoints"],list): 65 | if self["interpolationPoints"] != []: 66 | # Multiple interpolation points 67 | points = "( " + " ".join([str(point) for point in self["interpolationPoints"]]) + " )" 68 | else: 69 | # No interpolation points 70 | points = "" 71 | else: 72 | # Single interpolationPoint 73 | points = str(self["interpolationPoints"]) 74 | string = " ".join([edge,v1Name,v2Name,points]) 75 | return string.rstrip() 76 | -------------------------------------------------------------------------------- /pyblockmesh/face.py: -------------------------------------------------------------------------------- 1 | from collections.abc import MutableMapping 2 | from enum import Enum 3 | 4 | 5 | 6 | 7 | class Face(MutableMapping): 8 | patchTypes = Enum('patchType', 'patch wall symmetryPlane symmetry empty wedge cyclic cyclicAMI processor') 9 | 10 | def __init__(self, 11 | vertices=[], 12 | name=None, 13 | patchType=None, 14 | *args, **kw): 15 | 16 | if vertices == []: 17 | raise ValueError("In order to define a face, you must provide vertices") 18 | if isinstance(vertices,list): 19 | assert len(vertices) == 4, "Four vertices must be provided to instantiate a face" 20 | if name is None: 21 | raise ValueError("A face must have a name") 22 | if patchType is None: 23 | patchType = 'patch' 24 | 25 | self._storage = dict(patchType=patchType, 26 | name=name, 27 | *args, **kw) 28 | self._storage["vertices"] = {} 29 | self._storage["vertices"][0] = vertices[0] 30 | self._storage["vertices"][1] = vertices[1] 31 | self._storage["vertices"][2] = vertices[2] 32 | self._storage["vertices"][3] = vertices[3] 33 | 34 | def __getitem__(self, key): 35 | return self._storage[key] 36 | def __setitem__(self, key, value): 37 | self._storage[key] = value 38 | def __delitem__(self, key): 39 | del self._storage[key] 40 | def __len__(self): 41 | return 4 42 | def __iter__(self): 43 | return iter([self._storage["vertices"][0], 44 | self._storage["vertices"][1], 45 | self._storage["vertices"][2], 46 | self._storage["vertices"][3]]) 47 | def __eq__(self, other): 48 | if not isinstance(other,Face): 49 | return False 50 | else: 51 | for vertex in self: 52 | if vertex not in other['vertices'].values(): 53 | return False 54 | if self["patchType"] != other["patchType"]: 55 | return False 56 | return True 57 | 58 | def __repr__(self): 59 | faceName = self["name"] 60 | patchString = self["patchType"] 61 | verticesNumberString = "( " + " ".join([str(vertex["name"]) for vertex in [self["vertices"][i] for i in range(0,4)]]) + " )" 62 | string = faceName + "\n{\n type " + patchString + ";\n faces\n (\n " + verticesNumberString + " \n );\n}" 63 | return string 64 | 65 | -------------------------------------------------------------------------------- /pyblockmesh/hexahedron.py: -------------------------------------------------------------------------------- 1 | import pyblockmesh.vertex as v 2 | import pyblockmesh.edge as e 3 | import pyblockmesh.face as f 4 | 5 | from collections.abc import MutableMapping 6 | from collections import deque 7 | 8 | class Hexahedron(MutableMapping): 9 | instances = [] 10 | 11 | def __init__(self,vertices,numberOfCells,*args,**kw): 12 | 13 | # Tests or Assertions here to ensure that everything makes sense. 14 | # Will do later 15 | self._storage = dict(numberOfCells=numberOfCells, 16 | *args,**kw) 17 | 18 | self._storage["vertices"]={} 19 | self._storage["vertices"][0] = vertices[0] 20 | self._storage["vertices"][1] = vertices[1] 21 | self._storage["vertices"][2] = vertices[2] 22 | self._storage["vertices"][3] = vertices[3] 23 | self._storage["vertices"][4] = vertices[4] 24 | self._storage["vertices"][5] = vertices[5] 25 | self._storage["vertices"][6] = vertices[6] 26 | self._storage["vertices"][7] = vertices[7] 27 | 28 | self._storage["edges"] = {} 29 | self._storage["faces"] = [] 30 | Hexahedron.instances.append(self) 31 | 32 | def __getitem__(self, key): 33 | return self._storage[key] 34 | def __iter__(self): 35 | return iter(self._storage) 36 | def __len__(self): 37 | return len(self._storage) 38 | def __setitem__(self, key, value): 39 | self._storage[key] = value 40 | def __delitem__(self, key): 41 | del self._storage[key] 42 | def __repr__(self): 43 | list_of_vertices = [self["vertices"][0],self["vertices"][1],self["vertices"][2],self["vertices"][3], 44 | self["vertices"][4],self["vertices"][5],self["vertices"][6],self["vertices"][7]] 45 | 46 | v.Vertex.assign_names() 47 | prefix_string = "hex" 48 | vertex_string = " ".join([vertex["name"] for vertex in list_of_vertices]) 49 | numberCells_string = "( " + " ".join(str(i) for i in self["numberOfCells"]) + " )" 50 | return " ".join([prefix_string,vertex_string,numberCells_string]) 51 | 52 | def add_face(self,*args,**kwargs): 53 | try: 54 | face = f.Face(*args,**kwargs) 55 | except: 56 | ValueError("Face Creation Failed") 57 | list_of_vertices = [self["vertices"][0], 58 | self["vertices"][1], 59 | self["vertices"][2], 60 | self["vertices"][3], 61 | self["vertices"][4], 62 | self["vertices"][5], 63 | self["vertices"][6], 64 | self["vertices"][7]] 65 | # Ensure that the vertices are actually part of the hexahedron. This is important enough for us to throw an error. 66 | try: 67 | indexv0 = list_of_vertices.index(face["vertices"][0]) 68 | indexv1 = list_of_vertices.index(face["vertices"][1]) 69 | indexv2 = list_of_vertices.index(face["vertices"][2]) 70 | indexv3 = list_of_vertices.index(face["vertices"][3]) 71 | except: 72 | raise ValueError("The vertices given are not part of the hexahedron. Please check your vertices") 73 | 74 | # Now that we know that the vertices are actually part of the hexahedron, it is time to check if it is a valid face 75 | possible_faces = [[ list_of_vertices[0], list_of_vertices[3], list_of_vertices[2], list_of_vertices[1] ], 76 | [ list_of_vertices[5], list_of_vertices[6], list_of_vertices[7], list_of_vertices[4] ], 77 | [ list_of_vertices[0], list_of_vertices[4], list_of_vertices[7], list_of_vertices[3] ], 78 | [ list_of_vertices[1], list_of_vertices[2], list_of_vertices[6], list_of_vertices[5] ], 79 | [ list_of_vertices[0], list_of_vertices[1], list_of_vertices[5], list_of_vertices[4] ], 80 | [ list_of_vertices[3], list_of_vertices[1], list_of_vertices[6], list_of_vertices[7] ]] 81 | 82 | temp = False 83 | face_vertices = [face['vertices'][0],face['vertices'][1],face['vertices'][2],face['vertices'][3]] 84 | for possible_face in possible_faces: 85 | if sorted(face_vertices) == sorted(possible_face): 86 | # We've selected a face with similar elements to our index_list 87 | # So we return the list as it is 88 | 89 | face["vertices"][0] = possible_face[0] 90 | face["vertices"][1] = possible_face[1] 91 | face["vertices"][2] = possible_face[2] 92 | face["vertices"][3] = possible_face[3] 93 | 94 | 95 | temp = True 96 | 97 | # If we can't find similar faces, it does not exist. 98 | if temp is False: 99 | raise ValueError("Vertices given do not form a face. Please give valid vertices (they must all be adjacent to each other)") 100 | 101 | # At this stage, we have a face where the vertices are correctly formatted. 102 | # Now we need to check if a face with the same vertices exist and if so, raise a ValueError 103 | # If not, we add to the list 104 | 105 | # Sort the current list by order of vertices. Not that intensive and is qsort behind the scenes 106 | self["faces"] = sorted(self["faces"], key=lambda k: set(k['vertices'])) 107 | 108 | match = list(filter(lambda x: x['vertices'] == face["vertices"], self['faces'])) 109 | if match == []: 110 | # Awesome! You have a brand new face 111 | self['faces'].append(face) 112 | else: 113 | print(match) 114 | raise ValueError("Face already exists with those vertices") 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | def add_edge(self,*args,**kwargs): 126 | edge = e.Edge(*args,**kwargs) 127 | list_of_vertices = [self["vertices"][0],self["vertices"][1],self["vertices"][2],self["vertices"][3], 128 | self["vertices"][4],self["vertices"][5],self["vertices"][6],self["vertices"][7]] 129 | 130 | # Ensure that the vertices are actually part of the hexahedron. This is important enough for us to throw an error. 131 | try: 132 | indexv1 = list_of_vertices.index(edge["vertices"][0]) 133 | indexv2 = list_of_vertices.index(edge["vertices"][1]) 134 | 135 | assert -1 < indexv1 < 8 136 | assert -1 < indexv2 < 8 137 | except ValueError: 138 | raise ValueError("The vertices given are not part of the hexahedron. Please check your vertices") 139 | 140 | # Now that we know the edge is actually part of the hexahedron, it is time to check if it is a valid edge 141 | 142 | edgeDict = {} # This is a poor approximation of a directed graph but it works 143 | edgeDict[0] = {} 144 | edgeDict[1] = {} 145 | edgeDict[2] = {} 146 | edgeDict[3] = {} 147 | edgeDict[4] = {} 148 | edgeDict[5] = {} 149 | edgeDict[6] = {} 150 | edgeDict[7] = {} 151 | edgeDict[0][1] = 0 152 | edgeDict[3][2] = 1 153 | edgeDict[7][6] = 2 154 | edgeDict[4][5] = 3 155 | edgeDict[0][3] = 4 156 | edgeDict[1][2] = 5 157 | edgeDict[5][6] = 6 158 | edgeDict[4][7] = 7 159 | edgeDict[0][4] = 8 160 | edgeDict[1][5] = 9 161 | edgeDict[2][6] = 10 162 | edgeDict[3][7] = 11 163 | 164 | temp = edgeDict.get(indexv1,None) 165 | if temp is not None: 166 | edgeNumber = temp.get(indexv2,None) 167 | else: 168 | temp = edgeDict.get(indexv2,None) 169 | if temp is not None: 170 | edgeNumber = temp.get(indexv1,None) 171 | 172 | if edgeNumber is None: 173 | raise ValueError("The vertices given are not adjacent, ie they cannot form an edge.") 174 | 175 | 176 | self["edges"][edgeNumber] = edge 177 | 178 | @classmethod 179 | def list_all(cls): 180 | string = "\nblocks\n(" + "\n " + "\n ".join([str(hexahedron) for hexahedron in cls.instances]) + "\n)" 181 | return string 182 | 183 | -------------------------------------------------------------------------------- /pyblockmesh/vertex.py: -------------------------------------------------------------------------------- 1 | from collections.abc import MutableMapping 2 | import numpy as np 3 | 4 | class Vertex(MutableMapping): 5 | instances = [] 6 | 7 | def __init__(self, x=None, y=None, z=None, *args, **kw): 8 | if x is None or y is None or z is None: 9 | raise ValueError("(x,y,z) cannot contain null values") 10 | x, y, z = np.int64(x), np.int64(y), np.int64(z) 11 | self._storage = dict(x=x,y=y,z=z,name=None,*args, **kw) 12 | Vertex.instances.append(self) 13 | 14 | def __getitem__(self, key): 15 | return self._storage[key] 16 | def __setitem__(self, key, value): 17 | self._storage[key] = value 18 | def __delitem__(self, key): 19 | del self._storage[key] 20 | def __iter__(self): 21 | return iter([self["x"],self["y"],self["z"]]) 22 | def __len__(self): 23 | return 3 24 | def __repr__(self): 25 | string = "("+str(self["x"])+" "+str(self["y"])+" "+str(self["z"])+")" 26 | return string 27 | 28 | 29 | # Mathematical Functions: Addition, Negation and Subtraction 30 | def __add__(self, other): 31 | '''Adds a vertex, number or numpy array to a vertex together''' 32 | 33 | import numpy as np # Used to add numpy arrays of length 3 to the vertex 34 | 35 | if isinstance(other, Vertex): 36 | # Used to support Vertex(0,0,0) + Vertex(0,0,1) 37 | return Vertex(self["x"] + other["x"], 38 | self["y"] + other["y"], 39 | self["z"] + other["z"]) 40 | elif isinstance(other, list): 41 | # Used to support Vertex(0,0,0) + [1,2,3] 42 | assert len(other) is 3, "Length of list must be 3" 43 | return Vertex(self['x'] + other[0], 44 | self['y'] + other[1], 45 | self['z'] + other[2]) 46 | elif isinstance(other, np.ndarray): 47 | # Used to support Vertex(0,0,0) + np.array([1,2,3]) or 48 | # Vertex(0,0,0) + np.array([[1],[2],[3]]) 49 | dimension = other.shape 50 | # Ensure that other is either 1D or 2D 51 | assert len(dimension) is 2 or len(dimension) is 1, "numpy array must be of shape (3,) or (3,1)" 52 | 53 | # We need to find out if we're dealing with a vector in the math term or the programming term 54 | # programming term: theta = np.array([1,2,3,4,5]) 55 | # math term: np.array([1,2,3,4,5])[:,np.newaxis] 56 | 57 | # We should really raise a error or warning here but I am a benovelent god. 58 | # (Also, I kinda forget to switch axes all the time and I'm guessing there are people like me out there) 59 | 60 | if len(dimension) is 1: 61 | # We're dealing with arrays like np.array([1,2,3]) 62 | # aka programming term 63 | assert dimension[0] is 3, "numpy array should have only three elements" 64 | 65 | return Vertex(self['x'] + other[0], 66 | self['y'] + other[1], 67 | self['z'] + other[2]) 68 | elif len(dimension) is 2: 69 | # We're dealing with arrays like np,array([[1],[2],[3]]) 70 | # aka math term 71 | assert dimension[0] is 3, "numpy array should only have three elements" 72 | assert dimension[1] is 1, "numpy array must be a vector and have only three elements" 73 | 74 | return Vertex(self['x'] + other[0][0], 75 | self['y'] + other[1][0], 76 | self['z'] + other[2][0]) 77 | 78 | 79 | def __radd__(self,other): 80 | return self.__add__(other) 81 | def __neg__(self): 82 | '''Returns negative of self''' 83 | return Vertex(-self['x'], 84 | -self['y'], 85 | -self['z']) 86 | def __sub__(self,other): 87 | '''Implements subtraction. Refer __add__''' 88 | try: 89 | other = other.__neg__() 90 | except AttributeError: 91 | # Probably a list 92 | other_list = [] 93 | for i in other: 94 | i *= -1 95 | other_list.append(i) 96 | return self.__add__(other_list) 97 | return self.__add__(other) 98 | def __rsub__(self,other): 99 | return (self.__neg__()).__add__(other) 100 | 101 | def __mul__(self, other): 102 | ''' multiply self with other, e.g. Vertex(0,0,1) * 7 == Vertex(0,0,7) ''' 103 | 104 | from numbers import Number # Used to check if the variable 'other' is actually a number 105 | import numpy as np # Used for tensor multiplication 106 | 107 | if isinstance(other, Vertex): 108 | raise TypeError("Vertices cannot be multiplied together") 109 | elif isinstance(other, Number): 110 | return Vertex(self['x'] * other, 111 | self['y'] * other, 112 | self['z'] * other) 113 | elif isinstance(other,np.ndarray): 114 | dimension = other.shape 115 | 116 | assert dimension == (3, 3), "Only tensors of shape (3,3) can be used for multiplication" 117 | 118 | vector = np.array([self['x'],self['y'],self['z']])[:,np.newaxis] 119 | 120 | assert vector.shape == (3,1) 121 | ans = other.dot(vector) 122 | assert ans.shape == (3,1) 123 | 124 | import warnings 125 | warnings.warn("Please reverse order of multiplicands." + 126 | " While correct, it is best to keep the rules of matrix multiplication in mind." + 127 | " Vertex should be treated as a vector", UserWarning) 128 | 129 | return Vertex(ans[0][0], 130 | ans[1][0], 131 | ans[2][0]) 132 | else: 133 | raise TypeError("Vertices cannot be multiplied with %s" % type(other)) 134 | 135 | __array_priority__ = 10000 # Used so that other types respect your __rmul__ instead of using their __mul__ 136 | def __rmul__(self, other): 137 | ''' multiply other with self, e.g. 7 * Vertex(0,0,0) ''' 138 | import numpy as np # Used to check if other is a numpy array 139 | if isinstance(other,np.ndarray): 140 | 141 | dimension = other.shape 142 | 143 | assert dimension == (3,3), "Only tensors of shape (3,3) can be used for multiplication" 144 | 145 | vector = np.array([self['x'],self['y'],self['z']])[:,np.newaxis] 146 | assert vector.shape == (3,1) 147 | ans = other.dot(vector) 148 | assert ans.shape == (3,1) 149 | 150 | return Vertex(ans[0][0], 151 | ans[1][0], 152 | ans[2][0]) 153 | else: 154 | return self.__mul__(other) 155 | 156 | # Comparison Functions <, == 157 | def __lt__(self,other): 158 | ''' Less than is implemented via Lexicographical order''' 159 | x = self["x"] < other["x"] 160 | y = self["y"] < other["y"] 161 | z = self["z"] < other["z"] 162 | 163 | x1 = self["x"] == other["x"] 164 | y1 = self["y"] == other["y"] 165 | z1 = self["z"] == other["z"] 166 | 167 | if x and not x1: 168 | return True 169 | elif x1: 170 | if y and not y1: 171 | return True 172 | elif y1: 173 | if z and not z1: 174 | return True 175 | else: 176 | return False 177 | else: 178 | return False 179 | else: 180 | return False 181 | 182 | def __eq__(self, other): 183 | ''' Check for equality between vertices''' 184 | if type(other) is type(self): 185 | if self["x"] == other["x"] and self["y"] == other["y"] and self["z"] == other["z"]: 186 | return True 187 | else: 188 | return False 189 | else: 190 | return False 191 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | norecursedirs = venv* .* 3 | addopts = 4 | -r fEsxXw 5 | -vvv 6 | --doctest-modules 7 | --ignore setup.py 8 | --cov-report=term-missing 9 | --cov-report=xml 10 | --cov-report=html 11 | --cov=pyblockmesh 12 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | pytest-cov 3 | -------------------------------------------------------------------------------- /script/test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Test app 4 | # 5 | 6 | pip install -r requirements.txt 7 | 8 | py.test 9 | 10 | # vim: ft=sh: 11 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | # Inside of setup.cfg 2 | [metadata] 3 | description-file = README.org 4 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | 4 | setuptools.setup(name='pyblockMesh', 5 | version='0.0.3', 6 | description='Python wrapper around blockMeshDict creation', 7 | long_description=open('README.org').read().strip(), 8 | author='Vishakh Kumar', 9 | author_email='grokkingStuff@gmail.com', 10 | url='https://github.com/grokkingStuff/pyblockmesh', 11 | py_modules=['pyblockmesh.vertex','pyblockmesh.edge','pyblockmesh.face','pyblockmesh.hexahedron'], 12 | packages=['pyblockmesh'], 13 | install_requires=[], 14 | license='MIT License', 15 | zip_safe=False, 16 | python_requires='>=3', 17 | keywords='blockmesh blockmeshdict openfoam pyfoam', 18 | classifiers=[ 19 | # How mature is this project? Common values are 20 | # 3 - Alpha 21 | # 4 - Beta 22 | # 5 - Production/Stable 23 | 'Development Status :: 3 - Alpha', 24 | 25 | # Indicate who your project is intended for 26 | 'Intended Audience :: Developers', 27 | 28 | # Pick your license as you wish (should match "license" above) 29 | 'License :: OSI Approved :: MIT License', 30 | 31 | # Specify the Python versions you support here. In particular, ensure 32 | # that you indicate whether you support Python 2, Python 3 or both. 33 | 'Programming Language :: Python :: 3', 34 | 'Programming Language :: Python :: 3.2', 35 | 'Programming Language :: Python :: 3.2', 36 | 'Programming Language :: Python :: 3.3', 37 | 'Programming Language :: Python :: 3.4', 38 | ]) 39 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from tests.tests_helper import * 3 | import unittest 4 | from tests.helpers import * 5 | 6 | __all__ = [ 7 | 'pytest', 8 | 'unittest', 9 | 'tests_helper' 10 | ] 11 | -------------------------------------------------------------------------------- /tests/helpers/__init__.py: -------------------------------------------------------------------------------- 1 | from .my_helper import MyHelper 2 | 3 | 4 | __all__ = [ 5 | 'MyHelper' 6 | ] 7 | -------------------------------------------------------------------------------- /tests/helpers/my_helper.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | 4 | class MyHelper(): 5 | 6 | @classmethod 7 | def days_ago(cls, d): 8 | return (datetime.now().date() - d).days 9 | -------------------------------------------------------------------------------- /tests/test_edge_operations.py: -------------------------------------------------------------------------------- 1 | import pyblockmesh as pbm 2 | 3 | from tests import * 4 | from tests.helpers import * 5 | 6 | # Unit tests are great but what about property tests? 7 | 8 | class TestInitialization(unittest.TestCase): 9 | 10 | def test_expansionRatio(self): 11 | v1 = pbm.Vertex(1,3,1) 12 | v2 = pbm.Vertex(1,5,6) 13 | 14 | e1 = pbm.Edge([v1,v1],keyword='line') 15 | self.assertEqual(e1["expansionRatio"],1) 16 | 17 | e2 = pbm.Edge([v1,v1],expansionRatio=3,keyword='line') 18 | self.assertEqual(e2["expansionRatio"],3) 19 | 20 | def test_keyword(self): 21 | v1 = pbm.Vertex(1,3,1) 22 | v2 = pbm.Vertex(1,5,6) 23 | 24 | e1 = pbm.Edge([v1,v1]) 25 | self.assertEqual(e1["keyword"],'line') 26 | self.assertEqual(e1["interpolationPoints"],[]) 27 | 28 | e1 = pbm.Edge([v1,v1],keyword='spline') 29 | self.assertEqual(e1["keyword"],'spline') 30 | 31 | with pytest.raises(ValueError): 32 | e1 = pbm.Edge([v1,v1],keyword='Kenobi') 33 | self.assertEqual(e1["keyword"],'spline') 34 | 35 | e1 = pbm.Edge([v1,v2]) 36 | self.assertEqual(e1["keyword"],'line') 37 | self.assertEqual(e1["interpolationPoints"],[]) 38 | 39 | def test_iter(self): 40 | v1 = pbm.Vertex(1,2,3) 41 | v2 = pbm.Vertex(1,4,3) 42 | 43 | e1 = pbm.Edge([v1,v2]) 44 | for vertex in e1: 45 | self.assertEqual(vertex in [v1,v2],True) 46 | 47 | def test_del(self): 48 | v1 = pbm.Vertex(1,2,3) 49 | v2 = pbm.Vertex(3,4,2) 50 | 51 | v1["name"]=0 52 | v2["name"]=2 53 | 54 | e1 = pbm.Edge([v1,v2]) 55 | e1["name"] = "Elizabeth" 56 | e1.__delitem__("name") 57 | 58 | with pytest.raises(KeyError): 59 | self.assertEqual(e1["name"],"Elizabeth") 60 | 61 | def test_len(self): 62 | v1 = pbm.Vertex(1,2,3) 63 | v2 = pbm.Vertex(1,4,3) 64 | 65 | e1 = pbm.Edge([v1,v2]) 66 | self.assertEqual(len(e1),2) 67 | 68 | def test_repr(self): 69 | v1 = pbm.Vertex(1,2,3) 70 | v2 = pbm.Vertex(1,4,3) 71 | 72 | with pytest.raises(ValueError): 73 | e1 = pbm.Edge([v1,v2]) 74 | self.assertEqual(str(e1),"Elizabeth") 75 | 76 | v1["name"]=0 77 | v2["name"]=2 78 | 79 | e1 = pbm.Edge([v1,v2]) 80 | self.assertEqual(str(e1),"line 0 2") 81 | 82 | v3 = pbm.Vertex(1,3,4) 83 | e1 = pbm.Edge([v1,v2],keyword = 'arc',interpolationPoints = v3) 84 | self.assertEqual(str(e1),"arc 0 2 (1 3 4)") 85 | 86 | e1 = pbm.Edge([v1,v2],keyword = "spline",interpolationPoints = [v1,v2,v3]) 87 | self.assertEqual(str(e1),"spline 0 2 ( (1 2 3) (1 4 3) (1 3 4) )") 88 | 89 | def test_eq(self): 90 | v1 = pbm.Vertex(1,2,3) 91 | v2 = pbm.Vertex(1,4,3) 92 | 93 | e1 = pbm.Edge([v1,v2]) 94 | e2 = pbm.Edge([v1,v2]) 95 | self.assertEqual(e1,e2) 96 | 97 | e2 = pbm.Edge([v1,v2+[1,2,3]]) 98 | self.assertEqual(e1 == e2, False) 99 | 100 | e2 = "Elizabeth" 101 | self.assertEqual(e1 == e2, False) 102 | 103 | e2 = pbm.Edge([v1,v2],keyword='arc',interpolationPoints=v1+[1,0,0]) 104 | self.assertEqual(e1 == e2, False) 105 | 106 | e1 = pbm.Edge([v1,v2],keyword='arc',interpolationPoints=v1) 107 | self.assertEqual(e1 == e2, False) 108 | 109 | e2 = pbm.Edge([v1,v2],expansionRatio = 2) 110 | self.assertEqual(e1 == e2, False) 111 | 112 | 113 | -------------------------------------------------------------------------------- /tests/test_face_operations.py: -------------------------------------------------------------------------------- 1 | import pyblockmesh as pbm 2 | 3 | from tests import * 4 | from tests.helpers import * 5 | 6 | # Unit tests are great but what about property tests? 7 | 8 | class TestFace(unittest.TestCase): 9 | 10 | def test_initialization(self): 11 | v1 = pbm.Vertex(1,3,1) 12 | v2 = pbm.Vertex(1,5,6) 13 | v3 = pbm.Vertex(1,3,3) 14 | v4 = pbm.Vertex(1,5,7) 15 | 16 | # Must have vertices 17 | with pytest.raises(ValueError): 18 | f1 = pbm.Face([]) 19 | self.assertEqual(f1,"Elizabeth") 20 | 21 | # Must have 4 vertices 22 | with pytest.raises(AssertionError): 23 | f1 = pbm.Face([v1,v2,v3]) 24 | self.assertEqual(f1,"Elizabeth") 25 | 26 | # Face must have name 27 | with pytest.raises(ValueError): 28 | f1 = pbm.Face([v1,v2,v3,v4]) 29 | self.assertEqual(f1,"Elizabeth") 30 | 31 | #if patchtype is not defines, default to patch 32 | f1 = pbm.Face([v1,v2,v3,v4],name="inlet") 33 | self.assertEqual(f1["patchType"],'patch') 34 | 35 | def test_magic_methods(self): 36 | 37 | v1 = pbm.Vertex(1,3,1) 38 | v2 = pbm.Vertex(1,5,6) 39 | v3 = pbm.Vertex(1,3,3) 40 | v4 = pbm.Vertex(1,5,7) 41 | f1 = pbm.Face([v1,v2,v3,v4],name="inlet") 42 | 43 | # __setitem__ 44 | f1.__setitem__("nameFake","monkey") 45 | self.assertEqual(f1["nameFake"],"monkey") 46 | 47 | # __delitem__ 48 | f1.__delitem__("nameFake") 49 | with pytest.raises(KeyError): 50 | self.assertEqual(f1["nameFake"],"monkey") 51 | 52 | # __iter__ 53 | for v in f1: 54 | self.assertEqual(v in f1["vertices"].values(),True) 55 | 56 | # __len__ 57 | self.assertEqual(len(f1),4) 58 | 59 | # __eq__ 60 | 61 | # Two faces with the same vertices are equal 62 | f1 = pbm.Face([v1,v2,v3,v4],name="inlet") 63 | f2 = pbm.Face([v1,v3,v2,v4],name="outlet") 64 | 65 | self.assertEqual(f1,f2) 66 | 67 | # Faces with different vertices are not equal 68 | v5 = pbm.Vertex(4,5,2) 69 | f2 = pbm.Face([v1,v2,v3,v5],name="inlet") 70 | 71 | self.assertEqual(f1 == f2, False) 72 | 73 | # Faces with different patchTypes are different 74 | f2 = pbm.Face([v1,v2,v3,v4], 75 | name="outlet", 76 | patchType = 'wall') 77 | 78 | self.assertEqual(f1 == f2, False) 79 | 80 | # A face can only equal to another face 81 | self.assertEqual(f1 == "Elizabeth",False) 82 | 83 | # __repr__ 84 | 85 | v1["name"] = 0 86 | v2["name"] = 1 87 | v3["name"] = 2 88 | v4["name"] = 3 89 | string = "inlet\n{\n type patch;\n faces\n (\n ( 0 1 2 3 ) \n );\n}" 90 | self.assertEqual(str(f1),string) 91 | #Need to do this in a non shitty way 92 | -------------------------------------------------------------------------------- /tests/test_hexahedron_operations.py: -------------------------------------------------------------------------------- 1 | import pyblockmesh as pbm 2 | 3 | from tests import * 4 | from tests.helpers import * 5 | 6 | # Unit tests are great but what about property tests? 7 | 8 | class TestHexahedron(unittest.TestCase): 9 | 10 | def test_initialization(self): 11 | v1 = pbm.Vertex(1,3,1) 12 | v2 = pbm.Vertex(1,4,1) 13 | v3 = pbm.Vertex(1,2,3) 14 | v4 = pbm.Vertex(1,2,4) 15 | v5 = pbm.Vertex(2,3,1) 16 | v6 = pbm.Vertex(2,4,1) 17 | v7 = pbm.Vertex(2,2,3) 18 | v8 = pbm.Vertex(2,2,4) 19 | 20 | h1 = pbm.Hexahedron([v1,v2,v3,v4,v5,v6,v7,v8],numberOfCells=[1,2,3]) 21 | 22 | 23 | # __iter__ 24 | for vertex in h1: 25 | self.assertEqual(vertex in h1['vertices'],True) 26 | 27 | # __len__ 28 | self.assertEqual(len(h1),8) 29 | 30 | # __setitem__ 31 | h1.__setitem__("nameFake","Elizabeth") 32 | self.assertEqual(h1["nameFake"],"Elizabeth") 33 | 34 | # __delitem__ 35 | h1.__delitem__("nameFake") 36 | with pytest.raises(KeyError): 37 | self.assertEqual(h1["nameFake"],"Elizabeth") 38 | 39 | # __repr__ 40 | v1['name'] = 0 41 | v2['name'] = 1 42 | v3['name'] = 2 43 | v4['name'] = 3 44 | v5['name'] = 4 45 | v6['name'] = 5 46 | v7['name'] = 6 47 | v8['name'] = 7 48 | 49 | string = "hex (0 1 2 3 4 5 6 7) (1 2 3) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1)" 50 | self.assertEqual(str(h1),string) 51 | 52 | h1.add_edge([v1,v2],expansionRatio = 2) 53 | 54 | string = "hex (0 1 2 3 4 5 6 7) (1 2 3) edgeGrading (2 1 1 1 1 1 1 1 1 1 1 1)" 55 | self.assertEqual(str(h1),string) 56 | 57 | def test_add_edge(self): 58 | v1 = pbm.Vertex(1,3,1) 59 | v2 = pbm.Vertex(1,4,1) 60 | v3 = pbm.Vertex(1,2,3) 61 | v4 = pbm.Vertex(1,2,4) 62 | v5 = pbm.Vertex(2,3,1) 63 | v6 = pbm.Vertex(2,4,1) 64 | v7 = pbm.Vertex(2,2,3) 65 | v8 = pbm.Vertex(2,2,4) 66 | 67 | v1['name'] = 0 68 | v2['name'] = 1 69 | v3['name'] = 2 70 | v4['name'] = 3 71 | v5['name'] = 4 72 | v6['name'] = 5 73 | v7['name'] = 6 74 | v8['name'] = 7 75 | 76 | 77 | h1 = pbm.Hexahedron([v1,v2,v3,v4,v5,v6,v7,v8],numberOfCells=[1,2,3]) 78 | 79 | h1.add_edge([v1, v2], expansionRatio = 2) 80 | 81 | e1 = pbm.Edge([v1, v2], expansionRatio = 2) 82 | 83 | self.assertEqual(h1['edges'][0], e1) 84 | 85 | with pytest.raises(ValueError): 86 | h1.add_edge([v1,v7],expansionRatio = 1) 87 | 88 | with pytest.raises(ValueError): 89 | h1.add_edge([v1,v2+[1,2,3]], expansionRatio = 3) 90 | 91 | def test_add_face(self): 92 | v1 = pbm.Vertex(1,3,1) 93 | v2 = pbm.Vertex(1,4,1) 94 | v3 = pbm.Vertex(1,2,3) 95 | v4 = pbm.Vertex(1,2,4) 96 | v5 = pbm.Vertex(2,3,1) 97 | v6 = pbm.Vertex(2,4,1) 98 | v7 = pbm.Vertex(2,2,3) 99 | v8 = pbm.Vertex(2,2,4) 100 | 101 | v1['name'] = 0 102 | v2['name'] = 1 103 | v3['name'] = 2 104 | v4['name'] = 3 105 | v5['name'] = 4 106 | v6['name'] = 5 107 | v7['name'] = 6 108 | v8['name'] = 7 109 | 110 | 111 | h1 = pbm.Hexahedron([v1,v2,v3,v4,v5,v6,v7,v8],numberOfCells=[1,2,3]) 112 | 113 | h1.add_face([v1, v2, v3, v4], name="inlet") 114 | 115 | f1 = pbm.Face([v1, v2, v3, v4], name="outlet") 116 | 117 | self.assertEqual(h1['faces'][0], f1) 118 | 119 | with pytest.raises(ValueError): 120 | h1.add_face([v1,v7,v3,v2], name="monkey") 121 | 122 | with pytest.raises(ValueError): 123 | h1.add_face([v1,v2+[0,0,1],v3,v4], name="Elizabeth") 124 | 125 | with pytest.raises(ValueError): 126 | h1.add_face("Elizabeth") 127 | 128 | with pytest.raises(ValueError): 129 | h1.add_face([v1,v2,v3,v4], name="Elizabeth") 130 | h1.add_face([v1,v2,v3,v4], name="Elizabeth") 131 | -------------------------------------------------------------------------------- /tests/test_vertex_operations.py: -------------------------------------------------------------------------------- 1 | import pyblockmesh as pbm 2 | 3 | from tests import * 4 | from tests.helpers import * 5 | 6 | # Unit tests are great but what about property tests? 7 | 8 | class TestInitialization(unittest.TestCase): 9 | 10 | def test_initialization(self): 11 | with pytest.raises(ValueError): 12 | v1 = pbm.Vertex(None,3,1) 13 | 14 | 15 | def test_iter(self): 16 | v1 = pbm.Vertex(1,1,1) 17 | import numpy as np 18 | for i in v1: 19 | self.assertEqual(i,np.int64(1)) 20 | 21 | def test_len(self): 22 | v1 = pbm.Vertex(0,0,0) 23 | self.assertEqual(len(v1),3) 24 | 25 | def test_repr(self): 26 | v1 = pbm.Vertex(0,0,0) 27 | self.assertEqual(str(v1),"(0 0 0)") 28 | 29 | def test_del(self): 30 | v1 = pbm.Vertex(0,0,0) 31 | v1["name"] = "Henry" 32 | v1["name"] = "Elizabeth" 33 | v1.__delitem__("name") 34 | with pytest.raises(KeyError): 35 | self.assertEqual(v1["name"],"Elizabeth") 36 | 37 | class TestOperation(unittest.TestCase): 38 | 39 | def test_lt(self): 40 | v1 = pbm.Vertex(0,3,1) 41 | v2 = pbm.Vertex(1,2,2) 42 | self.assertEqual( v1 < v2, True) 43 | 44 | v2 = pbm.Vertex(0,4,1) 45 | self.assertEqual( v1 < v2, True) 46 | 47 | v2 = pbm.Vertex(0,3,2) 48 | self.assertEqual( v1 < v2, True) 49 | 50 | v2 = pbm.Vertex(0,3,0) 51 | self.assertEqual( v1 < v2, False) 52 | 53 | v2 = pbm.Vertex(0,2,0) 54 | self.assertEqual( v1 < v2, False) 55 | 56 | def test_equal(self): 57 | v1 = pbm.Vertex(0,0,0) 58 | v2 = pbm.Vertex(0,0,0) 59 | self.assertEqual( v1 == v2, True) 60 | 61 | v2 = pbm.Vertex(1,0,0) 62 | self.assertEqual( v1 == v2, False) 63 | 64 | v2 = "Hello World!" 65 | self.assertEqual( v1 == v2, False) 66 | 67 | def test_gt(self): 68 | v1 = pbm.Vertex(0,0,0) 69 | v2 = pbm.Vertex(1,0,0) 70 | self.assertEqual( v1 > v2, False) 71 | 72 | def test_add(self): 73 | 74 | # Addition of two vertices 75 | v1 = pbm.Vertex(0,0,0) 76 | v2 = pbm.Vertex(1,0,0) 77 | self.assertEqual( v1 + v2, pbm.Vertex(1,0,0) ) 78 | 79 | # Addition of list to vertex 80 | v2 = [1,0,0] 81 | self.assertEqual( v1 + v2, pbm.Vertex(1,0,0)) 82 | 83 | # Addition of np.array to vertex 84 | import numpy as np 85 | v2 = np.array([1,0,0]) 86 | self.assertEqual( v1 + v2, pbm.Vertex(1,0,0)) 87 | 88 | v2 = np.array([1,0,0])[:,np.newaxis] 89 | self.assertEqual(v1 + v2, pbm.Vertex(1,0,0)) 90 | 91 | with pytest.raises(AssertionError): 92 | v2 = np.array([1]) 93 | self.assertEqual(v1 + v2,0) 94 | 95 | # Test radd 96 | self.assertEqual(v1 + [1,2,3],[1,2,3] + v1) 97 | 98 | 99 | def test_sub(self): 100 | 101 | # Subtraction of two vertices 102 | v1 = pbm.Vertex(0,0,0) 103 | v2 = pbm.Vertex(1,0,0) 104 | self.assertEqual( v1 - v2, pbm.Vertex(-1,0,0) ) 105 | 106 | # Subtraction of list to vertex 107 | v2 = [1,0,0] 108 | self.assertEqual( v1 - v2, pbm.Vertex(-1,0,0)) 109 | 110 | # Subtraction of np.array to vertex 111 | import numpy as np 112 | v2 = np.array([1,0,0]) 113 | self.assertEqual( v1 - v2, pbm.Vertex(-1,0,0)) 114 | 115 | # Test radd 116 | self.assertEqual(v1 - np.array([1,2,3]),-(np.array([1,2,3]) - v1)) 117 | 118 | 119 | def test_mult(self): 120 | 121 | with pytest.raises(TypeError): 122 | # Multiplication of two vertices 123 | v1 = pbm.Vertex(0,0,0) 124 | v2 = pbm.Vertex(1,0,0) 125 | self.assertEqual( v1 * v2, pbm.Vertex(0,0,0) ) 126 | 127 | # Multiplication of number with vertex 128 | v1 = pbm.Vertex(1,0,0) 129 | v2 = 5 130 | self.assertEqual( v1 * v2, pbm.Vertex(5,0,0)) 131 | self.assertEqual( v2 * v1, pbm.Vertex(5,0,0)) 132 | with pytest.raises(AssertionError): 133 | # Multiplication of np.array to vertex 134 | import numpy as np 135 | v2 = np.array([1,0,0]) 136 | self.assertEqual( v1 * v2, pbm.Vertex(1,0,0)) 137 | 138 | with pytest.warns(UserWarning): 139 | import numpy as np 140 | v2 = np.array([[1,0,0],[0,1,0],[0,0,1]]) 141 | self.assertEqual(v1*v2, pbm.Vertex(1,0,0)) 142 | 143 | with pytest.raises(TypeError): 144 | v2 = "Hello there! General Kenobi" 145 | self.assertEqual(v1*v2,None) 146 | 147 | import numpy as np 148 | v2 = np.array([[1,0,0],[0,1,0],[0,0,1]]) 149 | self.assertEqual(v2 * v1, pbm.Vertex(1,0,0)) 150 | 151 | -------------------------------------------------------------------------------- /tests/tests_helper.py: -------------------------------------------------------------------------------- 1 | import tests.helpers 2 | 3 | 4 | def list_has(value, lst): 5 | found = False 6 | for val in lst: 7 | if val == value: 8 | found = True 9 | break 10 | return found 11 | --------------------------------------------------------------------------------