@@ -9,34 +9,43 @@ def CheckForNull(obj):
99
1010class DfsuFileType (IntEnum ):
1111
12+ # 1D series
13+ Dfsu1D = 1 ,
14+
1215 # 2D area series
13- Dfsu2D = 1 ,
16+ Dfsu2D = 2 ,
1417
1518 # 1D vertical column
16- DfsuVerticalColumn = 2 ,
19+ DfsuVerticalColumn = 3 ,
1720
1821 # 2D vertical slice through a Dfsu3DSigma
19- DfsuVerticalProfileSigma = 3 ,
22+ DfsuVerticalProfileSigma = 4 ,
2023
2124 # 2D vertical slice through a Dfsu3DSigmaZ
22- DfsuVerticalProfileSigmaZ = 4 ,
25+ DfsuVerticalProfileSigmaZ = 5 ,
2326
2427 # 3D file with sigma coordinates, i.e., a constant number of layers.
25- Dfsu3DSigma = 5 ,
28+ Dfsu3DSigma = 6 ,
2629
2730 # 3D file with sigma and Z coordinates, i.e. a varying number of layers.
28- Dfsu3DSigmaZ = 6 ,
31+ Dfsu3DSigmaZ = 7 ,
32+
33+ # 0D point series of spectral data (frequency, direction)
34+ DfsuSpectral0D = 8
35+
36+ # 1D line series of spectral data (node, frequency, direction)
37+ DfsuSpectral1D = 9
38+
39+ # 2D area series of spectral data (elmt, frequency, direction)
40+ DfsuSpectral2D = 10
41+
2942
3043class DfsuFile (object ):
3144 """
3245 Class for exposing data from a dfsu file.
33-
3446 Use the DfsFileFactory to open an existing dfsu file.
35-
3647 Use the DfsuBuilder to create a new dfsu file.
37-
3848 You can read, write and append item-timesteps to the file.
39-
4049 The geometry can be altered, by moving the nodes, but the element connectivity can not be changed.
4150 """
4251
@@ -46,6 +55,8 @@ def __init__(self, dfsFile = None):
4655 self .DfsuFileType = DfsuFileType .Dfsu2D ;
4756 self .NumberOfLayers = - 1 ;
4857 self .NumberOfSigmaLayers = - 1 ;
58+ self .NumberOfFrequencies = - 1 ;
59+ self .NumberOfDirections = - 1 ;
4960
5061 # Static item
5162 self .__nodeIdItem = None ;
@@ -70,6 +81,10 @@ def __init__(self, dfsFile = None):
7081 self .ElementType = None ;
7182 self .ElementTable = [];
7283
84+ # Spectral definition
85+ self .Frequencies = None ;
86+ self .Directions = None ;
87+
7388 if (not dfsFile is None ):
7489 self .__Init (dfsFile )
7590
@@ -103,19 +118,40 @@ def __Init(self, dfsFile, build = False):
103118 else :
104119 self .NumberOfSigmaLayers = self .NumberOfLayers ;
105120
121+ if (self .FileInfo .DataType in (2002 , 2003 ) or (self .FileInfo .DataType == 2001 and (customBlock .Count == 6 ))):
122+ self .NumberOfFrequencies = customBlock [4 ];
123+ self .NumberOfDirections = customBlock [5 ];
124+ else :
125+ self .NumberOfFrequencies = 0 ;
126+ self .NumberOfDirections = 0 ;
127+
106128 # Figuring out dfsu file type from custom block MIKE_FM
107129 if (dimensions == 1 ):
108- self .DfsuFileType = DfsuFileType .DfsuVerticalColumn ;
130+ if (self .NumberOfLayers > 0 ):
131+ self .DfsuFileType = DfsuFileType .DfsuVerticalColumn ;
132+ elif (self .FileInfo .DataType == 2001 and (self .NumberOfFrequencies == numberOfElmts or self .NumberOfDirections == numberOfElmts )):
133+ # Spectral Frequency-Direction (Rose-plot) geometry
134+ self .DfsuFileType = DfsuFileType .DfsuSpectral0D ;
135+ elif (self .FileInfo .DataType == 2002 and self .IsSpectral ):
136+ # Spectral Frequency or Direction geometry
137+ self .DfsuFileType = DfsuFileType .DfsuSpectral1D ;
138+ else :
139+ self .DfsuFileType = DfsuFileType .Dfsu1D ;
140+
109141 elif (dimensions == 2 ):
110- if (self .NumberOfLayers == 0 ):
142+ if (self .FileInfo .DataType == 2001 and (self .NumberOfFrequencies * self .NumberOfDirections == numberOfElmts )):
143+ # Spectral Frequency-Direction (Rose-plot) geometry
144+ self .DfsuFileType = DfsuFileType .DfsuSpectral0D ;
145+ elif self .FileInfo .DataType == 2003 :
146+ self .DfsuFileType = DfsuFileType .DfsuSpectral2D ;
147+ elif (self .NumberOfLayers == 0 ):
111148 self .DfsuFileType = DfsuFileType .Dfsu2D ;
112149 elif (self .NumberOfLayers == self .NumberOfSigmaLayers ):
113150 self .DfsuFileType = DfsuFileType .DfsuVerticalProfileSigma ;
114151 else :
115152 self .DfsuFileType = DfsuFileType .DfsuVerticalProfileSigmaZ ;
116-
117- elif (dimensions == 3 ):
118153
154+ elif (dimensions == 3 ):
119155 if (self .NumberOfLayers == self .NumberOfSigmaLayers ):
120156 self .DfsuFileType = DfsuFileType .Dfsu3DSigma ;
121157 else :
@@ -133,6 +169,9 @@ def __Init(self, dfsFile, build = False):
133169 # "Element type" , int
134170 # "No of nodes" , int
135171 # "Connectivity" , int
172+ # For spectral files also at least one of:
173+ # "Frequency" , double
174+ # "Direction" , double
136175
137176 self .__nodeIdItem = self .dfsFile .ReadStaticItemNext (); CheckForNull (self .__nodeIdItem );
138177 self .NodeIds = self .__nodeIdItem .Data
@@ -189,6 +228,14 @@ def __Init(self, dfsFile, build = False):
189228 for j in range (nodesInElement ):
190229 self .ElementTable [i ][j ] = connectivityArray [k ];
191230 k += 1
231+
232+ # Spectral Dfsu
233+ if (self .NumberOfFrequencies ):
234+ frequency = self .dfsFile .ReadStaticItemNext (); CheckForNull (frequency );
235+ self .Frequencies = frequency .Data
236+ if (self .NumberOfDirections ):
237+ direction = self .dfsFile .ReadStaticItemNext (); CheckForNull (direction );
238+ self .Directions = direction .Data
192239
193240 self .NumberOfNodes = self .NodeIds .size ;
194241 self .ItemInfo = self .dfsFile .ItemInfo
@@ -366,6 +413,9 @@ def __SetDeleteValueFloat(self, value):
366413 self .FileInfo .DeleteValueFloat = value
367414 DeleteValueFloat = property (__GetDeleteValueFloat , __SetDeleteValueFloat )
368415
416+ @property
417+ def IsSpectral (self ):
418+ return (self .NumberOfFrequencies > 0 ) or (self .NumberOfDirections > 0 )
369419
370420
371421 @staticmethod
@@ -438,20 +488,15 @@ def FindTopLayerElements(elementTable):
438488 """
439489 Find element indices (zero based) of the elements being the upper-most element
440490 in its column.
441-
442491 Each column is identified by matching node id numbers. For 3D elements the
443492 last half of the node numbers of the bottom element must match the first half
444493 of the node numbers in the top element. For 2D vertical elements the order of
445494 the node numbers in the bottom element (last half number of nodes) are reversed
446495 compared to those in the top element (first half number of nodes).
447-
448496 To find the number of elements in each column, assuming the result
449497 is stored in res:
450-
451498 For the first column it is res[0]+1.
452-
453499 For the i'th column, it is res[i]-res[i-1].
454-
455500 :returns: A list of element indices of top layer elements
456501 """
457502
@@ -504,17 +549,12 @@ def FindTopLayerElementsXY(elementTable, x, y):
504549 """
505550 Find element indices (zero based) of the elements being the upper-most element
506551 in its column.
507-
508552 This method uses the element center (x,y) coordinate, and identifies
509553 each column by having the same element center (x,y) coordinate.
510-
511554 To find the number of elements in each column, assuming the result
512555 is stored in res:
513-
514556 For the first column it is res[0]+1.
515-
516557 For the i'th column, it is res[i]-res[i-1].
517-
518558 :returns: A list of element indices of top layer elements
519559 """
520560
@@ -581,7 +621,6 @@ def FindMaxNumberOfLayers(topLayerElements):
581621 """
582622 Find the maximum number of layers, based on the indices of
583623 all top layer elements.
584-
585624 Assuming that the topLayerElements comes ordered.
586625 """
587626 # the first column has top-element-index + 1 layers
@@ -597,7 +636,6 @@ def FindMinNumberOfLayers(topLayerElements):
597636 """
598637 Find the minimum number of layers, based on the indices of
599638 all top layer elements.
600-
601639 Assuming that the <paramref name="topLayerElements"/> comes
602640 ordered.
603641 """
@@ -608,4 +646,3 @@ def FindMinNumberOfLayers(topLayerElements):
608646 if (layers < minLayers ):
609647 minLayers = layers ;
610648 return (minLayers );
611-
0 commit comments