"""
WolfArrayMNAP - MNAP mesh array class for WOLF2D simulations.
Extracted from wolf_array.py for modularity.
Author: HECE - University of Liege, Pierre Archambeau
Date: 2024
Copyright (c) 2024 University of Liege. All rights reserved.
This script and its content are protected by copyright law. Unauthorized
copying or distribution of this file, via any medium, is strictly prohibited.
"""
import os
import re
import logging
import numpy as np
from pathlib import Path
try:
from ..PyTranslate import _
except ImportError as e:
print(e)
raise Exception(_('Error importing modules'))
from ..PyVertexvectors import Zones, vector, zone, wolfvertex
from ._header_wolf import (
header_wolf,
getkeyblock,
WOLF_ARRAY_FULL_INTEGER8,
WOLF_ARRAY_MNAP_INTEGER,
)
from ._base_gui import WolfArray
from ._mb import WolfArrayMB
[docs]
def split_floatstring_from_FORTRAN(value:str) -> list[str]:
"""
Useful for reading MNAP files written by the FORTRAN executable from old simulations.
If the string contains two floats, returns a list where the input is
split into two strings.
Otherwise, returns a list with the original string as the only element.
!!! A list is returned to handle potential cases in the future where the second
float might be needed.
:param value: Input string potentially containing two floats concatenated.
:return: List of strings after splitting.
"""
test_split = value.split('.')
if len(test_split) == 3:
return [
test_split[0] + '.' + test_split[1][:5],
test_split[1][5:] + '.' + test_split[2]
]
else:
return [value]
[docs]
class WolfArrayMNAP(WolfArrayMB):
"""
Matrice MNAP d'une modélisation WOLF2D
Elle contient toutes les informations de maillage en Multi-blocks
ainsi que les relations de voisinage de blocs.
Surcharge de WolfArrayMB avec modification des opérations de lecture/écriture
car le fichier est au format TEXTE/ASCII et d'une structure spécifique.
"""
# Each zone will have the contour of one block.
def __init__(self, fname=None, mold=None, masknull=True, crop=None):
super().__init__(fname, mold, masknull, crop)
[docs]
def write_all(self):
def padf(n):
s = f"{n:.5f}"
return f"{s:>12}"
def padi(n):
return f"{n:>15}"
with open(self.filename,"w") as f:
f.write(padi(self.nb_blocks) + "\n")
for i in range(self.nb_blocks):
curkey = getkeyblock(i)
curarray: WolfArray = self.myblocks[curkey]
f.write(padf(curarray.dx)+ padf(curarray.dy) + "\n")
f.write(padf(curarray.origx + curarray.translx) + padf(curarray.origx + curarray.translx + curarray.dx*curarray.nbx) + "\n")
f.write(padf(curarray.origy + curarray.transly) + padf(curarray.origy + curarray.transly + curarray.dy*curarray.nby) + "\n")
f.write(padi(curarray.nbx) + padi(curarray.nby) + "\n")
# FIXME curarray.array = np.flipud(np.ma.asarray(myarray, order='F')).transpose()
mask = np.transpose(np.flipud(curarray.array.mask))
for y in range(curarray.nby):
f.write("".join([f"{int(not curarray.array.mask[x,y]):>4}" for x in range(curarray.nbx)]) + "\n")
vertices = self.contour.myzones[0].myvectors[0].myvertices
f.write(padi(len(vertices)) + "\n")
for v in vertices:
v : wolfvertex
f.write(padf(v.x) + padf(v.y) + "\n")
[docs]
def read_data(self):
# Vérification de l'existence de certains attributs
if self.myblocks is None:
self.myblocks = {}
# une matrice WolfArrayMB n'a pas de contour -> ajout d'un attribut spécifique
self.contour = Zones()
if Path(self.filename + '.mnap').exists():
with open(self.filename + '.mnap') as f:
# Lecture au format texte
lines = f.read().splitlines()
# nombre de blocks dans la première ligne
nb_blocks = abs(int(lines[0]))
decal = 1
for i in range(nb_blocks):
# bouclage sur chque block
curkey = getkeyblock(i)
curarray = WolfArray(whichtype=WOLF_ARRAY_FULL_INTEGER8)
self.myblocks[curkey] = curarray
assert curarray.wolftype == WOLF_ARRAY_FULL_INTEGER8, "Type de block incorrect"
curarray.isblock = True
curarray.blockindex = i
# Recherche des informations de maillage - dx, dy, origx, origy, nbx, nby
tmp = re.sub('\\s+', ' ', lines[decal].strip()).split(' ')
curarray.dx = float(tmp[0])
curarray.dy = float(tmp[1])
tmp = re.sub('\s+', ' ', lines[decal + 1].strip()).split(' ')
curarray.origx = float(split_floatstring_from_FORTRAN(tmp[0])[0]) - self.origx
tmp = re.sub('\s+', ' ', lines[decal + 2].strip()).split(' ')
curarray.origy = float(split_floatstring_from_FORTRAN(tmp[0])[0]) - self.origy
tmp = re.sub('\\s+', ' ', lines[decal + 3].strip()).split(' ')
curarray.nbx = int(tmp[0])
curarray.nby = int(tmp[1])
decal += 4
#Lecture de la matrice de maillage pour le block en cours
myarray = []
for j in range(curarray.nby):
newline = [np.int32(curval) for curval in re.sub('\\s+', ' ', lines[decal].strip()).split()]
while len(newline) != curarray.nbx:
decal += 1
newline = np.concatenate([newline, [np.int32(curval) for curval in
re.sub('\\s+', ' ', lines[decal].strip()).split()]])
myarray.append(newline)
decal += 1
curarray.array = np.flipud(np.ma.asarray(myarray, order='F', dtype=np.int8)).transpose()
# curarray.array[curarray.array < 0] = 0
assert curarray.dtype == np.int8, "Type de block incorrect"
assert curarray.array.dtype == np.int8
assert curarray.wolftype == WOLF_ARRAY_FULL_INTEGER8, "Type de block incorrect"
#Lecture du contour de block
curzone = zone(name=curkey)
contourblock = vector(name='contour')
curzone.add_vector(contourblock)
self.contour.add_zone(curzone)
nbvert = int(lines[decal])
for j in range(nbvert):
decal += 1
xy = re.sub('\\s+', ' ', lines[decal].strip()).split(' ')
myvert = wolfvertex(float(xy[0]), float(xy[1]))
contourblock.add_vertex(myvert)
decal += 1
curarray.translx = self.translx + self.origx
curarray.transly = self.transly + self.origy
# Remplissagze du header
# --> la matrice MNAP est la référence d'une simulation 2D
# pour obtenir les informations de maillage
curhead = self.head_blocks[getkeyblock(i)] = header_wolf()
curhead.nbx = curarray.nbx
curhead.nby = curarray.nby
curhead.dx = curarray.dx
curhead.dy = curarray.dy
curhead.origx = curarray.origx
curhead.origy = curarray.origy
curhead.translx = curarray.translx
curhead.transly = curarray.transly
[docs]
def get_one_mask(self, which:int | str):
"""
Return the mask of the block `which`
"""
if isinstance(which, int):
key = getkeyblock(which)
else:
key = which
return self.myblocks[key].array.data != 1
[docs]
def get_all_masks(self):
"""
Return all masks
"""
return [curblock.array.data != 1 for curblock in self.myblocks.values()]