Exemplo n.º 1
0
    def Create(dfsuFile: DfsuFile) -> MeshFile:
        """Create a mesh file from the provided dfsu file.
        The dfsu file must be a 2D dfsu file.
        """
        if dfsuFile.ZUnit != eumUnit.eumUUnitUndefined:
            bathyQuantity = eumQuantity(eumItem.eumIBathymetry, dfsuFile.ZUnit)
        else:
            bathyQuantity = eumQuantity(eumItem.eumIBathymetry,
                                        eumUnit.eumUmeter)

        res = MeshFile.Create(bathyQuantity, dfsuFile.Projection.WKTString,
                              dfsuFile.NodeIds, dfsuFile.X, dfsuFile.Y,
                              dfsuFile.Z.astype(dtype=np.float32),
                              dfsuFile.Code, dfsuFile.ElementIds,
                              dfsuFile.ElementType, dfsuFile.ElementTable)
        return res
Exemplo n.º 2
0
    def CreateMesh(self) -> MeshFile:
        """Create and return a new MeshFile object"""
        self.Validate(dieOnError=True)

        # Creating default eumQuantity in meters
        if self.__eumQuantity is None:
            self.__eumQuantity = eumQuantity(eumItem.eumIBathymetry,
                                             eumUnit.eumUmeter)

        # Creating default node id's, if empty
        if self.__nodeIds is None:
            self.__nodeIds = np.arange(len(self.__x)) + 1

        # Creating default element id's, if empty
        if self.__elementIds is None:
            self.__elementIds = np.arange(len(self.__connectivity)) + 1

        # Creating additional element information
        elementType = np.zeros(len(self.__connectivity), dtype=np.int32)
        nodesPerElmt = np.zeros(len(self.__connectivity), dtype=np.int32)
        nodeElmtCount = 0  # total number of nodes listed in the connectivity table
        for i in range(len(elementType)):
            elmtTypeNumber = 0
            elmt = self.__connectivity[i]
            if len(elmt) == 3:
                elmtTypeNumber = 21
            elif len(elmt) == 4:
                elmtTypeNumber = 25
            elif len(elmt) == 6:
                elmtTypeNumber = 32
            elif len(elmt) == 8:
                elmtTypeNumber = 33
            else:
                raise Exception(
                    "Element with invalid number of nodes encountered")

            elementType[i] = elmtTypeNumber
            nodesPerElmt[i] = len(elmt)
            nodeElmtCount += len(elmt)

        # NotUsed
        # connectivityArray = np.zeros(nodeElmtCount, dtype=np.int32)
        # k = 0
        # for i in range(len(elementType)):
        #     elmt = self.__connectivity[i]
        #     for j in range(len(elmt)):
        #         connectivityArray[k] = elmt[j]
        #         k += 1

        res = MeshFile.Create(self.__eumQuantity, self.__projectionString,
                              self.__nodeIds, self.__x, self.__y, self.__z,
                              self.__code, self.__elementIds, elementType,
                              self.__connectivity)

        return res
