diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index e643ce117..ca3f300ad 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -51,6 +51,9 @@ include(${CMAKE_CURRENT_LIST_DIR}/XMLFile/CMakeLists.txt) # VTKFile include(${CMAKE_CURRENT_LIST_DIR}/VTKFile/CMakeLists.txt) +# PVDFile +include(${CMAKE_CURRENT_LIST_DIR}/PVDFile/CMakeLists.txt) + # Files include(${CMAKE_CURRENT_LIST_DIR}/Files/CMakeLists.txt) diff --git a/src/modules/Files/src/Files.F90 b/src/modules/Files/src/Files.F90 index 1743fba99..233e46263 100644 --- a/src/modules/Files/src/Files.F90 +++ b/src/modules/Files/src/Files.F90 @@ -28,4 +28,5 @@ MODULE Files USE HDF5File_Method USE XMLFile_Class USE VTKFile_Class +USE PVDFile_Class END MODULE Files diff --git a/src/modules/PVDFile/CMakeLists.txt b/src/modules/PVDFile/CMakeLists.txt new file mode 100644 index 000000000..0eed25d62 --- /dev/null +++ b/src/modules/PVDFile/CMakeLists.txt @@ -0,0 +1,19 @@ +# This program is a part of EASIFEM library Copyright (C) 2020-2021 Vikas +# Sharma, Ph.D +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see +# + +set(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +target_sources(${PROJECT_NAME} PRIVATE ${src_path}/PVDFile_Class.F90) diff --git a/src/modules/PVDFile/src/PVDFile_Class.F90 b/src/modules/PVDFile/src/PVDFile_Class.F90 new file mode 100644 index 000000000..bf4877669 --- /dev/null +++ b/src/modules/PVDFile/src/PVDFile_Class.F90 @@ -0,0 +1,262 @@ +! This program is a part of EASIFEM library +! Copyright (C) 2020-2021 Vikas Sharma, Ph.D +! +! This program is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with this program. If not, see +! + +MODULE PVDFile_Class +USE Globaldata +USE BaseType +USE String_Class, ONLY: String +USE XMLFile_Class +USE ExceptionHandler_Class, ONLY: e +IMPLICIT NONE +PRIVATE + +CHARACTER(*), PARAMETER :: modName = "PVDFile_Class" +INTEGER(I4B), PARAMETER, PUBLIC :: PVD_ASCII = 1 +INTEGER(I4B), PARAMETER, PUBLIC :: PVD_BINARY = 2 +INTEGER(I4B), PARAMETER, PUBLIC :: PVD_APPENDED = 3 +INTEGER(I4B), PARAMETER, PUBLIC :: PVD_RAW_APPENDED = 3 +INTEGER(I4B), PARAMETER, PUBLIC :: PVD_BINARY_APPENDED = 4 +CHARACTER(*), PARAMETER, DIMENSION(3) :: dataFormatName = & + & [ & + & "ascii ", & + & "binary ", & + & "appended" & + & ] +PUBLIC :: PVDFile_ +PUBLIC :: PVDFilePointer_ + +!---------------------------------------------------------------------------- +! PVDFile_ +!---------------------------------------------------------------------------- + +!> authors: Shion Shimizu +! date: 2024-02-03 +! summary: PVDFile + +TYPE, EXTENDS(XMLFile_) :: PVDFile_ + PRIVATE + ! INTEGER(I4B) :: dataFormat = 0 + !! PVD_ASCII + !! PVD_BINARY + !! PVD_APPENDED + !! PVD_RAW_APPENDED + !! PVD_BINARY_APPENDED + INTEGER(I4B) :: indent = 0 + !! Indent + TYPE(String), DIMENSION(4) :: attrNames + ! LOGICAL(LGT) :: search = .FALSE. +CONTAINS + PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods + PROCEDURE, PUBLIC, PASS(obj) :: InitiatePVDFile + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => obj_Deallocate + FINAL :: obj_Final + PROCEDURE, PUBLIC, PASS(obj) :: CLOSE => obj_Close + + ! IO: + ! @TagsMethods + PROCEDURE, PUBLIC, PASS(obj) :: WriteRootTag => obj_WriteRootTag + PROCEDURE, PUBLIC, PASS(obj) :: WriteDataSetTag => obj_WriteDataSetTag + PROCEDURE, PUBLIC, PASS(obj) :: WriteStartTag => obj_WriteStartTag + PROCEDURE, PUBLIC, PASS(obj) :: WriteEndTag => obj_WriteEndTag + PROCEDURE, PUBLIC, PASS(obj) :: WriteSelfClosingTag => & + & obj_WriteSelfClosingTag + PROCEDURE, PUBLIC, PASS(obj) :: WriteTag => obj_WriteTag + +END TYPE PVDFile_ + +!---------------------------------------------------------------------------- +! PVDFilePointer_ +!---------------------------------------------------------------------------- + +TYPE :: PVDFilePointer_ + CLASS(PVDFile_), POINTER :: ptr => NULL() +END TYPE PVDFilePointer_ + +!---------------------------------------------------------------------------- +! PVDFile@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Shion Shimizu +! date: 2024-02-03 +! summary: This function returns an instance of PVDFile +! +!# Introduction +! This function returns an instance if PVDFile. After calling this function +! This routine initiates the XMLFile, and opens it. +! It also write header file and dataStructure tag to the file. +! + +INTERFACE + MODULE SUBROUTINE InitiatePVDFile(obj, filename, mode, dataFormat) + CLASS(PVDFile_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: filename + !! Name of the file, where xml data will be printed + CHARACTER(*), OPTIONAL, INTENT(IN) :: mode + !! READ, WRITE, NEW, REPLACE + !! DEFAULT IS NEW + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dataFormat + !! PVD_ASCII, PVD_APPENEDED, PVD_BINARY + !! DEFAULT is PVD_BINARY_APPENDED + END SUBROUTINE InitiatePVDFile +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Shion Shimizu +! date: 2024-02-03 +! summary: Deallocates the content of PVDFile and close or delete it. + +INTERFACE + MODULE SUBROUTINE obj_Deallocate(obj, delete) + CLASS(PVDFile_), INTENT(INOUT) :: obj + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: delete + END SUBROUTINE obj_Deallocate +END INTERFACE + +!---------------------------------------------------------------------------- +! Final@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Shion Shimizu +! date: 2024-02-03 +! summary: Finalizer for PVDFile + +INTERFACE + MODULE SUBROUTINE obj_Final(obj) + TYPE(PVDFile_), INTENT(INOUT) :: obj + END SUBROUTINE obj_Final +END INTERFACE + +!---------------------------------------------------------------------------- +! Close@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Shion Shimizu +! date: 2024-02-03 +! summary: Close the file + +INTERFACE + MODULE SUBROUTINE obj_Close(obj) + CLASS(PVDFile_), INTENT(INOUT) :: obj + END SUBROUTINE obj_Close +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteRootTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Shion Shimizu +! date: 2024-02-03 +! summary: Write the root tag +! + +INTERFACE + MODULE SUBROUTINE obj_WriteRootTag(obj) + CLASS(PVDFile_), INTENT(INOUT) :: obj + END SUBROUTINE obj_WriteRootTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteDataSetTag@TagsMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE obj_WriteDataSetTag(obj, currentTime, filename, part, & + & group) + CLASS(PVDFile_), INTENT(INOUT) :: obj + REAL(DFP), INTENT(IN) :: currentTime + CHARACTER(*), INTENT(IN) :: filename + INTEGER(I4B), OPTIONAL, INTENT(IN) :: part + CHARACTER(*), OPTIONAL, INTENT(IN) :: group + END SUBROUTINE obj_WriteDataSetTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteStartTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Shion Shimizu +! date: 2024-02-03 +! summary: Write the start tag + +INTERFACE + MODULE SUBROUTINE obj_WriteStartTag(obj, name, attrNames, attrValues) + CLASS(PVDFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + TYPE(String), OPTIONAL, INTENT(IN) :: attrNames(:) + TYPE(String), OPTIONAL, INTENT(IN) :: attrValues(:) + END SUBROUTINE obj_WriteStartTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteEndTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Shion Shimizu +! date: 2024-02-03 +! summary: Write the End tag + +INTERFACE + MODULE SUBROUTINE obj_WriteEndTag(obj, name) + CLASS(PVDFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + END SUBROUTINE obj_WriteEndTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteSelfClosingTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Shion Shimizu +! date: 2024-02-03 +! summary: Write the self closing tag + +INTERFACE + MODULE SUBROUTINE obj_WriteSelfClosingTag(obj, name, attrNames, & + & attrValues) + CLASS(PVDFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + TYPE(String), OPTIONAL, INTENT(IN) :: attrNames(:) + TYPE(String), OPTIONAL, INTENT(IN) :: attrValues(:) + END SUBROUTINE obj_WriteSelfClosingTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Shion Shimizu +! date: 2024-02-03 +! summary: Write Tags and contents + +INTERFACE + MODULE SUBROUTINE obj_WriteTag(obj, name, attrNames, & + & attrValues, content) + CLASS(PVDFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + TYPE(String), OPTIONAL, INTENT(IN) :: attrNames(:) + TYPE(String), OPTIONAL, INTENT(IN) :: attrValues(:) + TYPE(String), OPTIONAL, INTENT(IN) :: content + END SUBROUTINE obj_WriteTag +END INTERFACE + +END MODULE PVDFile_Class diff --git a/src/submodules/CMakeLists.txt b/src/submodules/CMakeLists.txt index fbd8b4778..c752f215a 100644 --- a/src/submodules/CMakeLists.txt +++ b/src/submodules/CMakeLists.txt @@ -45,6 +45,9 @@ include(${CMAKE_CURRENT_LIST_DIR}/XMLFile/CMakeLists.txt) # VTKFile include(${CMAKE_CURRENT_LIST_DIR}/VTKFile/CMakeLists.txt) +# PVDFile +include(${CMAKE_CURRENT_LIST_DIR}/PVDFile/CMakeLists.txt) + # Toml include(${CMAKE_CURRENT_LIST_DIR}/Toml/CMakeLists.txt) diff --git a/src/submodules/PVDFile/CMakeLists.txt b/src/submodules/PVDFile/CMakeLists.txt new file mode 100644 index 000000000..5db270c92 --- /dev/null +++ b/src/submodules/PVDFile/CMakeLists.txt @@ -0,0 +1,21 @@ +# This program is a part of EASIFEM library Copyright (C) 2020-2021 Vikas +# Sharma, Ph.D +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see +# + +set(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +target_sources( + ${PROJECT_NAME} PRIVATE ${src_path}/PVDFile_Class@ConstructorMethods.F90 + ${src_path}/PVDFile_Class@TagsMethods.F90) diff --git a/src/submodules/PVDFile/src/PVDFile_Class@ConstructorMethods.F90 b/src/submodules/PVDFile/src/PVDFile_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..d22a96010 --- /dev/null +++ b/src/submodules/PVDFile/src/PVDFile_Class@ConstructorMethods.F90 @@ -0,0 +1,95 @@ +! This program is a part of EASIFEM library +! Copyright (C) 2020-2021 Vikas Sharma, Ph.D +! +! This program is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with this program. If not, see +! + +SUBMODULE(PVDFile_Class) ConstructorMethods +USE BaseMethod +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! PVDFile +!---------------------------------------------------------------------------- + +MODULE PROCEDURE InitiatePVDFile +CHARACTER(*), PARAMETER :: myName = "InitiatePVDFile()" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START]') +#endif + +IF (obj%isInitiated) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: PVDFile is already initiated, '// & + & ' call Deallocate() first') + RETURN +END IF + +! obj%dataFormat = Input(option=dataFormat, default=PVD_BINARY_APPENDED) +! obj%spacing = 1 +obj%attrNames = [String("part"), String("group"), String("timestep"), String("file")] + +CALL obj%Initiate(filename=filename, & + & mode=Input(option=mode, default="NEW")) +CALL obj%OPEN() + +CALL obj%WriteRootTag() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END]') +#endif +END PROCEDURE InitiatePVDFile + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_Deallocate +CALL xmlFile_Deallocate(obj, delete) +obj%indent = 0 +obj%attrNames = String("") +! obj%search = .FALSE. +END PROCEDURE obj_Deallocate + +!---------------------------------------------------------------------------- +! Final +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_Final +CALL obj%DEALLOCATE() +END PROCEDURE obj_Final + +!---------------------------------------------------------------------------- +! Close +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_Close +IF (obj%isOpen()) THEN + obj%indent = 2 + CALL obj%WriteEndTag(name=String("Collection")) + obj%indent = 0 + CALL obj%WriteEndTag(name=String('VTKFile')) + CALL xmlFile_Close(obj) +END IF +END PROCEDURE obj_Close + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/PVDFile/src/PVDFile_Class@TagsMethods.F90 b/src/submodules/PVDFile/src/PVDFile_Class@TagsMethods.F90 new file mode 100644 index 000000000..ec1f62f04 --- /dev/null +++ b/src/submodules/PVDFile/src/PVDFile_Class@TagsMethods.F90 @@ -0,0 +1,190 @@ +! This program is a part of EASIFEM library +! Copyright (C) 2020-2021 Vikas Sharma, Ph.D +! +! This program is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with this program. If not, see +! + +SUBMODULE(PVDFile_Class) TagsMethods +USE BaseMethod +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_WriteRootTag +CHARACTER(*), PARAMETER :: myName = "PVDFile_WriteRootTag()" +TYPE(String) :: buffer +CHARACTER(100) :: ioerrmsg +INTEGER(I4B) :: ierr + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ') +#endif + +IF (.NOT. obj%isInitiated) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & ' [INTERNAL ERROR] :: PVDFile is not initiated!') +END IF + +IF (.NOT. obj%isOpen()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: PVDFile is not open') +END IF + +IF (.NOT. obj%isWrite()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: PVDFile does not have write permission') +END IF + +buffer = ''//CHAR_LF + +IF (endian .EQ. endianL) THEN + buffer = buffer//'' +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP] not implemented yet') +END IF + +WRITE (obj%unitNo, "(a)", iostat=ierr, iomsg=ioerrmsg) & + & TRIM(buffer%chars())//CHAR_LF + +obj%indent = 2 + +CALL obj%WriteStartTag(name=String("Collection")) + +obj%indent = 4 + +IF (ierr .NE. 0) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: Error has occured while'// & + & 'writing header info in PVDFile iostat = '// & + & TRIM(str(ierr, .TRUE.))//' error msg :: '// & + & TRIM(ioerrmsg)) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ') +#endif +END PROCEDURE obj_WriteRootTag + +!---------------------------------------------------------------------------- +! WriteDataSetTag +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_WriteDataSetTag +CHARACTER(*), PARAMETER :: myName = "WriteDataSetTag" +INTEGER(I4B) :: part0 +TYPE(String) :: attrValues(4) +CHARACTER(:), ALLOCATABLE :: group0 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ') +#endif + +IF (.NOT. obj%isInitiated) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & ' [INTERNAL ERROR] :: PVDFile is not initiated!') +END IF + +IF (.NOT. obj%isOpen()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: PVDFile is not open') +END IF + +IF (.NOT. obj%isWrite()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: PVDFile does not have write permission') +END IF + +part0 = input(option=part, default=0) +group0 = input(option=group, default="") + +! IF (obj%search) THEN +! CALL e%RaiseWarning(modName//'::'//myName//' - '// & +! & '[TODO] searching is not implemented yet') +! END IF + +attrValues(1) = '"'//tostring(part0)//'"' +attrValues(2) = '"'//String(group0)//'"' +attrValues(3) = '"'//tostring(currentTime)//'"' +attrValues(4) = '"'//String(filename)//'"' + +CALL obj%WriteSelfClosingTag(name=String("DataSet"), attrNames=obj%attrNames, & +& attrValues=attrValues) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ') +#endif + +END PROCEDURE obj_WriteDataSetTag + +!---------------------------------------------------------------------------- +! WriteStartTag +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_WriteStartTag +TYPE(XMLTag_) :: tag +CALL tag%set(name=name, attrNames=attrNames, attrValues=attrValues, & + & Indent=obj%Indent) +CALL tag%WRITE(unitNo=obj%unitNo, isIndented=.TRUE., endRecord=CHAR_LF, & + & onlyStart=.TRUE.) +obj%Indent = obj%Indent + 2 +CALL tag%DEALLOCATE() +END PROCEDURE obj_WriteStartTag + +!---------------------------------------------------------------------------- +! WriteEndTag +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_WriteEndTag +TYPE(XMLTag_) :: tag +CALL tag%set(name=name, indent=obj%indent) +CALL tag%WRITE(unitNo=obj%unitNo, isIndented=.TRUE., endRecord=CHAR_LF, & + & onlyEnd=.TRUE.) +CALL tag%DEALLOCATE() +END PROCEDURE obj_WriteEndTag + +!---------------------------------------------------------------------------- +! WriteSelfClosingTag +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_WriteSelfClosingTag +TYPE(XMLTag_) :: tag +CALL tag%set(name=name, attrNames=attrNames, attrValues=attrValues, & + & indent=obj%Indent, isSelfClosing=.TRUE.) +CALL tag%WRITE(unitNo=obj%unitNo, isIndented=.TRUE., endRecord=CHAR_LF) +CALL tag%DEALLOCATE() +END PROCEDURE obj_WriteSelfClosingTag + +!---------------------------------------------------------------------------- +! WriteTag +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_WriteTag +TYPE(XMLTag_) :: tag +CALL tag%set(name=name, attrNames=attrNames, attrValues=attrValues, & + & content=content, Indent=obj%Indent) +CALL tag%WRITE(unitNo=obj%unitNo, isIndented=.TRUE., & + & isContentIndented=.TRUE., endRecord=CHAR_LF) +CALL tag%DEALLOCATE() +END PROCEDURE obj_WriteTag + +END SUBMODULE TagsMethods