From 4b2957323c1d824d259c3adda091fa8168257319 Mon Sep 17 00:00:00 2001 From: Henrik Andersson Date: Wed, 4 Jun 2025 17:19:56 +0200 Subject: [PATCH 1/4] Write dfsu spectra WIP --- mikecore/DfsuBuilder.py | 44 ++++++++++++++++++++++++++++++++++++++--- mikecore/DfsuFile.py | 9 ++++++++- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/mikecore/DfsuBuilder.py b/mikecore/DfsuBuilder.py index ee00760..43ad2c9 100644 --- a/mikecore/DfsuBuilder.py +++ b/mikecore/DfsuBuilder.py @@ -66,6 +66,10 @@ def __init__(self, dfsuFileType): # Dynamic item information self.__dynamicItemData = [] + # spectral + self.__frequencies = None + self.__directions = None + self.__dfsuFileType = dfsuFileType if dfsuFileType == DfsuFileType.Dfsu2D: self.FileTitle = "Area Series" @@ -113,6 +117,13 @@ def SetNumberOfSigmaLayers(self, numberOfSigmaLayers: int): else: raise Exception("dfsuFileType") + def SetFrequencies(self, frequencies): + self.__frequencies = frequencies + + def SetDirections(self, directions): + self.__directions = directions + + #/ #/ Set a non-standard temporal axis for the dfsu file. WARNING: The dfsu file will not be valid in all contexts. #/ @@ -278,7 +289,7 @@ def Validate(self, dieOnError: bool = False): errors.append("Nodes have not been set") if (not self.__isSetConnectivity): errors.append("Elements have not been set") - if (not self.__isSetNumberOfSigmaLayers and self.__dfsuFileType != DfsuFileType.Dfsu2D): + if (not self.__isSetNumberOfSigmaLayers and self.__dfsuFileType in (DfsuFileType.Dfsu3DSigma, DfsuFileType.Dfsu3DSigmaZ, DfsuFileType.DfsuVerticalColumn, DfsuFileType.DfsuVerticalProfileSigma, DfsuFileType.DfsuVerticalProfileSigmaZ)): errors.append("Number of sigma layers has not been set") # Check that all nodenumbers are within the range of @@ -326,7 +337,11 @@ def Validate(self, dieOnError: bool = False): minNumberOfLayers = DfsuUtil.FindMinNumberOfLayers(topLayerElements) if (minNumberOfLayers < self.__numberOfSigmaLayers): errors.append("The minimum number of layers is smaller than the number of sigma layers. Element table is invalid") + elif self.__dfsuFileType in (DfsuFileType.DfsuSpectral0D, DfsuFileType.DfsuSpectral1D, DfsuFileType.DfsuSpectral2D): + # TODO do we need to check frequency or directions? + pass else: + raise Exception("Dfsu file type {} not supported".format(self.__dfsuFileType)) @@ -384,7 +399,15 @@ def SetupBuilder(self): factory = DfsFactory() dfsBuilder = DfsBuilder.Create(self.FileTitle, self.ApplicationTitle, self.ApplicationVersion) - dfsBuilder.SetDataType(2001) + if self.__dfsuFileType == DfsuFileType.DfsuSpectral1D: + dfsBuilder.SetDataType(2002) + elif self.__dfsuFileType == DfsuFileType.DfsuSpectral2D: + dfsBuilder.SetDataType(2003) + else: + dfsBuilder.SetDataType(2001) + + + dfsBuilder.SetGeographicalProjection(self.__dfsProjection) if (self.__timeAxis != None): dfsBuilder.SetTemporalAxis(self.__timeAxis) @@ -410,6 +433,10 @@ def SetupBuilder(self): elif self.__dfsuFileType == DfsuFileType.Dfsu3DSigmaZ: maxNumberOfLayers = DfsuUtil.FindMaxNumberOfLayers(DfsuUtil.FindTopLayerElements(self.__connectivity)) dfsBuilder.AddCreateCustomBlock("MIKE_FM",np.array([ self.__x.size, len(self.__connectivity), 3, maxNumberOfLayers, self.__numberOfSigmaLayers ], np.int32)) + elif self.__dfsuFileType in (DfsuFileType.DfsuSpectral0D, DfsuFileType.DfsuSpectral1D, DfsuFileType.DfsuSpectral2D): + # TODO should "nlayers" be 0, 1, 2 for point, line, area? + nlayers = 1 + dfsBuilder.AddCreateCustomBlock("MIKE_FM",np.array([ self.__x.size, len(self.__connectivity), nlayers, 0, len(self.__frequencies), len(self.__directions)], np.int32)) else: raise Exception() @@ -446,6 +473,7 @@ def SetupBuilder(self): # dfsItem.SetAxis(factory.CreateAxisDummy(len(self.__connectivity))) #else # Set axis to have meter unit (not necessary, just to make file exactly equal) + # TODO adjust size of spatial axis for spectral data {n_nodes, n_elements} * n_freq * n_dir dfsItem.SetAxis(factory.CreateAxisEqD1(eumUnit.eumUmeter, len(self.__connectivity), 0, 1)) # Set to default ufs delete values (not used anyway, just to make file exactly equal) dfsItem.SetReferenceCoordinates(-1e-35, -1e-35, -1e-35) @@ -479,6 +507,7 @@ def CreateDfsu(self, dfsBuilder, elementType, nodesPerElmt, connectivityArray): intCode = eumQuantity(eumItem.eumIIntegerCode, eumUnit.eumUintCode) xyQuantity = eumQuantity(eumItem.eumIGeographicalCoordinate, eumUnit.eumUmeter) + # TODO: reenable: #if (MapProjection.IsValid(self.__dfsProjection.WKTString)): # if (MapProjection.IsGeographical(self.__dfsProjection.WKTString)): @@ -511,6 +540,13 @@ def CreateDfsu(self, dfsBuilder, elementType, nodesPerElmt, connectivityArray): # Connectivity connectivityItem = dfsBuilder.AddCreateStaticItem("Connectivity", intCode, connectivityArray) + # Spectral + + frequencyItem = dfsBuilder.AddCreateStaticItem("Frequency", eumQuantity(eumItem.eumIFrequency, eumUnit.eumUhertz), self.__frequencies) if self.__frequencies is not None else None + + # TODO unit + directionItem = dfsBuilder.AddCreateStaticItem("Direction", eumQuantity(eumItem.eumIDirection, eumUnit.eumUradian), self.__directions) if self.__directions is not None else None + dfsFile = dfsBuilder.GetFile() dfsuFile = DfsuFile() @@ -530,7 +566,9 @@ def CreateDfsu(self, dfsBuilder, elementType, nodesPerElmt, connectivityArray): self.__elementIds, elementType, self.__connectivity, - self.__zUnit + self.__zUnit, + frequencyItem, + directionItem ) return (dfsuFile) diff --git a/mikecore/DfsuFile.py b/mikecore/DfsuFile.py index 078a8af..76fd3ab 100644 --- a/mikecore/DfsuFile.py +++ b/mikecore/DfsuFile.py @@ -67,6 +67,9 @@ def __init__(self, dfsFile = None): self.__elmtIdItem = None; + self.__freqItem = None + self.__dirItem = None + # Node variables self.NodeIds = None; self.X = None; @@ -326,7 +329,9 @@ def DfsuFileBuild( elementIds, elementType, connectivity, - zUnit + zUnit, + freqItem, + dirItem, ): self.dfsFile = dfsFile; @@ -345,6 +350,8 @@ def DfsuFileBuild( self.ElementType = elementType; self.ElementTable = connectivity; self.ZUnit = zUnit; + self.__freqItem = freqItem + self.__dirItem = dirItem self.__Init(dfsFile, build = True) From 974d6ed42bdda9659888c85fd42d53448bf36394 Mon Sep 17 00:00:00 2001 From: Henrik Andersson Date: Thu, 5 Jun 2025 10:07:53 +0200 Subject: [PATCH 2/4] Adjust data size for line spectra (not yet point or area) --- mikecore/DfsuBuilder.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mikecore/DfsuBuilder.py b/mikecore/DfsuBuilder.py index 43ad2c9..75bc0b8 100644 --- a/mikecore/DfsuBuilder.py +++ b/mikecore/DfsuBuilder.py @@ -474,7 +474,16 @@ def SetupBuilder(self): #else # Set axis to have meter unit (not necessary, just to make file exactly equal) # TODO adjust size of spatial axis for spectral data {n_nodes, n_elements} * n_freq * n_dir - dfsItem.SetAxis(factory.CreateAxisEqD1(eumUnit.eumUmeter, len(self.__connectivity), 0, 1)) + if self.__dfsuFileType == DfsuFileType.DfsuSpectral1D: + size = self.__x.size + if self.__frequencies is not None: + size *= len(self.__frequencies) + if self.__directions is not None: + size *= len(self.__directions) + + dfsItem.SetAxis(factory.CreateAxisEqD1(eumUnit.eumUmeter, size, 0, 1)) + else: + dfsItem.SetAxis(factory.CreateAxisEqD1(eumUnit.eumUmeter, len(self.__connectivity), 0, 1)) # Set to default ufs delete values (not used anyway, just to make file exactly equal) dfsItem.SetReferenceCoordinates(-1e-35, -1e-35, -1e-35) dfsItem.SetOrientation(-1e-35, -1e-35, -1e-35) From b3e2ec95709737e2e3d3870b9189fb82ac6704a4 Mon Sep 17 00:00:00 2001 From: Henrik Andersson Date: Fri, 6 Jun 2025 12:13:44 +0200 Subject: [PATCH 3/4] Area spectra --- mikecore/DfsuBuilder.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/mikecore/DfsuBuilder.py b/mikecore/DfsuBuilder.py index 75bc0b8..b3076ca 100644 --- a/mikecore/DfsuBuilder.py +++ b/mikecore/DfsuBuilder.py @@ -433,10 +433,10 @@ def SetupBuilder(self): elif self.__dfsuFileType == DfsuFileType.Dfsu3DSigmaZ: maxNumberOfLayers = DfsuUtil.FindMaxNumberOfLayers(DfsuUtil.FindTopLayerElements(self.__connectivity)) dfsBuilder.AddCreateCustomBlock("MIKE_FM",np.array([ self.__x.size, len(self.__connectivity), 3, maxNumberOfLayers, self.__numberOfSigmaLayers ], np.int32)) - elif self.__dfsuFileType in (DfsuFileType.DfsuSpectral0D, DfsuFileType.DfsuSpectral1D, DfsuFileType.DfsuSpectral2D): - # TODO should "nlayers" be 0, 1, 2 for point, line, area? - nlayers = 1 - dfsBuilder.AddCreateCustomBlock("MIKE_FM",np.array([ self.__x.size, len(self.__connectivity), nlayers, 0, len(self.__frequencies), len(self.__directions)], np.int32)) + elif self.__dfsuFileType == DfsuFileType.DfsuSpectral1D: + dfsBuilder.AddCreateCustomBlock("MIKE_FM",np.array([ self.__x.size, len(self.__connectivity), 1, 0, len(self.__frequencies), len(self.__directions)], np.int32)) + elif self.__dfsuFileType == DfsuFileType.DfsuSpectral2D: + dfsBuilder.AddCreateCustomBlock("MIKE_FM",np.array([ self.__x.size, len(self.__connectivity), 2, 0, len(self.__frequencies), len(self.__directions)], np.int32)) else: raise Exception() @@ -473,7 +473,6 @@ def SetupBuilder(self): # dfsItem.SetAxis(factory.CreateAxisDummy(len(self.__connectivity))) #else # Set axis to have meter unit (not necessary, just to make file exactly equal) - # TODO adjust size of spatial axis for spectral data {n_nodes, n_elements} * n_freq * n_dir if self.__dfsuFileType == DfsuFileType.DfsuSpectral1D: size = self.__x.size if self.__frequencies is not None: @@ -481,6 +480,13 @@ def SetupBuilder(self): if self.__directions is not None: size *= len(self.__directions) + if self.__dfsuFileType == DfsuFileType.DfsuSpectral2D: + size = len(self.__connectivity) + if self.__frequencies is not None: + size *= len(self.__frequencies) + if self.__directions is not None: + size *= len(self.__directions) + dfsItem.SetAxis(factory.CreateAxisEqD1(eumUnit.eumUmeter, size, 0, 1)) else: dfsItem.SetAxis(factory.CreateAxisEqD1(eumUnit.eumUmeter, len(self.__connectivity), 0, 1)) @@ -550,7 +556,6 @@ def CreateDfsu(self, dfsBuilder, elementType, nodesPerElmt, connectivityArray): connectivityItem = dfsBuilder.AddCreateStaticItem("Connectivity", intCode, connectivityArray) # Spectral - frequencyItem = dfsBuilder.AddCreateStaticItem("Frequency", eumQuantity(eumItem.eumIFrequency, eumUnit.eumUhertz), self.__frequencies) if self.__frequencies is not None else None # TODO unit From b512b2585741bc08b895e13683ac712ce3c38692 Mon Sep 17 00:00:00 2001 From: Henrik Andersson Date: Wed, 11 Jun 2025 13:27:22 +0200 Subject: [PATCH 4/4] Correct size of line spectra --- mikecore/DfsuBuilder.py | 16 +++++++--------- mikecore/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/mikecore/DfsuBuilder.py b/mikecore/DfsuBuilder.py index b3076ca..8e18989 100644 --- a/mikecore/DfsuBuilder.py +++ b/mikecore/DfsuBuilder.py @@ -473,20 +473,18 @@ def SetupBuilder(self): # dfsItem.SetAxis(factory.CreateAxisDummy(len(self.__connectivity))) #else # Set axis to have meter unit (not necessary, just to make file exactly equal) - if self.__dfsuFileType == DfsuFileType.DfsuSpectral1D: - size = self.__x.size - if self.__frequencies is not None: - size *= len(self.__frequencies) - if self.__directions is not None: - size *= len(self.__directions) + + if self.__dfsuFileType in (DfsuFileType.DfsuSpectral1D, DfsuFileType.DfsuSpectral2D): + if self.__dfsuFileType == DfsuFileType.DfsuSpectral1D: + size = self.__x.size + if self.__dfsuFileType == DfsuFileType.DfsuSpectral2D: + size = len(self.__connectivity) - if self.__dfsuFileType == DfsuFileType.DfsuSpectral2D: - size = len(self.__connectivity) if self.__frequencies is not None: size *= len(self.__frequencies) if self.__directions is not None: size *= len(self.__directions) - + dfsItem.SetAxis(factory.CreateAxisEqD1(eumUnit.eumUmeter, size, 0, 1)) else: dfsItem.SetAxis(factory.CreateAxisEqD1(eumUnit.eumUmeter, len(self.__connectivity), 0, 1)) diff --git a/mikecore/__init__.py b/mikecore/__init__.py index 144c163..916c9c8 100644 --- a/mikecore/__init__.py +++ b/mikecore/__init__.py @@ -2,7 +2,7 @@ import platform from pathlib import Path -__version__ = "0.2.2" +__version__ = "0.3.0a0" p = platform.architecture() if not "64" in p[0]: diff --git a/setup.py b/setup.py index a3d4434..fcafb70 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="mikecore", - version="0.2.2", + version="0.3.0a0", install_requires=["numpy"], author="DHI", author_email="mike@dhigroup.com",