Exemplo n.º 3
0
    def Read(self, filename: str):
        """Read .mesh file and load all data.

        If an element specifies a node number of zero, that node number is ignored, and
        does not become a part of the mesh data structure. That is the case for e.g.
        mixed triangular/quadrilateral meshes, where all elements specify 4 nodes, 
        and triangular elements specifies the last node as zero.
        """
        with open(filename, 'r') as reader:
            # read header line
            line = reader.readline().lstrip()
            if line is None:
                raise IOError("Can not load mesh file. File is empty")

            noNodes = 0
            proj = None

            header2012 = lambda s: re.match(r"(\d+)\s+(\d+)\s+(\d+)\s+(.+)", s)
            header2011 = lambda s: re.match(r"(\d+)\s+(.+)", s)

            # First try match the 2012 header line format
            match = header2012(line)
            if match:
                groups = match.groups()
                itemType = eumItem(int(groups[0]))
                itemUnit = eumUnit(int(groups[1]))
                self.EumQuantity = eumQuantity(itemType, itemUnit)
                noNodes = int(groups[2])
                proj = groups[3]

            # If not successfull, try match the 2011 header line format
            if proj is None:
                match = header2011(line)
                if match:
                    self.EumQuantity = eumQuantity(eumItem.eumIBathymetry,
                                                   eumUnit.eumUmeter)
                    groups = match.groups()
                    noNodes = int(groups[0])
                    proj = groups[1]

            if proj is None:
                raise IOError(
                    "Can not load mesh file (failed reading mesh file header line): {0}"
                    .format(filename))

            self.ProjectionString = proj.strip()
            self.NodeIds = np.zeros(noNodes, dtype=np.int32)
            self.X = np.zeros(noNodes, dtype=np.float64)
            self.Y = np.zeros(noNodes, dtype=np.float64)
            self.Z = np.zeros(noNodes,
                              dtype=np.float64)  # TODO or np.float32 ?
            self.Code = np.zeros(noNodes, dtype=np.int32)

            # Read nodes
            try:
                for i in range(noNodes):
                    line = reader.readline().strip()
                    if line is None:
                        raise IOError("Unexpected end of file"
                                      )  # used as inner exception
                    strings = re.split(r"\s+", line)
                    self.NodeIds[i] = int(strings[0])
                    self.X[i] = float(strings[1])
                    self.Y[i] = float(strings[2])
                    self.Z[i] = float(strings[3])
                    self.Code[i] = int(strings[4])
            except Exception as inner:
                # DfsException
                raise Exception(
                    "Can not load mesh file (failed reading nodes): {0}. {1}".
                    format(filename, inner))

            # Reading element header line
            line = reader.readline().strip()
            if line is None:
                raise IOError(
                    "Can not load mesh file (unexpected end of file)")

            strings = re.split(r"\s+", line)
            if (len(strings) != 3):
                raise IOError(
                    "Can not load mesh file (failed reading element header line): {0}"
                    .format(filename))
            try:
                noElements = int(strings[0])
                elmtCode = int(strings[2])
            except Exception as ex:
                raise Exception(
                    "Can not load mesh file (failed reading element header line): {0}. {1}"
                    .format(filename, ex))

            # Element code must be 21 or 25 (21 for triangular meshes, 25 for mixed meshes)
            if (elmtCode != 21) or (elmtCode != 25):
                pass  # TODO?? Do we care?

            # Allocate memory for elements
            self.ElementIds = np.zeros(noElements, dtype=np.int32)
            self.ElementType = np.zeros(noElements, dtype=np.int32)
            self.ElementTable = []

            # Read all elements
            try:
                for i in range(noElements):

                    line = reader.readline().strip()
                    if line is None:
                        raise IOError("Unexpected end of file"
                                      )  # used as inner exception
                    strings = re.split(r"\s+", line)

                    self.ElementIds[i] = int(strings[0])
                    noNodesInElmt = len(strings) - 1
                    nodesInElement = np.zeros(noNodesInElmt, dtype=np.int32)
                    for j in range(noNodesInElmt):
                        nodeNumber = int(strings[j + 1])
                        if (nodeNumber < 0) or (nodeNumber > noNodes
                                                ):  # used as inner exception:
                            raise IOError(
                                "Node number in element table is negative or larger than number of nodes"
                            )
                        # It is only a node in the element if the node number is positive
                        if nodeNumber > 0:
                            nodesInElement[j] = nodeNumber

                    self.ElementTable.append(
                        nodesInElement[nodesInElement > 0])

                    # Get element type from number of nodes
                    if len(self.ElementTable[i]) == 3:
                        self.ElementType[i] = 21
                    elif len(self.ElementTable[i]) == 4:
                        self.ElementType[i] = 25
                        self._hasQuads = True
                    else:
                        self.ElementType[i] = 0
                        # TODO: Throw an exception?

            except Exception as inner:
                raise Exception(
                    "Can not load mesh file (failed reading elements): {0}. {1}"
                    .format(filename, inner))
Exemplo n.º 4
0
    def CreateDfsu(self, dfsBuilder, elementType, nodesPerElmt,
                   connectivityArray):
        # Add static items
        # Static items in a dfsu file:
        # "Node id"       , int
        # "X-coord"       , float
        # "Y-coord"       , float
        # "Z-coord"       , float
        # "Code"          , int
        # "Element id"    , int
        # "Element type"  , int
        # "No of nodes"   , int
        # "Connectivity"  , int

        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)):
        #        xyQuantity = eumQuantity(eumItem.eumILatLong, eumUnit.eumUdegree)

        # Node id
        nodeIdItem = dfsBuilder.AddCreateStaticItem("Node id", intCode,
                                                    self.__nodeIds)

        # X-coord
        xItem = dfsBuilder.AddCreateStaticItem("X-coord", xyQuantity, self.__x)

        # Y-coord
        yItem = dfsBuilder.AddCreateStaticItem("Y-coord", xyQuantity, self.__y)

        # Z-coord
        zItem = dfsBuilder.AddCreateStaticItem("Z-coord", self.__zQuantity,
                                               self.__z)

        # Code
        codeItem = dfsBuilder.AddCreateStaticItem("Code", intCode, self.__code)

        # Element id
        elmtIdItem = dfsBuilder.AddCreateStaticItem("Element id", intCode,
                                                    self.__elementIds)

        # Element type
        elmtTypeItem = dfsBuilder.AddCreateStaticItem("Element type", intCode,
                                                      elementType)

        # No of nodes (per element)
        nodesPerElmtItem = dfsBuilder.AddCreateStaticItem(
            "No of nodes", intCode, nodesPerElmt)

        # Connectivity
        connectivityItem = dfsBuilder.AddCreateStaticItem(
            "Connectivity", intCode, connectivityArray)

        dfsFile = dfsBuilder.GetFile()

        dfsuFile = DfsuFile()
        dfsuFile.DfsuFileBuild(dfsFile, nodeIdItem, xItem, yItem, zItem,
                               codeItem, elmtIdItem, self.__nodeIds, self.__x,
                               self.__y, self.__z, self.__code,
                               self.__elementIds, elementType,
                               self.__connectivity, self.__zUnit)

        return (dfsuFile)
