Source code for BasicTools.IO.FemmReader

# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#

"""Fem file reader
"""

import numpy as np
import re


from BasicTools.NumpyDefs import PBasicFloatType, PBasicIndexType

import BasicTools.Containers.UnstructuredMesh as UM
import BasicTools.Containers.ElementNames as ElementNames

from BasicTools.IO.ReaderBase import ReaderBase


[docs]def ReadFemm(fileName=None,string=None): """Function for reading a Femm (ans) result file Parameters ---------- fileName : str, optional name of the file to be read, by default None string : str, optional data to be read as a string instead of a file, by default None Returns ------- UnstructuredMesh output unstructured mesh object containing reading result """ obj = FemmReader() if fileName is not None: obj.SetFileName(fileName) if string is not None: obj.SetStringToRead(string) return obj.Read()
keysToIgnore = [ "[Format]", "[Comment]", "[Frequency]", "[Precision]", "[MinAngle]", "[DoSmartMesh]", "[Depth]", "[ProblemType]", "[Coordinates]", "[ACSolver]", "[PrevType]", "[PrevSoln]", "[Comment]", "[PointProps]", "[NumPoints]", "[NumSegments]", "[NumArcSegments]", "[NumHoles]", "[NumBlockLabels", ]
[docs]class FemmReader(ReaderBase): """Geof Reader class """ def __init__(self): super().__init__() self.readFormat = 'r' self.rescaleToMeters = True
[docs] def Read(self, fileName=None,string=None, blockAsFields = False): import BasicTools.Containers.UnstructuredMesh as UM if fileName is not None: self.SetFileName(fileName) if string is not None: self.SetStringToRead(string) self.StartReading() nbIP = 0 res = UM.UnstructuredMesh() def ReadBlock(): data = {} l = self.ReadCleanLine().strip() if not l.startswith("<Begin"): raise Exception(f"Line ({l}) is not the start of a block") while(True): l = self.ReadCleanLine().strip() if l.startswith("<End"): break key, value = re.findall(r'(?:[^\s="]|"(?:\\.|[^"])*")+', l) #key, value = l.split("=") key = key.strip(" <>") value = value.strip(' "') data[key] = value return data factorsFromUnit = {"millimeters":0.001, "centimeters":0.01, "meters":1, "inches": 2.54*0.01} factor = 1. while(True): l = self.ReadCleanLine() if l == None : break if l[0] != "[": continue if any([ l.startswith(x) for x in keysToIgnore ]): continue if l.startswith("[LengthUnits]"): factor = factorsFromUnit[(l.split("=")[1].strip())] continue if l.startswith("[BlockProps]"): self.BlockProps = [] nbBlocs = int(l.split("=")[1].strip()) for bn in range(nbBlocs): self.BlockProps.append( ReadBlock() ) continue if l.startswith("[BdryProps]"): self.BdryProps = [] nbBlocs = int(l.split("=")[1].strip()) for bn in range(nbBlocs): self.BdryProps.append( ReadBlock() ) continue if l.startswith("[CircuitProps]"): self.CircuitProps = [] nbBlocs = int(l.split("=")[1].strip()) for bn in range(nbBlocs): self.CircuitProps.append( ReadBlock() ) continue if l.startswith("[Solution]"): s = self.ReadCleanLine().split() nbNodes = int(s[0]) self.PrintDebug("Reading "+str(nbNodes)+ " Nodes ") res.nodes = np.empty((nbNodes,3), dtype=PBasicFloatType) res.originalIDNodes= np.empty((nbNodes,),dtype=PBasicIndexType) for x in range(nbNodes): s = self.ReadCleanLine().split() res.originalIDNodes[x] = x res.nodes[x,:] = list(map(float,s[0:3])) res.nodeFields["A"] = np.copy(res.nodes[:,2]) res.nodes[:,2] = 0 s = self.ReadCleanLine().split() nbElements = int(s[0]) tris = res.GetElementsOfType(ElementNames.Triangle_3) bars = res.GetElementsOfType(ElementNames.Bar_2) tris.Allocate(nbElements) conn = tris.connectivity tris.originalIds = np.arange(nbElements) tri_faces = ElementNames.faces[ElementNames.Triangle_3] tags = np.empty(nbElements,dtype=PBasicIndexType) for x in range(nbElements): l = self.ReadCleanLine() s = l.split() conn[x,:] = list(map(int,s[0:3])) tags[x] = int(s[3]) for b, val in enumerate(map(int,s[4:7])): if val == -1: continue n = bars.AddNewElement(conn[x,:][tri_faces[b][1]],0) -1 bars.tags.CreateTag("Bdry"+str(val),False).AddToTag(n) uniqueTags = np.unique(tags) if blockAsFields : block = np.zeros(tris.cpt+bars.cpt, dtype=PBasicIndexType) triOffset = res.ComputeGlobalOffset()[ElementNames.Triangle_3] block[triOffset:triOffset+tris.cpt] = tags res.elemFields["Blocks"] = block else: for tn in uniqueTags: tris.tags.CreateTag("Block"+str(tn)).SetIds(np.where(tags==tn)[0]) continue raise Exception(f" don't know how to treat this line: {l}" ) self.EndReading() if factor != 1. and self.rescaleToMeters: print("Changing units of the file to meters") res.nodes *= factor res.PrepareForOutput() return res
from BasicTools.IO.IOFactory import RegisterReaderClass RegisterReaderClass(".ans",FemmReader,)
[docs]def CheckIntegrity(): data = """[Format] = 4.0 [Frequency] = 0 [Precision] = 1e-008 [MinAngle] = 20 [DoSmartMesh] = 0 [Depth] = 100 [LengthUnits] = millimeters [ProblemType] = planar [Coordinates] = cartesian [ACSolver] = 0 [PrevType] = 0 [PrevSoln] = "" [Comment] = "" [PointProps] = 0 [BdryProps] = 1 <BeginBdry> <BdryName> = "A=0" <BdryType> = 0 <A_0> = 0 <A_1> = 0 <A_2> = 0 <Phi> = 0 <c0> = 0 <c0i> = 0 <c1> = 0 <c1i> = 0 <Mu_ssd> = 0 <Sigma_ssd> = 0 <innerangle> = 0 <outerangle> = 0 <EndBdry> [BlockProps] = 1 <BeginBlock> <BlockName> = "Silicon Core Iron" <Mu_x> = 7000 <Mu_y> = 7000 <H_c> = 0 <H_cAngle> = 0 <J_re> = 0 <J_im> = 0 <Sigma> = 0 <d_lam> = 0 <Phi_h> = 0 <Phi_hx> = 0 <Phi_hy> = 0 <LamType> = 0 <LamFill> = 1 <NStrands> = 0 <WireD> = 0 <BHPoints> = 0 <EndBlock> [CircuitProps] = 1 <BeginCircuit> <CircuitName> = "A" <TotalAmps_re> = 1 <TotalAmps_im> = 0 <CircuitType> = 1 <EndCircuit> [NumPoints] = 3 64.999999999999986 0 0 2 12.5 0 0 1 42.250000000000007 1.9000000000000004 0 0 [Solution] 4 0 151.6746 0 -1 2.6470867654124621 151.65149922376801 0 -1 -2.6470867654124017 151.65149922376759 0 -1 1.2931770755502037 148.18341546539696 0 -1 2 3 1 0 0 -1 5 -1 0 0 2 3 0 5 -1 -1 0 """ res = ReadFemm(string=data) print(res) from BasicTools.Helpers.Tests import WriteTempFile newFileName = WriteTempFile(filename="AnsFileTest.ans",content=data) import BasicTools.Containers.UnstructuredMesh as UM mesh = ReadFemm(fileName=newFileName) assert( mesh.GetNumberOfElements() == 4) assert( mesh.GetNumberOfNodes() == 4) return 'ok'
if __name__ == '__main__': print(CheckIntegrity())# pragma: no cover