Source code for wolfhece.wolf_array._mnap

"""
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.
[docs] contour: Zones
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 read_txt_header(self): """ Surcharge de la lecture du header Il n'y a pas en tant que tel de header d'un fichier MNAP. Les informations de translation sont dans le fichier ".trl". Les informations de tailles de maille 'fines', Nbx, Nby et coordonnées d'origine sont dans le fichier ".par" """ if os.path.exists(self.filename + '.trl'): with open(self.filename + '.trl') as f: lines = f.read().splitlines() self.translx = float(lines[1]) self.transly = float(lines[2]) if os.path.exists(self.filename + '.par'): with open(self.filename + '.par') as f: lines = f.read().splitlines() self.dx = float(lines[7]) self.dy = float(lines[8]) self.nbx = int(lines[9]) self.nby = int(lines[10]) self.origx = float(lines[11]) self.origy = float(lines[12]) # Imposition du type de stockage self.wolftype = WOLF_ARRAY_MNAP_INTEGER
[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()]