Exemplo n.º 5
0
    def SetupBuilder(self):
        self.__zQuantity = eumQuantity(eumItem.eumIItemGeometry3D,
                                       self.__zUnit)

        factory = DfsFactory()
        dfsBuilder = DfsBuilder.Create(self.FileTitle, self.ApplicationTitle,
                                       self.ApplicationVersion)

        dfsBuilder.SetDataType(2001)
        dfsBuilder.SetGeographicalProjection(self.__dfsProjection)
        if (self.__timeAxis != None):
            dfsBuilder.SetTemporalAxis(self.__timeAxis)
        else:
            dfsBuilder.SetTemporalAxis(
                factory.CreateTemporalEqCalendarAxis(eumUnit.eumUsec,
                                                     self.__startDateTime, 0,
                                                     self.__timeStepInSeconds))
        dfsBuilder.DeleteValueFloat = np.float32(1e-35)

        # Set up custom block
        if self.__dfsuFileType == DfsuFileType.Dfsu2D:
            dfsBuilder.AddCreateCustomBlock(
                "MIKE_FM",
                np.array([self.__x.size,
                          len(self.__connectivity), 2, 0, 0], np.int32))
        elif self.__dfsuFileType == DfsuFileType.DfsuVerticalColumn:
            maxNumberOfLayers = len(self.__connectivity)
            dfsBuilder.AddCreateCustomBlock(
                "MIKE_FM",
                np.array([
                    self.__x.size,
                    len(self.__connectivity), 1, maxNumberOfLayers,
                    self.__numberOfSigmaLayers
                ], np.int32))
        elif self.__dfsuFileType == DfsuFileType.DfsuVerticalProfileSigma:
            maxNumberOfLayers = self.__numberOfSigmaLayers
            dfsBuilder.AddCreateCustomBlock(
                "MIKE_FM",
                np.array([
                    self.__x.size,
                    len(self.__connectivity), 2, maxNumberOfLayers,
                    self.__numberOfSigmaLayers
                ], np.int32))
        elif self.__dfsuFileType == DfsuFileType.DfsuVerticalProfileSigmaZ:
            maxNumberOfLayers = DfsuUtil.FindMaxNumberOfLayers(
                DfsuUtil.FindTopLayerElements(self.__connectivity))
            dfsBuilder.AddCreateCustomBlock(
                "MIKE_FM",
                np.array([
                    self.__x.size,
                    len(self.__connectivity), 2, maxNumberOfLayers,
                    self.__numberOfSigmaLayers
                ], np.int32))
        elif self.__dfsuFileType == DfsuFileType.Dfsu3DSigma:
            maxNumberOfLayers = self.__numberOfSigmaLayers
            dfsBuilder.AddCreateCustomBlock(
                "MIKE_FM",
                np.array([
                    self.__x.size,
                    len(self.__connectivity), 3, maxNumberOfLayers,
                    self.__numberOfSigmaLayers
                ], np.int32))
        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))
        else:
            raise Exception()

        # For the files with a vertical dimension, the first dynamic item is the Z-coordinate
        if (self.__dfsuFileType == DfsuFileType.DfsuVerticalColumn
                or self.__dfsuFileType == DfsuFileType.DfsuVerticalProfileSigma
                or self.__dfsuFileType
                == DfsuFileType.DfsuVerticalProfileSigmaZ
                or self.__dfsuFileType == DfsuFileType.Dfsu3DSigma
                or self.__dfsuFileType == DfsuFileType.Dfsu3DSigmaZ):
            dfsItem = dfsBuilder.CreateDynamicItemBuilder()
            dfsItem.Set("Z coordinate", self.__zQuantity, DfsSimpleType.Float)
            dfsItem.SetValueType(DataValueType.Instantaneous)
            # Disabled to make the dfsu files exactly match those from the engine. Not necessary,
            # but enables binary compares
            #if (false):
            #  dfsItem.SetAxis(factory.CreateAxisDummy(len(self.__connectivity)))
            #else
            # Set axis to have meter unit (not necessary, just to make file exactly equal)
            dfsItem.SetAxis(
                factory.CreateAxisEqD1(eumUnit.eumUmeter, self.__x.size, 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)
            dfsBuilder.AddDynamicItem(dfsItem.GetDynamicItemInfo())

        # Set up dynamic items
        for i in range(len(self.__dynamicItemData)):
            itemData = self.__dynamicItemData[i]
            dfsItem = dfsBuilder.CreateDynamicItemBuilder()
            dfsItem.Set(itemData[0], itemData[1], DfsSimpleType.Float)
            dfsItem.SetValueType(DataValueType.Instantaneous)
            # Disabled to make the dfsu files exactly match those from the engine. Not necessary,
            # but enables binary compares
            #if (false):
            #  dfsItem.SetAxis(factory.CreateAxisDummy(len(self.__connectivity)))
            #else
            # Set axis to have meter unit (not necessary, just to make file exactly equal)
            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)
            dfsBuilder.AddDynamicItem(dfsItem.GetDynamicItemInfo())
        return dfsBuilder