# Copyright 2019 TerraPower, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test ASCII maps."""
import io
import unittest
from armi.utils import asciimaps
CARTESIAN_MAP = """2 2 2 2 2
2 2 2 2 2
2 1 1 1 2
2 1 3 1 2
2 3 1 1 2
2 2 2 2 2
"""
HEX_THIRD_MAP = """- - 3 3
- 3 3 3
3 2 2 3
3 2 2 2 3
2 1 1 2 3
1 1 1 2 3
1 1 1 1 2 3
1 1 1 1 2 3
1 1 1 1 2
1 1 1 1 1 3
1 1 1 1 2 3
1 1 1 1 2
1 1 1 1 1 3
1 1 1 1 2
1 1 1 1 3
1 1 1 1 2
1 1 1 1 3
1 1 1 1 2
"""
# This core map is from refTestBase, and exhibited some issues when trying to read with
# an older implementation of the 1/3 hex lattice reader.
HEX_THIRD_MAP_2 = """- - SH SH
- SH SH SH
SH OC OC SH
SH OC OC OC SH
OC EX EX OC SH
EX EX EX OC SH
EX MC MC EX OC SH
MC HX MC EX OC SH
MC MC PC EX OC
MC IC MC MC EX SH
IC IC MC MC OC SH
PC IC MC EX OC
FA FA IC TG EX SH
IC FA IC MC OC
IC US MC EX SH
EX IC IC MC OC
EX FA MC EX SH
EX IC IC PC OC
"""
HEX_THIRD_MAP_WITH_HOLES = """- - SH SH
- SH SH SH
SH OC OC SH
SH OC OC OC SH
OC EX EX OC SH
EX EX EX OC SH
EX MC MC EX OC SH
MC HX MC EX OC SH
MC - PC EX OC
MC IC MC MC EX SH
IC IC MC MC OC SH
PC IC MC EX OC
FA FA IC TG EX SH
IC FA IC - OC
- US MC EX SH
EX IC IC MC OC
EX FA MC EX SH
EX IC IC PC OC
"""
HEX_THIRD_MAP_WITH_EMPTY_ROW = """- - SH SH
- SH SH SH
SH OC OC SH
SH OC OC OC SH
OC EX EX OC SH
EX EX EX OC SH
EX MC MC EX OC SH
MC HX MC EX OC SH
MC - PC EX OC
MC IC MC MC EX SH
IC IC MC MC OC SH
- - - - -
FA FA IC TG EX SH
IC FA IC - OC
- US MC EX SH
EX IC IC MC OC
EX FA MC EX SH
EX IC IC PC OC
"""
# This is a "corners-up" hexagonal map.
HEX_FULL_MAP = """- - - - - - - - - 1 1 1 1 1 1 1 1 1 4
- - - - - - - - 1 1 1 1 1 1 1 1 1 1 1
- - - - - - - 1 8 1 1 1 1 1 1 1 1 1 1
- - - - - - 1 1 1 1 1 1 1 1 1 1 1 1 1
- - - - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1
- - - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
- - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
- - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
- 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
7 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 3 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 6 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
"""
# This is a "flats-up" hexagonal map.
HEX_FULL_MAP_FLAT = """- - - - ORS ORS ORS
- - - ORS ORS ORS ORS
- - - ORS IRS IRS IRS ORS
- - ORS IRS IRS IRS IRS ORS
- - ORS IRS RR89 RR89 RR89 IRS ORS
- ORS IRS RR89 RR89 RR89 RR89 IRS ORS
- ORS IRS RR89 RR89 RR7 RR89 RR89 IRS ORS
- IRS RR89 RR89 RR7 RR7 RR89 RR89 IRS
- ORS RR89 RR89 RR7 OC RR7 RR89 RR89 ORS
ORS IRS RR89 RR7 OC OC RR7 RR89 IRS ORS
- IRS RR89 RR7 OC OC FS RR7 RR89 IRS
ORS RR89 RR7 OC OC OC OC RR7 RR89 ORS
ORS IRS RR7 OC OC IC OC OC RR7 IRS ORS
IRS RR89 OC SC ICS IC SC OC RR89 IRS
ORS RR89 RR7 OC IC IC IC OC RR7 RR89 ORS
IRS RR89 OC IC IC IC IC OC RR89 IRS
ORS RR89 RR7 SC PC ICS PC SC RR7 RR89 ORS
IRS RR89 OC IC IC IC IC OC RR89 IRS
ORS RR89 RR7 OC IC IC IC OC RR7 RR89 ORS
IRS RR89 VOTA ICS IC IRT ICS OC RR89 IRS
ORS RR89 RR7 OC IC IC IC OC RR7 RR89 ORS
IRS RR89 OC IC IC IC IC OC RR89 IRS
ORS RR89 FS OC ICS PC ICS OC RR7 RR89 ORS
IRS RR89 OC OC IC IC OC OC RR89 IRS
ORS IRS RR7 OC OC IC OC OC RR7 IRS ORS
ORS RR89 RR7 OC SC SC OC FS RR89 ORS
- IRS RR89 RR7 OC OC OC RR7 RR89 IRS
ORS IRS RR89 RR7 OC OC RR7 RR89 IRS ORS
- ORS RR89 RR89 RR7 OC RR7 RR89 RR89 ORS
- IRS RR89 RR89 RR7 RR7 RR89 RR89 IRS
ORS IRS RR89 RR89 RR7 RR89 RR89 IRS ORS
ORS IRS RR89 RR89 RR89 RR89 IRS ORS
ORS IRS RR89 RR89 RR89 IRS ORS
ORS IRS IRS IRS IRS ORS
ORS IRS IRS IRS ORS
ORS ORS ORS ORS
ORS ORS ORS
"""
HEX_FULL_MAP_SMALL = """F
F F
F
F F
F
"""
[docs]class TestAsciiMaps(unittest.TestCase):
"""Test ascii maps."""
[docs] def test_cartesian(self):
"""Make sure we can read Cartesian maps."""
asciimap = asciimaps.AsciiMapCartesian()
with io.StringIO() as stream:
stream.write(CARTESIAN_MAP)
stream.seek(0)
asciimap.readAscii(stream.read())
self.assertEqual(asciimap[0, 0], "2")
self.assertEqual(asciimap[1, 1], "3")
self.assertEqual(asciimap[2, 2], "3")
self.assertEqual(asciimap[3, 3], "1")
with self.assertRaises(KeyError):
asciimap[5, 2]
outMap = asciimaps.AsciiMapCartesian()
outMap.asciiLabelByIndices = asciimap.asciiLabelByIndices
outMap.gridContentsToAscii()
with io.StringIO() as stream:
outMap.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, CARTESIAN_MAP)
[docs] def test_hexThird(self):
"""Read 1/3 core flats-up maps."""
asciimap = asciimaps.AsciiMapHexThirdFlatsUp()
with io.StringIO() as stream:
stream.write(HEX_THIRD_MAP)
stream.seek(0)
asciimap.readAscii(stream.read())
with io.StringIO() as stream:
asciimap.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, HEX_THIRD_MAP)
self.assertEqual(asciimap[7, 0], "2")
self.assertEqual(asciimap[8, 0], "3")
self.assertEqual(asciimap[8, -4], "2")
self.assertEqual(asciimap[0, 8], "3")
self.assertEqual(asciimap[0, 0], "1")
with self.assertRaises(KeyError):
asciimap[10, 0]
[docs] def test_hexWithHoles(self):
"""Read 1/3 core flats-up maps with holes."""
asciimap = asciimaps.AsciiMapHexThirdFlatsUp()
with io.StringIO() as stream:
stream.write(HEX_THIRD_MAP_WITH_HOLES)
stream.seek(0)
asciimap.readAscii(stream.read())
with io.StringIO() as stream:
asciimap.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, HEX_THIRD_MAP_WITH_HOLES)
self.assertEqual(asciimap[1, 1], asciimaps.PLACEHOLDER)
self.assertEqual(asciimap[5, 0], "TG")
with self.assertRaises(KeyError):
asciimap[10, 0]
# also test writing from pure data (vs. reading) gives the exact same map :o
with io.StringIO() as stream:
asciimap2 = asciimaps.AsciiMapHexThirdFlatsUp()
asciimap2.asciiLabelByIndices = asciimap.asciiLabelByIndices
asciimap2.gridContentsToAscii()
asciimap2.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, HEX_THIRD_MAP_WITH_HOLES)
[docs] def test_hexWithEmptyRow(self):
"""Read 1/3 core flats-up maps with one entirely empty row."""
asciimap = asciimaps.AsciiMapHexThirdFlatsUp()
with io.StringIO() as stream:
stream.write(HEX_THIRD_MAP_WITH_EMPTY_ROW)
stream.seek(0)
asciimap.readAscii(stream.read())
with io.StringIO() as stream:
asciimap.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, HEX_THIRD_MAP_WITH_EMPTY_ROW)
self.assertEqual(asciimap[1, 1], asciimaps.PLACEHOLDER)
self.assertEqual(asciimap[6, 0], asciimaps.PLACEHOLDER)
self.assertEqual(asciimap[5, 0], "TG")
with self.assertRaises(KeyError):
asciimap[10, 0]
[docs] def test_troublesomeHexThird(self):
asciimap = asciimaps.AsciiMapHexThirdFlatsUp()
with io.StringIO() as stream:
stream.write(HEX_THIRD_MAP_2)
stream.seek(0)
asciimap.readAscii(stream.read())
with io.StringIO() as stream:
asciimap.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, HEX_THIRD_MAP_2)
self.assertEqual(asciimap[5, 0], "TG")
[docs] def test_hexFullCornersUpSpotCheck(self):
"""Spot check some hex grid coordinates are what they should be."""
# The corners and a central line of non-zero values.
corners_map = """- - - - - - - - - 3 0 0 0 0 0 0 0 0 2
- - - - - - - - 0 0 0 0 0 0 0 0 0 0 0
- - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0
- - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0
- - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0
- - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
- - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
- - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
- 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0 0 6
"""
# hex map is 19 rows tall: from -9 to 9
asciimap = asciimaps.AsciiMapHexFullTipsUp()
asciimap.readAscii(corners_map)
# verify the corners
self.assertEqual(asciimap[9, -9], "1")
self.assertEqual(asciimap[9, 0], "2")
self.assertEqual(asciimap[0, 9], "3")
self.assertEqual(asciimap[-9, 9], "4")
self.assertEqual(asciimap[-9, 0], "5")
self.assertEqual(asciimap[0, -9], "6")
# verify a line of coordinates
self.assertEqual(asciimap[0, 0], "0")
self.assertEqual(asciimap[1, -1], "1")
self.assertEqual(asciimap[2, -2], "2")
self.assertEqual(asciimap[3, -3], "3")
self.assertEqual(asciimap[4, -4], "4")
self.assertEqual(asciimap[5, -5], "5")
self.assertEqual(asciimap[6, -6], "6")
self.assertEqual(asciimap[7, -7], "7")
[docs] def test_hexFullCornersUp(self):
"""Test sample full hex map (with hex corners up) against known answers."""
# hex map is 19 rows tall: from -9 to 9
asciimap = asciimaps.AsciiMapHexFullTipsUp()
asciimap.readAscii(HEX_FULL_MAP)
# spot check some values in the map
self.assertIn("7 1 1 1 1 1 1 1 1 0", str(asciimap))
self.assertEqual(asciimap[-9, 9], "7")
self.assertEqual(asciimap[-8, 0], "6")
self.assertEqual(asciimap[-1, 0], "2")
self.assertEqual(asciimap[-1, 8], "8")
self.assertEqual(asciimap[0, -6], "3")
self.assertEqual(asciimap[0, 0], "0")
self.assertEqual(asciimap[9, 0], "4")
# also test writing from pure data (vs. reading) gives the exact same map
asciimap2 = asciimaps.AsciiMapHexFullTipsUp()
for ij, spec in asciimap.items():
asciimap2.asciiLabelByIndices[ij] = spec
with io.StringIO() as stream:
asciimap2.gridContentsToAscii()
asciimap2.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, HEX_FULL_MAP)
self.assertIn("7 1 1 1 1 1 1 1 1 0", str(asciimap))
self.assertIn("7 1 1 1 1 1 1 1 1 0", str(asciimap2))
[docs] def test_hexFullFlatsUp(self):
"""Test sample full hex map (with hex flats up) against known answers."""
# hex map is 21 rows tall: from -10 to 10
asciimap = asciimaps.AsciiMapHexFullFlatsUp()
asciimap.readAscii(HEX_FULL_MAP_FLAT)
# spot check some values in the map
self.assertIn("VOTA ICS IC IRT ICS OC", str(asciimap))
self.assertEqual(asciimap[-3, 10], "ORS")
self.assertEqual(asciimap[0, -9], "ORS")
self.assertEqual(asciimap[0, 0], "IC")
self.assertEqual(asciimap[0, 9], "ORS")
self.assertEqual(asciimap[4, -6], "RR7")
self.assertEqual(asciimap[6, 0], "RR7")
self.assertEqual(asciimap[7, -1], "RR89")
# also test writing from pure data (vs. reading) gives the exact same map
asciimap2 = asciimaps.AsciiMapHexFullFlatsUp()
for ij, spec in asciimap.items():
asciimap2.asciiLabelByIndices[ij] = spec
with io.StringIO() as stream:
asciimap2.gridContentsToAscii()
asciimap2.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, HEX_FULL_MAP_FLAT)
self.assertIn("VOTA ICS IC IRT ICS OC", str(asciimap))
self.assertIn("VOTA ICS IC IRT ICS OC", str(asciimap2))
[docs] def test_hexFullFlat(self):
"""Test sample full hex map against known answers."""
# hex map is 19 rows tall, so it should go from -9 to 9
asciimap = asciimaps.AsciiMapHexFullFlatsUp()
with io.StringIO() as stream:
stream.write(HEX_FULL_MAP_FLAT)
stream.seek(0)
asciimap.readAscii(stream.read())
with io.StringIO() as stream:
asciimap.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, HEX_FULL_MAP_FLAT)
self.assertEqual(asciimap[0, 0], "IC")
self.assertEqual(asciimap[-5, 2], "VOTA")
self.assertEqual(asciimap[2, 3], "FS")
# also test writing from pure data (vs. reading) gives the exact same map
with io.StringIO() as stream:
asciimap2 = asciimaps.AsciiMapHexFullFlatsUp()
asciimap2.asciiLabelByIndices = asciimap.asciiLabelByIndices
asciimap2.gridContentsToAscii()
asciimap2.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, HEX_FULL_MAP_FLAT)
[docs] def test_hexSmallFlat(self):
asciimap = asciimaps.AsciiMapHexFullFlatsUp()
with io.StringIO() as stream:
stream.write(HEX_FULL_MAP_SMALL)
stream.seek(0)
asciimap.readAscii(stream.read())
with io.StringIO() as stream:
asciimap.writeAscii(stream)
stream.seek(0)
output = stream.read()
self.assertEqual(output, HEX_FULL_MAP_SMALL)
[docs] def test_flatHexBases(self):
"""For the full core with 2 lines chopped, get the first 3 bases."""
asciimap = asciimaps.AsciiMapHexFullFlatsUp()
with io.StringIO() as stream:
stream.write(HEX_FULL_MAP_FLAT)
stream.seek(0)
asciimap.readAscii(stream.read())
bases = []
for li in range(3):
bases.append(asciimap._getIJBaseByAsciiLine(li))
# self.assertEqual(bases, [(0, -10), (-1, -9), (-2, -8)]) # unchopped
self.assertEqual(bases, [(-2, -8), (-3, -7), (-4, -6)]) # chopped